mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 07:37:02 +02:00
[REORG] http: move the http-request rules to proto_http
And also rename "req_acl_rule" "http_req_rule". At the beginning that was a bit confusing to me, especially the "req_acl" list which in fact holds what we call rules. After some digging, it appeared that some part of the code is 100% HTTP and not just related to authentication anymore, so let's move that part to HTTP and keep the auth-only code in auth.c.
This commit is contained in:
parent
f68a15a951
commit
ff011f26e9
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* URI-based user authentication using the HTTP basic method.
|
* URI-based user authentication using the HTTP basic method.
|
||||||
*
|
*
|
||||||
* Copyright 2006-2007 Willy Tarreau <w@1wt.eu>
|
* Copyright 2006-2011 Willy Tarreau <w@1wt.eu>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -42,7 +42,7 @@ struct uri_auth {
|
|||||||
int flags; /* some flags describing the statistics page */
|
int flags; /* some flags describing the statistics page */
|
||||||
struct stat_scope *scope; /* linked list of authorized proxies */
|
struct stat_scope *scope; /* linked list of authorized proxies */
|
||||||
struct userlist *userlist; /* private userlist to emulate legacy "stats auth user:password" */
|
struct userlist *userlist; /* private userlist to emulate legacy "stats auth user:password" */
|
||||||
struct list req_acl; /* http stats ACL: allow/deny/auth */
|
struct list http_req_rules; /* stats http-request rules : allow/deny/auth */
|
||||||
struct list admin_rules; /* 'stats admin' rules (chained) */
|
struct list admin_rules; /* 'stats admin' rules (chained) */
|
||||||
struct uri_auth *next; /* Used at deinit() to build a list of unique elements */
|
struct uri_auth *next; /* Used at deinit() to build a list of unique elements */
|
||||||
};
|
};
|
||||||
|
@ -20,9 +20,7 @@ extern struct userlist *userlist;
|
|||||||
|
|
||||||
struct userlist *auth_find_userlist(char *name);
|
struct userlist *auth_find_userlist(char *name);
|
||||||
unsigned int auth_resolve_groups(struct userlist *l, char *groups);
|
unsigned int auth_resolve_groups(struct userlist *l, char *groups);
|
||||||
struct req_acl_rule *parse_auth_cond(const char **args, const char *file, int linenum, struct proxy *proxy);
|
|
||||||
void userlist_free(struct userlist *ul);
|
void userlist_free(struct userlist *ul);
|
||||||
void req_acl_free(struct list *r);
|
|
||||||
int acl_match_auth(struct acl_test *test, struct acl_pattern *pattern);
|
int acl_match_auth(struct acl_test *test, struct acl_pattern *pattern);
|
||||||
|
|
||||||
#endif /* _PROTO_AUTH_H */
|
#endif /* _PROTO_AUTH_H */
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* include/proto/proto_http.h
|
* include/proto/proto_http.h
|
||||||
* This file contains HTTP protocol definitions.
|
* This file contains HTTP protocol definitions.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
|
* Copyright (C) 2000-2011 Willy Tarreau - w@1wt.eu
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -99,6 +99,9 @@ void http_init_txn(struct session *s);
|
|||||||
void http_end_txn(struct session *s);
|
void http_end_txn(struct session *s);
|
||||||
void http_reset_txn(struct session *s);
|
void http_reset_txn(struct session *s);
|
||||||
|
|
||||||
|
struct http_req_rule *parse_http_req_cond(const char **args, const char *file, int linenum, struct proxy *proxy);
|
||||||
|
void free_http_req_rules(struct list *r);
|
||||||
|
|
||||||
/* to be used when contents change in an HTTP message */
|
/* to be used when contents change in an HTTP message */
|
||||||
#define http_msg_move_end(msg, bytes) do { \
|
#define http_msg_move_end(msg, bytes) do { \
|
||||||
unsigned int _bytes = (bytes); \
|
unsigned int _bytes = (bytes); \
|
||||||
|
@ -22,25 +22,6 @@
|
|||||||
|
|
||||||
#define AU_O_INSECURE 0x00000001 /* insecure, unencrypted password */
|
#define AU_O_INSECURE 0x00000001 /* insecure, unencrypted password */
|
||||||
|
|
||||||
enum {
|
|
||||||
PR_REQ_ACL_ACT_UNKNOWN = 0,
|
|
||||||
PR_REQ_ACL_ACT_ALLOW,
|
|
||||||
PR_REQ_ACL_ACT_DENY,
|
|
||||||
PR_REQ_ACL_ACT_HTTP_AUTH,
|
|
||||||
|
|
||||||
PR_REQ_ACL_ACT_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct req_acl_rule {
|
|
||||||
struct list list;
|
|
||||||
struct acl_cond *cond; /* acl condition to meet */
|
|
||||||
unsigned int action;
|
|
||||||
struct {
|
|
||||||
char *realm;
|
|
||||||
} http_auth;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct auth_users {
|
struct auth_users {
|
||||||
struct auth_users *next;
|
struct auth_users *next;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* include/types/proto_http.h
|
* include/types/proto_http.h
|
||||||
* This file contains HTTP protocol definitions.
|
* This file contains HTTP protocol definitions.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
|
* Copyright (C) 2000-2011 Willy Tarreau - w@1wt.eu
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -228,6 +228,14 @@ enum {
|
|||||||
HTTP_AUTH_DIGEST,
|
HTTP_AUTH_DIGEST,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
HTTP_REQ_ACT_UNKNOWN = 0,
|
||||||
|
HTTP_REQ_ACT_ALLOW,
|
||||||
|
HTTP_REQ_ACT_DENY,
|
||||||
|
HTTP_REQ_ACT_HTTP_AUTH,
|
||||||
|
HTTP_REQ_ACT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
/* This is an HTTP message, as described in RFC2616. It can be either a request
|
/* This is an HTTP message, as described in RFC2616. It can be either a request
|
||||||
* message or a response message.
|
* message or a response message.
|
||||||
*
|
*
|
||||||
@ -285,6 +293,15 @@ struct http_auth_data {
|
|||||||
char *user, *pass; /* extracted username & password */
|
char *user, *pass; /* extracted username & password */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct http_req_rule {
|
||||||
|
struct list list;
|
||||||
|
struct acl_cond *cond; /* acl condition to meet */
|
||||||
|
unsigned int action;
|
||||||
|
struct {
|
||||||
|
char *realm;
|
||||||
|
} http_auth;
|
||||||
|
};
|
||||||
|
|
||||||
/* This is an HTTP transaction. It contains both a request message and a
|
/* This is an HTTP transaction. It contains both a request message and a
|
||||||
* response message (which can be empty).
|
* response message (which can be empty).
|
||||||
*/
|
*/
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* include/types/proxy.h
|
* include/types/proxy.h
|
||||||
* This file defines everything related to proxies.
|
* This file defines everything related to proxies.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000-2010 Willy Tarreau - w@1wt.eu
|
* Copyright (C) 2000-2011 Willy Tarreau - w@1wt.eu
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -188,7 +188,7 @@ struct proxy {
|
|||||||
char *name; /* default backend name during config parse */
|
char *name; /* default backend name during config parse */
|
||||||
} defbe;
|
} defbe;
|
||||||
struct list acl; /* ACL declared on this proxy */
|
struct list acl; /* ACL declared on this proxy */
|
||||||
struct list req_acl; /* request ACL: allow/deny/http-auth */
|
struct list http_req_rules; /* HTTP request rules: allow/deny/http-auth */
|
||||||
struct list block_cond; /* early blocking conditions (chained) */
|
struct list block_cond; /* early blocking conditions (chained) */
|
||||||
struct list redirect_rules; /* content redirecting rules (chained) */
|
struct list redirect_rules; /* content redirecting rules (chained) */
|
||||||
struct list switching_rules; /* content switching rules (chained) */
|
struct list switching_rules; /* content switching rules (chained) */
|
||||||
|
72
src/auth.c
72
src/auth.c
@ -85,65 +85,6 @@ auth_resolve_groups(struct userlist *l, char *groups)
|
|||||||
return group_mask;
|
return group_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct req_acl_rule *
|
|
||||||
parse_auth_cond(const char **args, const char *file, int linenum, struct proxy *proxy)
|
|
||||||
{
|
|
||||||
struct req_acl_rule *req_acl;
|
|
||||||
int cur_arg;
|
|
||||||
|
|
||||||
req_acl = (struct req_acl_rule*)calloc(1, sizeof(struct req_acl_rule));
|
|
||||||
if (!req_acl) {
|
|
||||||
Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*args[0]) {
|
|
||||||
goto req_error_parsing;
|
|
||||||
} else if (!strcmp(args[0], "allow")) {
|
|
||||||
req_acl->action = PR_REQ_ACL_ACT_ALLOW;
|
|
||||||
cur_arg = 1;
|
|
||||||
} else if (!strcmp(args[0], "deny")) {
|
|
||||||
req_acl->action = PR_REQ_ACL_ACT_DENY;
|
|
||||||
cur_arg = 1;
|
|
||||||
} else if (!strcmp(args[0], "auth")) {
|
|
||||||
req_acl->action = PR_REQ_ACL_ACT_HTTP_AUTH;
|
|
||||||
cur_arg = 1;
|
|
||||||
|
|
||||||
while(*args[cur_arg]) {
|
|
||||||
if (!strcmp(args[cur_arg], "realm")) {
|
|
||||||
req_acl->http_auth.realm = strdup(args[cur_arg + 1]);
|
|
||||||
cur_arg+=2;
|
|
||||||
continue;
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
req_error_parsing:
|
|
||||||
Alert("parsing [%s:%d]: %s '%s', expects 'allow', 'deny', 'auth'.\n",
|
|
||||||
file, linenum, *args[1]?"unknown parameter":"missing keyword in", args[*args[1]?1:0]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(args[cur_arg], "if") == 0 || strcmp(args[cur_arg], "unless") == 0) {
|
|
||||||
struct acl_cond *cond;
|
|
||||||
|
|
||||||
if ((cond = build_acl_cond(file, linenum, proxy, args+cur_arg)) == NULL) {
|
|
||||||
Alert("parsing [%s:%d] : error detected while parsing an 'http-request %s' condition.\n",
|
|
||||||
file, linenum, args[0]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
req_acl->cond = cond;
|
|
||||||
}
|
|
||||||
else if (*args[cur_arg]) {
|
|
||||||
Alert("parsing [%s:%d]: 'http-request %s' expects 'realm' for 'auth' or"
|
|
||||||
" either 'if' or 'unless' followed by a condition but found '%s'.\n",
|
|
||||||
file, linenum, args[0], args[cur_arg]);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return req_acl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
userlist_free(struct userlist *ul)
|
userlist_free(struct userlist *ul)
|
||||||
{
|
{
|
||||||
@ -172,19 +113,6 @@ userlist_free(struct userlist *ul)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
req_acl_free(struct list *r) {
|
|
||||||
struct req_acl_rule *tr, *pr;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(pr, tr, r, list) {
|
|
||||||
LIST_DEL(&pr->list);
|
|
||||||
if (pr->action == PR_REQ_ACL_ACT_HTTP_AUTH)
|
|
||||||
free(pr->http_auth.realm);
|
|
||||||
|
|
||||||
free(pr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Authenticate and authorize user; return 1 if OK, 0 if case of error.
|
* Authenticate and authorize user; return 1 if OK, 0 if case of error.
|
||||||
*/
|
*/
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Configuration parser
|
* Configuration parser
|
||||||
*
|
*
|
||||||
* Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
|
* Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -1058,7 +1058,7 @@ static void init_new_proxy(struct proxy *p)
|
|||||||
memset(p, 0, sizeof(struct proxy));
|
memset(p, 0, sizeof(struct proxy));
|
||||||
LIST_INIT(&p->pendconns);
|
LIST_INIT(&p->pendconns);
|
||||||
LIST_INIT(&p->acl);
|
LIST_INIT(&p->acl);
|
||||||
LIST_INIT(&p->req_acl);
|
LIST_INIT(&p->http_req_rules);
|
||||||
LIST_INIT(&p->block_cond);
|
LIST_INIT(&p->block_cond);
|
||||||
LIST_INIT(&p->redirect_rules);
|
LIST_INIT(&p->redirect_rules);
|
||||||
LIST_INIT(&p->mon_fail_cond);
|
LIST_INIT(&p->mon_fail_cond);
|
||||||
@ -2462,7 +2462,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
curproxy->conn_retries = atol(args[1]);
|
curproxy->conn_retries = atol(args[1]);
|
||||||
}
|
}
|
||||||
else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
|
else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
|
||||||
struct req_acl_rule *req_acl;
|
struct http_req_rule *rule;
|
||||||
|
|
||||||
if (curproxy == &defproxy) {
|
if (curproxy == &defproxy) {
|
||||||
Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
|
Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
|
||||||
@ -2470,22 +2470,21 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
|
||||||
if (!LIST_ISEMPTY(&curproxy->req_acl) && !LIST_PREV(&curproxy->req_acl, struct req_acl_rule *, list)->cond) {
|
|
||||||
Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
|
Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
|
||||||
file, linenum, args[0]);
|
file, linenum, args[0]);
|
||||||
err_code |= ERR_WARN;
|
err_code |= ERR_WARN;
|
||||||
}
|
}
|
||||||
|
|
||||||
req_acl = parse_auth_cond((const char **)args + 1, file, linenum, curproxy);
|
rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
|
||||||
|
|
||||||
if (!req_acl) {
|
if (!rule) {
|
||||||
err_code |= ERR_ALERT | ERR_ABORT;
|
err_code |= ERR_ALERT | ERR_ABORT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
|
err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
|
||||||
LIST_ADDQ(&curproxy->req_acl, &req_acl->list);
|
LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
|
||||||
}
|
}
|
||||||
else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
|
else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
|
||||||
if (curproxy == &defproxy) {
|
if (curproxy == &defproxy) {
|
||||||
@ -3073,7 +3072,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
|
} else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
|
||||||
struct req_acl_rule *req_acl;
|
struct http_req_rule *rule;
|
||||||
|
|
||||||
if (curproxy == &defproxy) {
|
if (curproxy == &defproxy) {
|
||||||
Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
|
Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
|
||||||
@ -3087,22 +3086,22 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
|
if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
|
||||||
!LIST_PREV(&curproxy->uri_auth->req_acl, struct req_acl_rule *, list)->cond) {
|
!LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
|
||||||
Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
|
Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
|
||||||
file, linenum, args[0]);
|
file, linenum, args[0]);
|
||||||
err_code |= ERR_WARN;
|
err_code |= ERR_WARN;
|
||||||
}
|
}
|
||||||
|
|
||||||
req_acl = parse_auth_cond((const char **)args + 2, file, linenum, curproxy);
|
rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
|
||||||
|
|
||||||
if (!req_acl) {
|
if (!rule) {
|
||||||
err_code |= ERR_ALERT | ERR_ABORT;
|
err_code |= ERR_ALERT | ERR_ABORT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err_code |= warnif_cond_requires_resp(req_acl->cond, file, linenum);
|
err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
|
||||||
LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
|
LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
|
||||||
|
|
||||||
} else if (!strcmp(args[1], "auth")) {
|
} else if (!strcmp(args[1], "auth")) {
|
||||||
if (*(args[2]) == 0) {
|
if (*(args[2]) == 0) {
|
||||||
@ -5935,7 +5934,7 @@ int check_config_validity()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
|
if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
|
||||||
!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
|
!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
|
||||||
(curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
|
(curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
|
||||||
Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
|
Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
|
||||||
"proxy", curproxy->id);
|
"proxy", curproxy->id);
|
||||||
@ -5945,7 +5944,7 @@ int check_config_validity()
|
|||||||
|
|
||||||
if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
|
if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
|
||||||
const char *uri_auth_compat_req[10];
|
const char *uri_auth_compat_req[10];
|
||||||
struct req_acl_rule *req_acl;
|
struct http_req_rule *rule;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
/* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
|
/* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
|
||||||
@ -5962,13 +5961,13 @@ int check_config_validity()
|
|||||||
uri_auth_compat_req[i++] = "}";
|
uri_auth_compat_req[i++] = "}";
|
||||||
uri_auth_compat_req[i++] = "";
|
uri_auth_compat_req[i++] = "";
|
||||||
|
|
||||||
req_acl = parse_auth_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
|
rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
|
||||||
if (!req_acl) {
|
if (!rule) {
|
||||||
cfgerr++;
|
cfgerr++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIST_ADDQ(&curproxy->uri_auth->req_acl, &req_acl->list);
|
LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
|
||||||
|
|
||||||
if (curproxy->uri_auth->auth_realm) {
|
if (curproxy->uri_auth->auth_realm) {
|
||||||
free(curproxy->uri_auth->auth_realm);
|
free(curproxy->uri_auth->auth_realm);
|
||||||
|
@ -840,7 +840,7 @@ void deinit(void)
|
|||||||
free(p->desc);
|
free(p->desc);
|
||||||
free(p->fwdfor_hdr_name);
|
free(p->fwdfor_hdr_name);
|
||||||
|
|
||||||
req_acl_free(&p->req_acl);
|
free_http_req_rules(&p->http_req_rules);
|
||||||
|
|
||||||
pool_destroy2(p->req_cap_pool);
|
pool_destroy2(p->req_cap_pool);
|
||||||
pool_destroy2(p->rsp_cap_pool);
|
pool_destroy2(p->rsp_cap_pool);
|
||||||
@ -861,7 +861,7 @@ void deinit(void)
|
|||||||
free(uap->desc);
|
free(uap->desc);
|
||||||
|
|
||||||
userlist_free(uap->userlist);
|
userlist_free(uap->userlist);
|
||||||
req_acl_free(&uap->req_acl);
|
free_http_req_rules(&uap->http_req_rules);
|
||||||
|
|
||||||
free(uap);
|
free(uap);
|
||||||
}
|
}
|
||||||
|
102
src/proto_http.c
102
src/proto_http.c
@ -2983,31 +2983,31 @@ int http_process_req_stat_post(struct stream_interface *si, struct http_txn *txn
|
|||||||
/* returns a pointer to the first rule which forbids access (deny or http_auth),
|
/* returns a pointer to the first rule which forbids access (deny or http_auth),
|
||||||
* or NULL if everything's OK.
|
* or NULL if everything's OK.
|
||||||
*/
|
*/
|
||||||
static inline struct req_acl_rule *
|
static inline struct http_req_rule *
|
||||||
http_check_access_rule(struct proxy *px, struct list *rules, struct session *s, struct http_txn *txn)
|
http_check_access_rule(struct proxy *px, struct list *rules, struct session *s, struct http_txn *txn)
|
||||||
{
|
{
|
||||||
struct req_acl_rule *req_acl;
|
struct http_req_rule *rule;
|
||||||
|
|
||||||
list_for_each_entry(req_acl, rules, list) {
|
list_for_each_entry(rule, rules, list) {
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
|
||||||
if (req_acl->action >= PR_REQ_ACL_ACT_MAX)
|
if (rule->action >= HTTP_REQ_ACT_MAX)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* check condition, but only if attached */
|
/* check condition, but only if attached */
|
||||||
if (req_acl->cond) {
|
if (rule->cond) {
|
||||||
ret = acl_exec_cond(req_acl->cond, px, s, txn, ACL_DIR_REQ);
|
ret = acl_exec_cond(rule->cond, px, s, txn, ACL_DIR_REQ);
|
||||||
ret = acl_pass(ret);
|
ret = acl_pass(ret);
|
||||||
|
|
||||||
if (req_acl->cond->pol == ACL_COND_UNLESS)
|
if (rule->cond->pol == ACL_COND_UNLESS)
|
||||||
ret = !ret;
|
ret = !ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (req_acl->action == PR_REQ_ACL_ACT_ALLOW)
|
if (rule->action == HTTP_REQ_ACT_ALLOW)
|
||||||
return NULL; /* no problem */
|
return NULL; /* no problem */
|
||||||
else
|
else
|
||||||
return req_acl; /* most likely a deny or auth rule */
|
return rule; /* most likely a deny or auth rule */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -3025,7 +3025,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
|
|||||||
struct http_txn *txn = &s->txn;
|
struct http_txn *txn = &s->txn;
|
||||||
struct http_msg *msg = &txn->req;
|
struct http_msg *msg = &txn->req;
|
||||||
struct acl_cond *cond;
|
struct acl_cond *cond;
|
||||||
struct req_acl_rule *req_acl_final = NULL;
|
struct http_req_rule *http_req_last_rule = NULL;
|
||||||
struct redirect_rule *rule;
|
struct redirect_rule *rule;
|
||||||
struct cond_wordlist *wl;
|
struct cond_wordlist *wl;
|
||||||
int del_ka, del_cl, do_stats;
|
int del_ka, del_cl, do_stats;
|
||||||
@ -3067,19 +3067,19 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* evaluate http-request rules */
|
/* evaluate http-request rules */
|
||||||
req_acl_final = http_check_access_rule(px, &px->req_acl, s, txn);
|
http_req_last_rule = http_check_access_rule(px, &px->http_req_rules, s, txn);
|
||||||
|
|
||||||
/* evaluate stats http-request rules only if http-request is OK */
|
/* evaluate stats http-request rules only if http-request is OK */
|
||||||
if (!req_acl_final) {
|
if (!http_req_last_rule) {
|
||||||
do_stats = stats_check_uri(s->rep->prod, txn, px);
|
do_stats = stats_check_uri(s->rep->prod, txn, px);
|
||||||
if (do_stats)
|
if (do_stats)
|
||||||
req_acl_final = http_check_access_rule(px, &px->uri_auth->req_acl, s, txn);
|
http_req_last_rule = http_check_access_rule(px, &px->uri_auth->http_req_rules, s, txn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
do_stats = 0;
|
do_stats = 0;
|
||||||
|
|
||||||
/* return a 403 if either rule has blocked */
|
/* return a 403 if either rule has blocked */
|
||||||
if (req_acl_final && req_acl_final->action == PR_REQ_ACL_ACT_DENY) {
|
if (http_req_last_rule && http_req_last_rule->action == HTTP_REQ_ACT_DENY) {
|
||||||
txn->status = 403;
|
txn->status = 403;
|
||||||
s->logs.tv_request = now;
|
s->logs.tv_request = now;
|
||||||
stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_403));
|
stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_403));
|
||||||
@ -3180,9 +3180,9 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
|
|||||||
/* we can be blocked here because the request needs to be authenticated,
|
/* we can be blocked here because the request needs to be authenticated,
|
||||||
* either to pass or to access stats.
|
* either to pass or to access stats.
|
||||||
*/
|
*/
|
||||||
if (req_acl_final && req_acl_final->action == PR_REQ_ACL_ACT_HTTP_AUTH) {
|
if (http_req_last_rule && http_req_last_rule->action == HTTP_REQ_ACT_HTTP_AUTH) {
|
||||||
struct chunk msg;
|
struct chunk msg;
|
||||||
char *realm = req_acl_final->http_auth.realm;
|
char *realm = http_req_last_rule->http_auth.realm;
|
||||||
|
|
||||||
if (!realm)
|
if (!realm)
|
||||||
realm = do_stats?STATS_DEFAULT_REALM:px->id;
|
realm = do_stats?STATS_DEFAULT_REALM:px->id;
|
||||||
@ -7609,6 +7609,76 @@ void http_reset_txn(struct session *s)
|
|||||||
s->rep->analyse_exp = TICK_ETERNITY;
|
s->rep->analyse_exp = TICK_ETERNITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free_http_req_rules(struct list *r) {
|
||||||
|
struct http_req_rule *tr, *pr;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(pr, tr, r, list) {
|
||||||
|
LIST_DEL(&pr->list);
|
||||||
|
if (pr->action == HTTP_REQ_ACT_HTTP_AUTH)
|
||||||
|
free(pr->http_auth.realm);
|
||||||
|
|
||||||
|
free(pr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct http_req_rule *parse_http_req_cond(const char **args, const char *file, int linenum, struct proxy *proxy)
|
||||||
|
{
|
||||||
|
struct http_req_rule *rule;
|
||||||
|
int cur_arg;
|
||||||
|
|
||||||
|
rule = (struct http_req_rule*)calloc(1, sizeof(struct http_req_rule));
|
||||||
|
if (!rule) {
|
||||||
|
Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*args[0]) {
|
||||||
|
goto req_error_parsing;
|
||||||
|
} else if (!strcmp(args[0], "allow")) {
|
||||||
|
rule->action = HTTP_REQ_ACT_ALLOW;
|
||||||
|
cur_arg = 1;
|
||||||
|
} else if (!strcmp(args[0], "deny")) {
|
||||||
|
rule->action = HTTP_REQ_ACT_DENY;
|
||||||
|
cur_arg = 1;
|
||||||
|
} else if (!strcmp(args[0], "auth")) {
|
||||||
|
rule->action = HTTP_REQ_ACT_HTTP_AUTH;
|
||||||
|
cur_arg = 1;
|
||||||
|
|
||||||
|
while(*args[cur_arg]) {
|
||||||
|
if (!strcmp(args[cur_arg], "realm")) {
|
||||||
|
rule->http_auth.realm = strdup(args[cur_arg + 1]);
|
||||||
|
cur_arg+=2;
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
req_error_parsing:
|
||||||
|
Alert("parsing [%s:%d]: %s '%s', expects 'allow', 'deny', 'auth'.\n",
|
||||||
|
file, linenum, *args[1]?"unknown parameter":"missing keyword in", args[*args[1]?1:0]);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(args[cur_arg], "if") == 0 || strcmp(args[cur_arg], "unless") == 0) {
|
||||||
|
struct acl_cond *cond;
|
||||||
|
|
||||||
|
if ((cond = build_acl_cond(file, linenum, proxy, args+cur_arg)) == NULL) {
|
||||||
|
Alert("parsing [%s:%d] : error detected while parsing an 'http-request %s' condition.\n",
|
||||||
|
file, linenum, args[0]);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
rule->cond = cond;
|
||||||
|
}
|
||||||
|
else if (*args[cur_arg]) {
|
||||||
|
Alert("parsing [%s:%d]: 'http-request %s' expects 'realm' for 'auth' or"
|
||||||
|
" either 'if' or 'unless' followed by a condition but found '%s'.\n",
|
||||||
|
file, linenum, args[0], args[cur_arg]);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* The code below is dedicated to ACL parsing and matching */
|
/* The code below is dedicated to ACL parsing and matching */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -31,7 +31,7 @@ struct uri_auth *stats_check_init_uri_auth(struct uri_auth **root)
|
|||||||
if ((u = (struct uri_auth *)calloc(1, sizeof (*u))) == NULL)
|
if ((u = (struct uri_auth *)calloc(1, sizeof (*u))) == NULL)
|
||||||
goto out_u;
|
goto out_u;
|
||||||
|
|
||||||
LIST_INIT(&u->req_acl);
|
LIST_INIT(&u->http_req_rules);
|
||||||
LIST_INIT(&u->admin_rules);
|
LIST_INIT(&u->admin_rules);
|
||||||
} else
|
} else
|
||||||
u = *root;
|
u = *root;
|
||||||
|
Loading…
Reference in New Issue
Block a user