[MINOR] acl: support loading values from files

The "acl XXX -f <file>" syntax was supported but nothing was read from
the file. This is now possible. All lines are merged verbatim, even if
they contain spaces (useful for user-agents). There are shortcomings
though. The worst one is that error reporting is too approximative.
This commit is contained in:
Willy Tarreau 2010-05-09 23:45:24 +02:00
parent b1a34b68ca
commit 2b5285da33
2 changed files with 72 additions and 3 deletions

View File

@ -5886,9 +5886,27 @@ performance, they just consume a small amount of memory.
The following ACL flags are currently supported :
-i : ignore case during matching.
-i : ignore case during matching of all subsequent patterns.
-f : load patterns from a file.
-- : force end of flags. Useful when a string looks like one of the flags.
The "-f" flag is special as it loads all of the lines it finds in the file
specified in argument and loads all of them before continuing. It is even
possible to pass multiple "-f" arguments if the patterns are to be loaded from
multiple files. Also, note that the "-i" flag applies to subsequent entries and
not to entries loaded from files preceeding it. For instance :
acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test
In this example, each line of "exact-ua.lst" will be exactly matched against
the "user-agent" header of the request. Then each line of "generic-ua" will be
case-insensitively matched. Then the word "test" will be insensitively matched
too.
Note that right now it is difficult for the ACL parsers to report errors, so if
a file is unreadable or unparsable, the most you'll get is a parse error in the
ACL. Thus, file-based ACLs should only be produced by reliable processes.
Supported types of values are :
- integers or integer ranges

View File

@ -19,6 +19,8 @@
#include <common/standard.h>
#include <common/uri_auth.h>
#include <types/global.h>
#include <proto/acl.h>
#include <proto/auth.h>
#include <proto/log.h>
@ -658,6 +660,52 @@ static struct acl_expr *prune_acl_expr(struct acl_expr *expr)
return expr;
}
static int acl_read_patterns_from_file( struct acl_keyword *aclkw,
struct acl_expr *expr,
const char *filename, int patflags)
{
FILE *file;
char *c;
const char *args[2];
struct acl_pattern *pattern;
int opaque;
file = fopen(filename, "r");
if (!file)
return 0;
/* now parse all patterns. The file may contain only one pattern per
* line. If the line contains spaces, they will be part of the pattern.
* The pattern stops at the first CR, LF or EOF encountered.
*/
opaque = 0;
args[0] = trash;
args[1] = "";
while (fgets(trash, sizeof(trash), file) != NULL) {
c = trash;
while (*c && *c != '\n' && *c != '\r')
c++;
*c = 0;
pattern = (struct acl_pattern *)calloc(1, sizeof(*pattern));
if (!pattern)
goto out_close;
pattern->flags = patflags;
if (!aclkw->parse(args, pattern, &opaque))
goto out_free_pattern;
LIST_ADDQ(&expr->patterns, &pattern->list);
}
return 1;
out_free_pattern:
free_pattern(pattern);
out_close:
fclose(file);
return 0;
}
/* Parse an ACL expression starting at <args>[0], and return it.
* Right now, the only accepted syntax is :
* <subject> [<value>...]
@ -711,8 +759,11 @@ struct acl_expr *parse_acl_expr(const char **args)
while (**args == '-') {
if ((*args)[1] == 'i')
patflags |= ACL_PAT_F_IGNORE_CASE;
else if ((*args)[1] == 'f')
patflags |= ACL_PAT_F_FROM_FILE;
else if ((*args)[1] == 'f') {
if (!acl_read_patterns_from_file(aclkw, expr, args[1], patflags | ACL_PAT_F_FROM_FILE))
goto out_free_expr;
args++;
}
else if ((*args)[1] == '-') {
args++;
break;