Version in base suite: 2.7.5-3 Base version: glewlwyd_2.7.5-3 Target version: glewlwyd_2.7.5-3+deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/g/glewlwyd/glewlwyd_2.7.5-3.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/g/glewlwyd/glewlwyd_2.7.5-3+deb12u1.dsc changelog | 9 + patches/CVE-2023-49208.patch | 21 +++ patches/CVE-2024-25715.patch | 256 +++++++++++++++++++++++++++++++++++++++++++ patches/series | 3 4 files changed, 288 insertions(+), 1 deletion(-) diff -Nru glewlwyd-2.7.5/debian/changelog glewlwyd-2.7.5/debian/changelog --- glewlwyd-2.7.5/debian/changelog 2023-05-04 11:21:27.000000000 +0000 +++ glewlwyd-2.7.5/debian/changelog 2023-11-23 22:12:13.000000000 +0000 @@ -1,3 +1,12 @@ +glewlwyd (2.7.5-3+deb12u1) bookworm; urgency=medium + + * d/patches: Fix CVE-2023-49208 + possible buffer overflow during FIDO2 credentials validation + * d/patches: Fix CVE-2024-25715 + open redirection via redirect_uri + + -- Nicolas Mora Thu, 23 Nov 2023 17:12:13 -0500 + glewlwyd (2.7.5-3) unstable; urgency=medium * Install config.json as config-2.7.json (Closes: #1035503) diff -Nru glewlwyd-2.7.5/debian/patches/CVE-2023-49208.patch glewlwyd-2.7.5/debian/patches/CVE-2023-49208.patch --- glewlwyd-2.7.5/debian/patches/CVE-2023-49208.patch 1970-01-01 00:00:00.000000000 +0000 +++ glewlwyd-2.7.5/debian/patches/CVE-2023-49208.patch 2023-11-23 22:12:13.000000000 +0000 @@ -0,0 +1,21 @@ +Description: Fix CVE-2023-49208 for bookworm +Author: Nicolas Mora +Forwarded: not-needed +--- a/src/scheme/webauthn.c ++++ b/src/scheme/webauthn.c +@@ -2260,13 +2260,13 @@ + for (i=0; i +Forwarded: not-needed +--- a/src/plugin/protocol_oauth2.c ++++ b/src/plugin/protocol_oauth2.c +@@ -696,7 +696,7 @@ + + static json_t * check_client_valid(struct _oauth2_config * config, const char * client_id, const char * client_header_login, const char * client_header_password, const char * redirect_uri, unsigned short authorization_type, int implicit_flow, const char * ip_source) { + json_t * j_client, * j_element = NULL, * j_return; +- int uri_found, authorization_type_enabled; ++ int uri_found = 0, authorization_type_enabled; + size_t index = 0; + + if (client_id == NULL) { +@@ -707,20 +707,17 @@ + return json_pack("{si}", "result", G_ERROR_PARAM); + } + j_client = config->glewlwyd_config->glewlwyd_callback_check_client_valid(config->glewlwyd_config, client_id, client_header_password); +- if (check_result_value(j_client, G_OK)) { ++ if (check_result_value(j_client, G_OK) && json_object_get(json_object_get(j_client, "client"), "enabled") == json_true()) { + if (!implicit_flow && client_header_password == NULL && json_object_get(json_object_get(j_client, "client"), "confidential") == json_true()) { + y_log_message(Y_LOG_LEVEL_DEBUG, "check_client_valid - oauth2 - Error, confidential client must be authentified with its password, origin: %s", ip_source); + j_return = json_pack("{si}", "result", G_ERROR_UNAUTHORIZED); + } else { + if (redirect_uri != NULL) { +- uri_found = 0; + json_array_foreach(json_object_get(json_object_get(j_client, "client"), "redirect_uri"), index, j_element) { + if (0 == o_strcmp(json_string_value(j_element), redirect_uri)) { + uri_found = 1; + } + } +- } else { +- uri_found = 1; + } + + authorization_type_enabled = 0; +@@ -2444,8 +2441,8 @@ + // Check if client is allowed to perform this request + if (check_result_value(j_client, G_OK)) { + // Client is allowed to use auth_code grant with this redirection_uri +- if (u_map_has_key(request->map_url, "g_continue")) { +- if (!o_strnullempty(u_map_get(request->map_url, "scope"))) { ++ if (!o_strnullempty(u_map_get(request->map_url, "scope"))) { ++ if (u_map_has_key(request->map_url, "g_continue")) { + j_session = validate_session_client_scope(config, request, u_map_get(request->map_url, "client_id"), u_map_get(request->map_url, "scope")); + if (check_result_value(j_session, G_OK)) { + if (json_object_get(json_object_get(j_session, "session"), "authorization_required") == json_false()) { +@@ -2526,26 +2523,20 @@ + } + json_decref(j_session); + } else { +- // Scope is not allowed for this user +- y_log_message(Y_LOG_LEVEL_DEBUG, "check_auth_type_auth_code_grant - oauth2 - scope list is missing or empty, origin: %s", ip_source); +- response->status = 302; +- redirect_url = msprintf("%s%serror=invalid_scope%s", u_map_get(request->map_url, "redirect_uri"), (o_strchr(u_map_get(request->map_url, "redirect_uri"), '?')!=NULL?"&":"?"), state_param); ++ // Redirect to login page ++ redirect_url = get_login_url(config, request, "auth", u_map_get(request->map_url, "client_id"), u_map_get(request->map_url, "scope"), NULL); + ulfius_add_header_to_response(response, "Location", redirect_url); + o_free(redirect_url); ++ response->status = 302; + } + } else { +- // Redirect to login page +- redirect_url = get_login_url(config, request, "auth", u_map_get(request->map_url, "client_id"), u_map_get(request->map_url, "scope"), NULL); +- ulfius_add_header_to_response(response, "Location", redirect_url); +- o_free(redirect_url); +- response->status = 302; ++ // Scope is not allowed for this user ++ y_log_message(Y_LOG_LEVEL_DEBUG, "check_auth_type_auth_code_grant - oauth2 - scope list is missing or empty, origin: %s", ip_source); ++ response->status = 403; + } + } else { + // client is not authorized +- response->status = 302; +- redirect_url = msprintf("%s%serror=unauthorized_client%s%s", u_map_get(request->map_url, "redirect_uri"), (o_strchr(u_map_get(request->map_url, "redirect_uri"), '?')!=NULL?"&":"?"), (u_map_get(request->map_url, "state")!=NULL?"&state=":""), (u_map_get(request->map_url, "state")!=NULL?u_map_get(request->map_url, "state"):"")); +- ulfius_add_header_to_response(response, "Location", redirect_url); +- o_free(redirect_url); ++ response->status = 403; + config->glewlwyd_config->glewlwyd_plugin_callback_metrics_increment_counter(config->glewlwyd_config, GLWD_METRICS_OAUTH2_UNAUTHORIZED_CLIENT, 1, "plugin", config->name, NULL); + } + o_free(state_param); +@@ -2707,8 +2698,8 @@ + // Check if client is allowed to perform this request + if (check_result_value(j_client, G_OK)) { + // Client is allowed to use auth_code grant with this redirection_uri +- if (u_map_has_key(request->map_url, "g_continue")) { +- if (!o_strnullempty(u_map_get(request->map_url, "scope"))) { ++ if (!o_strnullempty(u_map_get(request->map_url, "scope"))) { ++ if (u_map_has_key(request->map_url, "g_continue")) { + j_session = validate_session_client_scope(config, request, u_map_get(request->map_url, "client_id"), u_map_get(request->map_url, "scope")); + if (check_result_value(j_session, G_OK)) { + if (json_object_get(json_object_get(j_session, "session"), "authorization_required") == json_false()) { +@@ -2791,25 +2782,19 @@ + } + json_decref(j_session); + } else { +- // Empty scope is not allowed +- response->status = 302; +- redirect_url = msprintf("%s%serror=invalid_scope%s", u_map_get(request->map_url, "redirect_uri"), (o_strchr(u_map_get(request->map_url, "redirect_uri"), '?')!=NULL?"&":"?"), state_param); ++ // Redirect to login page ++ redirect_url = get_login_url(config, request, "auth", u_map_get(request->map_url, "client_id"), u_map_get(request->map_url, "scope"), NULL); + ulfius_add_header_to_response(response, "Location", redirect_url); + o_free(redirect_url); ++ response->status = 302; + } + } else { +- // Redirect to login page +- redirect_url = get_login_url(config, request, "auth", u_map_get(request->map_url, "client_id"), u_map_get(request->map_url, "scope"), NULL); +- ulfius_add_header_to_response(response, "Location", redirect_url); +- o_free(redirect_url); +- response->status = 302; ++ // Empty scope is not allowed ++ response->status = 403; + } + } else { + // client is not authorized +- response->status = 302; +- redirect_url = msprintf("%s%serror=unauthorized_client%s%s", u_map_get(request->map_url, "redirect_uri"), (o_strchr(u_map_get(request->map_url, "redirect_uri"), '?')!=NULL?"&":"?"), (u_map_get(request->map_url, "state")!=NULL?"&state=":""), (u_map_get(request->map_url, "state")!=NULL?u_map_get(request->map_url, "state"):"")); +- ulfius_add_header_to_response(response, "Location", redirect_url); +- o_free(redirect_url); ++ response->status = 403; + } + o_free(state_param); + json_decref(j_client); +@@ -3313,7 +3298,7 @@ + static int callback_oauth2_authorization(const struct _u_request * request, struct _u_response * response, void * user_data) { + const char * response_type = u_map_get(request->map_url, "response_type"); + int result = U_CALLBACK_CONTINUE; +- char * redirect_url, * state_encoded = NULL, * state_param = NULL; ++ char * state_encoded = NULL, * state_param = NULL; + + u_map_put(response->map_header, "Cache-Control", "no-store"); + u_map_put(response->map_header, "Pragma", "no-cache"); +@@ -3326,41 +3311,21 @@ + } else { + state_param = o_strdup(""); + } ++ + if (0 == o_strcmp("code", response_type)) { + if (is_authorization_type_enabled((struct _oauth2_config *)user_data, GLEWLWYD_AUTHORIZATION_TYPE_AUTHORIZATION_CODE) && u_map_get(request->map_url, "redirect_uri") != NULL) { + result = check_auth_type_auth_code_grant(request, response, user_data); + } else { +- if (u_map_get(request->map_url, "redirect_uri") != NULL) { +- response->status = 302; +- redirect_url = msprintf("%s#error=unsupported_response_type%s", u_map_get(request->map_url, "redirect_uri"), state_param); +- ulfius_add_header_to_response(response, "Location", redirect_url); +- o_free(redirect_url); +- } else { +- response->status = 403; +- } ++ response->status = 403; + } + } else if (0 == o_strcmp("token", response_type)) { + if (is_authorization_type_enabled((struct _oauth2_config *)user_data, GLEWLWYD_AUTHORIZATION_TYPE_IMPLICIT) && u_map_get(request->map_url, "redirect_uri") != NULL) { + result = check_auth_type_implicit_grant(request, response, user_data); + } else { +- if (u_map_get(request->map_url, "redirect_uri") != NULL) { +- response->status = 302; +- redirect_url = msprintf("%s#error=unsupported_response_type%s", u_map_get(request->map_url, "redirect_uri"), state_param); +- ulfius_add_header_to_response(response, "Location", redirect_url); +- o_free(redirect_url); +- } else { +- response->status = 403; +- } +- } +- } else { +- if (u_map_get(request->map_url, "redirect_uri") != NULL) { +- response->status = 302; +- redirect_url = msprintf("%s#error=unsupported_response_type%s", u_map_get(request->map_url, "redirect_uri"), state_param); +- ulfius_add_header_to_response(response, "Location", redirect_url); +- o_free(redirect_url); +- } else { + response->status = 403; + } ++ } else { ++ response->status = 403; + } + o_free(state_param); + +--- a/src/plugin/protocol_oidc.c ++++ b/src/plugin/protocol_oidc.c +@@ -3789,6 +3789,36 @@ + return (authorization_type <= 7)?config->auth_type_enabled[authorization_type]:0; + } + ++static int check_client_redirect_uri_valid(struct _oidc_config * config, ++ const char * client_id, ++ const char * redirect_uri, ++ const char * ip_source) { ++ json_t * j_client = config->glewlwyd_config->glewlwyd_plugin_callback_get_client(config->glewlwyd_config, client_id); ++ int uri_found = 0, ret; ++ ++ if (check_result_value(j_client, G_OK) && json_object_get(json_object_get(j_client, "client"), "enabled") == json_true()) { ++ if (!o_strnullempty(redirect_uri)) { ++ if (json_array_has_string(json_object_get(json_object_get(j_client, "client"), "redirect_uri"), redirect_uri)) { ++ uri_found = 1; ++ } else { ++ uri_found = 0; ++ } ++ } else { ++ uri_found = 1; ++ } ++ if (!uri_found) { ++ y_log_message(Y_LOG_LEVEL_DEBUG, "check_client_redirect_uri_valid - oidc - Error, redirect_uri '%s' is invalid for the client '%s', origin: %s", redirect_uri, client_id, ip_source); ++ ret = G_ERROR_UNAUTHORIZED; ++ } else { ++ ret = G_OK; ++ } ++ } else { ++ ret = G_ERROR_UNAUTHORIZED; ++ } ++ json_decref(j_client); ++ return ret; ++} ++ + /** + * Verify if a client is valid without checking its secret + */ +@@ -14127,6 +14157,13 @@ + response_mode = GLEWLWYD_RESPONSE_MODE_FRAGMENT; + } + } ++ ++ if (!o_strnullempty(response_type) && check_client_redirect_uri_valid(config, client_id, redirect_uri, ip_source) != G_OK) { ++ y_log_message(Y_LOG_LEVEL_DEBUG, "callback_oidc_authorization - invlid client identified with redirect_uri"); ++ response->status = 403; ++ break; ++ } ++ + if (u_map_has_key(map, "response_mode")) { + str_response_mode = u_map_get(map, "response_mode"); + if (0 == o_strcmp("query", str_response_mode)) { +@@ -14230,6 +14267,11 @@ + login_hint = json_string_value(json_object_get(json_object_get(j_request, "request"), "login_hint")); + prompt = json_string_value(json_object_get(json_object_get(j_request, "request"), "prompt")); + max_age = json_string_value(json_object_get(json_object_get(j_request, "request"), "max_age")); ++ if (check_client_redirect_uri_valid(config, client_id, redirect_uri, ip_source) != G_OK) { ++ y_log_message(Y_LOG_LEVEL_DEBUG, "callback_oidc_authorization - invlid client identified with redirect_uri"); ++ response->status = 403; ++ break; ++ } + if (code_challenge == NULL || request_par) { + code_challenge = json_string_value(json_object_get(json_object_get(j_request, "request"), "code_challenge")); + } +@@ -14474,10 +14516,7 @@ + + // Check if at least one scope has been provided + if (o_strnullempty(scope)) { +- // Scope is not allowed for this user +- y_log_message(Y_LOG_LEVEL_DEBUG, "oidc validate_endpoint_auth - scope list is missing or empty or scope 'openid' missing, origin: %s", ip_source); +- u_map_put(&map_redirect, "error", "invalid_scope"); +- build_auth_response(config, response, response_mode, json_object_get(j_client, "client"), redirect_uri, &map_redirect); ++ response->status = 403; + break; + } + diff -Nru glewlwyd-2.7.5/debian/patches/series glewlwyd-2.7.5/debian/patches/series --- glewlwyd-2.7.5/debian/patches/series 2023-01-19 00:01:39.000000000 +0000 +++ glewlwyd-2.7.5/debian/patches/series 2023-11-23 22:12:13.000000000 +0000 @@ -1,2 +1,3 @@ - webpack.patch +CVE-2023-49208.patch +CVE-2024-25715.patch