forked from mirrors/tftp-hpa-google
Interpret the \i and \x escape sequences to insert the IP of the
requesting host
This commit is contained in:
parent
fc1a21c942
commit
57044bc5df
5 changed files with 108 additions and 26 deletions
|
@ -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 ) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue