From: Remi Tricot-Le Breton Date: Fri, 1 Oct 2021 13:36:53 +0000 (+0200) Subject: MINOR: http: Add http_auth_bearer sample fetch X-Git-Tag: v2.5-dev10~52 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f5dd337b12b39a9f81dca4d8367732e16b43b3dd;p=thirdparty%2Fhaproxy.git MINOR: http: Add http_auth_bearer sample fetch This fetch can be used to retrieve the data contained in an HTTP Authorization header when the Bearer scheme is used. This is used when transmitting JSON Web Tokens for instance. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 621ca2fb14..5466487ea6 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -20038,6 +20038,13 @@ http_auth() : boolean fetch function is not really useful outside of ACLs. Currently only http basic auth is supported. +http_auth_bearer([
]) : string + Returns the client-provided token found in the authorization data when the + Bearer scheme is used (to send JSON Web Tokens for instance). No check is + performed on the data sent by the client. + If a specific
is supplied, it will parse this header instead of the + Authorization one. + http_auth_group() : string Returns a string corresponding to the user name found in the authentication data received from the client if both the user name and password are valid diff --git a/include/haproxy/http-t.h b/include/haproxy/http-t.h index c6c50c95e1..3165082f9e 100644 --- a/include/haproxy/http-t.h +++ b/include/haproxy/http-t.h @@ -77,6 +77,7 @@ enum ht_auth_m { HTTP_AUTH_UNKNOWN = 0, HTTP_AUTH_BASIC, HTTP_AUTH_DIGEST, + HTTP_AUTH_BEARER, } __attribute__((packed)); /* All implemented HTTP status codes */ diff --git a/src/http_fetch.c b/src/http_fetch.c index d3192aa6c4..7b4e41d85f 100644 --- a/src/http_fetch.c +++ b/src/http_fetch.c @@ -146,6 +146,9 @@ static int get_http_auth(struct sample *smp, struct htx *htx) txn->auth.method = HTTP_AUTH_BASIC; return 1; + } else if (!strncasecmp("Bearer", auth_method.area, auth_method.data)) { + txn->auth.method = HTTP_AUTH_BEARER; + return 1; } return 0; @@ -1291,6 +1294,10 @@ static int smp_fetch_http_auth_type(const struct arg *args, struct sample *smp, smp->data.u.str.area = "Digest"; smp->data.u.str.data = 6; break; + case HTTP_AUTH_BEARER: + smp->data.u.str.area = "Bearer"; + smp->data.u.str.data = 6; + break; default: return 0; } @@ -1313,7 +1320,7 @@ static int smp_fetch_http_auth_user(const struct arg *args, struct sample *smp, return 0; txn = smp->strm->txn; - if (!get_http_auth(smp, htx)) + if (!get_http_auth(smp, htx) || txn->auth.method != HTTP_AUTH_BASIC) return 0; smp->data.type = SMP_T_STR; @@ -1336,7 +1343,7 @@ static int smp_fetch_http_auth_pass(const struct arg *args, struct sample *smp, return 0; txn = smp->strm->txn; - if (!get_http_auth(smp, htx)) + if (!get_http_auth(smp, htx) || txn->auth.method != HTTP_AUTH_BASIC) return 0; smp->data.type = SMP_T_STR; @@ -1346,6 +1353,43 @@ static int smp_fetch_http_auth_pass(const struct arg *args, struct sample *smp, return 1; } +static int smp_fetch_http_auth_bearer(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + struct channel *chn = SMP_REQ_CHN(smp); + struct htx *htx = smp_prefetch_htx(smp, chn, NULL, 1); + struct http_txn *txn; + struct buffer bearer_val = {}; + + if (!htx) + return 0; + + if (args->type == ARGT_STR) { + struct http_hdr_ctx ctx; + struct ist hdr_name = ist2(args->data.str.area, args->data.str.data); + + ctx.blk = NULL; + if (http_find_header(htx, hdr_name, &ctx, 0)) { + char *space = NULL; + space = memchr(ctx.value.ptr, ' ', ctx.value.len); + if (space && strncasecmp("Bearer", ctx.value.ptr, ctx.value.len) == 0) { + chunk_initlen(&bearer_val, space+1, 0, ctx.value.len - (space - ctx.value.ptr) - 1); + } + } + } + else { + txn = smp->strm->txn; + if (!get_http_auth(smp, htx) || txn->auth.method != HTTP_AUTH_BEARER) + return 0; + + bearer_val = txn->auth.method_data; + } + + smp->data.type = SMP_T_STR; + smp->data.u.str = bearer_val; + smp->flags = SMP_F_CONST; + return 1; +} + /* Accepts exactly 1 argument of type userlist */ static int smp_fetch_http_auth(const struct arg *args, struct sample *smp, const char *kw, void *private) { @@ -1357,7 +1401,7 @@ static int smp_fetch_http_auth(const struct arg *args, struct sample *smp, const if (!htx) return 0; - if (!get_http_auth(smp, htx)) + if (!get_http_auth(smp, htx) || smp->strm->txn->auth.method != HTTP_AUTH_BASIC) return 0; smp->data.type = SMP_T_BOOL; @@ -1377,7 +1421,7 @@ static int smp_fetch_http_auth_grp(const struct arg *args, struct sample *smp, c if (!htx) return 0; - if (!get_http_auth(smp, htx)) + if (!get_http_auth(smp, htx) || smp->strm->txn->auth.method != HTTP_AUTH_BASIC) return 0; /* if the user does not belong to the userlist or has a wrong password, @@ -2097,6 +2141,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { { "http_auth_type", smp_fetch_http_auth_type, 0, NULL, SMP_T_STR, SMP_USE_HRQHV }, { "http_auth_user", smp_fetch_http_auth_user, 0, NULL, SMP_T_STR, SMP_USE_HRQHV }, { "http_auth_pass", smp_fetch_http_auth_pass, 0, NULL, SMP_T_STR, SMP_USE_HRQHV }, + { "http_auth_bearer", smp_fetch_http_auth_bearer, ARG1(0,STR), NULL, SMP_T_STR, SMP_USE_HRQHV }, { "http_auth", smp_fetch_http_auth, ARG1(1,USR), NULL, SMP_T_BOOL, SMP_USE_HRQHV }, { "http_auth_group", smp_fetch_http_auth_grp, ARG1(1,USR), NULL, SMP_T_STR, SMP_USE_HRQHV }, { "http_first_req", smp_fetch_http_first_req, 0, NULL, SMP_T_BOOL, SMP_USE_HRQHP },