summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorHans-Joerg Hoexer <hshoexer@cvs.openbsd.org>2007-09-12 20:23:00 +0000
committerHans-Joerg Hoexer <hshoexer@cvs.openbsd.org>2007-09-12 20:23:00 +0000
commit2dd5b05d4eb47692d49629a46c4865c6734ed0d2 (patch)
tree96bfed4add26d9ef643f7362005af032d9c178b5 /sbin
parentc20005204aa187c2b5b0fecb07ba48166c363c5e (diff)
Here too: Add support to the lex for parsing number out of the stream.
handle this in the parser. better range checks. with and ok deraadt@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/ipsecctl/parse.y159
1 files changed, 100 insertions, 59 deletions
diff --git a/sbin/ipsecctl/parse.y b/sbin/ipsecctl/parse.y
index a0933976947..7960c1b6c9e 100644
--- a/sbin/ipsecctl/parse.y
+++ b/sbin/ipsecctl/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.125 2007/08/10 12:32:12 markus Exp $ */
+/* $OpenBSD: parse.y,v 1.126 2007/09/12 20:22:59 hshoexer Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -187,7 +187,7 @@ struct ipsec_transforms *ipsec_transforms;
typedef struct {
union {
- u_int32_t number;
+ int64_t number;
u_int8_t ikemode;
u_int8_t dir;
u_int8_t satype; /* encapsulating prococol */
@@ -236,14 +236,16 @@ typedef struct {
%token PASSIVE ACTIVE ANY IPIP IPCOMP COMPXF TUNNEL TRANSPORT DYNAMIC LIFE
%token TYPE DENY BYPASS LOCAL PROTO USE ACQUIRE REQUIRE DONTACQ GROUP PORT TAG
%token <v.string> STRING
+%token <v.number> NUMBER
%type <v.string> string
%type <v.dir> dir
%type <v.satype> satype
%type <v.proto> proto
+%type <v.number> protoval
%type <v.tmode> tmode
-%type <v.number> number
%type <v.hosts> hosts
%type <v.port> port
+%type <v.number> portval
%type <v.peers> peers
%type <v.singlehost> singlehost
%type <v.host> host host_list
@@ -272,24 +274,6 @@ grammar : /* empty */
| grammar error '\n' { errors++; }
;
-number : STRING {
- unsigned long ulval;
-
- if (atoul($1, &ulval) == -1) {
- yyerror("%s is not a number", $1);
- free($1);
- YYERROR;
- }
- if (ulval > UINT_MAX) {
- yyerror("0x%lx out of range", ulval);
- free($1);
- YYERROR;
- }
- $$ = (u_int32_t)ulval;
- free($1);
- }
- ;
-
comma : ','
| /* empty */
;
@@ -356,24 +340,28 @@ satype : /* empty */ { $$ = IPSEC_ESP; }
;
proto : /* empty */ { $$ = 0; }
- | PROTO STRING {
+ | PROTO protoval { $$ = $2; }
+ | PROTO ESP { $$ = IPPROTO_ESP; }
+ | PROTO AH { $$ = IPPROTO_AH; }
+ ;
+
+protoval : STRING {
struct protoent *p;
- const char *errstr;
- int proto;
- if ((p = getprotobyname($2)) != NULL) {
- $$ = p->p_proto;
- } else {
- errstr = NULL;
- proto = strtonum($2, 0, 255, &errstr);
- if (errstr)
- errx(1, "unknown protocol: %s", $2);
- $$ = proto;
+ p = getprotobyname($1);
+ if (p == NULL) {
+ yyerror("unknown protocol: %s", $1);
+ YYERROR;
+ }
+ $$ = p->p_proto;
+ free($1);
+ }
+ | NUMBER {
+ if ($1 > 255 || $1 < 0) {
+ yyerror("protocol outside range");
+ YYERROR;
}
-
}
- | PROTO ESP { $$ = IPPROTO_ESP; }
- | PROTO AH { $$ = IPPROTO_AH; }
;
tmode : /* empty */ { $$ = IPSEC_TUNNEL; }
@@ -401,23 +389,26 @@ hosts : FROM host port TO host port {
;
port : /* empty */ { $$ = 0; }
- | PORT STRING {
+ | PORT portval { $$ = $2; }
+ ;
+
+portval : STRING {
struct servent *s;
- const char *errstr;
- int port;
- if ((s = getservbyname($2, "tcp")) != NULL ||
- (s = getservbyname($2, "udp")) != NULL) {
+ if ((s = getservbyname($1, "tcp")) != NULL ||
+ (s = getservbyname($1, "udp")) != NULL) {
$$ = s->s_port;
} else {
- errstr = NULL;
- port = strtonum($2, 0, USHRT_MAX, &errstr);
- if (errstr) {
- yyerror("unknown port: %s", $2);
- YYERROR;
- }
- $$ = htons(port);
+ yyerror("unknown port: %s", $1);
+ YYERROR;
+ }
+ }
+ | NUMBER {
+ if ($1 > USHRT_MAX || $1 < 0) {
+ yyerror("port outside range");
+ YYERROR;
}
+ $$ = htons($1);
}
;
@@ -476,10 +467,10 @@ host : STRING {
}
free($1);
}
- | STRING '/' number {
+ | STRING '/' NUMBER {
char *buf;
- if (asprintf(&buf, "%s/%u", $1, $3) == -1)
+ if (asprintf(&buf, "%s/%lld", $1, $3) == -1)
err(1, "host: asprintf");
free($1);
if (($$ = host(buf)) == NULL) {
@@ -555,7 +546,6 @@ spispec : SPI STRING {
*p++ = 0;
if (atospi(p, &spi) == -1) {
- yyerror("%s is not a valid spi", p);
free($2);
YYERROR;
}
@@ -564,7 +554,6 @@ spispec : SPI STRING {
$$.spiin = 0;
if (atospi($2, &spi) == -1) {
- yyerror("%s is not a valid spi", $2);
free($2);
YYERROR;
}
@@ -573,6 +562,19 @@ spispec : SPI STRING {
free($2);
}
+ | SPI NUMBER {
+ if ($2 > UINT_MAX || $2 < 0) {
+ yyerror("%lld not a valid spi", $2);
+ YYERROR;
+ }
+ if ($2 >= SPI_RESERVED_MIN && $2 <= SPI_RESERVED_MAX) {
+ yyerror("%lld within reserved spi range", $2);
+ YYERROR;
+ }
+
+ $$.spiin = 0;
+ $$.spiout = $2;
+ }
;
transforms : {
@@ -697,13 +699,12 @@ life : /* empty */ {
life->lifevolume = -1;
$$ = life;
}
- | LIFE number {
- struct ipsec_life *life;
-
- life = parse_life($2);
- if (life == NULL)
- yyerror("%s not a valid lifetime", $2);
- $$ = life;
+ | LIFE NUMBER {
+ if ($2 > INT_MAX || $2 < 0) {
+ yyerror("%lld not a valid lifetime", $2);
+ YYERROR;
+ }
+ $$ = parse_life($2);
}
;
@@ -1061,6 +1062,42 @@ top:
return (STRING);
}
+#define allowed_to_end_number(x) \
+ (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}')
+
+ if (c == '-' || isdigit(c)) {
+ do {
+ *p++ = c;
+ if ((unsigned)(p-buf) >= sizeof(buf)) {
+ yyerror("string too long");
+ return (findeol());
+ }
+ } while ((c = lgetc(fin)) != EOF && isdigit(c));
+ lungetc(c);
+ if (p == buf + 1 && buf[0] == '-')
+ goto nodigits;
+ if (c == EOF || allowed_to_end_number(c)) {
+ const char *errstr = NULL;
+
+ *p = '\0';
+ yylval.v.number = strtonum(buf, LLONG_MIN,
+ LLONG_MAX, &errstr);
+ if (errstr) {
+ yyerror("\"%s\" invalid number: %s",
+ buf, errstr);
+ return (findeol());
+ }
+ return (NUMBER);
+ } else {
+nodigits:
+ while (p > buf + 1)
+ lungetc(*--p);
+ c = *--p;
+ if (c == '-')
+ return (c);
+ }
+ }
+
#define allowed_in_string(x) \
(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
x != '{' && x != '}' && x != '<' && x != '>' && \
@@ -1214,8 +1251,12 @@ atospi(char *s, u_int32_t *spivalp)
if (atoul(s, &ulval) == -1)
return (-1);
+ if (ulval > UINT_MAX) {
+ yyerror("%lld not a valid spi", ulval);
+ return (-1);
+ }
if (ulval >= SPI_RESERVED_MIN && ulval <= SPI_RESERVED_MAX) {
- yyerror("illegal SPI value");
+ yyerror("%lld within reserved spi range", ulval);
return (-1);
}
*spivalp = ulval;