mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 22:01:31 +02:00
[MEDIUM] moved uri_auth check to a separate function
The check of uri_auth is now in a separate function which is checked after every backend switch, so that it will be possible to have an uri_auth for the frontend and another one for the backend.
This commit is contained in:
parent
921d7c0a70
commit
b251390f7e
@ -50,6 +50,8 @@ void debug_hdr(const char *dir, struct session *t, const char *start, const char
|
|||||||
void get_srv_from_appsession(struct session *t, const char *begin, const char *end);
|
void get_srv_from_appsession(struct session *t, const char *begin, const char *end);
|
||||||
void apply_filters_to_session(struct session *t, struct buffer *req, struct hdr_exp *exp);
|
void apply_filters_to_session(struct session *t, struct buffer *req, struct hdr_exp *exp);
|
||||||
void manage_client_side_cookies(struct session *t, struct buffer *req);
|
void manage_client_side_cookies(struct session *t, struct buffer *req);
|
||||||
|
static http_meth_t find_http_meth(const char *str, const int len);
|
||||||
|
int stats_check_uri_auth(struct session *t, struct proxy *backend);
|
||||||
|
|
||||||
#endif /* _PROTO_PROTO_HTTP_H */
|
#endif /* _PROTO_PROTO_HTTP_H */
|
||||||
|
|
||||||
|
206
src/proto_http.c
206
src/proto_http.c
@ -304,7 +304,7 @@ int process_cli(struct session *t)
|
|||||||
struct buffer *rep = t->rep;
|
struct buffer *rep = t->rep;
|
||||||
int delete_header = 0;
|
int delete_header = 0;
|
||||||
|
|
||||||
int cur_hdr, cur_idx;
|
int cur_hdr;
|
||||||
|
|
||||||
DPRINTF(stderr,"process_cli: c=%s s=%s set(r,w)=%d,%d exp(r,w)=%d.%d,%d.%d\n",
|
DPRINTF(stderr,"process_cli: c=%s s=%s set(r,w)=%d,%d exp(r,w)=%d.%d,%d.%d\n",
|
||||||
cli_stnames[c], srv_stnames[s],
|
cli_stnames[c], srv_stnames[s],
|
||||||
@ -855,6 +855,7 @@ int process_cli(struct session *t)
|
|||||||
|
|
||||||
t->hreq.start.str = req->data + t->hreq.sor; /* start of the REQURI */
|
t->hreq.start.str = req->data + t->hreq.sor; /* start of the REQURI */
|
||||||
t->hreq.start.len = t->hreq.hdr_idx.v[t->hreq.hdr_idx.v[0].next].len; /* end of the REQURI */
|
t->hreq.start.len = t->hreq.hdr_idx.v[t->hreq.hdr_idx.v[0].next].len; /* end of the REQURI */
|
||||||
|
t->hreq.meth = find_http_meth(t->hreq.start.str, t->hreq.start.len);
|
||||||
|
|
||||||
if ((t->fe->monitor_uri_len != 0) &&
|
if ((t->fe->monitor_uri_len != 0) &&
|
||||||
(t->hreq.start.len >= t->fe->monitor_uri_len)) {
|
(t->hreq.start.len >= t->fe->monitor_uri_len)) {
|
||||||
@ -905,10 +906,6 @@ int process_cli(struct session *t)
|
|||||||
* to match the reverse of the forward sequence.
|
* to match the reverse of the forward sequence.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t->hreq.start.str = req->data + t->hreq.sor; /* start of the REQURI */
|
|
||||||
t->hreq.start.len = t->hreq.hdr_idx.v[t->hreq.hdr_idx.v[0].next].len; /* end of the REQURI */
|
|
||||||
t->hreq.meth = find_http_meth(t->hreq.start.str, t->hreq.start.len);
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
rule_set = t->be;
|
rule_set = t->be;
|
||||||
|
|
||||||
@ -943,6 +940,13 @@ int process_cli(struct session *t)
|
|||||||
if (hdr_idx_add(len - 2, 1, &t->hreq.hdr_idx, t->hreq.hdr_idx.tail) < 0)
|
if (hdr_idx_add(len - 2, 1, &t->hreq.hdr_idx, t->hreq.hdr_idx.tail) < 0)
|
||||||
goto return_bad_req;
|
goto return_bad_req;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rule_set->uri_auth != NULL && t->hreq.meth == HTTP_METH_GET) {
|
||||||
|
/* we have to check the URI and auth for this request */
|
||||||
|
if (stats_check_uri_auth(t, rule_set))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
} while (rule_set != t->be); /* we loop only if t->be has changed */
|
} while (rule_set != t->be); /* we loop only if t->be has changed */
|
||||||
|
|
||||||
|
|
||||||
@ -957,7 +961,7 @@ int process_cli(struct session *t)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 4: the appsession cookie was looked up very early in 1.2,
|
* 3: the appsession cookie was looked up very early in 1.2,
|
||||||
* so let's do the same now.
|
* so let's do the same now.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -970,7 +974,7 @@ int process_cli(struct session *t)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 5: Now we can work with the cookies.
|
* 4: Now we can work with the cookies.
|
||||||
* Note that doing so might move headers in the request, but
|
* Note that doing so might move headers in the request, but
|
||||||
* the fields will stay coherent and the URI will not move.
|
* the fields will stay coherent and the URI will not move.
|
||||||
* This should only be performed in the backend.
|
* This should only be performed in the backend.
|
||||||
@ -980,91 +984,7 @@ int process_cli(struct session *t)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME:
|
* 5: add X-Forwarded-For : Should depend on the backend only.
|
||||||
* we could run the whole list of headers right here to extract
|
|
||||||
* commonly used headers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 6: check if the user tries to access a protected URI.
|
|
||||||
*/
|
|
||||||
if (t->be->uri_auth != NULL
|
|
||||||
&& t->hreq.meth == HTTP_METH_GET
|
|
||||||
&& t->hreq.start.len >= t->be->uri_auth->uri_len + 4) { /* +4 for "GET /" */
|
|
||||||
if (!memcmp(t->hreq.start.str + 4,
|
|
||||||
t->be->uri_auth->uri_prefix, t->be->uri_auth->uri_len)) {
|
|
||||||
struct user_auth *user;
|
|
||||||
int authenticated;
|
|
||||||
char *h;
|
|
||||||
|
|
||||||
/* we are in front of a interceptable URI. Let's check
|
|
||||||
* if there's an authentication and if it's valid.
|
|
||||||
*/
|
|
||||||
user = t->be->uri_auth->users;
|
|
||||||
if (!user) {
|
|
||||||
/* no user auth required, it's OK */
|
|
||||||
authenticated = 1;
|
|
||||||
} else {
|
|
||||||
authenticated = 0;
|
|
||||||
|
|
||||||
/* a user list is defined, we have to check.
|
|
||||||
* skip 21 chars for "Authorization: Basic ".
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* FIXME: this should move to an earlier place */
|
|
||||||
cur_idx = 0;
|
|
||||||
h = req->data + t->hreq.sor;
|
|
||||||
while ((cur_idx = t->hreq.hdr_idx.v[cur_idx].next)) {
|
|
||||||
int len = t->hreq.hdr_idx.v[cur_idx].len;
|
|
||||||
if (len > 14 &&
|
|
||||||
!strncasecmp("Authorization:", h, 14)) {
|
|
||||||
t->hreq.auth_hdr.str = h;
|
|
||||||
t->hreq.auth_hdr.len = len;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
h += len + t->hreq.hdr_idx.v[cur_idx].cr + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (t->hreq.auth_hdr.len < 21 ||
|
|
||||||
memcmp(t->hreq.auth_hdr.str + 14, " Basic ", 7))
|
|
||||||
user = NULL;
|
|
||||||
|
|
||||||
while (user) {
|
|
||||||
if ((t->hreq.auth_hdr.len == user->user_len + 14 + 7)
|
|
||||||
&& !memcmp(t->hreq.auth_hdr.str + 14 + 7,
|
|
||||||
user->user_pwd, user->user_len)) {
|
|
||||||
authenticated = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
user = user->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!authenticated) {
|
|
||||||
int msglen;
|
|
||||||
|
|
||||||
/* no need to go further */
|
|
||||||
|
|
||||||
msglen = sprintf(trash, HTTP_401_fmt, t->be->uri_auth->auth_realm);
|
|
||||||
t->logs.status = 401;
|
|
||||||
client_retnclose(t, msglen, trash);
|
|
||||||
goto return_prx_cond;
|
|
||||||
}
|
|
||||||
|
|
||||||
t->cli_state = CL_STSHUTR;
|
|
||||||
req->rlim = req->data + BUFSIZE; /* no more rewrite needed */
|
|
||||||
t->logs.t_request = tv_diff(&t->logs.tv_accept, &now);
|
|
||||||
t->data_source = DATA_SRC_STATS;
|
|
||||||
t->data_state = DATA_ST_INIT;
|
|
||||||
produce_content(t);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 7: add X-Forwarded-For : Should depend on the backend only.
|
|
||||||
*/
|
*/
|
||||||
if (t->be->options & PR_O_FWDFOR) {
|
if (t->be->options & PR_O_FWDFOR) {
|
||||||
if (t->cli_addr.ss_family == AF_INET) {
|
if (t->cli_addr.ss_family == AF_INET) {
|
||||||
@ -1098,10 +1018,13 @@ int process_cli(struct session *t)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 8: add "Connection:"
|
* 6: add "Connection:"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* add a "connection: close" line if needed */
|
/* add a "connection: close" line if needed.
|
||||||
|
* FIXME: this should depend on both the frontend and the backend.
|
||||||
|
* Header removals should be performed when the filters are run.
|
||||||
|
*/
|
||||||
if (t->fe->options & PR_O_HTTP_CLOSE) {
|
if (t->fe->options & PR_O_HTTP_CLOSE) {
|
||||||
int len;
|
int len;
|
||||||
len = buffer_replace2(req, req->data + t->hreq.eoh,
|
len = buffer_replace2(req, req->data + t->hreq.eoh,
|
||||||
@ -3581,6 +3504,101 @@ void get_srv_from_appsession(struct session *t, const char *begin, const char *e
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In a GET request, check if the requested URI matches the stats uri for the
|
||||||
|
* current backend, and if an authorization has been passed and is valid.
|
||||||
|
*
|
||||||
|
* It is assumed that the request is a GET and that the t->be->uri_auth field
|
||||||
|
* is valid. An HTTP/401 response may be sent, or produce_content() can be
|
||||||
|
* called to start sending data.
|
||||||
|
*
|
||||||
|
* Returns 1 if the session's state changes, otherwise 0.
|
||||||
|
*/
|
||||||
|
int stats_check_uri_auth(struct session *t, struct proxy *backend)
|
||||||
|
{
|
||||||
|
struct uri_auth *uri_auth = backend->uri_auth;
|
||||||
|
struct user_auth *user;
|
||||||
|
int authenticated, cur_idx;
|
||||||
|
char *h;
|
||||||
|
|
||||||
|
if (t->hreq.start.len < uri_auth->uri_len + 4) /* +4 for "GET " */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (memcmp(t->hreq.start.str + 4, uri_auth->uri_prefix, uri_auth->uri_len) != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* we are in front of a interceptable URI. Let's check
|
||||||
|
* if there's an authentication and if it's valid.
|
||||||
|
*/
|
||||||
|
user = uri_auth->users;
|
||||||
|
if (!user) {
|
||||||
|
/* no user auth required, it's OK */
|
||||||
|
authenticated = 1;
|
||||||
|
} else {
|
||||||
|
authenticated = 0;
|
||||||
|
|
||||||
|
/* a user list is defined, we have to check.
|
||||||
|
* skip 21 chars for "Authorization: Basic ".
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* FIXME: this should move to an earlier place */
|
||||||
|
cur_idx = 0;
|
||||||
|
h = t->req->data + t->hreq.sor;
|
||||||
|
while ((cur_idx = t->hreq.hdr_idx.v[cur_idx].next)) {
|
||||||
|
int len = t->hreq.hdr_idx.v[cur_idx].len;
|
||||||
|
if (len > 14 &&
|
||||||
|
!strncasecmp("Authorization:", h, 14)) {
|
||||||
|
t->hreq.auth_hdr.str = h;
|
||||||
|
t->hreq.auth_hdr.len = len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
h += len + t->hreq.hdr_idx.v[cur_idx].cr + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t->hreq.auth_hdr.len < 21 ||
|
||||||
|
memcmp(t->hreq.auth_hdr.str + 14, " Basic ", 7))
|
||||||
|
user = NULL;
|
||||||
|
|
||||||
|
while (user) {
|
||||||
|
if ((t->hreq.auth_hdr.len == user->user_len + 14 + 7)
|
||||||
|
&& !memcmp(t->hreq.auth_hdr.str + 14 + 7,
|
||||||
|
user->user_pwd, user->user_len)) {
|
||||||
|
authenticated = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
user = user->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authenticated) {
|
||||||
|
int msglen;
|
||||||
|
|
||||||
|
/* no need to go further */
|
||||||
|
msglen = sprintf(trash, HTTP_401_fmt, uri_auth->auth_realm);
|
||||||
|
t->logs.status = 401;
|
||||||
|
client_retnclose(t, msglen, trash);
|
||||||
|
if (!(t->flags & SN_ERR_MASK))
|
||||||
|
t->flags |= SN_ERR_PRXCOND;
|
||||||
|
if (!(t->flags & SN_FINST_MASK))
|
||||||
|
t->flags |= SN_FINST_R;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The request is valid, the user is authenticate. Let's start sending
|
||||||
|
* data.
|
||||||
|
*/
|
||||||
|
t->cli_state = CL_STSHUTR;
|
||||||
|
t->req->rlim = t->req->data + BUFSIZE; /* no more rewrite needed */
|
||||||
|
t->logs.t_request = tv_diff(&t->logs.tv_accept, &now);
|
||||||
|
t->data_source = DATA_SRC_STATS;
|
||||||
|
t->data_state = DATA_ST_INIT;
|
||||||
|
produce_content(t);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Print a debug line with a header
|
* Print a debug line with a header
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user