#include <time.h>
-static const char *get_field(const struct json_tree *tree, const char *key,
- enum json_type *type_r)
+static const char *
+get_field(const struct json_tree *tree, const char *key,
+ enum json_type *type_r)
{
const struct json_tree_node *root = json_tree_root(tree);
const struct json_tree_node *value_node = json_tree_find_key(root, key);
+
if (value_node == NULL || value_node->value_type == JSON_TYPE_OBJECT ||
value_node->value_type == JSON_TYPE_ARRAY)
return NULL;
return json_tree_get_value_str(value_node);
}
-static const char *get_field_multiple(const struct json_tree *tree, const char *key)
+static const char *
+get_field_multiple(const struct json_tree *tree, const char *key)
{
const struct json_tree_node *root = json_tree_root(tree);
const struct json_tree_node *value_node = json_tree_find_key(root, key);
+
if (value_node == NULL || value_node->value_type == JSON_TYPE_OBJECT)
return NULL;
if (value_node->value_type != JSON_TYPE_ARRAY)
const struct json_tree_node *entry_node = json_tree_get_child(value_node);
string_t *values = t_str_new(64);
+
for (; entry_node != NULL; entry_node = entry_node->next) {
if (entry_node->value_type == JSON_TYPE_OBJECT ||
entry_node->value_type == JSON_TYPE_ARRAY)
continue;
+
const char *value_str = json_tree_get_value_str(entry_node);
+
if (str_len(values) > 0)
str_append_c(values, '\t');
str_append_tabescaped(values, value_str);
return str_c(values);
}
-static int get_time_field(const struct json_tree *tree, const char *key,
- int64_t *value_r)
+static int
+get_time_field(const struct json_tree *tree, const char *key, int64_t *value_r)
{
time_t tvalue;
enum json_type value_type;
const char *value = get_field(tree, key, &value_type);
-
int tz_offset ATTR_UNUSED;
+
if (value == NULL)
return 0;
if (value_type == JSON_TYPE_NUMBER) {
- /* Parse with atof() to handle the json valid exponential formats,
- but discard the decimal part of the fields as we are not
- interested in them.
+ /* Parse with atof() to handle the json valid exponential
+ formats, but discard the decimal part of the fields as we are
+ not interested in them.
- The worst case of x.99999 would appear as almost a second older
- than the actual x which is same as saying we processed it a
- second later for the purpose of JWT tokens */
+ The worst case of x.99999 would appear as almost a second
+ older than the actual x which is same as saying we processed
+ it a second later for the purpose of JWT tokens */
double v = atof(value);
*value_r = (int64_t) v;
if (*value_r < 0)
return -1;
return 1;
- } else if (iso8601_date_parse((const unsigned char*)value, strlen(value),
- &tvalue, &tz_offset)) {
+ } else if (iso8601_date_parse((const unsigned char*)value,
+ strlen(value), &tvalue, &tz_offset)) {
if (tvalue < 0)
return -1;
*value_r = tvalue;
static const char *escape_identifier(const char *identifier)
{
size_t pos = strcspn(identifier, "/%");
+
/* nothing to escape */
if (identifier[pos] == '\0')
return identifier;
size_t len = strlen(identifier);
string_t *new_id = t_str_new(len);
+
str_append_data(new_id, identifier, pos);
for (size_t i = pos; i < len; i++) {
}
const buffer_t *key;
+
if (oauth2_lookup_hmac_key(set, azp, alg, key_id, &key, error_r) < 0)
return -1;
struct hmac_context ctx;
+ unsigned char digest[method->digest_size];
+
hmac_init(&ctx, key->data, key->used, method);
hmac_update(&ctx, blobs[0], strlen(blobs[0]));
hmac_update(&ctx, ".", 1);
hmac_update(&ctx, blobs[1], strlen(blobs[1]));
- unsigned char digest[method->digest_size];
-
hmac_final(&ctx, digest);
buffer_t *their_digest =
/* try to load key */
struct dcrypt_public_key *pubkey;
const char *error;
+
if (!dcrypt_key_load_public(&pubkey, key_str, &error)) {
*error_r = t_strdup_printf("Cannot load key: %s", error);
return -1;
{
pool_t pool = array_get_pool(fields);
ARRAY(struct jwt_node) nodes;
+
t_array_init(&nodes, 1);
+
struct jwt_node *root = array_append_space(&nodes);
+
root->prefix = "";
root->root = json_tree_root(tree);
while (array_count(&nodes) > 0) {
const struct jwt_node *subroot = array_front(&nodes);
const struct json_tree_node *node = subroot->root;
+
while (node != NULL) {
if (node->value_type == JSON_TYPE_OBJECT ||
node->value_type == JSON_TYPE_ARRAY) {
} else {
struct oauth2_field *field;
const char *name;
+
if (subroot->array) {
name = strrchr(subroot->prefix, '_');
if (name != NULL)
field = array_append_space(fields);
field->name = p_strconcat(pool, subroot->prefix, node->key, NULL);
}
+
const char *value = str_tabescape(json_tree_get_value_str(node));
+
if (field->value != NULL) {
field->value = p_strconcat(pool, field->value, "\t", value, NULL);
} else {
const char **error_r)
{
const char *sub = get_field(tree, "sub", NULL);
-
- int ret;
int64_t t0 = time(NULL);
/* default IAT and NBF to now */
int64_t iat, nbf, exp;
int tz_offset ATTR_UNUSED;
+ int ret;
if (sub == NULL) {
*error_r = "Missing 'sub' field";
}
const char *iss = get_field(tree, "iss", NULL);
+
if (set->issuers != NULL && *set->issuers != NULL) {
if (iss == NULL) {
*error_r = "Token is missing 'iss' field";
}
const char *aud = get_field_multiple(tree, "aud");
+
/* if there is client_id configured, then aud should be present */
if (set->client_id != NULL && *set->client_id != '\0') {
if (aud == NULL) {
}
if (!check_scope(req_scope, got_scope)) {
- *error_r = t_strdup_printf("configured scope '%s' missing from token scope '%s'",
- req_scope, got_scope);
+ *error_r = t_strdup_printf(
+ "configured scope '%s' missing from token scope '%s'",
+ req_scope, got_scope);
return -1;
}
}