tftpd: allow IPv4/6-specific remapping rules

Allow remapping rules to be conditional on IPv4 vs IPv6.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2014-06-07 12:52:57 -07:00
parent c89a63a441
commit 18ee96a03f
3 changed files with 28 additions and 13 deletions

View file

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- * /* ----------------------------------------------------------------------- *
* *
* Copyright 2001-2007 H. Peter Anvin - All Rights Reserved * Copyright 2001-2014 H. Peter Anvin - All Rights Reserved
* *
* This program is free software available under the same license * This program is free software available under the same license
* as the "OpenBSD" operating system, distributed at * as the "OpenBSD" operating system, distributed at
@ -31,6 +31,8 @@
#define RULE_RESTART 0x08 /* Restart at the top after matching this rule */ #define RULE_RESTART 0x08 /* Restart at the top after matching this rule */
#define RULE_ABORT 0x10 /* Terminate processing with an error */ #define RULE_ABORT 0x10 /* Terminate processing with an error */
#define RULE_INVERSE 0x20 /* Execute if regex *doesn't* match */ #define RULE_INVERSE 0x20 /* Execute if regex *doesn't* match */
#define RULE_IPV4 0x40 /* IPv4 only */
#define RULE_IPV6 0x80 /* IPv6 only */
struct rule { struct rule {
struct rule *next; struct rule *next;
@ -223,6 +225,12 @@ static int parseline(char *line, struct rule *r, int lineno)
case '~': case '~':
r->rule_flags |= RULE_INVERSE; r->rule_flags |= RULE_INVERSE;
break; break;
case '4':
r->rule_flags |= RULE_IPV4;
break;
case '6':
r->rule_flags |= RULE_IPV6;
break;
case 'G': case 'G':
case 'P': case 'P':
r->rule_mode = *p; r->rule_mode = *p;
@ -326,7 +334,7 @@ void freerules(struct rule *r)
/* Execute a rule set on a string; returns a malloc'd new string. */ /* Execute a rule set on a string; returns a malloc'd new string. */
char *rewrite_string(const char *input, const struct rule *rules, char *rewrite_string(const char *input, const struct rule *rules,
char mode, match_pattern_callback macrosub, char mode, int af, match_pattern_callback macrosub,
const char **errmsg) const char **errmsg)
{ {
char *current = tfstrdup(input); char *current = tfstrdup(input);
@ -348,6 +356,12 @@ char *rewrite_string(const char *input, const struct rule *rules,
if (ruleptr->rule_mode && ruleptr->rule_mode != mode) if (ruleptr->rule_mode && ruleptr->rule_mode != mode)
continue; /* Rule not applicable, try next */ continue; /* Rule not applicable, try next */
if ((ruleptr->rule_flags & RULE_IPV4) && (af != AF_INET))
continue; /* Rule not applicable, try next */
if ((ruleptr->rule_flags & RULE_IPV6) && (af != AF_INET6))
continue; /* Rule not applicable, try next */
if (!deadman--) { if (!deadman--) {
syslog(LOG_WARNING, syslog(LOG_WARNING,
"remap: Breaking loop, input = %s, last = %s", input, "remap: Breaking loop, input = %s, last = %s", input,

View file

@ -35,7 +35,7 @@ struct rule *parserulefile(FILE *);
void freerules(struct rule *); void freerules(struct rule *);
/* Execute a rule set on a string; returns a malloc'd new string. */ /* Execute a rule set on a string; returns a malloc'd new string. */
char *rewrite_string(const char *, const struct rule *, char, char *rewrite_string(const char *, const struct rule *, char, int,
match_pattern_callback, const char **); match_pattern_callback, const char **);
#endif /* WITH_REGEX */ #endif /* WITH_REGEX */

View file

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 1983 Regents of the University of California. * Copyright (c) 1983 Regents of the University of California.
* Copyright (c) 1999-2009 H. Peter Anvin * Copyright (c) 1999-2009 H. Peter Anvin
* Copyright (c) 2011 Intel Corporation; author: H. Peter Anvin * Copyright (c) 2011-2014 Intel Corporation; author: H. Peter Anvin
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -1043,14 +1043,14 @@ int main(int argc, char **argv)
exit(0); exit(0);
} }
static char *rewrite_access(char *, int, const char **); static char *rewrite_access(char *, int, int, const char **);
static int validate_access(char *, int, const struct formats *, const char **); static int validate_access(char *, int, const struct formats *, const char **);
static void tftp_sendfile(const struct formats *, struct tftphdr *, int); static void tftp_sendfile(const struct formats *, struct tftphdr *, int);
static void tftp_recvfile(const struct formats *, struct tftphdr *, int); static void tftp_recvfile(const struct formats *, struct tftphdr *, int);
struct formats { struct formats {
const char *f_mode; const char *f_mode;
char *(*f_rewrite) (char *, int, const char **); char *(*f_rewrite) (char *, int, int, const char **);
int (*f_validate) (char *, int, const struct formats *, const char **); int (*f_validate) (char *, int, const struct formats *, const char **);
void (*f_send) (const struct formats *, struct tftphdr *, int); void (*f_send) (const struct formats *, struct tftphdr *, int);
void (*f_recv) (const struct formats *, struct tftphdr *, int); void (*f_recv) (const struct formats *, struct tftphdr *, int);
@ -1112,9 +1112,8 @@ int tftp(struct tftphdr *tp, int size)
nak(EBADOP, "Unknown mode"); nak(EBADOP, "Unknown mode");
exit(0); exit(0);
} }
if (!(filename = if (!(filename = (*pf->f_rewrite)
(*pf->f_rewrite) (origfilename, tp_opcode, (origfilename, tp_opcode, from.sa.sa_family, &errmsgptr))) {
&errmsgptr))) {
nak(EACCESS, errmsgptr); /* File denied by mapping rule */ nak(EACCESS, errmsgptr); /* File denied by mapping rule */
exit(0); exit(0);
} }
@ -1398,12 +1397,13 @@ static int rewrite_macros(char macro, char *output)
/* /*
* Modify the filename, if applicable. If it returns NULL, deny the access. * Modify the filename, if applicable. If it returns NULL, deny the access.
*/ */
static char *rewrite_access(char *filename, int mode, const char **msg) static char *rewrite_access(char *filename, int mode, int af,
const char **msg)
{ {
if (rewrite_rules) { if (rewrite_rules) {
char *newname = char *newname =
rewrite_string(filename, rewrite_rules, rewrite_string(filename, rewrite_rules,
mode != RRQ ? 'P' : 'G', mode != RRQ ? 'P' : 'G', af,
rewrite_macros, msg); rewrite_macros, msg);
filename = newname; filename = newname;
} }
@ -1411,10 +1411,11 @@ static char *rewrite_access(char *filename, int mode, const char **msg)
} }
#else #else
static char *rewrite_access(char *filename, int mode, const char **msg) static char *rewrite_access(char *filename, int mode, int af, const char **msg)
{ {
(void)mode; /* Avoid warning */ (void)mode; /* Avoid warning */
(void)msg; (void)msg;
(void)af;
return filename; return filename;
} }
#endif #endif