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