return json_tree_get_value_str(value_node);
}
-static int get_time_field(const struct json_tree *tree, const char *key,
- long *value_r)
+static int
+get_time_field(const struct json_tree *tree, const char *key, long *value_r)
{
const char *value = get_field(tree, key);
int tz_offset ATTR_UNUSED;
return 1;
}
-static int oauth2_lookup_hmac_key(const struct oauth2_settings *set,
- const char *azp, const char *alg, const char *key_id,
- const buffer_t **hmac_key_r,
- const char **error_r)
+static int
+oauth2_lookup_hmac_key(const struct oauth2_settings *set, const char *azp,
+ const char *alg, const char *key_id,
+ const buffer_t **hmac_key_r, const char **error_r)
{
const char *base64_key;
- const char *cache_key_id = t_strconcat(azp, ".", alg, ".", key_id, NULL);
- if (oauth2_validation_key_cache_lookup_hmac_key(set->key_cache, cache_key_id,
- hmac_key_r) == 0)
- return 0;
+ const char *cache_key_id, *lookup_key;
int ret;
- const char *lookup_key = t_strconcat(DICT_PATH_SHARED, azp, "/", alg, "/", key_id, NULL);
+
+ cache_key_id = t_strconcat(azp, ".", alg, ".", key_id, NULL);
+ if (oauth2_validation_key_cache_lookup_hmac_key(
+ set->key_cache, cache_key_id, hmac_key_r) == 0)
+ return 0;
+
+
/* do a synchronous dict lookup */
+ lookup_key = t_strconcat(DICT_PATH_SHARED, azp, "/", alg, "/", key_id,
+ NULL);
if ((ret = dict_lookup(set->key_dict, pool_datastack_create(),
lookup_key, &base64_key, error_r)) < 0) {
return -1;
} else if (ret == 0) {
- *error_r = t_strdup_printf("%s key '%s' not found", alg, key_id);
+ *error_r = t_strdup_printf("%s key '%s' not found",
+ alg, key_id);
return -1;
}
*error_r = "Invalid base64 encoded key";
return -1;
}
- oauth2_validation_key_cache_insert_hmac_key(set->key_cache, cache_key_id, key);
+ oauth2_validation_key_cache_insert_hmac_key(set->key_cache,
+ cache_key_id, key);
*hmac_key_r = key;
return 0;
}
-static int oauth2_validate_hmac(const struct oauth2_settings *set,
- const char *azp, const char *alg, const char *key_id,
- const char *const *blobs, const char **error_r)
+static int
+oauth2_validate_hmac(const struct oauth2_settings *set, const char *azp,
+ const char *alg, const char *key_id,
+ const char *const *blobs, const char **error_r)
{
const struct hash_method *method;
+
if (strcmp(alg, "HS256") == 0)
method = hash_method_lookup("sha256");
else if (strcmp(alg, "HS384") == 0)
const buffer_t *key;
if (oauth2_lookup_hmac_key(set, azp, alg, key_id, &key, error_r) < 0)
return -1;
+
struct hmac_context ctx;
hmac_init(&ctx, key->data, key->used, method);
hmac_update(&ctx, blobs[0], strlen(blobs[0]));
buffer_t *their_digest =
t_base64url_decode_str(BASE64_DECODE_FLAG_NO_PADDING, blobs[2]);
if (method->digest_size != their_digest->used ||
- !mem_equals_timing_safe(digest, their_digest->data, method->digest_size)) {
+ !mem_equals_timing_safe(digest, their_digest->data,
+ method->digest_size)) {
*error_r = "Incorrect JWT signature";
return -1;
}
return 0;
}
-static int oauth2_lookup_pubkey(const struct oauth2_settings *set,
- const char *azp, const char *alg, const char *key_id,
- struct dcrypt_public_key **key_r,
- const char **error_r)
+static int
+oauth2_lookup_pubkey(const struct oauth2_settings *set, const char *azp,
+ const char *alg, const char *key_id,
+ struct dcrypt_public_key **key_r, const char **error_r)
{
const char *key_str;
- const char *cache_key_id = t_strconcat(azp, ".", alg, ".", key_id, NULL);
- if (oauth2_validation_key_cache_lookup_pubkey(set->key_cache, cache_key_id, key_r) == 0)
- return 0;
+ const char *cache_key_id, *lookup_key;
int ret;
- const char *lookup_key = t_strconcat(DICT_PATH_SHARED, azp, "/", alg, "/", key_id, NULL);
+
+ cache_key_id = t_strconcat(azp, ".", alg, ".", key_id, NULL);
+ if (oauth2_validation_key_cache_lookup_pubkey(
+ set->key_cache, cache_key_id, key_r) == 0)
+ return 0;
+
/* do a synchronous dict lookup */
+ lookup_key = t_strconcat(DICT_PATH_SHARED, azp, "/", alg, "/", key_id,
+ NULL);
if ((ret = dict_lookup(set->key_dict, pool_datastack_create(),
lookup_key, &key_str, error_r)) < 0) {
return -1;
} else if (ret == 0) {
- *error_r = t_strdup_printf("%s key '%s' not found", alg, key_id);
+ *error_r = t_strdup_printf("%s key '%s' not found",
+ alg, key_id);
return -1;
}
}
/* cache key */
- oauth2_validation_key_cache_insert_pubkey(set->key_cache, cache_key_id, pubkey);
+ oauth2_validation_key_cache_insert_pubkey(set->key_cache, cache_key_id,
+ pubkey);
*key_r = pubkey;
return 0;
}
-static int oauth2_validate_rsa_ecdsa(const struct oauth2_settings *set,
- const char *azp, const char *alg, const char *key_id,
- const char *const *blobs, const char **error_r)
+static int
+oauth2_validate_rsa_ecdsa(const struct oauth2_settings *set,
+ const char *azp, const char *alg, const char *key_id,
+ const char *const *blobs, const char **error_r)
{
const char *method;
enum dcrypt_padding padding;
enum dcrypt_signature_format sig_format;
+
if (!dcrypt_is_initialized()) {
*error_r = "No crypto library loaded";
return -1;
/* verify signature */
bool valid;
if (!dcrypt_verify(pubkey, method, sig_format, data, strlen(data),
- signature->data, signature->used, &valid, padding, error_r)) {
+ signature->data, signature->used, &valid, padding,
+ error_r)) {
valid = FALSE;
} else if (!valid) {
*error_r = "Bad signature";
return valid ? 0 : -1;
}
-static int oauth2_validate_signature(const struct oauth2_settings *set,
- const char *azp, const char *alg, const char *key_id,
- const char *const *blobs, const char **error_r)
+static int
+oauth2_validate_signature(const struct oauth2_settings *set, const char *azp,
+ const char *alg, const char *key_id,
+ const char *const *blobs, const char **error_r)
{
- if (str_begins(alg, "HS"))
- return oauth2_validate_hmac(set, azp, alg, key_id, blobs, error_r);
- else if (str_begins(alg, "RS") || str_begins(alg, "PS") ||
- str_begins(alg, "ES"))
- return oauth2_validate_rsa_ecdsa(set, azp, alg, key_id, blobs, error_r);
+ if (str_begins(alg, "HS")) {
+ return oauth2_validate_hmac(set, azp, alg, key_id, blobs,
+ error_r);
+ } else if (str_begins(alg, "RS") || str_begins(alg, "PS") ||
+ str_begins(alg, "ES")) {
+ return oauth2_validate_rsa_ecdsa(set, azp, alg, key_id, blobs,
+ error_r);
+ }
*error_r = t_strdup_printf("Unsupported algorithm '%s'", alg);
return -1;
{
pool_t pool = array_get_pool(fields);
ARRAY(const struct json_tree_node*) nodes;
- t_array_init(&nodes, 1);
const struct json_tree_node *root = json_tree_root(tree);
+
+ t_array_init(&nodes, 1);
array_push_back(&nodes, &root);
while (array_count(&nodes) > 0) {
struct oauth2_field *field =
array_append_space(fields);
field->name = p_strdup(pool, node->key);
- field->value = p_strdup(pool, json_tree_get_value_str(node));
+ field->value = p_strdup(
+ pool, json_tree_get_value_str(node));
}
node = node->next;
}
}
static int
-oauth2_jwt_body_process(const struct oauth2_settings *set, const char *alg, const char *kid,
- ARRAY_TYPE(oauth2_field) *fields, struct json_tree *tree,
- const char *const *blobs, const char **error_r)
+oauth2_jwt_body_process(const struct oauth2_settings *set, const char *alg,
+ const char *kid, ARRAY_TYPE(oauth2_field) *fields,
+ struct json_tree *tree, const char *const *blobs,
+ const char **error_r)
{
const char *sub = get_field(tree, "sub");
size_t pos = strcspn(kid, "./%");
if (pos < strlen(kid)) {
- /* sanitize kid, cannot allow dots or / in it, so we encode them */
+ /* sanitize kid, cannot allow dots or / in it, so we encode them
+ */
string_t *new_kid = t_str_new(strlen(kid));
/* put initial data */
str_append_data(new_kid, kid, pos);
t_base64url_decode_str(BASE64_DECODE_FLAG_NO_PADDING, blobs[1]);
if (oauth2_json_tree_build(body, &body_tree, error_r) == -1)
return -1;
- ret = oauth2_jwt_body_process(set, alg, kid, fields, body_tree, blobs, error_r);
+ ret = oauth2_jwt_body_process(set, alg, kid, fields, body_tree, blobs,
+ error_r);
json_tree_deinit(&body_tree);
return ret;