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