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

@ -5,7 +5,10 @@ Changes in 0.27:
Alan Sundell for helping out with this platform!
Make the AIX 4.3 platform work again. Thanks to Josef Siemes
for helping me out with this platform!
for helping out with this platform!
Allow replacement patterns to include the IP address of the
requesting host (\i).
Changes in 0.26:

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