parse.y revision 1.37
1/* $OpenBSD: parse.y,v 1.37 2005/11/12 17:04:32 deraadt Exp $ */ 2 3/* 4 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> 5 * Copyright (c) 2001 Markus Friedl. All rights reserved. 6 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 7 * Copyright (c) 2001 Theo de Raadt. All rights reserved. 8 * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org> 9 * 10 * Permission to use, copy, modify, and distribute this software for any 11 * purpose with or without fee is hereby granted, provided that the above 12 * copyright notice and this permission notice appear in all copies. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 20 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23%{ 24#include <sys/types.h> 25#include <sys/queue.h> 26#include <sys/socket.h> 27#include <sys/stat.h> 28#include <netinet/in.h> 29#include <netinet/ip_ipsp.h> 30#include <arpa/inet.h> 31 32#include <ctype.h> 33#include <err.h> 34#include <errno.h> 35#include <fcntl.h> 36#include <limits.h> 37#include <stdarg.h> 38#include <stdio.h> 39#include <string.h> 40#include <syslog.h> 41#include <unistd.h> 42 43#include "ipsecctl.h" 44 45#define KEYSIZE_LIMIT 1024 46 47static struct ipsecctl *ipsec = NULL; 48static FILE *fin = NULL; 49static int lineno = 1; 50static int errors = 0; 51static int debug = 0; 52 53const struct ipsec_xf authxfs[] = { 54 { "unknown", AUTHXF_UNKNOWN, 0, 0 }, 55 { "none", AUTHXF_NONE, 0, 0 }, 56 { "hmac-md5", AUTHXF_HMAC_MD5, 16, 0 }, 57 { "hmac-ripemd160", AUTHXF_HMAC_RIPEMD160, 20, 0 }, 58 { "hmac-sha1", AUTHXF_HMAC_SHA1, 20, 0 }, 59 { "hmac-sha2-256", AUTHXF_HMAC_SHA2_256, 32, 0 }, 60 { "hmac-sha2-384", AUTHXF_HMAC_SHA2_384, 48, 0 }, 61 { "hmac-sha2-512", AUTHXF_HMAC_SHA2_512, 64, 0 }, 62 { "md5", AUTHXF_MD5, 16, 0 }, 63 { "sha1", AUTHXF_SHA1, 20, 0 }, 64 { NULL, 0, 0, 0 }, 65}; 66 67const struct ipsec_xf encxfs[] = { 68 { "unknown", ENCXF_UNKNOWN, 0, 0 }, 69 { "none", ENCXF_NONE, 0, 0 }, 70 { "3des-cbc", ENCXF_3DES_CBC, 24, 24 }, 71 { "des-cbc", ENCXF_DES_CBC, 8, 8 }, 72 { "aes", ENCXF_AES, 16, 32 }, 73 { "aesctr", ENCXF_AESCTR, 16+4, 32+4 }, 74 { "blowfish", ENCXF_BLOWFISH, 5, 56 }, 75 { "cast128", ENCXF_CAST128, 5, 16 }, 76 { "null", ENCXF_NULL, 0, 0 }, 77 { "skipjack", ENCXF_SKIPJACK, 10, 10 }, 78 { NULL, 0, 0, 0 }, 79}; 80 81const struct ipsec_xf compxfs[] = { 82 { "unknown", COMPXF_UNKNOWN, 0, 0 }, 83 { "deflate", COMPXF_DEFLATE, 0, 0 }, 84 { "lzs", COMPXF_LZS, 0, 0 }, 85 { NULL, 0, 0, 0 }, 86}; 87 88int yyerror(const char *, ...); 89int yyparse(void); 90int kw_cmp(const void *, const void *); 91int lookup(char *); 92int lgetc(FILE *); 93int lungetc(int); 94int findeol(void); 95int yylex(void); 96 97TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 98struct sym { 99 TAILQ_ENTRY(sym) entries; 100 int used; 101 int persist; 102 char *nam; 103 char *val; 104}; 105 106int symset(const char *, const char *, int); 107int cmdline_symset(char *); 108char *symget(const char *); 109int atoul(char *, u_long *); 110int atospi(char *, u_int32_t *); 111u_int8_t x2i(unsigned char *); 112struct ipsec_key *parsekey(unsigned char *, size_t); 113struct ipsec_key *parsekeyfile(char *); 114struct ipsec_addr_wrap *host(const char *); 115struct ipsec_addr_wrap *host_v4(const char *, int); 116void set_ipmask(struct ipsec_addr_wrap *, u_int8_t); 117struct ipsec_addr_wrap *copyhost(const struct ipsec_addr_wrap *); 118const struct ipsec_xf *parse_xf(const char *, const struct ipsec_xf *); 119struct ipsec_transforms *transforms(const char *, const char *, const char *); 120struct ipsec_transforms *copytransforms(const struct ipsec_transforms *); 121int validate_sa(u_int32_t, u_int8_t, 122 struct ipsec_transforms *, struct ipsec_key *, 123 struct ipsec_key *, u_int8_t); 124struct ipsec_rule *create_sa(u_int8_t, u_int8_t, struct ipsec_addr_wrap *, 125 struct ipsec_addr_wrap *, u_int32_t, 126 struct ipsec_transforms *, struct ipsec_key *, 127 struct ipsec_key *); 128struct ipsec_rule *reverse_sa(struct ipsec_rule *, u_int32_t, 129 struct ipsec_key *, struct ipsec_key *); 130struct ipsec_rule *create_flow(u_int8_t, struct ipsec_addr_wrap *, struct 131 ipsec_addr_wrap *, struct ipsec_addr_wrap *, 132 u_int8_t, char *, char *, u_int16_t); 133struct ipsec_rule *reverse_rule(struct ipsec_rule *); 134struct ipsec_rule *create_ike(struct ipsec_addr_wrap *, struct 135 ipsec_addr_wrap *, struct ipsec_addr_wrap *, 136 struct ipsec_transforms *, struct 137 ipsec_transforms *, u_int8_t, u_int8_t, char *, 138 char *); 139 140typedef struct { 141 union { 142 u_int32_t number; 143 u_int8_t ikemode; 144 u_int8_t dir; 145 u_int8_t protocol; 146 u_int8_t tmode; 147 char *string; 148 struct { 149 struct ipsec_addr_wrap *src; 150 struct ipsec_addr_wrap *dst; 151 } hosts; 152 struct ipsec_addr_wrap *peer; 153 struct ipsec_addr_wrap *host; 154 struct { 155 char *srcid; 156 char *dstid; 157 } ids; 158 char *id; 159 u_int16_t authtype; 160 struct { 161 u_int32_t spiout; 162 u_int32_t spiin; 163 } spis; 164 struct { 165 struct ipsec_key *keyout; 166 struct ipsec_key *keyin; 167 } authkeys; 168 struct { 169 struct ipsec_key *keyout; 170 struct ipsec_key *keyin; 171 } enckeys; 172 struct { 173 struct ipsec_key *keyout; 174 struct ipsec_key *keyin; 175 } keys; 176 struct ipsec_transforms *transforms; 177 struct ipsec_transforms *mmxfs; 178 struct ipsec_transforms *qmxfs; 179 } v; 180 int lineno; 181} YYSTYPE; 182 183%} 184 185%token FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI 186%token AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK PASSIVE 187%token ACTIVE ANY IPCOMP COMPXF TUNNEL TRANSPORT 188%token <v.string> STRING 189%type <v.dir> dir 190%type <v.protocol> protocol 191%type <v.tmode> tmode 192%type <v.number> number 193%type <v.hosts> hosts 194%type <v.peer> peer 195%type <v.host> host 196%type <v.ids> ids 197%type <v.id> id 198%type <v.authtype> authtype 199%type <v.spis> spispec 200%type <v.authkeys> authkeyspec 201%type <v.enckeys> enckeyspec 202%type <v.keys> keyspec 203%type <v.transforms> transforms 204%type <v.mmxfs> mmxfs 205%type <v.qmxfs> qmxfs 206%type <v.ikemode> ikemode 207%% 208 209grammar : /* empty */ 210 | grammar '\n' 211 | grammar ikerule '\n' 212 | grammar flowrule '\n' 213 | grammar sarule '\n' 214 | grammar tcpmd5rule '\n' 215 | grammar error '\n' { errors++; } 216 ; 217 218number : STRING { 219 unsigned long ulval; 220 221 if (atoul($1, &ulval) == -1) { 222 yyerror("%s is not a number", $1); 223 free($1); 224 YYERROR; 225 } 226 if (ulval > UINT_MAX) { 227 yyerror("0x%lx out of range", ulval); 228 free($1); 229 YYERROR; 230 } 231 $$ = (u_int32_t)ulval; 232 free($1); 233 } 234 ; 235 236tcpmd5rule : TCPMD5 hosts spispec authkeyspec { 237 struct ipsec_rule *r; 238 239 r = create_sa(IPSEC_TCPMD5, IPSEC_TRANSPORT, $2.src, 240 $2.dst, $3.spiout, NULL, $4.keyout, NULL); 241 if (r == NULL) 242 YYERROR; 243 r->nr = ipsec->rule_nr++; 244 245 if (ipsecctl_add_rule(ipsec, r)) 246 errx(1, "tcpmd5rule: ipsecctl_add_rule"); 247 248 /* Create and add reverse SA rule. */ 249 if ($3.spiin != 0 || $4.keyin != NULL) { 250 r = reverse_sa(r, $3.spiin, $4.keyin, NULL); 251 if (r == NULL) 252 YYERROR; 253 r->nr = ipsec->rule_nr++; 254 255 if (ipsecctl_add_rule(ipsec, r)) 256 errx(1, "tcpmd5rule: ipsecctl_add_rule"); 257 } 258 } 259 ; 260 261sarule : protocol tmode hosts spispec transforms authkeyspec 262 enckeyspec { 263 struct ipsec_rule *r; 264 265 r = create_sa($1, $2, $3.src, $3.dst, $4.spiout, $5, 266 $6.keyout, $7.keyout); 267 if (r == NULL) 268 YYERROR; 269 r->nr = ipsec->rule_nr++; 270 271 if (ipsecctl_add_rule(ipsec, r)) 272 errx(1, "sarule: ipsecctl_add_rule"); 273 274 /* Create and add reverse SA rule. */ 275 if ($4.spiin != 0 || $6.keyin || $7.keyin) { 276 r = reverse_sa(r, $4.spiin, $6.keyin, 277 $7.keyin); 278 if (r == NULL) 279 YYERROR; 280 r->nr = ipsec->rule_nr++; 281 282 if (ipsecctl_add_rule(ipsec, r)) 283 errx(1, "sarule: ipsecctl_add_rule"); 284 } 285 } 286 ; 287 288flowrule : FLOW protocol dir hosts peer ids authtype { 289 struct ipsec_rule *r; 290 291 r = create_flow($3, $4.src, $4.dst, $5, $2, $6.srcid, 292 $6.dstid, $7); 293 if (r == NULL) 294 YYERROR; 295 r->nr = ipsec->rule_nr++; 296 297 if (ipsecctl_add_rule(ipsec, r)) 298 errx(1, "flowrule: ipsecctl_add_rule"); 299 300 /* Create and add reverse flow rule. */ 301 if ($3 == IPSEC_INOUT) { 302 r = reverse_rule(r); 303 r->nr = ipsec->rule_nr++; 304 305 if (ipsecctl_add_rule(ipsec, r)) 306 errx(1, "flowrule: ipsecctl_add_rule"); 307 } 308 } 309 ; 310 311ikerule : IKE ikemode protocol hosts peer mmxfs qmxfs ids { 312 struct ipsec_rule *r; 313 314 r = create_ike($4.src, $4.dst, $5, $6, $7, $3, $2, 315 $8.srcid, $8.dstid); 316 if (r == NULL) 317 YYERROR; 318 r->nr = ipsec->rule_nr++; 319 320 if (ipsecctl_add_rule(ipsec, r)) 321 errx(1, "ikerule: ipsecctl_add_rule"); 322 } 323 ; 324 325protocol : /* empty */ { $$ = IPSEC_ESP; } 326 | ESP { $$ = IPSEC_ESP; } 327 | AH { $$ = IPSEC_AH; } 328 | IPCOMP { $$ = IPSEC_IPCOMP; } 329 ; 330 331tmode : /* empty */ { $$ = IPSEC_TUNNEL; } 332 | TUNNEL { $$ = IPSEC_TUNNEL; } 333 | TRANSPORT { $$ = IPSEC_TRANSPORT; } 334 ; 335 336dir : /* empty */ { $$ = IPSEC_INOUT; } 337 | IN { $$ = IPSEC_IN; } 338 | OUT { $$ = IPSEC_OUT; } 339 ; 340 341hosts : FROM host TO host { 342 $$.src = $2; 343 $$.dst = $4; 344 } 345 ; 346 347peer : /* empty */ { $$ = NULL; } 348 | PEER STRING { 349 if (($$ = host($2)) == NULL) { 350 free($2); 351 yyerror("could not parse host specification"); 352 YYERROR; 353 } 354 free($2); 355 } 356 ; 357 358host : STRING { 359 if (($$ = host($1)) == NULL) { 360 free($1); 361 yyerror("could not parse host specification"); 362 YYERROR; 363 } 364 free($1); 365 } 366 | STRING '/' number { 367 char *buf; 368 369 if (asprintf(&buf, "%s/%u", $1, $3) == -1) 370 err(1, "host: asprintf"); 371 free($1); 372 if (($$ = host(buf)) == NULL) { 373 free(buf); 374 yyerror("could not parse host specification"); 375 YYERROR; 376 } 377 free(buf); 378 } 379 | ANY { 380 struct ipsec_addr_wrap *ipa; 381 382 ipa = calloc(1, sizeof(struct ipsec_addr_wrap)); 383 if (ipa == NULL) 384 err(1, "host: calloc"); 385 386 ipa->af = AF_INET; 387 ipa->netaddress = 1; 388 if ((ipa->name = strdup("0.0.0.0/0")) == NULL) 389 err(1, "host: strdup"); 390 $$ = ipa; 391 } 392 ; 393 394ids : /* empty */ { 395 $$.srcid = NULL; 396 $$.dstid = NULL; 397 } 398 | SRCID id DSTID id { 399 $$.srcid = $2; 400 $$.dstid = $4; 401 } 402 | SRCID id { 403 $$.srcid = $2; 404 $$.dstid = NULL; 405 } 406 | DSTID id { 407 $$.srcid = NULL; 408 $$.dstid = $2; 409 } 410 ; 411 412id : STRING { $$ = $1; } 413 ; 414 415authtype : /* empty */ { $$ = 0; } 416 | RSA { $$ = AUTH_RSA; } 417 | PSK { $$ = AUTH_PSK; } 418 ; 419 420spispec : SPI STRING { 421 u_int32_t spi; 422 char *p = strchr($2, ':'); 423 424 if (p != NULL) { 425 *p++ = 0; 426 427 if (atospi(p, &spi) == -1) { 428 yyerror("%s is not a valid spi", p); 429 free($2); 430 YYERROR; 431 } 432 $$.spiin = spi; 433 } 434 if (atospi($2, &spi) == -1) { 435 yyerror("%s is not a valid spi", $2); 436 free($2); 437 YYERROR; 438 } 439 $$.spiout = spi; 440 441 442 free($2); 443 } 444 ; 445 446transforms : /* empty */ { 447 struct ipsec_transforms *xfs; 448 449 /* We create just an empty transform */ 450 if ((xfs = calloc(1, sizeof(struct ipsec_transforms))) 451 == NULL) 452 err(1, "transforms: calloc"); 453 $$ = xfs; 454 } 455 | AUTHXF STRING ENCXF STRING { 456 if (($$ = transforms($2, $4, NULL)) == NULL) { 457 free($2); 458 free($4); 459 yyerror("could not parse transforms"); 460 YYERROR; 461 } 462 free($2); 463 free($4); 464 } 465 | AUTHXF STRING { 466 if (($$ = transforms($2, NULL, NULL)) == NULL) { 467 free($2); 468 yyerror("could not parse transforms"); 469 YYERROR; 470 } 471 free($2); 472 } 473 | ENCXF STRING { 474 if (($$ = transforms(NULL, $2, NULL)) == NULL) { 475 free($2); 476 yyerror("could not parse transforms"); 477 YYERROR; 478 } 479 free($2); 480 } 481 | COMPXF STRING { 482 if (($$ = transforms(NULL, NULL, $2)) == NULL) { 483 free($2); 484 yyerror("could not parse transforms"); 485 YYERROR; 486 } 487 free($2); 488 } 489 ; 490 491mmxfs : /* empty */ { 492 struct ipsec_transforms *xfs; 493 494 /* We create just an empty transform */ 495 if ((xfs = calloc(1, sizeof(struct ipsec_transforms))) 496 == NULL) 497 err(1, "mmxfs: calloc"); 498 $$ = xfs; 499 } 500 | MAIN transforms { $$ = $2; } 501 ; 502 503qmxfs : /* empty */ { 504 struct ipsec_transforms *xfs; 505 506 /* We create just an empty transform */ 507 if ((xfs = calloc(1, sizeof(struct ipsec_transforms))) 508 == NULL) 509 err(1, "qmxfs: calloc"); 510 $$ = xfs; 511 } 512 | QUICK transforms { $$ = $2; } 513 ; 514 515authkeyspec : /* empty */ { 516 $$.keyout = NULL; 517 $$.keyin = NULL; 518 } 519 | AUTHKEY keyspec { 520 $$.keyout = $2.keyout; 521 $$.keyin = $2.keyin; 522 } 523 ; 524 525enckeyspec : /* empty */ { 526 $$.keyout = NULL; 527 $$.keyin = NULL; 528 } 529 | ENCKEY keyspec { 530 $$.keyout = $2.keyout; 531 $$.keyin = $2.keyin; 532 } 533 ; 534 535keyspec : STRING { 536 unsigned char *hex; 537 unsigned char *p = strchr($1, ':'); 538 539 if (p != NULL ) { 540 *p++ = 0; 541 542 if (!strncmp(p, "0x", 2)) 543 p += 2; 544 $$.keyin = parsekey(p, strlen(p)); 545 } 546 547 hex = $1; 548 if (!strncmp(hex, "0x", 2)) 549 hex += 2; 550 $$.keyout = parsekey(hex, strlen(hex)); 551 552 free($1); 553 } 554 | FILENAME STRING { 555 unsigned char *p = strchr($2, ':'); 556 557 if (p != NULL) { 558 *p++ = 0; 559 $$.keyin = parsekeyfile(p); 560 } 561 $$.keyout = parsekeyfile($2); 562 free($2); 563 } 564 ; 565ikemode : /* empty */ { $$ = IKE_ACTIVE; } 566 | PASSIVE { $$ = IKE_PASSIVE; } 567 | ACTIVE { $$ = IKE_ACTIVE; } 568 ; 569%% 570 571struct keywords { 572 const char *k_name; 573 int k_val; 574}; 575 576int 577yyerror(const char *fmt, ...) 578{ 579 va_list ap; 580 extern char *infile; 581 582 errors = 1; 583 va_start(ap, fmt); 584 fprintf(stderr, "%s: %d: ", infile, yyval.lineno); 585 vfprintf(stderr, fmt, ap); 586 fprintf(stderr, "\n"); 587 va_end(ap); 588 return (0); 589} 590 591int 592kw_cmp(const void *k, const void *e) 593{ 594 return (strcmp(k, ((const struct keywords *)e)->k_name)); 595} 596 597int 598lookup(char *s) 599{ 600 /* this has to be sorted always */ 601 static const struct keywords keywords[] = { 602 { "active", ACTIVE }, 603 { "ah", AH }, 604 { "any", ANY }, 605 { "auth", AUTHXF }, 606 { "authkey", AUTHKEY }, 607 { "comp", COMPXF }, 608 { "dstid", DSTID }, 609 { "enc", ENCXF }, 610 { "enckey", ENCKEY }, 611 { "esp", ESP }, 612 { "file", FILENAME }, 613 { "flow", FLOW }, 614 { "from", FROM }, 615 { "ike", IKE }, 616 { "in", IN }, 617 { "ipcomp", IPCOMP }, 618 { "main", MAIN }, 619 { "out", OUT }, 620 { "passive", PASSIVE }, 621 { "peer", PEER }, 622 { "psk", PSK }, 623 { "quick", QUICK }, 624 { "rsa", RSA }, 625 { "spi", SPI }, 626 { "srcid", SRCID }, 627 { "tcpmd5", TCPMD5 }, 628 { "to", TO }, 629 { "transport", TRANSPORT }, 630 { "tunnel", TUNNEL }, 631 }; 632 const struct keywords *p; 633 634 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 635 sizeof(keywords[0]), kw_cmp); 636 637 if (p) { 638 if (debug > 1) 639 fprintf(stderr, "%s: %d\n", s, p->k_val); 640 return (p->k_val); 641 } else { 642 if (debug > 1) 643 fprintf(stderr, "string: %s\n", s); 644 return (STRING); 645 } 646} 647 648#define MAXPUSHBACK 128 649 650char *parsebuf; 651int parseindex; 652char pushback_buffer[MAXPUSHBACK]; 653int pushback_index = 0; 654 655int 656lgetc(FILE *f) 657{ 658 int c, next; 659 660 if (parsebuf) { 661 /* Read character from the parsebuffer instead of input. */ 662 if (parseindex >= 0) { 663 c = parsebuf[parseindex++]; 664 if (c != '\0') 665 return (c); 666 parsebuf = NULL; 667 } else 668 parseindex++; 669 } 670 671 if (pushback_index) 672 return (pushback_buffer[--pushback_index]); 673 674 while ((c = getc(f)) == '\\') { 675 next = getc(f); 676 if (next != '\n') { 677 if (isspace(next)) 678 yyerror("whitespace after \\"); 679 ungetc(next, f); 680 break; 681 } 682 yylval.lineno = lineno; 683 lineno++; 684 } 685 if (c == '\t' || c == ' ') { 686 /* Compress blanks to a single space. */ 687 do { 688 c = getc(f); 689 } while (c == '\t' || c == ' '); 690 ungetc(c, f); 691 c = ' '; 692 } 693 694 return (c); 695} 696 697int 698lungetc(int c) 699{ 700 if (c == EOF) 701 return (EOF); 702 if (parsebuf) { 703 parseindex--; 704 if (parseindex >= 0) 705 return (c); 706 } 707 if (pushback_index < MAXPUSHBACK-1) 708 return (pushback_buffer[pushback_index++] = c); 709 else 710 return (EOF); 711} 712 713int 714findeol(void) 715{ 716 int c; 717 718 parsebuf = NULL; 719 pushback_index = 0; 720 721 /* skip to either EOF or the first real EOL */ 722 while (1) { 723 c = lgetc(fin); 724 if (c == '\n') { 725 lineno++; 726 break; 727 } 728 if (c == EOF) 729 break; 730 } 731 return (ERROR); 732} 733 734int 735yylex(void) 736{ 737 char buf[8096]; 738 char *p, *val; 739 int endc, c; 740 int token; 741 742top: 743 p = buf; 744 while ((c = lgetc(fin)) == ' ') 745 ; /* nothing */ 746 747 yylval.lineno = lineno; 748 if (c == '#') 749 while ((c = lgetc(fin)) != '\n' && c != EOF) 750 ; /* nothing */ 751 if (c == '$' && parsebuf == NULL) { 752 while (1) { 753 if ((c = lgetc(fin)) == EOF) 754 return (0); 755 756 if (p + 1 >= buf + sizeof(buf) - 1) { 757 yyerror("string too long"); 758 return (findeol()); 759 } 760 if (isalnum(c) || c == '_') { 761 *p++ = (char)c; 762 continue; 763 } 764 *p = '\0'; 765 lungetc(c); 766 break; 767 } 768 val = symget(buf); 769 if (val == NULL) { 770 yyerror("macro \"%s\" not defined", buf); 771 return (findeol()); 772 } 773 parsebuf = val; 774 parseindex = 0; 775 goto top; 776 } 777 778 switch (c) { 779 case '\'': 780 case '"': 781 endc = c; 782 while (1) { 783 if ((c = lgetc(fin)) == EOF) 784 return (0); 785 if (c == endc) { 786 *p = '\0'; 787 break; 788 } 789 if (c == '\n') { 790 lineno++; 791 continue; 792 } 793 if (p + 1 >= buf + sizeof(buf) - 1) { 794 yyerror("string too long"); 795 return (findeol()); 796 } 797 *p++ = (char)c; 798 } 799 yylval.v.string = strdup(buf); 800 if (yylval.v.string == NULL) 801 err(1, "yylex: strdup"); 802 return (STRING); 803 } 804 805#define allowed_in_string(x) \ 806 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 807 x != '{' && x != '}' && x != '<' && x != '>' && \ 808 x != '!' && x != '=' && x != '/' && x != '#' && \ 809 x != ',')) 810 811 if (isalnum(c) || c == ':' || c == '_' || c == '*') { 812 do { 813 *p++ = c; 814 if ((unsigned)(p-buf) >= sizeof(buf)) { 815 yyerror("string too long"); 816 return (findeol()); 817 } 818 } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c))); 819 lungetc(c); 820 *p = '\0'; 821 if ((token = lookup(buf)) == STRING) 822 if ((yylval.v.string = strdup(buf)) == NULL) 823 err(1, "yylex: strdup"); 824 return (token); 825 } 826 if (c == '\n') { 827 yylval.lineno = lineno; 828 lineno++; 829 } 830 if (c == EOF) 831 return (0); 832 return (c); 833} 834 835int 836parse_rules(FILE *input, struct ipsecctl *ipsecx) 837{ 838 struct sym *sym; 839 840 ipsec = ipsecx; 841 fin = input; 842 lineno = 1; 843 errors = 0; 844 845 yyparse(); 846 847 /* Free macros and check which have not been used. */ 848 while ((sym = TAILQ_FIRST(&symhead))) { 849 TAILQ_REMOVE(&symhead, sym, entries); 850 free(sym->nam); 851 free(sym->val); 852 free(sym); 853 } 854 855 return (errors ? -1 : 0); 856} 857 858int 859symset(const char *nam, const char *val, int persist) 860{ 861 struct sym *sym; 862 863 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 864 sym = TAILQ_NEXT(sym, entries)) 865 ; /* nothing */ 866 867 if (sym != NULL) { 868 if (sym->persist == 1) 869 return (0); 870 else { 871 TAILQ_REMOVE(&symhead, sym, entries); 872 free(sym->nam); 873 free(sym->val); 874 free(sym); 875 } 876 } 877 if ((sym = calloc(1, sizeof(*sym))) == NULL) 878 return (-1); 879 880 sym->nam = strdup(nam); 881 if (sym->nam == NULL) { 882 free(sym); 883 return (-1); 884 } 885 sym->val = strdup(val); 886 if (sym->val == NULL) { 887 free(sym->nam); 888 free(sym); 889 return (-1); 890 } 891 sym->used = 0; 892 sym->persist = persist; 893 TAILQ_INSERT_TAIL(&symhead, sym, entries); 894 return (0); 895} 896 897int 898cmdline_symset(char *s) 899{ 900 char *sym, *val; 901 int ret; 902 size_t len; 903 904 if ((val = strrchr(s, '=')) == NULL) 905 return (-1); 906 907 len = strlen(s) - strlen(val) + 1; 908 if ((sym = malloc(len)) == NULL) 909 err(1, "cmdline_symset: malloc"); 910 911 strlcpy(sym, s, len); 912 913 ret = symset(sym, val + 1, 1); 914 free(sym); 915 916 return (ret); 917} 918 919char * 920symget(const char *nam) 921{ 922 struct sym *sym; 923 924 TAILQ_FOREACH(sym, &symhead, entries) 925 if (strcmp(nam, sym->nam) == 0) { 926 sym->used = 1; 927 return (sym->val); 928 } 929 return (NULL); 930} 931 932int 933atoul(char *s, u_long *ulvalp) 934{ 935 u_long ulval; 936 char *ep; 937 938 errno = 0; 939 ulval = strtoul(s, &ep, 0); 940 if (s[0] == '\0' || *ep != '\0') 941 return (-1); 942 if (errno == ERANGE && ulval == ULONG_MAX) 943 return (-1); 944 *ulvalp = ulval; 945 return (0); 946} 947 948int 949atospi(char *s, u_int32_t *spivalp) 950{ 951 unsigned long ulval; 952 953 if (atoul(s, &ulval) == -1) 954 return (-1); 955 if (ulval >= SPI_RESERVED_MIN && ulval <= SPI_RESERVED_MAX) { 956 yyerror("illegal SPI value"); 957 return (-1); 958 } 959 *spivalp = ulval; 960 return (0); 961} 962 963u_int8_t 964x2i(unsigned char *s) 965{ 966 char ss[3]; 967 968 ss[0] = s[0]; 969 ss[1] = s[1]; 970 ss[2] = 0; 971 972 if (!isxdigit(s[0]) || !isxdigit(s[1])) { 973 yyerror("keys need to be specified in hex digits"); 974 return (-1); 975 } 976 return ((u_int8_t)strtoul(ss, NULL, 16)); 977} 978 979struct ipsec_key * 980parsekey(unsigned char *hexkey, size_t len) 981{ 982 struct ipsec_key *key; 983 int i; 984 985 key = calloc(1, sizeof(struct ipsec_key)); 986 if (key == NULL) 987 err(1, "parsekey: calloc"); 988 989 key->len = len / 2; 990 key->data = calloc(key->len, sizeof(u_int8_t)); 991 if (key->data == NULL) 992 err(1, "parsekey: calloc"); 993 994 for (i = 0; i < (int)key->len; i++) 995 key->data[i] = x2i(hexkey + 2 * i); 996 997 return (key); 998} 999 1000struct ipsec_key * 1001parsekeyfile(char *filename) 1002{ 1003 struct stat sb; 1004 int fd; 1005 unsigned char *hex; 1006 1007 if ((fd = open(filename, O_RDONLY)) < 0) 1008 err(1, "parsekeyfile: open"); 1009 if (fstat(fd, &sb) < 0) 1010 err(1, "parsekeyfile: stat %s", filename); 1011 if ((sb.st_size > KEYSIZE_LIMIT) || (sb.st_size == 0)) 1012 errx(1, "parsekeyfile: key too %s", sb.st_size ? "large" : 1013 "small"); 1014 if ((hex = calloc(sb.st_size, sizeof(unsigned char))) == NULL) 1015 err(1, "parsekeyfile: calloc"); 1016 if (read(fd, hex, sb.st_size) < sb.st_size) 1017 err(1, "parsekeyfile: read"); 1018 close(fd); 1019 return (parsekey(hex, sb.st_size)); 1020} 1021 1022struct ipsec_addr_wrap * 1023host(const char *s) 1024{ 1025 struct ipsec_addr_wrap *ipa = NULL; 1026 int mask, v4mask, cont = 1; 1027 char *p, *q, *ps; 1028 1029 if ((p = strrchr(s, '/')) != NULL) { 1030 mask = strtol(p + 1, &q, 0); 1031 if (!q || *q || mask > 32 || q == (p + 1)) 1032 errx(1, "host: invalid netmask '%s'", p); 1033 if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL) 1034 err(1, "host: calloc"); 1035 strlcpy(ps, s, strlen(s) - strlen(p) + 1); 1036 v4mask = mask; 1037 } else { 1038 if ((ps = strdup(s)) == NULL) 1039 err(1, "host: strdup"); 1040 v4mask = 32; 1041 mask = -1; 1042 } 1043 1044#if notyet 1045 /* Does interface with this name exist? */ 1046 if (cont && (ipa = host_if(ps, mask)) != NULL) 1047 cont = 0; 1048#endif 1049 1050 /* IPv4 address? */ 1051 if (cont && (ipa = host_v4(s, mask)) != NULL) 1052 cont = 0; 1053 1054#if notyet 1055 /* IPv6 address? */ 1056 if (cont && (ipa = host_dsn(ps, v4mask, 0)) != NULL) 1057 cont = 0; 1058#endif 1059 free(ps); 1060 1061 if (ipa == NULL || cont == 1) { 1062 fprintf(stderr, "no IP address found for %s\n", s); 1063 return (NULL); 1064 } 1065 return (ipa); 1066} 1067 1068struct ipsec_addr_wrap * 1069host_v4(const char *s, int mask) 1070{ 1071 struct ipsec_addr_wrap *ipa = NULL; 1072 struct in_addr ina; 1073 int bits = 32; 1074 1075 bzero(&ina, sizeof(struct in_addr)); 1076 if (strrchr(s, '/') != NULL) { 1077 if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1) 1078 return (NULL); 1079 } else { 1080 if (inet_pton(AF_INET, s, &ina) != 1) 1081 return (NULL); 1082 } 1083 1084 ipa = calloc(1, sizeof(struct ipsec_addr_wrap)); 1085 if (ipa == NULL) 1086 err(1, "host_v4: calloc"); 1087 1088 ipa->address.v4 = ina; 1089 ipa->name = strdup(s); 1090 if (ipa->name == NULL) 1091 err(1, "host_v4: strdup"); 1092 ipa->af = AF_INET; 1093 1094 set_ipmask(ipa, bits); 1095 if (bits != (ipa->af == AF_INET ? 32 : 128)) 1096 ipa->netaddress = 1; 1097 1098 return (ipa); 1099} 1100 1101void 1102set_ipmask(struct ipsec_addr_wrap *address, u_int8_t b) 1103{ 1104 struct ipsec_addr *ipa; 1105 int i, j = 0; 1106 1107 ipa = &address->mask; 1108 bzero(ipa, sizeof(struct ipsec_addr)); 1109 1110 while (b >= 32) { 1111 ipa->addr32[j++] = 0xffffffff; 1112 b -= 32; 1113 } 1114 for (i = 31; i > 31 - b; --i) 1115 ipa->addr32[j] |= (1 << i); 1116 if (b) 1117 ipa->addr32[j] = htonl(ipa->addr32[j]); 1118} 1119 1120struct ipsec_addr_wrap * 1121copyhost(const struct ipsec_addr_wrap *src) 1122{ 1123 struct ipsec_addr_wrap *dst; 1124 1125 dst = calloc(1, sizeof(struct ipsec_addr_wrap)); 1126 if (dst == NULL) 1127 err(1, "copyhost: calloc"); 1128 1129 memcpy(dst, src, sizeof(struct ipsec_addr_wrap)); 1130 1131 if ((dst->name = strdup(src->name)) == NULL) 1132 err(1, "copyhost: strdup"); 1133 1134 return dst; 1135} 1136 1137const struct ipsec_xf * 1138parse_xf(const char *name, const struct ipsec_xf xfs[]) 1139{ 1140 int i; 1141 1142 for (i = 0; xfs[i].name != NULL; i++) { 1143 if (strncmp(name, xfs[i].name, strlen(name))) 1144 continue; 1145 return &xfs[i]; 1146 } 1147 return (NULL); 1148} 1149 1150struct ipsec_transforms * 1151transforms(const char *authname, const char *encname, const char *compname) 1152{ 1153 struct ipsec_transforms *xfs; 1154 1155 xfs = calloc(1, sizeof(struct ipsec_transforms)); 1156 if (xfs == NULL) 1157 err(1, "transforms: calloc"); 1158 1159 if (authname) { 1160 xfs->authxf = parse_xf(authname, authxfs); 1161 if (xfs->authxf == NULL) 1162 yyerror("%s not a valid transform", authname); 1163 } 1164 if (encname) { 1165 xfs->encxf = parse_xf(encname, encxfs); 1166 if (xfs->encxf == NULL) 1167 yyerror("%s not a valid transform", encname); 1168 } 1169 if (compname) { 1170 xfs->compxf = parse_xf(compname, compxfs); 1171 if (xfs->compxf == NULL) 1172 yyerror("%s not a valid transform", compname); 1173 } 1174 1175 return (xfs); 1176} 1177 1178struct ipsec_transforms * 1179copytransforms(const struct ipsec_transforms *xfs) 1180{ 1181 struct ipsec_transforms *newxfs; 1182 1183 if (xfs == NULL) 1184 return (NULL); 1185 1186 newxfs = calloc(1, sizeof(struct ipsec_transforms)); 1187 if (newxfs == NULL) 1188 err(1, "copytransforms: calloc"); 1189 1190 memcpy(newxfs, xfs, sizeof(struct ipsec_transforms)); 1191 return (newxfs); 1192} 1193 1194int 1195validate_sa(u_int32_t spi, u_int8_t protocol, struct ipsec_transforms *xfs, 1196 struct ipsec_key *authkey, struct ipsec_key *enckey, u_int8_t tmode) 1197{ 1198 /* Sanity checks */ 1199 if (spi == 0) { 1200 yyerror("no SPI specified"); 1201 return (0); 1202 } 1203 if (protocol == IPSEC_AH) { 1204 if (!xfs) { 1205 yyerror("no transforms specified"); 1206 return (0); 1207 } 1208 if (!xfs->authxf) 1209 xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256]; 1210 if (xfs->encxf) { 1211 yyerror("ah does not provide encryption"); 1212 return (0); 1213 } 1214 } 1215 if (protocol == IPSEC_ESP) { 1216 if (!xfs) { 1217 yyerror("no transforms specified"); 1218 return (0); 1219 } 1220 if (!xfs->authxf) 1221 xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256]; 1222 if (!xfs->encxf) 1223 xfs->encxf = &encxfs[ENCXF_AESCTR]; 1224 } 1225 if (protocol == IPSEC_IPCOMP) { 1226 if (!xfs) { 1227 yyerror("no transform specified"); 1228 return (0); 1229 } 1230 if (!xfs->compxf) 1231 xfs->compxf = &compxfs[COMPXF_DEFLATE]; 1232 } 1233 if (protocol == IPSEC_TCPMD5 && authkey == NULL && tmode != 1234 IPSEC_TRANSPORT) { 1235 yyerror("authentication key needed for tcpmd5"); 1236 return (0); 1237 } 1238 if (xfs && xfs->authxf) { 1239 if (!authkey) { 1240 yyerror("no authentication key specified"); 1241 return (0); 1242 } 1243 if (authkey->len != xfs->authxf->keymin) { 1244 yyerror("wrong authentication key length, needs to be " 1245 "%d bits", xfs->authxf->keymin * 8); 1246 return (0); 1247 } 1248 } 1249 if (xfs && xfs->encxf) { 1250 if (!enckey && xfs->encxf != &encxfs[ENCXF_NULL]) { 1251 yyerror("no encryption key specified"); 1252 return (0); 1253 } 1254 if (enckey) { 1255 if (enckey->len < xfs->encxf->keymin) { 1256 yyerror("encryption key too short, minimum %d bits", 1257 xfs->encxf->keymin * 8); 1258 return (0); 1259 } 1260 if (xfs->encxf->keymax < enckey->len) { 1261 yyerror("encryption key too long, maximum %d bits", 1262 xfs->encxf->keymax * 8); 1263 return (0); 1264 } 1265 } 1266 } 1267 1268 return 1; 1269} 1270 1271struct ipsec_rule * 1272create_sa(u_int8_t protocol, u_int8_t tmode, struct ipsec_addr_wrap *src, struct 1273 ipsec_addr_wrap *dst, u_int32_t spi, struct ipsec_transforms *xfs, 1274 struct ipsec_key *authkey, struct ipsec_key *enckey) 1275{ 1276 struct ipsec_rule *r; 1277 1278 if (validate_sa(spi, protocol, xfs, authkey, enckey, tmode) == 0) 1279 return (NULL); 1280 1281 r = calloc(1, sizeof(struct ipsec_rule)); 1282 if (r == NULL) 1283 err(1, "create_sa: calloc"); 1284 1285 r->type |= RULE_SA; 1286 r->proto = protocol; 1287 r->tmode = tmode; 1288 r->src = src; 1289 r->dst = dst; 1290 r->spi = spi; 1291 r->xfs = xfs; 1292 r->authkey = authkey; 1293 r->enckey = enckey; 1294 1295 return r; 1296} 1297 1298struct ipsec_rule * 1299reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey, 1300 struct ipsec_key *enckey) 1301{ 1302 struct ipsec_rule *reverse; 1303 1304 if (validate_sa(spi, rule->proto, rule->xfs, authkey, enckey, 1305 rule->tmode) == 0) 1306 return (NULL); 1307 1308 reverse = calloc(1, sizeof(struct ipsec_rule)); 1309 if (reverse == NULL) 1310 err(1, "reverse_sa: calloc"); 1311 1312 reverse->type |= RULE_SA; 1313 reverse->proto = rule->proto; 1314 reverse->tmode = rule->tmode; 1315 reverse->src = copyhost(rule->dst); 1316 reverse->dst = copyhost(rule->src); 1317 reverse->spi = spi; 1318 reverse->xfs = copytransforms(rule->xfs); 1319 reverse->authkey = authkey; 1320 reverse->enckey = enckey; 1321 1322 return (reverse); 1323} 1324 1325struct ipsec_rule * 1326create_flow(u_int8_t dir, struct ipsec_addr_wrap *src, struct ipsec_addr_wrap 1327 *dst, struct ipsec_addr_wrap *peer, u_int8_t proto, char *srcid, char 1328 *dstid, u_int16_t authtype) 1329{ 1330 struct ipsec_rule *r; 1331 1332 r = calloc(1, sizeof(struct ipsec_rule)); 1333 if (r == NULL) 1334 err(1, "create_flow: calloc"); 1335 1336 r->type |= RULE_FLOW; 1337 1338 if (dir == IPSEC_INOUT) 1339 r->direction = IPSEC_OUT; 1340 else 1341 r->direction = dir; 1342 1343 if (r->direction == IPSEC_IN) 1344 r->flowtype = TYPE_USE; 1345 else 1346 r->flowtype = TYPE_REQUIRE; 1347 1348 r->src = src; 1349 r->dst = dst; 1350 1351 if (peer == NULL) { 1352 /* Set peer to remote host. Must be a host address. */ 1353 if (r->direction == IPSEC_IN) { 1354 if (r->src->netaddress) { 1355 yyerror("no peer specified"); 1356 goto errout; 1357 } 1358 r->peer = copyhost(r->src); 1359 } else { 1360 if (r->dst->netaddress) { 1361 yyerror("no peer specified"); 1362 goto errout; 1363 } 1364 r->peer = copyhost(r->dst); 1365 } 1366 } else 1367 r->peer = peer; 1368 1369 r->proto = proto; 1370 r->auth = calloc(1, sizeof(struct ipsec_auth)); 1371 if (r->auth == NULL) 1372 err(1, "create_flow: calloc"); 1373 r->auth->srcid = srcid; 1374 r->auth->dstid = dstid; 1375 r->auth->idtype = ID_FQDN; /* XXX For now only FQDN. */ 1376#ifdef notyet 1377 r->auth->type = authtype; 1378#endif 1379 1380 return r; 1381 1382errout: 1383 free(r); 1384 if (srcid) 1385 free(srcid); 1386 if (dstid) 1387 free(dstid); 1388 free(src); 1389 free(dst); 1390 1391 return NULL; 1392} 1393 1394struct ipsec_rule * 1395reverse_rule(struct ipsec_rule *rule) 1396{ 1397 struct ipsec_rule *reverse; 1398 1399 reverse = calloc(1, sizeof(struct ipsec_rule)); 1400 if (reverse == NULL) 1401 err(1, "reverse_rule: calloc"); 1402 1403 reverse->type |= RULE_FLOW; 1404 1405 if (rule->direction == (u_int8_t)IPSEC_OUT) { 1406 reverse->direction = (u_int8_t)IPSEC_IN; 1407 reverse->flowtype = TYPE_USE; 1408 } else { 1409 reverse->direction = (u_int8_t)IPSEC_OUT; 1410 reverse->flowtype = TYPE_REQUIRE; 1411 } 1412 1413 reverse->src = copyhost(rule->dst); 1414 reverse->dst = copyhost(rule->src); 1415 reverse->peer = copyhost(rule->peer); 1416 reverse->proto = (u_int8_t)rule->proto; 1417 1418 reverse->auth = calloc(1, sizeof(struct ipsec_auth)); 1419 if (reverse->auth == NULL) 1420 err(1, "reverse_rule: calloc"); 1421 if (rule->auth->dstid && (reverse->auth->dstid = 1422 strdup(rule->auth->dstid)) == NULL) 1423 err(1, "reverse_rule: strdup"); 1424 if (rule->auth->srcid && (reverse->auth->srcid = 1425 strdup(rule->auth->srcid)) == NULL) 1426 err(1, "reverse_rule: strdup"); 1427 reverse->auth->idtype = rule->auth->idtype; 1428 reverse->auth->type = rule->auth->type; 1429 1430 return reverse; 1431} 1432 1433struct ipsec_rule * 1434create_ike(struct ipsec_addr_wrap *src, struct ipsec_addr_wrap *dst, struct 1435 ipsec_addr_wrap * peer, struct ipsec_transforms *mmxfs, struct 1436 ipsec_transforms *qmxfs, u_int8_t proto, u_int8_t mode, char *srcid, char 1437 *dstid) 1438{ 1439 struct ipsec_rule *r; 1440 1441 r = calloc(1, sizeof(struct ipsec_rule)); 1442 if (r == NULL) 1443 err(1, "create_ike: calloc"); 1444 1445 r->type = RULE_IKE; 1446 1447 r->src = src; 1448 r->dst = dst; 1449 1450 if (peer == NULL) { 1451 /* Set peer to remote host. Must be a host address. */ 1452 if (r->direction == IPSEC_IN) { 1453 if (r->src->netaddress) { 1454 yyerror("no peer specified"); 1455 goto errout; 1456 } 1457 r->peer = copyhost(r->src); 1458 } else { 1459 if (r->dst->netaddress) { 1460 yyerror("no peer specified"); 1461 goto errout; 1462 } 1463 r->peer = copyhost(r->dst); 1464 } 1465 } else 1466 r->peer = peer; 1467 1468 r->proto = proto; 1469 r->ikemode = mode; 1470 r->mmxfs = mmxfs; 1471 r->qmxfs = qmxfs; 1472 r->auth = calloc(1, sizeof(struct ipsec_auth)); 1473 if (r->auth == NULL) 1474 err(1, "create_ike: calloc"); 1475 r->auth->srcid = srcid; 1476 r->auth->dstid = dstid; 1477 r->auth->idtype = ID_FQDN; /* XXX For now only FQDN. */ 1478 1479 return (r); 1480 1481errout: 1482 free(r); 1483 if (srcid) 1484 free(srcid); 1485 if (dstid) 1486 free(dstid); 1487 free(src); 1488 free(dst); 1489 1490 return (NULL); 1491} 1492