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