From ca046f24b83ee12b4d5d3ac1b51565a69c0c9248 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 8 Jan 2025 14:13:51 -0500 Subject: [PATCH] Isolate get_js_*() functions in jwt-validate - All remnants of errno removed except in jwt-validate.c - All uses of broken get_js_* functions isolated as well Wide spread use of jwt_write_error() Signed-off-by: Ben Collins --- libjwt/jwks.c | 1 - libjwt/jwt-encode.c | 74 +++++++++++++++++++++++++++---------------- libjwt/jwt-memory.c | 1 - libjwt/jwt-private.h | 8 ----- libjwt/jwt-validate.c | 59 ++++++++++++++++++++++++++++++++++ libjwt/jwt-verify.c | 35 ++++++++++++-------- libjwt/jwt.c | 62 +----------------------------------- 7 files changed, 129 insertions(+), 111 deletions(-) diff --git a/libjwt/jwks.c b/libjwt/jwks.c index d9529286..2c2f13fc 100644 --- a/libjwt/jwks.c +++ b/libjwt/jwks.c @@ -8,7 +8,6 @@ #include #include -#include #include #include "jwt-private.h" diff --git a/libjwt/jwt-encode.c b/libjwt/jwt-encode.c index 802e7bed..3ba553e0 100644 --- a/libjwt/jwt-encode.c +++ b/libjwt/jwt-encode.c @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -20,7 +19,7 @@ #define APPEND_STR(__buf, __str) do { \ if (__append_str(__buf, __str)) \ - return ENOMEM; \ + return 1; \ } while (0) static int write_js(const json_t *js, char **buf, int pretty) @@ -58,15 +57,20 @@ static int jwt_write_head(jwt_t *jwt, char **buf, int pretty) * RFC 8225. */ jwt_set_ADD_STR(&jval, "typ", "JWT"); if (jwt_header_add(jwt, &jval)) { - if (jval.error != JWT_VALUE_ERR_EXIST) - return jval.error; + if (jval.error != JWT_VALUE_ERR_EXIST) { + jwt_write_error(jwt, + "Error setting \"typ\" in header"); + return 1; + } } } jwt_set_ADD_STR(&jval, "alg", jwt_alg_str(jwt->alg)); jval.replace = 1; - if (jwt_header_add(jwt, &jval)) - return jval.error; + if (jwt_header_add(jwt, &jval)) { + jwt_write_error(jwt, "Error setting \"typ\" in header"); + return 1; + } return write_js(jwt->headers, buf, pretty); } @@ -83,36 +87,46 @@ static int jwt_encode(jwt_t *jwt, char **out) int ret, head_len, body_len; unsigned int sig_len; - if (out == NULL) - return EINVAL; + if (out == NULL) { + jwt_write_error(jwt, "No string passed to write out to"); + return 1; + } *out = NULL; /* First the header. */ ret = jwt_write_head(jwt, &buf, 0); if (ret) - return ret; + return 1; /* Encode it */ head_len = jwt_base64uri_encode(&head, buf, (int)strlen(buf)); jwt_freemem(buf); - if (head_len <= 0) - return -head_len; + if (head_len <= 0) { + jwt_write_error(jwt, "Error encoding header"); + return 1; + } /* Now the body. */ ret = jwt_write_body(jwt, &buf, 0); - if (ret) - return ret; + if (ret) { + jwt_write_error(jwt, "Error writing body"); + return 1; + } body_len = jwt_base64uri_encode(&body, buf, (int)strlen(buf)); jwt_freemem(buf); - if (body_len <= 0) - return -body_len; + if (body_len <= 0) { + jwt_write_error(jwt, "Error encoding body"); + return 1; + } /* The part we need to sign, but add space for 2 dots and a nil */ buf = jwt_malloc(head_len + body_len + 3); - if (buf == NULL) - return ENOMEM; + if (buf == NULL) { + jwt_write_error(jwt, "Error allocating memory"); + return 1; + } strcpy(buf, head); strcat(buf, "."); @@ -130,14 +144,18 @@ static int jwt_encode(jwt_t *jwt, char **out) /* Now the signature. */ ret = jwt_sign(jwt, &sig, &sig_len, buf, strlen(buf)); jwt_freemem(buf); - if (ret) + if (ret) { + jwt_write_error(jwt, "Error allocating memory"); return ret; + } ret = jwt_base64uri_encode(&buf, sig, sig_len); /* At this point buf has b64 of sig and ret is size of it */ - if (ret < 0) - return ENOMEM; + if (ret < 0) { + jwt_write_error(jwt, "Error allocating memory"); + return 1; + } /* plus 2 dots and a nil */ ret = strlen(head) + strlen(body) + strlen(buf) + 3; @@ -145,7 +163,8 @@ static int jwt_encode(jwt_t *jwt, char **out) /* We're good, so let's get it all together */ *out = jwt_malloc(ret); if (*out == NULL) { - ret = ENOMEM; + jwt_write_error(jwt, "Error allocating memory"); + ret = 1; } else { sprintf(*out, "%s.%s.%s", head, body, buf); ret = 0; @@ -160,19 +179,20 @@ int jwt_encode_fp(jwt_t *jwt, FILE *fp) { char_auto *str = NULL; - errno = jwt_encode(jwt, &str); - if (!errno) - fputs(str, fp); + if (jwt_encode(jwt, &str)) + return 1; + + if (fputs(str, fp) == EOF) + return 1; - return errno; + return 0; } char *jwt_encode_str(jwt_t *jwt) { char *str = NULL; - errno = jwt_encode(jwt, &str); - if (errno) + if (jwt_encode(jwt, &str)) jwt_freemem(str); return str; diff --git a/libjwt/jwt-memory.c b/libjwt/jwt-memory.c index 2d046619..66badfd3 100644 --- a/libjwt/jwt-memory.c +++ b/libjwt/jwt-memory.c @@ -8,7 +8,6 @@ #include #include -#include #include #include diff --git a/libjwt/jwt-private.h b/libjwt/jwt-private.h index cfeca9f2..611663f2 100644 --- a/libjwt/jwt-private.h +++ b/libjwt/jwt-private.h @@ -173,14 +173,6 @@ int jwt_base64uri_encode(char **_dst, const char *plain, int plain_len); JWT_NO_EXPORT void *jwt_base64uri_decode(const char *src, int *ret_len); -/* JSON stuff */ -JWT_NO_EXPORT -const char *get_js_string(const json_t *js, const char *key); -JWT_NO_EXPORT -long get_js_int(const json_t *js, const char *key); -JWT_NO_EXPORT -int get_js_bool(const json_t *js, const char *key); - /* A time-safe strcmp function */ JWT_NO_EXPORT int jwt_strcmp(const char *str1, const char *str2); diff --git a/libjwt/jwt-validate.c b/libjwt/jwt-validate.c index fc16b541..6e98da18 100644 --- a/libjwt/jwt-validate.c +++ b/libjwt/jwt-validate.c @@ -14,6 +14,65 @@ #include "jwt-private.h" +static const char *get_js_string(const json_t *js, const char *key) +{ + const char *val = NULL; + json_t *js_val; + + js_val = json_object_get(js, key); + if (js_val) { + if (json_is_string(js_val)) + val = json_string_value(js_val); + else + errno = EINVAL; + } else { + errno = ENOENT; + } + + return val; +} + +static long get_js_int(const json_t *js, const char *key) +{ + long val = -1; + json_t *js_val; + + js_val = json_object_get(js, key); + if (js_val) { + if (json_is_integer(js_val)) + val = (long)json_integer_value(js_val); + else + errno = EINVAL; + } else { + errno = ENOENT; + } + + return val; +} + +static int get_js_bool(const json_t *js, const char *key) +{ + int val = -1; + json_t *js_val; + + js_val = json_object_get(js, key); + if (js_val) { + switch (json_typeof(js_val)) { + case JSON_TRUE: + val = 1; + break; + case JSON_FALSE: + val = 0; + break; + default: + errno = EINVAL; + } + } else { + errno = ENOENT; + } + return val; +} + int jwt_valid_new(jwt_valid_t **jwt_valid, jwt_alg_t alg) { if (!jwt_valid) diff --git a/libjwt/jwt-verify.c b/libjwt/jwt-verify.c index 8ac40983..7d3e4df6 100644 --- a/libjwt/jwt-verify.c +++ b/libjwt/jwt-verify.c @@ -40,27 +40,40 @@ static int jwt_parse_body(jwt_t *jwt, char *body) json_decrefp(&(jwt->grants)); jwt->grants = jwt_base64uri_decode_to_json(body); - if (!jwt->grants) + if (!jwt->grants) { + jwt_write_error(jwt, "Error parsing body"); return 1; + } return 0; } static int jwt_parse_head(jwt_t *jwt, char *head) { - const char *alg; + json_t *jalg; if (jwt->headers) json_decrefp(&(jwt->headers)); jwt->headers = jwt_base64uri_decode_to_json(head); - if (!jwt->headers) + if (!jwt->headers) { + jwt_write_error(jwt, "Error parsing header"); return 1; + } - alg = get_js_string(jwt->headers, "alg"); - jwt->alg = jwt_str_alg(alg); - if (jwt->alg >= JWT_ALG_INVAL) - return 1; + jwt->alg = JWT_ALG_NONE; + + jalg = json_object_get(jwt->headers, "alg"); + if (jalg && json_is_string(jalg)) { + const char *alg = json_string_value(jalg); + + jwt->alg = jwt_str_alg(alg); + + if (jwt->alg >= JWT_ALG_INVAL) { + jwt_write_error(jwt, "Invalid ALG: [%s]", alg); + return 1; + } + } return 0; } @@ -101,15 +114,11 @@ static int jwt_parse(jwt_t *jwt, const char *token, unsigned int *len) /* Now that we have everything split up, let's check out the * header. */ - if (jwt_parse_head(jwt, head)) { - jwt_write_error(jwt, "Error parsing header"); + if (jwt_parse_head(jwt, head)) return 1; - } - if (jwt_parse_body(jwt, body)) { - jwt_write_error(jwt, "Error parsing body"); + if (jwt_parse_body(jwt, body)) return 1; - } *len = sig - head; diff --git a/libjwt/jwt.c b/libjwt/jwt.c index 63e2e20d..fa613f60 100644 --- a/libjwt/jwt.c +++ b/libjwt/jwt.c @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -247,65 +246,6 @@ jwt_t *jwt_dup(jwt_t *jwt) return new; } -const char *get_js_string(const json_t *js, const char *key) -{ - const char *val = NULL; - json_t *js_val; - - js_val = json_object_get(js, key); - if (js_val) { - if (json_is_string(js_val)) - val = json_string_value(js_val); - else - errno = EINVAL; - } else { - errno = ENOENT; - } - - return val; -} - -long get_js_int(const json_t *js, const char *key) -{ - long val = -1; - json_t *js_val; - - js_val = json_object_get(js, key); - if (js_val) { - if (json_is_integer(js_val)) - val = (long)json_integer_value(js_val); - else - errno = EINVAL; - } else { - errno = ENOENT; - } - - return val; -} - -int get_js_bool(const json_t *js, const char *key) -{ - int val = -1; - json_t *js_val; - - js_val = json_object_get(js, key); - if (js_val) { - switch (json_typeof(js_val)) { - case JSON_TRUE: - val = 1; - break; - case JSON_FALSE: - val = 0; - break; - default: - errno = EINVAL; - } - } else { - errno = ENOENT; - } - return val; -} - void *jwt_base64uri_decode(const char *src, int *ret_len) { void *buf; @@ -369,7 +309,7 @@ int jwt_base64uri_encode(char **_dst, const char *plain, int plain_len) len = BASE64_ENCODE_OUT_SIZE(plain_len); dst = jwt_malloc(len + 1); if (dst == NULL) - return -ENOMEM; // LCOV_EXCL_LINE + return -1; // LCOV_EXCL_LINE /* First, a normal base64 encoding */ len = base64_encode((const unsigned char *)plain, plain_len, dst);