From 18ee96a03f8656031b67dd13ad2fcadb5af7ffaf Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 7 Jun 2014 12:52:57 -0700 Subject: tftpd: allow IPv4/6-specific remapping rules Allow remapping rules to be conditional on IPv4 vs IPv6. Signed-off-by: H. Peter Anvin --- tftpd/remap.c | 18 ++++++++++++++++-- tftpd/remap.h | 2 +- tftpd/tftpd.c | 21 +++++++++++---------- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/tftpd/remap.c b/tftpd/remap.c index 1e7abe7..6f5b409 100644 --- a/tftpd/remap.c +++ b/tftpd/remap.c @@ -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 * 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_ABORT 0x10 /* Terminate processing with an error */ #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 *next; @@ -223,6 +225,12 @@ static int parseline(char *line, struct rule *r, int lineno) case '~': r->rule_flags |= RULE_INVERSE; break; + case '4': + r->rule_flags |= RULE_IPV4; + break; + case '6': + r->rule_flags |= RULE_IPV6; + break; case 'G': case '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. */ 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) { 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) 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--) { syslog(LOG_WARNING, "remap: Breaking loop, input = %s, last = %s", input, diff --git a/tftpd/remap.h b/tftpd/remap.h index 69ca08d..7efcf6a 100644 --- a/tftpd/remap.h +++ b/tftpd/remap.h @@ -35,7 +35,7 @@ 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 *, char, +char *rewrite_string(const char *, const struct rule *, char, int, match_pattern_callback, const char **); #endif /* WITH_REGEX */ diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c index 1873e70..88d2812 100644 --- a/tftpd/tftpd.c +++ b/tftpd/tftpd.c @@ -1,7 +1,7 @@ /* * Copyright (c) 1983 Regents of the University of California. * 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. * * Redistribution and use in source and binary forms, with or without @@ -1039,18 +1039,18 @@ int main(int argc, char **argv) tp = (struct tftphdr *)buf; tp_opcode = ntohs(tp->th_opcode); if (tp_opcode == RRQ || tp_opcode == WRQ) - tftp(tp, n); + tftp(tp, n); 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 void tftp_sendfile(const struct formats *, struct tftphdr *, int); static void tftp_recvfile(const struct formats *, struct tftphdr *, int); struct formats { 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 **); void (*f_send) (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"); exit(0); } - if (!(filename = - (*pf->f_rewrite) (origfilename, tp_opcode, - &errmsgptr))) { + if (!(filename = (*pf->f_rewrite) + (origfilename, tp_opcode, from.sa.sa_family, &errmsgptr))) { nak(EACCESS, errmsgptr); /* File denied by mapping rule */ 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. */ -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) { char *newname = rewrite_string(filename, rewrite_rules, - mode != RRQ ? 'P' : 'G', + mode != RRQ ? 'P' : 'G', af, rewrite_macros, msg); filename = newname; } @@ -1411,10 +1411,11 @@ static char *rewrite_access(char *filename, int mode, const char **msg) } #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)msg; + (void)af; return filename; } #endif -- cgit v1.2.1