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