BUG/MINOR: http: http_auth_bearer fetch does not work on custom header name
The http_auth_bearer sample fetch can take a header name as parameter, in which case it will try to extract a Bearer value out of the given header name instead of the default "Authorization" one. In this case, the extraction would not have worked because of a misuse of strncasecmp. This patch fixes this by replacing the standard string functions by ist ones. It also properly manages the multiple spaces that could be found between the scheme and its value. No backport needed, that's part of JWT which is only in 2.5. Co-authored-by: Tim Duesterhus <tim@bastelstu.be>
This commit is contained in:
parent
68c4eae87f
commit
7da35bff9f
|
@ -16,7 +16,7 @@ feature cmd "$HAPROXY_PROGRAM -cc 'feature(OPENSSL)'"
|
||||||
feature cmd "command -v socat"
|
feature cmd "command -v socat"
|
||||||
feature ignore_unknown_macro
|
feature ignore_unknown_macro
|
||||||
|
|
||||||
server s1 -repeat 18 {
|
server s1 -repeat 22 {
|
||||||
rxreq
|
rxreq
|
||||||
txresp
|
txresp
|
||||||
} -start
|
} -start
|
||||||
|
@ -36,11 +36,10 @@ haproxy h1 -conf {
|
||||||
listen main-fe
|
listen main-fe
|
||||||
bind "fd@${mainfe}"
|
bind "fd@${mainfe}"
|
||||||
|
|
||||||
http-request deny unless { req.hdr(authorization) -m found }
|
|
||||||
|
|
||||||
use_backend hsXXX_be if { path_beg /hs }
|
use_backend hsXXX_be if { path_beg /hs }
|
||||||
use_backend rsXXX_be if { path_beg /rs }
|
use_backend rsXXX_be if { path_beg /rs }
|
||||||
use_backend esXXX_be if { path_beg /es }
|
use_backend esXXX_be if { path_beg /es }
|
||||||
|
use_backend auth_bearer_be if { path /auth_bearer }
|
||||||
default_backend dflt_be
|
default_backend dflt_be
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,6 +85,16 @@ haproxy h1 -conf {
|
||||||
http-response set-header x-jwt-verify-ES512 %[var(txn.bearer),jwt_verify(txn.jwt_alg,"${testdir}/es512-public.pem")] if { var(txn.jwt_alg) "ES512" }
|
http-response set-header x-jwt-verify-ES512 %[var(txn.bearer),jwt_verify(txn.jwt_alg,"${testdir}/es512-public.pem")] if { var(txn.jwt_alg) "ES512" }
|
||||||
server s1 ${s1_addr}:${s1_port}
|
server s1 ${s1_addr}:${s1_port}
|
||||||
|
|
||||||
|
|
||||||
|
# This backend will only be used to test the http_auth_bearer sample fetch.
|
||||||
|
# No jwt_verify will then be performed.
|
||||||
|
backend auth_bearer_be
|
||||||
|
http-request set-var(txn.bearer) http_auth_bearer("Custom-Authorization")
|
||||||
|
|
||||||
|
http-response set-header x-jwt-token %[var(txn.bearer)]
|
||||||
|
|
||||||
|
server s1 ${s1_addr}:${s1_port}
|
||||||
|
|
||||||
# This backend will mostly be used to test error cases (invalid tokens, algorithm and so on)
|
# This backend will mostly be used to test error cases (invalid tokens, algorithm and so on)
|
||||||
backend dflt_be
|
backend dflt_be
|
||||||
http-request set-var(txn.bearer) http_auth_bearer
|
http-request set-var(txn.bearer) http_auth_bearer
|
||||||
|
@ -334,3 +343,36 @@ client c18 -connect ${h1_mainfe_sock} {
|
||||||
# Unmanaged algorithm
|
# Unmanaged algorithm
|
||||||
expect resp.http.x-jwt-verify == "-5"
|
expect resp.http.x-jwt-verify == "-5"
|
||||||
} -run
|
} -run
|
||||||
|
|
||||||
|
|
||||||
|
# Test the http_auth_bearer special cases (other header than the default "Authorization" one)
|
||||||
|
client c19 -connect ${h1_mainfe_sock} {
|
||||||
|
txreq -url "/auth_bearer" -hdr "Custom-Authorization: Bearer random_value"
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 200
|
||||||
|
expect resp.http.x-jwt-token == "random_value"
|
||||||
|
} -run
|
||||||
|
|
||||||
|
# Test the http_auth_bearer special cases (multiple spaces after the scheme)
|
||||||
|
client c20 -connect ${h1_mainfe_sock} {
|
||||||
|
txreq -url "/auth_bearer" -hdr "Custom-Authorization: Bearer random_value"
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 200
|
||||||
|
expect resp.http.x-jwt-token == "random_value"
|
||||||
|
} -run
|
||||||
|
|
||||||
|
# Test the http_auth_bearer special cases (no value after the scheme)
|
||||||
|
client c21 -connect ${h1_mainfe_sock} {
|
||||||
|
txreq -url "/auth_bearer" -hdr "Custom-Authorization: Bearer "
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 200
|
||||||
|
expect resp.http.x-jwt-token == ""
|
||||||
|
} -run
|
||||||
|
|
||||||
|
# Test the http_auth_bearer special cases (no value after the scheme)
|
||||||
|
client c22 -connect ${h1_mainfe_sock} {
|
||||||
|
txreq -url "/errors" -hdr "Authorization: Bearer "
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 200
|
||||||
|
expect resp.http.x-jwt-token == ""
|
||||||
|
} -run
|
||||||
|
|
|
@ -1376,11 +1376,16 @@ static int smp_fetch_http_auth_bearer(const struct arg *args, struct sample *smp
|
||||||
|
|
||||||
ctx.blk = NULL;
|
ctx.blk = NULL;
|
||||||
if (http_find_header(htx, hdr_name, &ctx, 0)) {
|
if (http_find_header(htx, hdr_name, &ctx, 0)) {
|
||||||
char *space = NULL;
|
struct ist type = istsplit(&ctx.value, ' ');
|
||||||
space = memchr(ctx.value.ptr, ' ', ctx.value.len);
|
|
||||||
if (space && strncasecmp("Bearer", ctx.value.ptr, ctx.value.len) == 0) {
|
/* There must be "at least" one space character between
|
||||||
chunk_initlen(&bearer_val, space+1, 0, ctx.value.len - (space - ctx.value.ptr) - 1);
|
* the scheme and the following value so ctx.value might
|
||||||
}
|
* still have leading spaces here (see RFC7235).
|
||||||
|
*/
|
||||||
|
ctx.value = istskip(ctx.value, ' ');
|
||||||
|
|
||||||
|
if (isteqi(type, ist("Bearer")) && istlen(ctx.value))
|
||||||
|
chunk_initlen(&bearer_val, istptr(ctx.value), 0, istlen(ctx.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Reference in New Issue