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