Skip to content

Commit

Permalink
Isolate get_js_*() functions in jwt-validate
Browse files Browse the repository at this point in the history
- 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 <[email protected]>
  • Loading branch information
benmcollins committed Jan 8, 2025
1 parent 2fc28fd commit ca046f2
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 111 deletions.
1 change: 0 additions & 1 deletion libjwt/jwks.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <jwt.h>
#include "jwt-private.h"
Expand Down
74 changes: 47 additions & 27 deletions libjwt/jwt-encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

#include <jwt.h>
Expand All @@ -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)
Expand Down Expand Up @@ -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);
}
Expand All @@ -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, ".");
Expand All @@ -130,22 +144,27 @@ 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;

/* 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;
Expand All @@ -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;
Expand Down
1 change: 0 additions & 1 deletion libjwt/jwt-memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

#include <jwt.h>
Expand Down
8 changes: 0 additions & 8 deletions libjwt/jwt-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
59 changes: 59 additions & 0 deletions libjwt/jwt-validate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
35 changes: 22 additions & 13 deletions libjwt/jwt-verify.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;

Expand Down
Loading

0 comments on commit ca046f2

Please sign in to comment.