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