diff --git a/src/jose.c b/src/jose.c index 91ccb51c..8a961895 100644 --- a/src/jose.c +++ b/src/jose.c @@ -181,30 +181,42 @@ const char *oidc_jwt_hdr_get(oidc_jwt_t *jwt, const char *key) { /* * perform compact serialization on a JWT and return the resulting string */ -char *oidc_jwt_serialize(apr_pool_t *pool, oidc_jwt_t *jwt, oidc_jose_error_t *err) { +char *oidc_jose_jwt_serialize(apr_pool_t *pool, oidc_jwt_t *jwt, oidc_jose_error_t *err) { cjose_err cjose_err; - const char *cser = NULL; - if (_oidc_strcmp(jwt->header.alg, CJOSE_HDR_ALG_NONE) != 0) { - if (cjose_jws_export(jwt->cjose_jws, &cser, &cjose_err) == FALSE) { - oidc_jose_error(err, "cjose_jws_export failed: %s", oidc_cjose_e2s(pool, cjose_err)); + char *result = NULL, *s_payload = NULL, *out = NULL; + size_t out_len; + + if (_oidc_strcmp(jwt->header.alg, CJOSE_HDR_ALG_NONE) == 0) { + + s_payload = oidc_util_encode_json(pool, jwt->payload.value.json, JSON_PRESERVE_ORDER | JSON_COMPACT); + if (s_payload == NULL) { + oidc_jose_error(err, "oidc_util_encode_json failed"); return NULL; } - } else { - - char *s_payload = - oidc_util_encode_json(pool, jwt->payload.value.json, JSON_PRESERVE_ORDER | JSON_COMPACT); - char *out = NULL; - size_t out_len; + // out is allocated by cjose and must be freed explicitly by cjose_get_dealloc()() if (cjose_base64url_encode((const uint8_t *)s_payload, _oidc_strlen(s_payload), &out, &out_len, - &cjose_err) == FALSE) + &cjose_err) == FALSE) { + oidc_jose_error(err, "cjose_base64url_encode failed: %s", oidc_cjose_e2s(pool, cjose_err)); return NULL; - cser = apr_pstrmemdup(pool, out, out_len); + } + + result = apr_pstrmemdup(pool, out, out_len); cjose_get_dealloc()(out); + result = apr_psprintf(pool, "%s.%s.", OIDC_JOSE_HDR_ALG_NONE, result); - cser = apr_psprintf(pool, "%s.%s.", OIDC_JOSE_HDR_ALG_NONE, cser); + } else { + + // out: "the returned string pointer is owned by the JWS, the caller should not attempt to free it directly" + if (cjose_jws_export(jwt->cjose_jws, (const char **)&out, &cjose_err) == FALSE) { + oidc_jose_error(err, "cjose_jws_export failed: %s", oidc_cjose_e2s(pool, cjose_err)); + return NULL; + } + + result = apr_pstrdup(pool, out); } - return apr_pstrdup(pool, cser); + + return result; } /* @@ -530,7 +542,6 @@ apr_byte_t oidc_jwk_to_json(apr_pool_t *pool, const oidc_jwk_t *jwk, char **s_js json_t *json = NULL, *temp = NULL; json_error_t json_error; int i = 0; - void *iter = NULL; // input sanity checks if ((jwk == NULL) || (s_json == NULL)) diff --git a/src/jose.h b/src/jose.h index 4802c29a..1e3adaf8 100644 --- a/src/jose.h +++ b/src/jose.h @@ -257,7 +257,7 @@ apr_byte_t oidc_jwt_sign(apr_pool_t *pool, oidc_jwt_t *jwt, oidc_jwk_t *jwk, apr /* verify a JWT a key in a list of JWKs */ apr_byte_t oidc_jwt_verify(apr_pool_t *pool, oidc_jwt_t *jwt, apr_hash_t *keys, oidc_jose_error_t *err); /* perform compact serialization on a JWT and return the resulting string */ -char *oidc_jwt_serialize(apr_pool_t *pool, oidc_jwt_t *jwt, oidc_jose_error_t *err); +char *oidc_jose_jwt_serialize(apr_pool_t *pool, oidc_jwt_t *jwt, oidc_jose_error_t *err); /* encrypt JWT */ apr_byte_t oidc_jwt_encrypt(apr_pool_t *pool, oidc_jwt_t *jwe, oidc_jwk_t *jwk, const char *payload, int payload_len, char **serialized, oidc_jose_error_t *err); diff --git a/src/proto/jwt.c b/src/proto/jwt.c index a055e8fc..fde9f1e0 100644 --- a/src/proto/jwt.c +++ b/src/proto/jwt.c @@ -290,9 +290,9 @@ apr_byte_t oidc_proto_jwt_sign_and_serialize(request_rec *r, oidc_jwk_t *jwk, oi goto end; } - *cser = oidc_jwt_serialize(r->pool, jwt, &err); + *cser = oidc_jose_jwt_serialize(r->pool, jwt, &err); if (*cser == NULL) { - oidc_error(r, "oidc_jwt_serialize failed: %s", oidc_jose_e2s(r->pool, err)); + oidc_error(r, "oidc_jose_jwt_serialize failed: %s", oidc_jose_e2s(r->pool, err)); goto end; } diff --git a/src/proto/request.c b/src/proto/request.c index c14400e8..aec3ac58 100644 --- a/src/proto/request.c +++ b/src/proto/request.c @@ -439,7 +439,7 @@ static char *oidc_request_uri_request_object(request_rec *r, struct oidc_provide oidc_util_json_object_get_string(r->pool, crypto, "crypt_alg", &jwe->header.alg, NULL); oidc_util_json_object_get_string(r->pool, crypto, "crypt_enc", &jwe->header.enc, NULL); - char *cser = oidc_jwt_serialize(r->pool, request_object, &err); + char *cser = oidc_jose_jwt_serialize(r->pool, request_object, &err); /* see if we need to encrypt the request object */ if (jwe->header.alg != NULL) { diff --git a/test/test.c b/test/test.c index bd0da2df..b6d0295c 100644 --- a/test/test.c +++ b/test/test.c @@ -544,8 +544,8 @@ static char *test_jwt_sign_verify(apr_pool_t *pool) { jwt->header.alg = apr_pstrdup(pool, CJOSE_HDR_ALG_RS256); TST_ASSERT_ERR("oidc_jwt_sign (rsa)", oidc_jwt_sign(pool, jwt, jwk, FALSE, &err), pool, err); - cser = oidc_jwt_serialize(pool, jwt, &err); - TST_ASSERT_ERR("oidc_jwt_serialize (rsa)", cser != NULL, pool, err); + cser = oidc_jose_jwt_serialize(pool, jwt, &err); + TST_ASSERT_ERR("oidc_jose_jwt_serialize (rsa)", cser != NULL, pool, err); oidc_jwt_t *rsa_jwt = NULL; TST_ASSERT_ERR("oidc_jwt_parse (rsa)", oidc_jwt_parse(pool, cser, &rsa_jwt, NULL, FALSE, &err), pool, err); @@ -563,8 +563,8 @@ static char *test_jwt_sign_verify(apr_pool_t *pool) { jwt->header.alg = apr_pstrdup(pool, "HS256"); TST_ASSERT_ERR("oidc_jwt_sign (hmac)", oidc_jwt_sign(pool, jwt, jwk, FALSE, &err), pool, err); - cser = oidc_jwt_serialize(pool, jwt, &err); - TST_ASSERT_ERR("oidc_jwt_serialize (hmac)", cser != NULL, pool, err); + cser = oidc_jose_jwt_serialize(pool, jwt, &err); + TST_ASSERT_ERR("oidc_jose_jwt_serialize (hmac)", cser != NULL, pool, err); oidc_jwt_t *hmac_jwt = NULL; TST_ASSERT_ERR("oidc_jwt_parse (rsa)", oidc_jwt_parse(pool, cser, &hmac_jwt, NULL, FALSE, &err), pool, err);