#ifdef USE_OPENSSL
enum jwt_alg jwt_parse_alg(const char *alg_str, unsigned int alg_len);
-int jwt_tokenize(const struct buffer *jwt, struct jwt_item *items, unsigned int *item_num);
+int jwt_tokenize(const struct buffer *jwt, struct jwt_item *items, unsigned int item_num);
int jwt_tree_load_cert(char *path, int pathlen, int tryload_cert, const char *file, int line, char **err);
enum jwt_vrfy_status jwt_verify(const struct buffer *token, const struct buffer *alg,
feature cmd "command -v socat"
feature ignore_unknown_macro
-server s1 -repeat 27 {
+server s1 -repeat 40 {
rxreq
txresp
} -start
expect resp.http.x-jwt-verify-RS256-var2 == "1"
} -run
+
+client c28 -connect ${h1_mainfe_sock} {
+ # Token content : {"alg":"none"}
+ # {"iss":"joe", "exp":1300819380, "http://example.com/is_root":true}
+ txreq -url "/none" -hdr "Authorization: Bearer eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ."
+ rxresp
+ expect resp.status == 200
+ expect resp.http.x-jwt-alg == "none"
+ expect resp.http.x-jwt-verify == "1"
+} -run
+
+client c29 -connect ${h1_mainfe_sock} {
+ # Invalid Token : too many subparts
+ txreq -url "/errors" -hdr "Authorization: Bearer eyJhbGciOiJub25lIn0.aa.aa.aa"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.x-jwt-alg == "none"
+ expect resp.http.x-jwt-verify == "-3"
+
+ # Invalid Token : too many subparts
+ txreq -url "/errors" -hdr "Authorization: Bearer eyJhbGciOiJub25lIn0.aa.aa."
+ rxresp
+ expect resp.status == 200
+ expect resp.http.x-jwt-alg == "none"
+ expect resp.http.x-jwt-verify == "-3"
+
+ # Invalid Token : too few subparts
+ txreq -url "/errors" -hdr "Authorization: Bearer eyJhbGciOiJub25lIn0.aa"
+ rxresp
+ expect resp.status == 200
+ expect resp.http.x-jwt-alg == "none"
+ expect resp.http.x-jwt-verify == "-3"
+
+ # Invalid Token : no signature but alg different than "none"
+ txreq -url "/errors" -hdr "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ."
+ rxresp
+ expect resp.status == 200
+ expect resp.http.x-jwt-alg == "RS256"
+ expect resp.http.x-jwt-verify == "-3"
+} -run
+
if (!chunk_cpy(input, &smp->data.u.str))
goto end;
- if (jwt_tokenize(input, items, &item_num) || item_num != JWE_ELT_MAX)
+ if (jwt_tokenize(input, items, item_num))
goto end;
alg_tag = alloc_trash_chunk();
if (!chunk_cpy(input, &smp->data.u.str))
goto end;
- if (jwt_tokenize(input, items, &item_num) || item_num != JWE_ELT_MAX)
+ if (jwt_tokenize(input, items, item_num))
goto end;
/* Base64Url decode the JOSE header */
if (!chunk_cpy(input, &smp->data.u.str))
goto end;
- if (jwt_tokenize(input, items, &item_num) || item_num != JWE_ELT_MAX)
+ if (jwt_tokenize(input, items, item_num))
goto end;
alg_tag = alloc_trash_chunk();
* now, we don't need to manage more than three subparts in the tokens.
* See section 3.1 of RFC7515 for more information about JWS Compact
* Serialization.
- * Returns 0 in case of success.
+ * Returns -1 in case of error, 0 if the token has exactly <item_num> parts, a
+ * positive value otherwise.
*/
-int jwt_tokenize(const struct buffer *jwt, struct jwt_item *items, unsigned int *item_num)
+int jwt_tokenize(const struct buffer *jwt, struct jwt_item *items, unsigned int item_num)
{
char *ptr = jwt->area;
char *jwt_end = jwt->area + jwt->data;
unsigned int index = 0;
unsigned int length = 0;
- if (index < *item_num) {
- items[index].start = ptr;
- items[index].length = 0;
- }
+ if (item_num == 0)
+ return -1;
- while (index < *item_num && ptr < jwt_end) {
+ items[index].start = ptr;
+ items[index].length = 0;
+
+ while (ptr < jwt_end) {
if (*ptr++ == '.') {
items[index++].length = length;
+ /* We found enough items, no need to keep looking for
+ * separators. */
+ if (index == item_num)
+ return 1;
- if (index == *item_num)
- return -1;
items[index].start = ptr;
items[index].length = 0;
length = 0;
++length;
}
- if (index < *item_num)
- items[index].length = length;
+ /* We might not have found enough items */
+ if (index < item_num - 1)
+ return -1;
- *item_num = (index+1);
+ items[index].length = length;
return (ptr != jwt_end);
}
if (ctx.alg == JWT_ALG_DEFAULT)
return JWT_VRFY_UNKNOWN_ALG;
- if (jwt_tokenize(token, items, &item_num))
+ if (jwt_tokenize(token, items, item_num))
return JWT_VRFY_INVALID_TOKEN;
- if (item_num != JWT_ELT_MAX)
- if (ctx.alg != JWS_ALG_NONE || item_num != JWT_ELT_SIG)
- return JWT_VRFY_INVALID_TOKEN;
-
ctx.jose = items[JWT_ELT_JOSE];
ctx.claims = items[JWT_ELT_CLAIMS];
ctx.signature = items[JWT_ELT_SIG];
int retval = 0;
int ret;
- jwt_tokenize(&smp->data.u.str, items, &item_num);
-
- if (item_num < member + 1)
+ /* We don't need to extract all the parts from the token, we only need a
+ * specific one.
+ */
+ if (jwt_tokenize(&smp->data.u.str, items, item_num) < 0)
goto end;
decoded_header = get_trash_chunk_sz(items[member].length);