diff --git a/ChangeLog b/ChangeLog index 1de11a11..7ce559c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +10/31/2023 +- add capability to seamlessly rollover OIDCCryptoPassphrase using a (temporary) 2nd value that holds the old one +- bump to 2.4.15rc1 + 10/30/2023 - do not apply logout_on_error and authenticate_on_error when a parallel refresh token request is detected see https://github.com/OpenIDC/mod_auth_openidc/discussions/1132; thanks @esunke diff --git a/auth_openidc.conf b/auth_openidc.conf index 66a96515..5bd068d3 100644 --- a/auth_openidc.conf +++ b/auth_openidc.conf @@ -22,7 +22,12 @@ # OIDCCryptoPassphrase "exec:/bin/bash -c \"head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32\"" # (notice that the above typically only works in non-clustered environments) # The command may be absolute or relative to the web server root. -#OIDCCryptoPassphrase [ | "exec:/path/to/otherProgram arg1" ] +# +# A second value can be used temporarily in case of passphrase rollover: the first (i.e. new) passphrase +# will be used for encryption of new values (including a "kid" in the JWEs during the time 2 values are defined), +# both values will be used for verification (leveraging the "kid" if present); for seamless rollover one should +# (at minimum) wait for OIDCSessionInActivityTimeout seconds before removing the 2nd (i.e. old) passprase again. +#OIDCCryptoPassphrase [ | "exec:/path/to/otherProgram arg1" ] [ | "exec:/path/to/otherProgram arg2" ] # # All other entries below this are optional though some may be required in a diff --git a/configure.ac b/configure.ac index 8c6cb876..a6d384a3 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([mod_auth_openidc],[2.4.15rc0],[hans.zandbelt@openidc.com]) +AC_INIT([mod_auth_openidc],[2.4.15rc1],[hans.zandbelt@openidc.com]) AC_SUBST(NAMEVER, AC_PACKAGE_TARNAME()-AC_PACKAGE_VERSION()) diff --git a/src/cache/common.c b/src/cache/common.c index 5276b8b7..4d066cc0 100644 --- a/src/cache/common.c +++ b/src/cache/common.c @@ -244,16 +244,20 @@ apr_byte_t oidc_cache_mutex_destroy(server_rec *s, oidc_cache_mutex_t *m) { * AES GCM encrypt using the crypto passphrase as symmetric key */ static apr_byte_t oidc_cache_crypto_encrypt(request_rec *r, - const char *plaintext, const char *key, char **result) { - return oidc_util_jwt_create(r, key, plaintext, result); + const char *plaintext, const oidc_crypto_passphrase_t *passphrase, + char **result) { + return oidc_util_jwt_create(r, passphrase, plaintext, result); } /* * AES GCM decrypt using the crypto passphrase as symmetric key */ static apr_byte_t oidc_cache_crypto_decrypt(request_rec *r, - const char *cache_value, const char *key, char **plaintext) { - return oidc_util_jwt_verify(r, key, cache_value, plaintext); + const char *cache_value, char *secret, char **plaintext) { + oidc_crypto_passphrase_t passphrase; + passphrase.secret1 = secret; + passphrase.secret2 = NULL; + return oidc_util_jwt_verify(r, &passphrase, cache_value, plaintext); } /* @@ -283,24 +287,43 @@ apr_byte_t oidc_cache_get(request_rec *r, const char *section, const char *key, int encrypted = oidc_cfg_cache_encrypt(r); apr_byte_t rc = TRUE; char *msg = NULL; - char *cache_value = NULL; + const char *s_key = NULL; + char *cache_value = NULL, *s_secret = NULL; - oidc_debug(r, "enter: %s (section=%s, decrypt=%d, type=%s)", key, section, - encrypted, cfg->cache->name); + oidc_debug(r, "enter: %s (section=%s, decrypt=%d, type=%s)", section, + section, encrypted, cfg->cache->name); + s_key = key; /* see if encryption is turned on */ - if (encrypted == 1) - key = oidc_cache_get_hashed_key(r, cfg->crypto_passphrase, key); + if (encrypted == 1) { + if (cfg->crypto_passphrase.secret1 == NULL) { + oidc_error(r, + "could not decrypt cache entry because " OIDCCryptoPassphrase " is not set"); + goto out; + } + s_secret = cfg->crypto_passphrase.secret1; + s_key = oidc_cache_get_hashed_key(r, s_secret, key); + } /* get the value from the cache */ - if (cfg->cache->get(r, section, key, &cache_value) == FALSE) { + if (cfg->cache->get(r, section, s_key, &cache_value) == FALSE) { rc = FALSE; goto out; } /* see if it is any good */ - if (cache_value == NULL) - goto out; + if (cache_value == NULL) { + if ((encrypted != 1) || (cfg->crypto_passphrase.secret2 == NULL)) { + rc = FALSE; + goto out; + } + s_secret = cfg->crypto_passphrase.secret2; + s_key = oidc_cache_get_hashed_key(r, s_secret, key); + if (cfg->cache->get(r, section, s_key, &cache_value) == FALSE) { + rc = FALSE; + goto out; + } + } /* see if encryption is turned on */ if (encrypted == 0) { @@ -308,14 +331,7 @@ apr_byte_t oidc_cache_get(request_rec *r, const char *section, const char *key, goto out; } - if (cfg->crypto_passphrase == NULL) { - oidc_error(r, - "could not decrypt cache entry because " OIDCCryptoPassphrase " is not set"); - goto out; - } - - rc = oidc_cache_crypto_decrypt(r, cache_value, cfg->crypto_passphrase, - value); + rc = oidc_cache_crypto_decrypt(r, cache_value, s_secret, value); out: /* log the result */ @@ -354,17 +370,18 @@ apr_byte_t oidc_cache_set(request_rec *r, const char *section, const char *key, /* see if we need to encrypt */ if (encrypted == 1) { - key = oidc_cache_get_hashed_key(r, cfg->crypto_passphrase, key); + if (cfg->crypto_passphrase.secret1 == NULL) { + oidc_error(r, + "could not encrypt cache entry because " OIDCCryptoPassphrase " is not set"); + goto out; + } + + key = oidc_cache_get_hashed_key(r, cfg->crypto_passphrase.secret1, key); if (key == NULL) goto out; if (value != NULL) { - if (cfg->crypto_passphrase == NULL) { - oidc_error(r, - "could not encrypt cache entry because " OIDCCryptoPassphrase " is not set"); - goto out; - } - if (oidc_cache_crypto_encrypt(r, value, cfg->crypto_passphrase, + if (oidc_cache_crypto_encrypt(r, value, &cfg->crypto_passphrase, &encoded) == FALSE) goto out; value = encoded; diff --git a/src/config.c b/src/config.c index adc0a8d7..dbff176e 100644 --- a/src/config.c +++ b/src/config.c @@ -598,14 +598,11 @@ static const char* oidc_set_outgoing_proxy_slot(cmd_parms *cmd, void *ptr, /* * set a string value in the server config with exec support */ -static const char* oidc_set_passphrase_slot(cmd_parms *cmd, void *struct_ptr, - const char *arg) { - oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config, - &auth_openidc_module); - const char *passphrase = NULL; - int arglen = _oidc_strlen(arg); +static const char* oidc_parse_passphrase(cmd_parms *cmd, const char *arg, + char **passphrase) { char **argv = NULL; char *result = NULL; + int arglen = _oidc_strlen(arg); /* Based on code from mod_session_crypto. */ if (arglen > 5 && _oidc_strncmp(arg, "exec:", 5) == 0) { if (apr_tokenize_to_argv(arg + 5, &argv, cmd->temp_pool) != APR_SUCCESS) { @@ -626,12 +623,35 @@ static const char* oidc_set_passphrase_slot(cmd_parms *cmd, void *struct_ptr, if (_oidc_strlen(result) == 0) return apr_pstrdup(cmd->pool, "the output of the crypto passphrase generation command is empty (perhaps you need to pass it to bash -c \"\"?)"); - passphrase = result; + *passphrase = apr_pstrdup(cmd->pool, result); } else { - passphrase = arg; + *passphrase = apr_pstrdup(cmd->pool, arg); } + return NULL; +} + +static const char* oidc_set_crypto_passphrase_slot(cmd_parms *cmd, + void *struct_ptr, const char *arg1, const char *arg2) { + oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config, + &auth_openidc_module); + const char *rv = NULL; + if (arg1) + rv = oidc_parse_passphrase(cmd, arg1, &cfg->crypto_passphrase.secret1); + if ((rv == NULL) && (arg2 != NULL)) + rv = oidc_parse_passphrase(cmd, arg2, &cfg->crypto_passphrase.secret2); + return NULL; +} - return ap_set_string_slot(cmd, cfg, passphrase); +static const char* oidc_set_passphrase_slot(cmd_parms *cmd, void *struct_ptr, + const char *arg) { + oidc_cfg *cfg = (oidc_cfg*) ap_get_module_config(cmd->server->module_config, + &auth_openidc_module); + const char *rv = NULL; + char *secret = NULL; + rv = oidc_parse_passphrase(cmd, arg, &secret); + if (rv == NULL) + rv = ap_set_string_slot(cmd, cfg, secret); + return rv; } /* @@ -1891,7 +1911,8 @@ void* oidc_create_server_config(apr_pool_t *pool, server_rec *svr) { c->outgoing_proxy.username_password = NULL; c->outgoing_proxy.auth_type = OIDC_CONFIG_POS_INT_UNSET; - c->crypto_passphrase = NULL; + c->crypto_passphrase.secret1 = NULL; + c->crypto_passphrase.secret2 = NULL; c->error_template = NULL; c->post_preserve_template = NULL; @@ -2234,9 +2255,12 @@ void* oidc_merge_server_config(apr_pool_t *pool, void *BASE, void *ADD) { add->outgoing_proxy.auth_type : base->outgoing_proxy.auth_type; - c->crypto_passphrase = - add->crypto_passphrase != NULL ? - add->crypto_passphrase : base->crypto_passphrase; + c->crypto_passphrase.secret1 = + add->crypto_passphrase.secret1 != NULL ? + add->crypto_passphrase.secret1 : base->crypto_passphrase.secret1; + c->crypto_passphrase.secret2 = + add->crypto_passphrase.secret2 != NULL ? + add->crypto_passphrase.secret1 : base->crypto_passphrase.secret2; c->error_template = add->error_template != NULL ? @@ -2693,7 +2717,7 @@ static int oidc_check_config_openid_openidc(server_rec *s, oidc_cfg *c) { return oidc_check_config_error(s, OIDCRedirectURI); redirect_uri_is_relative = (c->redirect_uri[0] == OIDC_CHAR_FORWARD_SLASH); - if (c->crypto_passphrase == NULL) + if (c->crypto_passphrase.secret1 == NULL) return oidc_check_config_error(s, OIDCCryptoPassphrase); if (c->metadata_dir == NULL) { @@ -2787,7 +2811,7 @@ static int oidc_check_config_oauth(server_rec *s, oidc_cfg *c) { } - if ((c->cache_encrypt == 1) && (c->crypto_passphrase == NULL)) + if ((c->cache_encrypt == 1) && (c->crypto_passphrase.secret1 == NULL)) return oidc_check_config_error(s, OIDCCryptoPassphrase); return OK; @@ -3506,8 +3530,8 @@ const command_rec oidc_config_cmds[] = { (void*)APR_OFFSETOF(oidc_cfg, outgoing_proxy), RSRC_CONF, "Specify an outgoing proxy for your network ([:]."), - AP_INIT_TAKE1(OIDCCryptoPassphrase, - oidc_set_passphrase_slot, + AP_INIT_TAKE12(OIDCCryptoPassphrase, + oidc_set_crypto_passphrase_slot, (void*)APR_OFFSETOF(oidc_cfg, crypto_passphrase), RSRC_CONF, "Passphrase used for AES crypto on cookies and state."), diff --git a/src/mod_auth_openidc.h b/src/mod_auth_openidc.h index 94791e7d..a2135db9 100644 --- a/src/mod_auth_openidc.h +++ b/src/mod_auth_openidc.h @@ -405,6 +405,11 @@ typedef struct oidc_http_timeout_t { apr_time_t retry_interval; } oidc_http_timeout_t; +typedef struct oidc_crypto_passphrase_t { + char *secret1; + char *secret2; +} oidc_crypto_passphrase_t; + typedef struct oidc_cfg { /* indicates whether this is a derived config, merged from a base one */ unsigned int merged; @@ -496,7 +501,7 @@ typedef struct oidc_cfg { oidc_outgoing_proxy_t outgoing_proxy; - char *crypto_passphrase; + oidc_crypto_passphrase_t crypto_passphrase; int provider_metadata_refresh_interval; @@ -728,7 +733,7 @@ void oidc_proto_state_set_timestamp_now(oidc_proto_state_t *proto_state); apr_byte_t oidc_proto_token_endpoint_auth(request_rec *r, oidc_cfg *cfg, const char *token_endpoint_auth, const char *client_id, const char *client_secret, const apr_array_header_t *client_keys, const char *audience, apr_table_t *params, const char *bearer_access_token, char **basic_auth_str, char **bearer_auth_str); -char *oidc_proto_peek_jwt_header(request_rec *r, const char *jwt, char **alg, char **enc); +char *oidc_proto_peek_jwt_header(request_rec *r, const char *jwt, char **alg, char **enc, char **kid); int oidc_proto_authorization_request(request_rec *r, struct oidc_provider_t *provider, const char *login_hint, const char *redirect_uri, const char *state, oidc_proto_state_t *proto_state, const char *id_token_hint, const char *code_challenge, const char *auth_request_params, const char *path_scope); apr_byte_t oidc_proto_is_post_authorization_response(request_rec *r, oidc_cfg *cfg); apr_byte_t oidc_proto_is_redirect_authorization_response(request_rec *r, oidc_cfg *cfg); @@ -892,8 +897,8 @@ apr_byte_t oidc_util_regexp_first_match(apr_pool_t *pool, const char *input, con apr_byte_t oidc_util_json_merge(request_rec *r, json_t *src, json_t *dst); int oidc_util_cookie_domain_valid(const char *hostname, char *cookie_domain); apr_byte_t oidc_util_hash_string_and_base64url_encode(request_rec *r, const char *openssl_hash_algo, const char *input, char **output); -apr_byte_t oidc_util_jwt_create(request_rec *r, const char *secret, const char *s_payload, char **compact_encoded_jwt); -apr_byte_t oidc_util_jwt_verify(request_rec *r, const char *secret, const char *compact_encoded_jwt, char **s_payload); +apr_byte_t oidc_util_jwt_create(request_rec *r, const oidc_crypto_passphrase_t *passphrase, const char *s_payload, char **compact_encoded_jwt); +apr_byte_t oidc_util_jwt_verify(request_rec *r, const oidc_crypto_passphrase_t *passphrase, const char *compact_encoded_jwt, char **s_payload); char *oidc_util_get_chunked_cookie(request_rec *r, const char *cookieName, int cookie_chunk_size); void oidc_util_set_chunked_cookie(request_rec *r, const char *cookieName, const char *cookieValue, apr_time_t expires, int chunkSize, const char *ext); apr_byte_t oidc_util_create_symmetric_key(request_rec *r, const char *client_secret, unsigned int r_key_len, const char *hash_algo, apr_byte_t set_kid, oidc_jwk_t **jwk); diff --git a/src/oauth.c b/src/oauth.c index c01df7f2..7684710d 100644 --- a/src/oauth.c +++ b/src/oauth.c @@ -573,7 +573,7 @@ static apr_byte_t oidc_oauth_validate_jwt_access_token(request_rec *r, oidc_cfg *c, const char *access_token, json_t **token, char **response) { oidc_debug(r, "enter: JWT access_token header=%s", - oidc_proto_peek_jwt_header(r, access_token, NULL, NULL)); + oidc_proto_peek_jwt_header(r, access_token, NULL, NULL, NULL)); oidc_jose_error_t err; oidc_jwk_t *jwk = NULL; diff --git a/src/proto.c b/src/proto.c index 492421a6..b51348f2 100644 --- a/src/proto.c +++ b/src/proto.c @@ -464,7 +464,7 @@ char* oidc_proto_create_request_object(request_rec *r, json_decref(request_object_config); oidc_debug(r, "serialized request object JWT header = \"%s\"", - oidc_proto_peek_jwt_header(r, serialized_request_object, NULL, NULL)); + oidc_proto_peek_jwt_header(r, serialized_request_object, NULL, NULL, NULL)); oidc_debug(r, "serialized request object = \"%s\"", serialized_request_object); @@ -967,7 +967,7 @@ void oidc_proto_state_destroy(oidc_proto_state_t *proto_state) { apr_byte_t oidc_proto_check_crypto_passphrase(request_rec *r, oidc_cfg *c, const char *action) { - if (c->crypto_passphrase == NULL) { + if (c->crypto_passphrase.secret1 == NULL) { oidc_error(r, "cannot %s state cookie because " OIDCCryptoPassphrase " is not set; please check your OIDC Provider configuration as well or avoid using AuthType openid-connect", action); @@ -982,7 +982,7 @@ oidc_proto_state_t* oidc_proto_state_from_cookie(request_rec *r, oidc_cfg *c, json_t *result = NULL; if (oidc_proto_check_crypto_passphrase(r, c, "parse") == FALSE) return NULL; - oidc_util_jwt_verify(r, c->crypto_passphrase, cookieValue, &s_payload); + oidc_util_jwt_verify(r, &c->crypto_passphrase, cookieValue, &s_payload); oidc_util_decode_json_object(r, s_payload, &result); return result; } @@ -992,7 +992,7 @@ char* oidc_proto_state_to_cookie(request_rec *r, oidc_cfg *c, char *cookieValue = NULL; if (oidc_proto_check_crypto_passphrase(r, c, "create") == FALSE) return NULL; - oidc_util_jwt_create(r, c->crypto_passphrase, + oidc_util_jwt_create(r, &c->crypto_passphrase, oidc_util_encode_json_object(r, proto_state, JSON_COMPACT), &cookieValue); return cookieValue; @@ -1637,7 +1637,7 @@ apr_byte_t oidc_proto_jwt_verify(request_rec *r, oidc_cfg *cfg, oidc_jwt_t *jwt, * return the compact-encoded JWT header contents */ char* oidc_proto_peek_jwt_header(request_rec *r, - const char *compact_encoded_jwt, char **alg, char **enc) { + const char *compact_encoded_jwt, char **alg, char **enc, char **kid) { char *input = NULL, *result = NULL; char *p = strstr(compact_encoded_jwt ? compact_encoded_jwt : "", "."); if (p == NULL) { @@ -1663,6 +1663,10 @@ char* oidc_proto_peek_jwt_header(request_rec *r, *enc = apr_pstrdup(r->pool, json_string_value( json_object_get(json, CJOSE_HDR_ENC))); + if (kid) + *kid = apr_pstrdup(r->pool, + json_string_value( + json_object_get(json, CJOSE_HDR_KID))); } json_decref(json); } @@ -1678,7 +1682,7 @@ apr_byte_t oidc_proto_parse_idtoken(request_rec *r, oidc_cfg *cfg, char *alg = NULL; oidc_debug(r, "enter: id_token header=%s", - oidc_proto_peek_jwt_header(r, id_token, &alg, NULL)); + oidc_proto_peek_jwt_header(r, id_token, &alg, NULL, NULL)); apr_hash_t *decryption_keys = NULL; char buf[APR_RFC822_DATE_LEN + 1]; @@ -2179,7 +2183,7 @@ static apr_byte_t oidc_user_info_response_validate(request_rec *r, || (provider->userinfo_encrypted_response_alg != NULL) || (provider->userinfo_encrypted_response_enc != NULL)) { oidc_debug(r, "JWT header=%s", - oidc_proto_peek_jwt_header(r, *response, &alg, NULL)); + oidc_proto_peek_jwt_header(r, *response, &alg, NULL, NULL)); } oidc_jose_error_t err; diff --git a/src/session.c b/src/session.c index d21c0b8e..0774f28a 100644 --- a/src/session.c +++ b/src/session.c @@ -64,13 +64,13 @@ static apr_byte_t oidc_session_encode(request_rec *r, oidc_cfg *c, if (encrypt == FALSE) { *s_value = oidc_util_encode_json_object(r, z->state, JSON_COMPACT); return (*s_value != NULL); - } else if (c->crypto_passphrase == NULL) { + } else if (c->crypto_passphrase.secret1 == NULL) { oidc_error(r, "cannot encrypt session state because " OIDCCryptoPassphrase " is not set"); return FALSE; } - if (oidc_util_jwt_create(r, c->crypto_passphrase, + if (oidc_util_jwt_create(r, &c->crypto_passphrase, oidc_util_encode_json_object(r, z->state, JSON_COMPACT), s_value) == FALSE) return FALSE; @@ -84,13 +84,13 @@ static apr_byte_t oidc_session_decode(request_rec *r, oidc_cfg *c, if (encrypt == FALSE) { return oidc_util_decode_json_object(r, s_json, &z->state); - } else if (c->crypto_passphrase == NULL) { + } else if (c->crypto_passphrase.secret1 == NULL) { oidc_error(r, "cannot decrypt session state because " OIDCCryptoPassphrase " is not set"); return FALSE; } - if (oidc_util_jwt_verify(r, c->crypto_passphrase, s_json, + if (oidc_util_jwt_verify(r, &c->crypto_passphrase, s_json, &s_payload) == FALSE) { oidc_error(r, "could not verify secure JWT: cache value possibly corrupted"); diff --git a/src/util.c b/src/util.c index e6b7ce52..2266d836 100644 --- a/src/util.c +++ b/src/util.c @@ -128,12 +128,15 @@ static const char* oidc_util_get__oidc_jwt_hdr_dir_a256gcm(request_rec *r, char *compact_encoded_jwt = NULL; char *p = NULL; static const char *_oidc_jwt_hdr_dir_a256gcm = NULL; + static oidc_crypto_passphrase_t passphrase; if (_oidc_jwt_hdr_dir_a256gcm != NULL) return _oidc_jwt_hdr_dir_a256gcm; if (input == NULL) { - oidc_util_jwt_create(r, "needs_non_empty_string", "some_string", + passphrase.secret1 = "needs_non_empty_string"; + passphrase.secret2 = NULL; + oidc_util_jwt_create(r, &passphrase, "some_string", &compact_encoded_jwt); } else { compact_encoded_jwt = input; @@ -176,8 +179,9 @@ static apr_byte_t oidc_util_jwt_internal_strip_header(request_rec *r) { TRUE); } -apr_byte_t oidc_util_jwt_create(request_rec *r, const char *secret, - const char *s_payload, char **compact_encoded_jwt) { +apr_byte_t oidc_util_jwt_create(request_rec *r, + const oidc_crypto_passphrase_t *passphrase, const char *s_payload, + char **compact_encoded_jwt) { apr_byte_t rv = FALSE; oidc_jose_error_t err; @@ -187,12 +191,13 @@ apr_byte_t oidc_util_jwt_create(request_rec *r, const char *secret, oidc_jwk_t *jwk = NULL; oidc_jwt_t *jwe = NULL; - if (secret == NULL) { + if (passphrase->secret1 == NULL) { oidc_error(r, "secret is not set"); goto end; } - if (oidc_util_create_symmetric_key(r, secret, 0, OIDC_JOSE_ALG_SHA256, + if (oidc_util_create_symmetric_key(r, passphrase->secret1, 0, + OIDC_JOSE_ALG_SHA256, FALSE, &jwk) == FALSE) goto end; @@ -216,6 +221,8 @@ apr_byte_t oidc_util_jwt_create(request_rec *r, const char *secret, jwe->header.alg = apr_pstrdup(r->pool, CJOSE_HDR_ALG_DIR); jwe->header.enc = apr_pstrdup(r->pool, CJOSE_HDR_ENC_A256GCM); + if (passphrase->secret2 != NULL) + jwe->header.kid = apr_pstrdup(r->pool, "1"); if (oidc_jwt_encrypt(r->pool, jwe, jwk, cser, cser_len, compact_encoded_jwt, &err) == FALSE) { @@ -241,42 +248,50 @@ apr_byte_t oidc_util_jwt_create(request_rec *r, const char *secret, return rv; } -apr_byte_t oidc_util_jwt_verify(request_rec *r, const char *secret, +apr_byte_t oidc_util_jwt_verify(request_rec *r, + const oidc_crypto_passphrase_t *passphrase, const char *compact_encoded_jwt, char **s_payload) { apr_byte_t rv = FALSE; oidc_jose_error_t err; - oidc_jwk_t *jwk = NULL; oidc_jwt_t *jwt = NULL; - - if (oidc_util_jwt_internal_strip_header(r)) - compact_encoded_jwt = apr_pstrcat(r->pool, - oidc_util_get__oidc_jwt_hdr_dir_a256gcm(r, NULL), - compact_encoded_jwt, NULL); - - if (oidc_util_create_symmetric_key(r, secret, 0, OIDC_JOSE_ALG_SHA256, - FALSE, &jwk) == FALSE) - goto end; - - apr_hash_t *keys = apr_hash_make(r->pool); - apr_hash_set(keys, "", APR_HASH_KEY_STRING, jwk); - char *payload = NULL; int payload_len = 0; - char *plaintext = NULL; int plaintext_len = 0; - + apr_hash_t *keys = NULL; char *alg = NULL; char *enc = NULL; - oidc_proto_peek_jwt_header(r, compact_encoded_jwt, &alg, &enc); + char *kid = NULL; + + if (oidc_util_jwt_internal_strip_header(r)) + compact_encoded_jwt = apr_pstrcat(r->pool, + oidc_util_get__oidc_jwt_hdr_dir_a256gcm(r, NULL), + compact_encoded_jwt, NULL); + + oidc_proto_peek_jwt_header(r, compact_encoded_jwt, &alg, &enc, &kid); if ((_oidc_strcmp(alg, CJOSE_HDR_ALG_DIR) != 0) || (_oidc_strcmp(enc, CJOSE_HDR_ENC_A256GCM) != 0)) { oidc_error(r, "corrupted JWE header, alg=\"%s\" enc=\"%s\"", alg, enc); goto end; } + keys = apr_hash_make(r->pool); + + if ((passphrase->secret2 != NULL) && (kid == NULL)) { + if (oidc_util_create_symmetric_key(r, passphrase->secret2, 0, + OIDC_JOSE_ALG_SHA256, + FALSE, &jwk) == FALSE) + goto end; + } else { + if (oidc_util_create_symmetric_key(r, passphrase->secret1, 0, + OIDC_JOSE_ALG_SHA256, + FALSE, &jwk) == FALSE) + goto end; + } + apr_hash_set(keys, "1", APR_HASH_KEY_STRING, jwk); + if (oidc_jwe_decrypt(r->pool, compact_encoded_jwt, keys, &plaintext, &plaintext_len, &err, FALSE) == FALSE) { oidc_error(r, "decrypting JWE failed: %s", oidc_jose_e2s(r->pool, err)); diff --git a/test/test.c b/test/test.c index 68de2984..fc2799ac 100755 --- a/test/test.c +++ b/test/test.c @@ -1961,7 +1961,7 @@ static request_rec * test_setup(apr_pool_t *pool) { cfg); ap_set_module_config(request->per_dir_config, &auth_openidc_module, d_cfg); - cfg->crypto_passphrase = "12345678901234567890123456789012"; + cfg->crypto_passphrase.secret1 = "12345678901234567890123456789012"; cfg->cache = &oidc_cache_shm; cfg->cache_cfg = NULL; cfg->cache_shm_size_max = 500;