Interpret the \i and \x escape sequences to insert the IP of the

requesting host
This commit is contained in:
hpa 2001-11-16 23:38:29 +00:00
parent fc1a21c942
commit 57044bc5df
5 changed files with 108 additions and 26 deletions

View file

@ -43,7 +43,8 @@ struct rule {
};
/* Do \-substitution. Call with string == NULL to get length only. */
static int genmatchstring(char *string, const char *pattern, const char *input, const regmatch_t *pmatch)
static int genmatchstring(char *string, const char *pattern, const char *input,
const regmatch_t *pmatch, match_pattern_callback macrosub)
{
int len = 0;
int n, mlen;
@ -60,11 +61,8 @@ static int genmatchstring(char *string, const char *pattern, const char *input,
/* Transform matched section */
while ( *pattern ) {
if ( *pattern == '\\' && pattern[1] != '\0' ) {
if ( pattern[1] < '0' || pattern[1] > '9' ) {
len++;
if ( string )
*string++ = pattern[1];
} else {
char macro = pattern[1];
if ( macro >= '0' && macro <= '9' ) {
n = pattern[1] - '0';
if ( pmatch[n].rm_so != -1 ) {
@ -75,6 +73,16 @@ static int genmatchstring(char *string, const char *pattern, const char *input,
string += mlen;
}
}
} else {
int sublen;
if ( macrosub &&
(sublen = macrosub(macro, string)) >= 0 ) {
len += sublen;
} else {
len++;
if ( string )
*string++ = pattern[1];
}
}
pattern += 2;
} else {
@ -257,7 +265,8 @@ void freerules(struct rule *r)
}
/* Execute a rule set on a string; returns a malloc'd new string. */
char *rewrite_string(const char *input, const struct rule *rules, int is_put)
char *rewrite_string(const char *input, const struct rule *rules,
int is_put, match_pattern_callback macrosub)
{
char *current = tfstrdup(input);
char *newstr;
@ -299,9 +308,11 @@ char *rewrite_string(const char *input, const struct rule *rules, int is_put)
}
if ( ruleptr->rule_flags & RULE_REWRITE ) {
len = genmatchstring(NULL, ruleptr->pattern, current, pmatch);
len = genmatchstring(NULL, ruleptr->pattern, current,
pmatch, macrosub);
newstr = tfmalloc(len+1);
genmatchstring(newstr, ruleptr->pattern, current, pmatch);
genmatchstring(newstr, ruleptr->pattern, current,
pmatch, macrosub);
free(current);
current = newstr;
if ( verbosity >= 3 ) {

View file

@ -18,15 +18,17 @@
#ifndef TFTPD_REMAP_H
#define TFTPD_REMAP_H
#include <stdlib.h>
#include <stdio.h>
#include "../config.h"
/* Opaque type */
struct rule;
#ifdef WITH_REGEX
/* This is called when we encounter a substitution like \i. The
macro character is passed as the first argument; the output buffer,
if any, is passed as the second argument. The function should return
the number of characters output, or -1 on failure. */
typedef int (*match_pattern_callback)(char, char *);
/* Read a rule file */
struct rule *parserulefile(FILE *);
@ -34,7 +36,8 @@ struct rule *parserulefile(FILE *);
void freerules(struct rule *);
/* Execute a rule set on a string; returns a malloc'd new string. */
char *rewrite_string(const char *, const struct rule *, int);
char *rewrite_string(const char *, const struct rule *, int,
match_pattern_callback);
#endif /* WITH_REGEX */
#endif /* TFTPD_REMAP_H */

View file

@ -177,12 +177,7 @@ Replace the substring matched by
.I regex
by the
.IR "replacement pattern" .
The escape sequence
\\0
can be used to copy the entire matched string, and the sequences
\\1 to \\9
copies parenthesized subexpressions. To specify a backslash, white
space or hash mark, you need to \\-escape it.
The replacement pattern may contain escape sequences; see below.
.TP
.B g
Repeat this rule until it no longer matches. This is always used with
@ -210,6 +205,35 @@ This rule applies to GET (RRQ) requests only.
.B P
This rule applies to PUT (WRQ) requests only.
.PP
The following escape sequences are recognized as part of the
.IR "replacement pattern" :
.TP
\fB\\0\fP
The entire string matched by the
.IR regex .
.TP
\fB\\1\fP to \fB\\9\fP
Match the first nine parentensized subexpressions, \\( ... \\) of the
.I regex
pattern.
.TP
\fB\\i\fP
The IP address of the requesting host, in dotted-quad notation
(e.g. 192.0.2.169).
.TP
\fB\\x\fP
The IP address of the requesting host, in hexadecimal notation
(e.g. C00002A9).
.TP
\fB\\\fP
Literal backslash.
.TP
\fB\\\fP\fIwhitespace\fP
Literal whitespace.
.TP
\fB\\#\fI
Literal hash mark.
.PP
If the mapping file is changed, you need to send
.B SIGHUP
to any outstanding

View file

@ -779,23 +779,64 @@ do_opt(char *opt, char *val, char **ap)
return;
}
#ifdef WITH_REGEX
/*
* This is called by the remap engine when it encounters macros such
* as \i. It should write the output in "output" if non-NULL, and
* return the length of the output (generated or not).
*
* Return -1 on failure.
*/
int
rewrite_macros(char macro, char *output);
int
rewrite_macros(char macro, char *output)
{
char *p;
switch (macro) {
case 'i':
p = inet_ntoa(from.sin_addr);
if ( output )
strcpy(output, p);
return strlen(p);
case 'x':
if ( output )
sprintf(output, "%08X",
ntohl(from.sin_addr.s_addr));
return 8;
default:
return -1;
}
}
/*
* Modify the filename, if applicable. If it returns NULL, deny the access.
*/
char *
rewrite_access(char *filename, int mode)
{
#ifdef WITH_REGEX
if ( rewrite_rules ) {
char *newname = rewrite_string(filename, rewrite_rules, mode != RRQ);
char *newname = rewrite_string(filename, rewrite_rules,
mode != RRQ, rewrite_macros);
filename = newname;
}
#else
(void)mode; /* Suppress unused warning */
#endif
return filename;
}
#else
char *
rewrite_access(char *filename, int mode)
{
(void)mode; /* Avoid warning */
return filename;
}
#endif
FILE *file;
/*
* Validate file access. Since we