Skip to content

Commit

Permalink
jwks: Implement jwks_error_any(), jwks_item_free_bad(), and jwks_item…
Browse files Browse the repository at this point in the history
…_count()

Closes #209

Signed-off-by: Ben Collins <[email protected]>
  • Loading branch information
benmcollins committed Feb 12, 2025
1 parent b494699 commit 0d15d75
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 17 deletions.
33 changes: 27 additions & 6 deletions include/jwt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1296,10 +1296,10 @@ int jwks_error(const jwk_set_t *jwk_set);
* the jwk_item_t in the set.
*
* @param jwk_set An existing jwk_set_t
* @return 0 if no error exists, 1 if any exists.
* @return 0 if no error exists, or the number of errors in the set
*/
JWT_EXPORT
int jwks_error_any(jwk_set_t *jwk_set);
int jwks_error_any(const jwk_set_t *jwk_set);

/**
* @brief Retrieve an error message from a jwk_set
Expand Down Expand Up @@ -1504,25 +1504,46 @@ JWT_EXPORT
int jwks_item_key_bits(const jwk_item_t *item);

/**
* Free all memory associated with the nth jwk_item_t in a jwk_set
* @brief Free remove and free the nth jwk_item_t in a jwk_set
*
* @param jwk_set A JWKS object
* @param jwk_set Pointer to a JWKS object
* @param index the position of the item in the index
* @return 0 if no item was was deleted (found), 1 if it was
*/
JWT_EXPORT
int jwks_item_free(jwk_set_t *jwk_set, size_t index);

/**
* Free all memory associated with all @ref jwk_item_t in a @ref jwk_set_t.
* @brief Remove and free all jwk_item_t in a jwk_set_t
*
* The jwk_set_t becomes an empty set.
*
* @param jwk_set A JWKS object
* @param jwk_set Pointer to a JWKS object
* @return The number of items deleted
*/
JWT_EXPORT
int jwks_item_free_all(jwk_set_t *jwk_set);

/**
* @brief Free all keys marked with an error in a jwk_set_t
*
* The jwk_set_t becomes an empty set.
*
* @param jwk_set Pointer to a JWKS object
* @return The number of items with an error that were deleted
*/
JWT_EXPORT
int jwks_item_free_bad(jwk_set_t *jwk_set);

/**
* @brief Return the number of keys in a jwk_set_t
*
* @param jwk_set Pointer to a JWKS object
* @return The number of items in the set
*/
JWT_EXPORT
size_t jwks_item_count(const jwk_set_t *jwk_set);

/**
* @}
* @noop jwks_item_grp
Expand Down
66 changes: 55 additions & 11 deletions libjwt/jwks.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,19 @@ const jwk_item_t *jwks_item_get(const jwk_set_t *jwk_set, size_t index)
return NULL;
}

int jwks_error_any(const jwk_set_t *jwk_set)
{
jwk_item_t *item = NULL;
int count = jwk_set->error;

list_for_each_entry(item, &jwk_set->head, node) {
if (item->error)
count++;
}

return count;
}

int jwks_item_is_private(const jwk_item_t *item)
{
return item->is_private_key ? 1 : 0;
Expand Down Expand Up @@ -297,6 +310,22 @@ static int jwks_item_add(jwk_set_t *jwk_set, jwk_item_t *item)
return 0;
}

static void __item_free(jwk_item_t *todel)
{
if (todel->provider == JWT_CRYPTO_OPS_ANY)
jwt_freemem(todel->oct.key);
else
jwt_ops->process_item_free(todel);

/* A few non-crypto specific things. */
jwt_freemem(todel->kid);
json_decrefp(&todel->json);
list_del(&todel->node);

/* Free the container and the item itself. */
jwt_freemem(todel);
}

int jwks_item_free(jwk_set_t *jwk_set, const size_t index)
{
jwk_item_t *item = NULL, *todel = NULL;
Expand All @@ -316,20 +345,35 @@ int jwks_item_free(jwk_set_t *jwk_set, const size_t index)
if (todel == NULL)
return 0;

if (todel->provider == JWT_CRYPTO_OPS_ANY)
jwt_freemem(todel->oct.key);
else
jwt_ops->process_item_free(todel);
__item_free(todel);

/* A few non-crypto specific things. */
jwt_freemem(todel->kid);
json_decrefp(&todel->json);
list_del(&todel->node);
return 1;
}

/* Free the container and the item itself. */
jwt_freemem(todel);
size_t jwks_item_count(const jwk_set_t *jwk_set)
{
size_t count = 0;
jwk_item_t *item = NULL;

return 1;
list_for_each_entry(item, &jwk_set->head, node)
count++;

return count;
}

int jwks_item_free_bad(jwk_set_t *jwk_set)
{
jwk_item_t *item, *pos;
int count = 0;

list_for_each_entry_safe(item, pos, &jwk_set->head, node) {
if (!item->error)
continue;
__item_free(item);
count++;
}

return count;
}

int jwks_item_free_all(jwk_set_t *jwk_set)
Expand Down
20 changes: 20 additions & 0 deletions tests/jwt_jwks.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,21 @@ START_TEST(test_jwks_keyring_load)
}
ck_assert_int_eq(fails, 0);

ck_assert_int_eq(i, 27);
i = jwks_item_count(g_jwk_set);
ck_assert_int_eq(i, 27);

ck_assert(jwks_item_free(g_jwk_set, 3));

i = jwks_item_count(g_jwk_set);
ck_assert_int_eq(i, 26);

i = jwks_item_free_bad(g_jwk_set);
ck_assert_int_eq(i, 0);

i = jwks_item_count(g_jwk_set);
ck_assert_int_eq(i, 26);

free_key();
}
END_TEST
Expand All @@ -72,6 +83,9 @@ START_TEST(test_jwks_keyring_all_bad)
jwk_set = jwks_create_fromfile(KEYDIR "/bad_keys.json");
ck_assert_ptr_nonnull(jwk_set);

i = jwks_error_any(jwk_set);
ck_assert_int_eq(i, 14);

for (i = 0; (item = jwks_item_get(jwk_set, i)); i++) {
if (!jwks_item_error(item)) {
fprintf(stderr, "KID: %s\n",
Expand All @@ -81,6 +95,12 @@ START_TEST(test_jwks_keyring_all_bad)
}

ck_assert_int_eq(i, 14);

i = jwks_item_free_bad(jwk_set);
ck_assert_int_eq(i, 14);

i = jwks_item_count(jwk_set);
ck_assert_int_eq(i, 0);
}
END_TEST

Expand Down

0 comments on commit 0d15d75

Please sign in to comment.