summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/ipf/ipf.h6
-rw-r--r--sbin/ipf/parse.c206
2 files changed, 146 insertions, 66 deletions
diff --git a/sbin/ipf/ipf.h b/sbin/ipf/ipf.h
index f4806ddaa9f..04705ab16ec 100644
--- a/sbin/ipf/ipf.h
+++ b/sbin/ipf/ipf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipf.h,v 1.9 1999/02/05 05:58:42 deraadt Exp $ */
+/* $OpenBSD: ipf.h,v 1.10 1999/07/05 20:12:43 kjell Exp $ */
/*
* Copyright (C) 1993-1998 by Darren Reed.
*
@@ -7,7 +7,7 @@
* to the original author and the contributors.
*
* @(#)ipf.h 1.12 6/5/96
- * $Id: ipf.h,v 1.9 1999/02/05 05:58:42 deraadt Exp $
+ * $Id: ipf.h,v 1.10 1999/07/05 20:12:43 kjell Exp $
*/
#ifndef __IPF_H__
@@ -53,7 +53,7 @@ extern struct frentry *parse __P((char *));
extern void printfr __P((struct frentry *));
extern void binprint __P((struct frentry *)), initparse __P((void));
-extern u_short portnum __P((char *));
+extern int portnum __P((char *, u_short *));
struct ipopt_names {
diff --git a/sbin/ipf/parse.c b/sbin/ipf/parse.c
index 2b39a865c0e..ba5f6a99277 100644
--- a/sbin/ipf/parse.c
+++ b/sbin/ipf/parse.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.c,v 1.24 1999/06/06 20:34:55 deraadt Exp $ */
+/* $OpenBSD: parse.c,v 1.25 1999/07/05 20:12:44 kjell Exp $ */
/*
* Copyright (C) 1993-1998 by Darren Reed.
*
@@ -30,23 +30,19 @@
#include <arpa/inet.h>
#include <resolv.h>
#include <ctype.h>
-#if defined(__OpenBSD__)
-# include <netinet/ip_fil_compat.h>
-#else
-# include <netinet/ip_compat.h>
-#endif
+#include <netinet/ip_fil_compat.h>
#include <netinet/ip_fil.h>
#include "ipf.h"
#if !defined(lint)
static const char sccsid[] ="@(#)parse.c 1.44 6/5/96 (C) 1993-1996 Darren Reed";
-static const char rcsid[] = "@(#)$Id: parse.c,v 1.24 1999/06/06 20:34:55 deraadt Exp $";
+static const char rcsid[] = "@(#)$Id: parse.c,v 1.25 1999/07/05 20:12:44 kjell Exp $";
#endif
extern struct ipopt_names ionames[], secclass[];
extern int opts;
-u_short portnum __P((char *));
+int portnum __P((char *, u_short *));
u_char tcp_flags __P((char *, u_char *));
int addicmp __P((char ***, struct frentry *));
int extras __P((char ***, struct frentry *));
@@ -64,6 +60,7 @@ void print_toif __P((char *, frdest_t *));
void optprint __P((u_short, u_short, u_long, u_long));
int countbits __P((u_32_t));
char *portname __P((int, int));
+int ratoi __P((char *, int *, int, int));
char *proto = NULL;
@@ -89,7 +86,7 @@ char *line;
{
static struct frentry fil;
struct protoent *p = NULL;
- char *cps[31], **cpp;
+ char *cps[31], **cpp, *endptr;
u_char ch;
int i, cnt = 1;
@@ -111,7 +108,7 @@ char *line;
cps[i] = NULL;
if (cnt < 3) {
- (void)fprintf(stderr,"not enough segments in line\n");
+ (void)fprintf(stderr, "not enough segments in line\n");
return NULL;
}
@@ -129,7 +126,7 @@ char *line;
i = icmpcode(*cpp + 12);
if (i == -1) {
fprintf(stderr,
- "uncrecognised icmp code %s\n",
+ "unrecognised icmp code %s\n",
*cpp + 12);
return NULL;
}
@@ -149,11 +146,12 @@ char *line;
fil.fr_flags |= FR_PREAUTH;
} else if (!strcasecmp("skip", *cpp)) {
cpp++;
- if (!isdigit(**cpp)) {
+ if (ratoi(*cpp, &i, 0, INT_MAX))
+ fil.fr_skip = i;
+ else {
(void)fprintf(stderr, "integer must follow skip\n");
return NULL;
}
- fil.fr_skip = atoi(*cpp);
} else if (!strcasecmp("log", *cpp)) {
fil.fr_flags |= FR_LOG;
if (!strcasecmp(*(cpp+1), "body")) {
@@ -276,7 +274,12 @@ char *line;
(void)fprintf(stderr, "ttl missing hopcount value\n");
return NULL;
}
- fil.fr_ttl = atoi(*cpp);
+ if (ratoi(*cpp, &i, 0, 255))
+ fil.fr_ttl = i;
+ else {
+ (void)fprintf(stderr, "invalid ttl (%s)\n", *cpp);
+ return NULL;
+ }
fil.fr_mip.fi_ttl = 0xff;
cpp++;
}
@@ -301,8 +304,15 @@ char *line;
}
if (p)
fil.fr_proto = p->p_proto;
- else if (isdigit(**cpp))
- fil.fr_proto = atoi(*cpp);
+ else if (isdigit(**cpp)) {
+ i = (int)strtol(*cpp, &endptr, 0);
+ if (*endptr != '\0' || i < 0 || i > 255) {
+ (void)fprintf(stderr,
+ "unknown protocol (%s)\n", *cpp);
+ return NULL;
+ }
+ fil.fr_proto = i;
+ }
fil.fr_mip.fi_p = 0xff;
}
proto = *cpp;
@@ -351,7 +361,6 @@ char *line;
if (hostmask(&cpp, (u_32_t *)&fil.fr_src,
(u_32_t *)&fil.fr_smsk, &fil.fr_sport, &ch,
&fil.fr_stop)) {
- (void)fprintf(stderr, "bad host (%s)\n", *cpp);
return NULL;
}
fil.fr_scmp = ch;
@@ -380,7 +389,6 @@ char *line;
if (hostmask(&cpp, (u_32_t *)&fil.fr_dst,
(u_32_t *)&fil.fr_dmsk, &fil.fr_dport, &ch,
&fil.fr_dtop)) {
- (void)fprintf(stderr, "bad host (%s)\n", *cpp);
return NULL;
}
fil.fr_dcmp = ch;
@@ -450,7 +458,12 @@ char *line;
(void)fprintf(stderr, "head without group #\n");
return NULL;
}
- fil.fr_grhead = atoi(*cpp);
+ if (ratoi(*cpp, &i, 0, USHRT_MAX))
+ fil.fr_grhead = i;
+ else {
+ (void)fprintf(stderr, "invalid group (%s)\n", *cpp);
+ return NULL;
+ }
cpp++;
}
@@ -462,7 +475,12 @@ char *line;
(void)fprintf(stderr, "group without group #\n");
return NULL;
}
- fil.fr_group = atoi(*cpp);
+ if (ratoi(*cpp, &i, 0, USHRT_MAX))
+ fil.fr_group = i;
+ else {
+ (void)fprintf(stderr, "invalid group (%s)\n", *cpp);
+ return NULL;
+ }
cpp++;
}
@@ -541,8 +559,9 @@ frdest_t *fdp;
/*
- * returns false if neither "hostmask/num" or "hostmask mask addr" are
- * found in the line segments
+ * returns -1 if neither "hostmask/num" or "hostmask mask addr" are
+ * found in the line segments, there is an error processing this information,
+ * or there is an error processing ports information.
*/
int hostmask(seg, sa, msk, pp, cp, tp)
char ***seg;
@@ -550,34 +569,44 @@ u_32_t *sa, *msk;
u_short *pp, *tp;
u_char *cp;
{
- char *s;
+ char *s, *endptr;
int bits = -1, resolved;
+ struct in_addr maskaddr;
/*
* is it possibly hostname/num ?
*/
if ((s = index(**seg, '/')) || (s = index(**seg, ':'))) {
*s++ = '\0';
- if (!isdigit(*s))
- return -1;
- if (index(s, '.'))
- *msk = inet_addr(s);
- if (!index(s, '.') && !index(s, 'x')) {
+ if (index(s, '.') || index(s, 'x')) {
+ /*
+ * Netmask possibly of the form xxx.xxx.xxx.xxx
+ * or 0xYYYYYYYY
+ */
+ if (inet_aton(s, &maskaddr) == 0) {
+ (void)fprintf(stderr, "bad mask (%s)\n", s);
+ return -1;
+ }
+ *msk = maskaddr.s_addr;
+ } else {
/*
* set x most significant bits
*/
- for (bits = atoi(s); bits; bits--) {
- *msk /= 2;
- *msk |= ntohl(inet_addr("128.0.0.0"));
- }
- *msk = htonl(*msk);
- } else {
- if (inet_aton(s, (struct in_addr *)msk) == -1)
+ bits = (int)strtol(s, &endptr, 0);
+ if (*endptr != '\0' || bits > 32 || bits < 0) {
+ (void)fprintf(stderr, "bad mask (/%s)\n", s);
return -1;
+ }
+ if (bits == 0)
+ *msk = 0;
+ else
+ *msk = htonl(0xffffffff << (32 - bits));
}
*sa = hostnum(**seg, &resolved) & *msk;
- if (resolved == -1)
+ if (resolved == -1) {
+ (void)fprintf(stderr, "bad host (%s)\n", **seg);
return -1;
+ }
(*seg)++;
return ports(seg, pp, cp, tp);
}
@@ -587,12 +616,17 @@ u_char *cp;
*/
if (*(*seg+1) && *(*seg+2) && !strcasecmp(*(*seg+1), "mask")) {
*sa = hostnum(**seg, &resolved);
- if (resolved == -1)
+ if (resolved == -1) {
+ (void)fprintf(stderr, "bad host (%s)\n", **seg);
return -1;
+ }
(*seg)++;
(*seg)++;
- if (inet_aton(**seg, (struct in_addr *)msk) == -1)
+ if (inet_aton(**seg, &maskaddr) == 0) {
+ (void)fprintf(stderr, "bad mask (%s)\n", **seg);
return -1;
+ }
+ *msk = maskaddr.s_addr;
(*seg)++;
*sa &= *msk;
return ports(seg, pp, cp, tp);
@@ -600,13 +634,16 @@ u_char *cp;
if (**seg) {
*sa = hostnum(**seg, &resolved);
- if (resolved == -1)
+ if (resolved == -1) {
+ (void)fprintf(stderr, "bad host (%s)\n", **seg);
return -1;
+ }
(*seg)++;
*msk = (*sa ? inet_addr("255.255.255.255") : 0L);
*sa &= *msk;
return ports(seg, pp, cp, tp);
}
+ (void)fprintf(stderr, "bad host (%s)\n", **seg);
return -1;
}
@@ -623,7 +660,7 @@ int *resolved;
struct in_addr addr;
*resolved = 0;
- if (!strcasecmp("any",host))
+ if (!strcasecmp("any", host))
return 0L;
if (inet_aton(host, &addr))
return addr.s_addr;
@@ -656,19 +693,25 @@ u_char *cp;
if (!strcasecmp(**seg, "port") && *(*seg + 1) && *(*seg + 2)) {
(*seg)++;
if (isdigit(***seg) && *(*seg + 2)) {
- *pp = portnum(**seg);
+ if (portnum(**seg, pp) == 0)
+ return -1;
(*seg)++;
if (!strcmp(**seg, "<>"))
comp = FR_OUTRANGE;
else if (!strcmp(**seg, "><"))
comp = FR_INRANGE;
else {
- fprintf(stderr,"unknown range operator (%s)\n",
- **seg);
+ fprintf(stderr, "unknown range operator (%s)\n",
+ **seg);
return -1;
}
(*seg)++;
- *tp = portnum(**seg);
+ if (**seg == NULL) {
+ fprintf(stderr, "missing 2nd port value\n");
+ return -1;
+ }
+ if (portnum(**seg, tp) == 0)
+ return -1;
} else if (!strcmp(**seg, "=") || !strcasecmp(**seg, "eq"))
comp = FR_EQUAL;
else if (!strcmp(**seg, "!=") || !strcasecmp(**seg, "ne"))
@@ -682,13 +725,14 @@ u_char *cp;
else if (!strcmp(**seg, ">=") || !strcasecmp(**seg, "ge"))
comp = FR_GREATERTE;
else {
- (void)fprintf(stderr,"unknown comparator (%s)\n",
+ (void)fprintf(stderr, "unknown comparator (%s)\n",
**seg);
return -1;
}
if (comp != FR_OUTRANGE && comp != FR_INRANGE) {
(*seg)++;
- *pp = portnum(**seg);
+ if (portnum(**seg, pp) == 0)
+ return -1;
}
*cp = comp;
(*seg)++;
@@ -698,27 +742,34 @@ u_char *cp;
/*
* find the port number given by the name, either from getservbyname() or
- * straight atoi()
+ * straight atoi(). Return 1 on success, 0 on failure
*/
-u_short portnum(name)
+int portnum(name, port)
char *name;
+u_short *port;
{
struct servent *sp, *sp2;
u_short p1 = 0;
-
- if (isdigit(*name))
- return (u_short)atoi(name);
- if (!proto)
- proto = "tcp/udp";
- if (strcasecmp(proto, "tcp/udp")) {
+ int i;
+ if (isdigit(*name)) {
+ if (ratoi(name, &i, 0, USHRT_MAX)) {
+ *port = (u_short)i;
+ return 1;
+ }
+ (void)fprintf(stderr, "unknown port \"%s\"\n", name);
+ return 0;
+ }
+ if (proto != NULL && strcasecmp(proto, "tcp/udp") != 0) {
sp = getservbyname(name, proto);
- if (sp)
- return ntohs(sp->s_port);
+ if (sp) {
+ *port = ntohs(sp->s_port);
+ return 1;
+ }
(void) fprintf(stderr, "unknown service \"%s\".\n", name);
return 0;
}
sp = getservbyname(name, "tcp");
- if (sp)
+ if (sp)
p1 = sp->s_port;
sp2 = getservbyname(name, "udp");
if (!sp || !sp2) {
@@ -732,7 +783,8 @@ char *name;
(void) fprintf(stderr, "%s %d/udp\n", name, sp->s_port);
return 0;
}
- return ntohs(p1);
+ *port = ntohs(p1);
+ return 1;
}
@@ -999,7 +1051,11 @@ struct frentry *fp;
if (!fp->fr_proto) /* to catch lusers */
fp->fr_proto = IPPROTO_ICMP;
if (isdigit(***cp)) {
- i = atoi(**cp);
+ if (!ratoi(**cp, &i, 0, 255)) {
+ (void)fprintf(stderr,
+ "Invalid icmp-type (%s) specified\n", **cp);
+ return -1;
+ }
} else {
for (t = icmptypes, i = 0; ; t++, i++) {
if (!*t)
@@ -1027,12 +1083,17 @@ struct frentry *fp;
return 0;
(*cp)++;
if (isdigit(***cp)) {
- i = atoi(**cp);
+ if (!ratoi(**cp, &i, 0, 255)) {
+ (void)fprintf(stderr,
+ "Invalid icmp code (%s) specified\n", **cp);
+ return -1;
+ }
fp->fr_icmp |= (u_short)i;
fp->fr_icmpm = (u_short)0xffff;
(*cp)++;
return 0;
}
+ (void)fprintf(stderr, "Invalid icmp code (%s) specified\n", **cp);
return -1;
}
@@ -1055,8 +1116,12 @@ char *str;
if (!(s = strrchr(str, ')')))
return -1;
*s = '\0';
- if (isdigit(*str))
- return atoi(str);
+ if (isdigit(*str)) {
+ if (!ratoi(str, &i, 0, 255))
+ return -1;
+ else
+ return i;
+ }
len = strlen(str);
for (i = 0; icmpcodes[i]; i++)
if (!strncasecmp(str, icmpcodes[i], MIN(len,
@@ -1349,7 +1414,7 @@ struct frentry *fp;
for (s = (u_char *)fp; i; i--, s++) {
j++;
- (void)printf("%02x ",*s);
+ (void)printf("%02x ", *s);
if (j == 16) {
(void)printf("\n");
j = 0;
@@ -1358,3 +1423,18 @@ struct frentry *fp;
putchar('\n');
(void)fflush(stdout);
}
+
+
+int ratoi(ps, pi, min, max)
+char *ps;
+int *pi, min, max;
+{
+ int i;
+ char *pe;
+
+ i = (int)strtol(ps, &pe, 0);
+ if (*pe != '\0' || i < min || i > max)
+ return 0;
+ *pi = i;
+ return 1;
+}