From: Marco Bettini Date: Tue, 3 Oct 2023 13:11:49 +0000 (+0000) Subject: oauth: Accept multiple entries in aud field X-Git-Tag: 2.3.21.1~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ac2bc5da92eebc9e982bf8217992a3e27cf16314;p=thirdparty%2Fdovecot%2Fcore.git oauth: Accept multiple entries in aud field --- diff --git a/src/auth/db-oauth2.c b/src/auth/db-oauth2.c index b36a4ced3f..d5ef604188 100644 --- a/src/auth/db-oauth2.c +++ b/src/auth/db-oauth2.c @@ -3,6 +3,7 @@ #include "auth-common.h" #include "array.h" #include "str.h" +#include "strescape.h" #include "var-expand.h" #include "env-util.h" #include "var-expand.h" @@ -650,7 +651,8 @@ db_oauth2_token_in_scope(struct db_oauth2_request *req, if (*req->db->set.scope != '\0') { bool found = FALSE; const char *value = auth_fields_find(req->fields, "scope"); - if (value == NULL) + bool has_scope = value != NULL; + if (!has_scope) value = auth_fields_find(req->fields, "aud"); e_debug(authdb_event(req->auth_request), "Token scope(s): %s", @@ -658,9 +660,11 @@ db_oauth2_token_in_scope(struct db_oauth2_request *req, if (value != NULL) { const char **wanted_scopes = t_strsplit_spaces(req->db->set.scope, " "); - const char **scopes = t_strsplit_spaces(value, " "); + const char *const *entries = has_scope ? + t_strsplit_spaces(value, " ") : + t_strsplit_tabescaped(value); for (; !found && *wanted_scopes != NULL; wanted_scopes++) - found = str_array_find(scopes, *wanted_scopes); + found = str_array_find(entries, *wanted_scopes); } if (!found) { *error_r = t_strdup_printf("Token is not valid for scope '%s'", diff --git a/src/lib-oauth2/oauth2-jwt.c b/src/lib-oauth2/oauth2-jwt.c index bc7779fe1d..04db602e9d 100644 --- a/src/lib-oauth2/oauth2-jwt.c +++ b/src/lib-oauth2/oauth2-jwt.c @@ -3,6 +3,7 @@ #include "lib.h" #include "buffer.h" #include "str.h" +#include "strescape.h" #include "hmac.h" #include "array.h" #include "hash-method.h" @@ -30,6 +31,29 @@ static const char *get_field(const struct json_tree *tree, const char *key) return json_tree_get_value_str(value_node); } +static const char *get_field_multiple(const struct json_tree *tree, const char *key) +{ + const struct json_tree_node *root = json_tree_root(tree); + const struct json_tree_node *value_node = json_tree_find_key(root, key); + if (value_node == NULL || value_node->value_type == JSON_TYPE_OBJECT) + return NULL; + if (value_node->value_type != JSON_TYPE_ARRAY) + return json_tree_get_value_str(value_node); + + const struct json_tree_node *entry_node = json_tree_get_child(value_node); + string_t *values = t_str_new(64); + for (; entry_node != NULL; entry_node = entry_node->next) { + if (entry_node->value_type == JSON_TYPE_OBJECT || + entry_node->value_type == JSON_TYPE_ARRAY) + continue; + const char *value_str = json_tree_get_value_str(entry_node); + if (str_len(values) > 0) + str_append_c(values, '\t'); + str_append_tabescaped(values, value_str); + } + return str_c(values); +} + static int get_time_field(const struct json_tree *tree, const char *key, int64_t *value_r) { @@ -418,7 +442,7 @@ oauth2_jwt_body_process(const struct oauth2_settings *set, const char *alg, } } - const char *aud = get_field(tree, "aud"); + const char *aud = get_field_multiple(tree, "aud"); /* if there is client_id configured, then aud should be present */ if (set->client_id != NULL && *set->client_id != '\0') { if (aud == NULL) { @@ -426,7 +450,7 @@ oauth2_jwt_body_process(const struct oauth2_settings *set, const char *alg, return -1; } - const char *const *auds = t_strsplit_spaces(aud, " "); + const char *const *auds = t_strsplit_tabescaped(aud); if (!str_array_find(auds, set->client_id)) { *error_r = "client_id not found in aud field"; return -1;