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