diff options
author | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2007-09-12 20:23:00 +0000 |
---|---|---|
committer | Hans-Joerg Hoexer <hshoexer@cvs.openbsd.org> | 2007-09-12 20:23:00 +0000 |
commit | 2dd5b05d4eb47692d49629a46c4865c6734ed0d2 (patch) | |
tree | 96bfed4add26d9ef643f7362005af032d9c178b5 | |
parent | c20005204aa187c2b5b0fecb07ba48166c363c5e (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@
-rw-r--r-- | sbin/ipsecctl/parse.y | 159 |
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; |