1/* $KAME: cfparse.y,v 1.112 2002/02/21 14:47:38 sakane Exp $ */ 2 3%{ 4#include <sys/types.h> 5#include <sys/param.h> 6#include <sys/queue.h> 7#include <sys/socket.h> 8 9#include <netinet/in.h> 10#include <netinet/ipsec.h> 11 12#include <stdlib.h> 13#include <stdio.h> 14#include <string.h> 15#include <errno.h> 16#include <netdb.h> 17#if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO) 18#include "addrinfo.h" 19#endif 20 21#include "var.h" 22#include "misc.h" 23#include "vmbuf.h" 24#include "plog.h" 25#include "sockmisc.h" 26#include "str2val.h" 27#include "debug.h" 28 29#include "cfparse.h" 30#include "cftoken.h" 31#include "algorithm.h" 32#include "localconf.h" 33#include "policy.h" 34#include "sainfo.h" 35#include "oakley.h" 36#include "pfkey.h" 37#include "remoteconf.h" 38#include "grabmyaddr.h" 39#include "isakmp_var.h" 40#include "handler.h" 41#include "isakmp.h" 42#include "ipsec_doi.h" 43#include "strnames.h" 44#include "gcmalloc.h" 45#ifdef HAVE_GSSAPI 46#include "gssapi.h" 47#endif 48#include "vendorid.h" 49 50struct proposalspec { 51 time_t lifetime; /* for isakmp/ipsec */ 52 int lifebyte; /* for isakmp/ipsec */ 53 struct secprotospec *spspec; /* the head is always current spec. */ 54 struct proposalspec *next; /* the tail is the most prefered. */ 55 struct proposalspec *prev; 56}; 57 58struct secprotospec { 59 int prop_no; 60 int trns_no; 61 int strength; /* for isakmp/ipsec */ 62 int encklen; /* for isakmp/ipsec */ 63 time_t lifetime; /* for isakmp */ 64 int lifebyte; /* for isakmp */ 65 int proto_id; /* for ipsec (isakmp?) */ 66 int ipsec_level; /* for ipsec */ 67 int encmode; /* for ipsec */ 68 int vendorid; /* for isakmp */ 69 char *gssid; 70 struct sockaddr *remote; 71 int algclass[MAXALGCLASS]; 72 73 struct secprotospec *next; /* the tail is the most prefiered. */ 74 struct secprotospec *prev; 75 struct proposalspec *back; 76}; 77 78static int num2dhgroup[] = { 79 0, 80 OAKLEY_ATTR_GRP_DESC_MODP768, 81 OAKLEY_ATTR_GRP_DESC_MODP1024, 82 OAKLEY_ATTR_GRP_DESC_EC2N155, 83 OAKLEY_ATTR_GRP_DESC_EC2N185, 84 OAKLEY_ATTR_GRP_DESC_MODP1536, 85}; 86 87static struct remoteconf *cur_rmconf; 88static int tmpalgtype[MAXALGCLASS]; 89static struct sainfo *cur_sainfo; 90static int cur_algclass; 91 92static struct proposalspec *prhead; /* the head is always current. */ 93 94static struct proposalspec *newprspec __P((void)); 95static void cleanprhead __P((void)); 96static void insprspec __P((struct proposalspec *, struct proposalspec **)); 97static struct secprotospec *newspspec __P((void)); 98static void insspspec __P((struct secprotospec *, struct proposalspec **)); 99 100static int set_isakmp_proposal 101 __P((struct remoteconf *, struct proposalspec *)); 102static void clean_tmpalgtype __P((void)); 103static int expand_isakmpspec __P((int, int, int *, 104 int, int, time_t, int, int, int, char *, struct remoteconf *)); 105 106#if 0 107static int fix_lifebyte __P((u_long)); 108#endif 109%} 110 111%union { 112 unsigned long num; 113 vchar_t *val; 114 struct remoteconf *rmconf; 115 struct sockaddr *saddr; 116 struct sainfoalg *alg; 117} 118 119 /* path */ 120%token PATH PATHTYPE 121 /* include */ 122%token INCLUDE 123 /* self information */ 124%token IDENTIFIER VENDORID 125 /* logging */ 126%token LOGGING LOGLEV 127 /* padding */ 128%token PADDING PAD_RANDOMIZE PAD_RANDOMIZELEN PAD_MAXLEN PAD_STRICT PAD_EXCLTAIL 129 /* listen */ 130%token LISTEN X_ISAKMP X_ADMIN STRICT_ADDRESS 131 /* timer */ 132%token RETRY RETRY_COUNTER RETRY_INTERVAL RETRY_PERSEND 133%token RETRY_PHASE1 RETRY_PHASE2 134 /* algorithm */ 135%token ALGORITHM_CLASS ALGORITHMTYPE STRENGTHTYPE 136 /* sainfo */ 137%token SAINFO 138 /* remote */ 139%token REMOTE ANONYMOUS 140%token EXCHANGE_MODE EXCHANGETYPE DOI DOITYPE SITUATION SITUATIONTYPE 141%token CERTIFICATE_TYPE CERTTYPE PEERS_CERTFILE VERIFY_CERT SEND_CERT SEND_CR 142%token IDENTIFIERTYPE MY_IDENTIFIER PEERS_IDENTIFIER VERIFY_IDENTIFIER 143%token DNSSEC CERT_X509 144%token NONCE_SIZE DH_GROUP KEEPALIVE PASSIVE INITIAL_CONTACT 145%token PROPOSAL_CHECK PROPOSAL_CHECK_LEVEL 146%token GENERATE_POLICY SUPPORT_MIP6 147%token PROPOSAL 148%token EXEC_PATH EXEC_COMMAND EXEC_SUCCESS EXEC_FAILURE 149%token GSSAPI_ID 150%token COMPLEX_BUNDLE 151 152%token PREFIX PORT PORTANY UL_PROTO ANY 153%token PFS_GROUP LIFETIME LIFETYPE_TIME LIFETYPE_BYTE STRENGTH 154 155%token NUMBER SWITCH BOOLEAN 156%token HEXSTRING QUOTEDSTRING ADDRSTRING 157%token UNITTYPE_BYTE UNITTYPE_KBYTES UNITTYPE_MBYTES UNITTYPE_TBYTES 158%token UNITTYPE_SEC UNITTYPE_MIN UNITTYPE_HOUR 159%token EOS BOC EOC COMMA 160 161%type <num> NUMBER BOOLEAN SWITCH keylength 162%type <num> PATHTYPE IDENTIFIERTYPE LOGLEV 163%type <num> ALGORITHM_CLASS dh_group_num 164%type <num> ALGORITHMTYPE STRENGTHTYPE 165%type <num> PREFIX prefix PORT port ike_port 166%type <num> ul_proto UL_PROTO 167%type <num> EXCHANGETYPE DOITYPE SITUATIONTYPE 168%type <num> CERTTYPE CERT_X509 PROPOSAL_CHECK_LEVEL 169%type <num> unittype_time unittype_byte 170%type <val> QUOTEDSTRING HEXSTRING ADDRSTRING sainfo_id 171%type <val> identifierstring 172%type <saddr> remote_index ike_addrinfo_port 173%type <alg> algorithm 174 175%% 176 177statements 178 : /* nothing */ 179 | statements statement 180 ; 181statement 182 : path_statement 183 | include_statement 184 | identifier_statement 185 | logging_statement 186 | padding_statement 187 | listen_statement 188 | timer_statement 189 | sainfo_statement 190 | remote_statement 191 | special_statement 192 ; 193 194 /* path */ 195path_statement 196 : PATH PATHTYPE QUOTEDSTRING 197 { 198 if ($2 > LC_PATHTYPE_MAX) { 199 yyerror("invalid path type %d", $2); 200 return -1; 201 } 202 203 /* free old pathinfo */ 204 if (lcconf->pathinfo[$2]) 205 racoon_free(lcconf->pathinfo[$2]); 206 207 /* set new pathinfo */ 208 lcconf->pathinfo[$2] = strdup($3->v); 209 vfree($3); 210 } 211 EOS 212 ; 213 214 /* special */ 215special_statement 216 : COMPLEX_BUNDLE SWITCH { lcconf->complex_bundle = $2; } EOS 217 ; 218 219 /* include */ 220include_statement 221 : INCLUDE QUOTEDSTRING 222 { 223 char path[MAXPATHLEN]; 224 225 getpathname(path, sizeof(path), 226 LC_PATHTYPE_INCLUDE, $2->v); 227 vfree($2); 228 if (yycf_switch_buffer(path) != 0) 229 return -1; 230 } 231 EOS 232 ; 233 234 /* self infomation */ 235identifier_statement 236 : IDENTIFIER identifier_stmt 237 ; 238identifier_stmt 239 : VENDORID 240 { 241 /*XXX to be deleted */ 242 } 243 QUOTEDSTRING EOS 244 | IDENTIFIERTYPE QUOTEDSTRING 245 { 246 /*XXX to be deleted */ 247 $2->l--; /* nuke '\0' */ 248 lcconf->ident[$1] = $2; 249 if (lcconf->ident[$1] == NULL) { 250 yyerror("failed to set my ident: %s", 251 strerror(errno)); 252 return -1; 253 } 254 } 255 EOS 256 ; 257 258 /* logging */ 259logging_statement 260 : LOGGING log_level EOS 261 ; 262log_level 263 : HEXSTRING 264 { 265 /* 266 * XXX ignore it because this specification 267 * will be obsoleted. 268 */ 269 yywarn("see racoon.conf(5), such a log specification will be obsoleted."); 270 vfree($1); 271 } 272 | LOGLEV 273 { 274 /* 275 * set the loglevel by configuration file only when 276 * the command line did not specify any loglevel. 277 */ 278 if (loglevel <= LLV_BASE) 279 loglevel += $1; 280 } 281 ; 282 283 /* padding */ 284padding_statement 285 : PADDING BOC padding_stmts EOC 286 ; 287padding_stmts 288 : /* nothing */ 289 | padding_stmts padding_stmt 290 ; 291padding_stmt 292 : PAD_RANDOMIZE SWITCH { lcconf->pad_random = $2; } EOS 293 | PAD_RANDOMIZELEN SWITCH { lcconf->pad_randomlen = $2; } EOS 294 | PAD_MAXLEN NUMBER { lcconf->pad_maxsize = $2; } EOS 295 | PAD_STRICT SWITCH { lcconf->pad_strict = $2; } EOS 296 | PAD_EXCLTAIL SWITCH { lcconf->pad_excltail = $2; } EOS 297 ; 298 299 /* listen */ 300listen_statement 301 : LISTEN BOC listen_stmts EOC 302 ; 303listen_stmts 304 : /* nothing */ 305 | listen_stmts listen_stmt 306 ; 307listen_stmt 308 : X_ISAKMP ike_addrinfo_port 309 { 310 struct myaddrs *p; 311 312 p = newmyaddr(); 313 if (p == NULL) { 314 yyerror("failed to allocate myaddrs"); 315 return -1; 316 } 317 p->addr = $2; 318 if (p->addr == NULL) { 319 yyerror("failed to copy sockaddr "); 320 delmyaddr(p); 321 return -1; 322 } 323 324 insmyaddr(p, &lcconf->myaddrs); 325 326 lcconf->autograbaddr = 0; 327 } 328 EOS 329 | X_ADMIN 330 { 331 yyerror("admin directive is obsoleted."); 332 } 333 PORT EOS 334 | STRICT_ADDRESS { lcconf->strict_address = TRUE; } EOS 335 ; 336ike_addrinfo_port 337 : ADDRSTRING ike_port 338 { 339 char portbuf[10]; 340 341 snprintf(portbuf, sizeof(portbuf), "%ld", $2); 342 $$ = str2saddr($1->v, portbuf); 343 vfree($1); 344 if (!$$) 345 return -1; 346 } 347 ; 348ike_port 349 : /* nothing */ { $$ = PORT_ISAKMP; } 350 | PORT { $$ = $1; } 351 ; 352 353 /* timer */ 354timer_statement 355 : RETRY BOC timer_stmts EOC 356 ; 357timer_stmts 358 : /* nothing */ 359 | timer_stmts timer_stmt 360 ; 361timer_stmt 362 : RETRY_COUNTER NUMBER 363 { 364 lcconf->retry_counter = $2; 365 } 366 EOS 367 | RETRY_INTERVAL NUMBER unittype_time 368 { 369 lcconf->retry_interval = $2 * $3; 370 } 371 EOS 372 | RETRY_PERSEND NUMBER 373 { 374 lcconf->count_persend = $2; 375 } 376 EOS 377 | RETRY_PHASE1 NUMBER unittype_time 378 { 379 lcconf->retry_checkph1 = $2 * $3; 380 } 381 EOS 382 | RETRY_PHASE2 NUMBER unittype_time 383 { 384 lcconf->wait_ph2complete = $2 * $3; 385 } 386 EOS 387 ; 388 389 /* sainfo */ 390sainfo_statement 391 : SAINFO 392 { 393 cur_sainfo = newsainfo(); 394 if (cur_sainfo == NULL) { 395 yyerror("failed to allocate sainfo"); 396 return -1; 397 } 398 } 399 sainfo_name BOC sainfo_specs 400 { 401 struct sainfo *check; 402 403 /* default */ 404 if (cur_sainfo->algs[algclass_ipsec_enc] == 0) { 405 yyerror("no encryption algorithm at %s", 406 sainfo2str(cur_sainfo)); 407 return -1; 408 } 409 if (cur_sainfo->algs[algclass_ipsec_auth] == 0) { 410 yyerror("no authentication algorithm at %s", 411 sainfo2str(cur_sainfo)); 412 return -1; 413 } 414 if (cur_sainfo->algs[algclass_ipsec_comp] == 0) { 415 yyerror("no compression algorithm at %s", 416 sainfo2str(cur_sainfo)); 417 return -1; 418 } 419 420 /* duplicate check */ 421 check = getsainfo(cur_sainfo->idsrc, cur_sainfo->iddst); 422 if (check && (!check->idsrc && !cur_sainfo->idsrc)) { 423 yyerror("duplicated sainfo: %s", 424 sainfo2str(cur_sainfo)); 425 return -1; 426 } 427 inssainfo(cur_sainfo); 428 } 429 EOC 430 ; 431sainfo_name 432 : ANONYMOUS 433 { 434 cur_sainfo->idsrc = NULL; 435 cur_sainfo->iddst = NULL; 436 } 437 | sainfo_id sainfo_id 438 { 439 cur_sainfo->idsrc = $1; 440 cur_sainfo->iddst = $2; 441 } 442 ; 443sainfo_id 444 : IDENTIFIERTYPE ADDRSTRING prefix port ul_proto 445 { 446 char portbuf[10]; 447 struct sockaddr *saddr; 448 449 if (($5 == IPPROTO_ICMP || $5 == IPPROTO_ICMPV6) 450 && ($4 != IPSEC_PORT_ANY || $4 != IPSEC_PORT_ANY)) { 451 yyerror("port number must be \"any\"."); 452 return -1; 453 } 454 455 snprintf(portbuf, sizeof(portbuf), "%lu", $4); 456 saddr = str2saddr($2->v, portbuf); 457 vfree($2); 458 if (saddr == NULL) 459 return -1; 460 461 switch (saddr->sa_family) { 462 case AF_INET: 463 if ($5 == IPPROTO_ICMPV6) { 464 yyerror("upper layer protocol mismatched.\n"); 465 racoon_free(saddr); 466 return -1; 467 } 468 $$ = ipsecdoi_sockaddr2id(saddr, 469 $3 == ~0 ? (sizeof(struct in_addr) << 3): $3, 470 $5); 471 break; 472#ifdef INET6 473 case AF_INET6: 474 if ($5 == IPPROTO_ICMP) { 475 yyerror("upper layer protocol mismatched.\n"); 476 racoon_free(saddr); 477 return -1; 478 } 479 $$ = ipsecdoi_sockaddr2id(saddr, 480 $3 == ~0 ? (sizeof(struct in6_addr) << 3) : $3, 481 $5); 482 break; 483#endif 484 default: 485 yyerror("invalid family: %d", saddr->sa_family); 486 break; 487 } 488 racoon_free(saddr); 489 if ($$ == NULL) 490 return -1; 491 } 492 | IDENTIFIERTYPE QUOTEDSTRING 493 { 494 struct ipsecdoi_id_b *id_b; 495 496 if ($1 == IDTYPE_ASN1DN) { 497 yyerror("id type forbidden: %d", $1); 498 return -1; 499 } 500 501 $2->l--; 502 503 $$ = vmalloc(sizeof(*id_b) + $2->l); 504 if ($$ == NULL) { 505 yyerror("failed to allocate identifier"); 506 return -1; 507 } 508 509 id_b = (struct ipsecdoi_id_b *)$$->v; 510 id_b->type = idtype2doi($1); 511 512 id_b->proto_id = 0; 513 id_b->port = 0; 514 515 memcpy($$->v + sizeof(*id_b), $2->v, $2->l); 516 } 517 ; 518sainfo_specs 519 : /* nothing */ 520 | sainfo_specs sainfo_spec 521 ; 522sainfo_spec 523 : PFS_GROUP dh_group_num 524 { 525 cur_sainfo->pfs_group = $2; 526 } 527 EOS 528 | LIFETIME LIFETYPE_TIME NUMBER unittype_time 529 { 530 cur_sainfo->lifetime = $3 * $4; 531 } 532 EOS 533 | LIFETIME LIFETYPE_BYTE NUMBER unittype_byte 534 { 535#if 1 536 yyerror("byte lifetime support is deprecated"); 537 return -1; 538#else 539 cur_sainfo->lifebyte = fix_lifebyte($3 * $4); 540 if (cur_sainfo->lifebyte == 0) 541 return -1; 542#endif 543 } 544 EOS 545 | ALGORITHM_CLASS { 546 cur_algclass = $1; 547 } 548 algorithms EOS 549 | IDENTIFIER IDENTIFIERTYPE 550 { 551 yyerror("it's deprecated to specify a identifier in phase 2"); 552 } 553 EOS 554 | MY_IDENTIFIER IDENTIFIERTYPE QUOTEDSTRING 555 { 556 yyerror("it's deprecated to specify a identifier in phase 2"); 557 } 558 EOS 559 ; 560 561algorithms 562 : algorithm 563 { 564 inssainfoalg(&cur_sainfo->algs[cur_algclass], $1); 565 } 566 | algorithm 567 { 568 inssainfoalg(&cur_sainfo->algs[cur_algclass], $1); 569 } 570 COMMA algorithms 571 ; 572algorithm 573 : ALGORITHMTYPE keylength 574 { 575 int defklen; 576 577 $$ = newsainfoalg(); 578 if ($$ == NULL) { 579 yyerror("failed to get algorithm alocation"); 580 return -1; 581 } 582 583 $$->alg = algtype2doi(cur_algclass, $1); 584 if ($$->alg == -1) { 585 yyerror("algorithm mismatched"); 586 racoon_free($$); 587 return -1; 588 } 589 590 defklen = default_keylen(cur_algclass, $1); 591 if (defklen == 0) { 592 if ($2) { 593 yyerror("keylen not allowed"); 594 racoon_free($$); 595 return -1; 596 } 597 } else { 598 if ($2 && check_keylen(cur_algclass, $1, $2) < 0) { 599 yyerror("invalid keylen %d", $2); 600 racoon_free($$); 601 return -1; 602 } 603 } 604 605 if ($2) 606 $$->encklen = $2; 607 else 608 $$->encklen = defklen; 609 610 /* check if it's supported algorithm by kernel */ 611 if (!(cur_algclass == algclass_ipsec_auth && $1 == algtype_non_auth) 612 && pk_checkalg(cur_algclass, $1, $$->encklen)) { 613 int a = algclass2doi(cur_algclass); 614 int b = algtype2doi(cur_algclass, $1); 615 if (a == IPSECDOI_ATTR_AUTH) 616 a = IPSECDOI_PROTO_IPSEC_AH; 617 yyerror("algorithm %s not supported", 618 s_ipsecdoi_trns(a, b)); 619 racoon_free($$); 620 return -1; 621 } 622 } 623 ; 624prefix 625 : /* nothing */ { $$ = ~0; } 626 | PREFIX { $$ = $1; } 627 ; 628port 629 : /* nothing */ { $$ = IPSEC_PORT_ANY; } 630 | PORT { $$ = $1; } 631 | PORTANY { $$ = IPSEC_PORT_ANY; } 632 ; 633ul_proto 634 : NUMBER { $$ = $1; } 635 | UL_PROTO { $$ = $1; } 636 | ANY { $$ = IPSEC_ULPROTO_ANY; } 637 ; 638keylength 639 : /* nothing */ { $$ = 0; } 640 | NUMBER { $$ = $1; } 641 ; 642 643 /* remote */ 644remote_statement 645 : REMOTE remote_index 646 { 647 struct remoteconf *new; 648 struct proposalspec *prspec; 649 650 new = newrmconf(); 651 if (new == NULL) { 652 yyerror("failed to get new remoteconf."); 653 return -1; 654 } 655 656 new->remote = $2; 657 cur_rmconf = new; 658 659 prspec = newprspec(); 660 if (prspec == NULL) 661 return -1; 662 prspec->lifetime = oakley_get_defaultlifetime(); 663 insprspec(prspec, &prhead); 664 } 665 BOC remote_specs 666 { 667 /* check a exchange mode */ 668 if (cur_rmconf->etypes == NULL) { 669 yyerror("no exchange mode specified.\n"); 670 return -1; 671 } 672 673 if (cur_rmconf->idvtype == IDTYPE_ASN1DN 674 && cur_rmconf->mycertfile == NULL) { 675 yyerror("id type mismatched due to " 676 "no CERT defined.\n"); 677 return -1; 678 } 679 680 if (set_isakmp_proposal(cur_rmconf, prhead) != 0) 681 return -1; 682 683 /* DH group settting if aggressive mode is there. */ 684 if (check_etypeok(cur_rmconf, ISAKMP_ETYPE_AGG) != NULL) { 685 struct isakmpsa *p; 686 int b = 0; 687 688 /* DH group */ 689 for (p = cur_rmconf->proposal; p; p = p->next) { 690 if (b == 0 || (b && b == p->dh_group)) { 691 b = p->dh_group; 692 continue; 693 } 694 yyerror("DH group must be equal " 695 "to each proposals's " 696 "when aggressive mode is " 697 "used.\n"); 698 return -1; 699 } 700 cur_rmconf->dh_group = b; 701 702 if (cur_rmconf->dh_group == 0) { 703 yyerror("DH group must be required.\n"); 704 return -1; 705 } 706 707 /* DH group settting if PFS is required. */ 708 if (oakley_setdhgroup(cur_rmconf->dh_group, 709 &cur_rmconf->dhgrp) < 0) { 710 yyerror("failed to set DH value.\n"); 711 return -1; 712 } 713 } 714 715 insrmconf(cur_rmconf); 716 717 cleanprhead(); 718 } 719 EOC 720 ; 721remote_index 722 : ANONYMOUS ike_port 723 { 724 $$ = newsaddr(sizeof(struct sockaddr *)); 725 $$->sa_family = AF_UNSPEC; 726 ((struct sockaddr_in *)$$)->sin_port = htons($2); 727 } 728 | ike_addrinfo_port 729 { 730 $$ = $1; 731 if ($$ == NULL) { 732 yyerror("failed to allocate sockaddr"); 733 return -1; 734 } 735 } 736 ; 737remote_specs 738 : /* nothing */ 739 | remote_specs remote_spec 740 ; 741remote_spec 742 : EXCHANGE_MODE exchange_types EOS 743 | DOI DOITYPE { cur_rmconf->doitype = $2; } EOS 744 | SITUATION SITUATIONTYPE { cur_rmconf->sittype = $2; } EOS 745 | CERTIFICATE_TYPE cert_spec 746 | PEERS_CERTFILE QUOTEDSTRING 747 { 748#ifdef HAVE_SIGNING_C 749 cur_rmconf->getcert_method = ISAKMP_GETCERT_LOCALFILE; 750 cur_rmconf->peerscertfile = strdup($2->v); 751 vfree($2); 752#else 753 yyerror("directive not supported"); 754 return -1; 755#endif 756 } 757 EOS 758 | PEERS_CERTFILE DNSSEC 759 { 760#ifdef HAVE_SIGNING_C 761 cur_rmconf->getcert_method = ISAKMP_GETCERT_DNS; 762 cur_rmconf->peerscertfile = NULL; 763#else 764 yyerror("directive not supported"); 765 return -1; 766#endif 767 } 768 EOS 769 | VERIFY_CERT SWITCH { cur_rmconf->verify_cert = $2; } EOS 770 | SEND_CERT SWITCH { cur_rmconf->send_cert = $2; } EOS 771 | SEND_CR SWITCH { cur_rmconf->send_cr = $2; } EOS 772 | IDENTIFIER IDENTIFIERTYPE 773 { 774 /*XXX to be deleted */ 775 cur_rmconf->idvtype = $2; 776 } 777 EOS 778 | MY_IDENTIFIER IDENTIFIERTYPE identifierstring 779 { 780 if (set_identifier(&cur_rmconf->idv, $2, $3) != 0) { 781 yyerror("failed to set identifer.\n"); 782 return -1; 783 } 784 cur_rmconf->idvtype = $2; 785 } 786 EOS 787 | PEERS_IDENTIFIER IDENTIFIERTYPE identifierstring 788 { 789 if (set_identifier(&cur_rmconf->idv_p, $2, $3) != 0) { 790 yyerror("failed to set identifer.\n"); 791 return -1; 792 } 793 cur_rmconf->idvtype_p = $2; 794 } 795 EOS 796 | VERIFY_IDENTIFIER SWITCH { cur_rmconf->verify_identifier = $2; } EOS 797 | NONCE_SIZE NUMBER { cur_rmconf->nonce_size = $2; } EOS 798 | DH_GROUP 799 { 800 yyerror("dh_group cannot be defined here."); 801 return -1; 802 } 803 dh_group_num EOS 804 | KEEPALIVE { cur_rmconf->keepalive = TRUE; } EOS 805 | PASSIVE SWITCH { cur_rmconf->passive = $2; } EOS 806 | GENERATE_POLICY SWITCH { cur_rmconf->gen_policy = $2; } EOS 807 | SUPPORT_MIP6 SWITCH { cur_rmconf->support_mip6 = $2; } EOS 808 | INITIAL_CONTACT SWITCH { cur_rmconf->ini_contact = $2; } EOS 809 | PROPOSAL_CHECK PROPOSAL_CHECK_LEVEL { cur_rmconf->pcheck_level = $2; } EOS 810 | LIFETIME LIFETYPE_TIME NUMBER unittype_time 811 { 812 prhead->lifetime = $3 * $4; 813 } 814 EOS 815 | LIFETIME LIFETYPE_BYTE NUMBER unittype_byte 816 { 817#if 1 818 yyerror("byte lifetime support is deprecated"); 819 return -1; 820#else 821 yywarn("the lifetime of bytes in phase 1 " 822 "will be ignored at the moment."); 823 prhead->lifebyte = fix_lifebyte($3 * $4); 824 if (prhead->lifebyte == 0) 825 return -1; 826#endif 827 } 828 EOS 829 | PROPOSAL 830 { 831 struct secprotospec *spspec; 832 833 spspec = newspspec(); 834 if (spspec == NULL) 835 return -1; 836 insspspec(spspec, &prhead); 837 } 838 BOC isakmpproposal_specs EOC 839 ; 840exchange_types 841 : /* nothing */ 842 | exchange_types EXCHANGETYPE 843 { 844 struct etypes *new; 845 new = racoon_malloc(sizeof(struct etypes)); 846 if (new == NULL) { 847 yyerror("filed to allocate etypes"); 848 return -1; 849 } 850 new->type = $2; 851 new->next = NULL; 852 if (cur_rmconf->etypes == NULL) 853 cur_rmconf->etypes = new; 854 else { 855 struct etypes *p; 856 for (p = cur_rmconf->etypes; 857 p->next != NULL; 858 p = p->next) 859 ; 860 p->next = new; 861 } 862 } 863 ; 864cert_spec 865 : CERT_X509 QUOTEDSTRING QUOTEDSTRING 866 { 867#ifdef HAVE_SIGNING_C 868 cur_rmconf->certtype = $1; 869 cur_rmconf->mycertfile = strdup($2->v); 870 vfree($2); 871 cur_rmconf->myprivfile = strdup($3->v); 872 vfree($3); 873#else 874 yyerror("directive not supported"); 875 return -1; 876#endif 877 } 878 EOS 879 ; 880dh_group_num 881 : ALGORITHMTYPE 882 { 883 $$ = algtype2doi(algclass_isakmp_dh, $1); 884 if ($$ == -1) { 885 yyerror("must be DH group"); 886 return -1; 887 } 888 } 889 | NUMBER 890 { 891 if (ARRAYLEN(num2dhgroup) > $1 && num2dhgroup[$1] != 0) { 892 $$ = num2dhgroup[$1]; 893 } else { 894 yyerror("must be DH group"); 895 return -1; 896 } 897 } 898 ; 899identifierstring 900 : /* nothing */ { $$ = NULL; } 901 | ADDRSTRING { $$ = $1; } 902 | QUOTEDSTRING { $$ = $1; } 903 ; 904isakmpproposal_specs 905 : /* nothing */ 906 | isakmpproposal_specs isakmpproposal_spec 907 ; 908isakmpproposal_spec 909 : STRENGTH 910 { 911 yyerror("strength directive is obsoleted."); 912 } STRENGTHTYPE EOS 913 | LIFETIME LIFETYPE_TIME NUMBER unittype_time 914 { 915 prhead->spspec->lifetime = $3 * $4; 916 } 917 EOS 918 | LIFETIME LIFETYPE_BYTE NUMBER unittype_byte 919 { 920#if 1 921 yyerror("byte lifetime support is deprecated"); 922 return -1; 923#else 924 prhead->spspec->lifebyte = fix_lifebyte($3 * $4); 925 if (prhead->spspec->lifebyte == 0) 926 return -1; 927#endif 928 } 929 EOS 930 | DH_GROUP dh_group_num 931 { 932 prhead->spspec->algclass[algclass_isakmp_dh] = $2; 933 } 934 EOS 935 | GSSAPI_ID QUOTEDSTRING 936 { 937 if (prhead->spspec->vendorid != VENDORID_GSSAPI) { 938 yyerror("wrong Vendor ID for gssapi_id"); 939 return -1; 940 } 941 prhead->spspec->gssid = strdup($2->v); 942 } 943 EOS 944 | ALGORITHM_CLASS ALGORITHMTYPE keylength 945 { 946 int doi; 947 int defklen; 948 949 doi = algtype2doi($1, $2); 950 if (doi == -1) { 951 yyerror("algorithm mismatched 1"); 952 return -1; 953 } 954 955 switch ($1) { 956 case algclass_isakmp_enc: 957 /* reject suppressed algorithms */ 958#ifndef HAVE_OPENSSL_RC5_H 959 if ($2 == algtype_rc5) { 960 yyerror("algorithm %s not supported", 961 s_attr_isakmp_enc(doi)); 962 return -1; 963 } 964#endif 965#ifndef HAVE_OPENSSL_IDEA_H 966 if ($2 == algtype_idea) { 967 yyerror("algorithm %s not supported", 968 s_attr_isakmp_enc(doi)); 969 return -1; 970 } 971#endif 972 973 prhead->spspec->algclass[algclass_isakmp_enc] = doi; 974 defklen = default_keylen($1, $2); 975 if (defklen == 0) { 976 if ($3) { 977 yyerror("keylen not allowed"); 978 return -1; 979 } 980 } else { 981 if ($3 && check_keylen($1, $2, $3) < 0) { 982 yyerror("invalid keylen %d", $3); 983 return -1; 984 } 985 } 986 if ($3) 987 prhead->spspec->encklen = $3; 988 else 989 prhead->spspec->encklen = defklen; 990 break; 991 case algclass_isakmp_hash: 992 prhead->spspec->algclass[algclass_isakmp_hash] = doi; 993 break; 994 case algclass_isakmp_ameth: 995 prhead->spspec->algclass[algclass_isakmp_ameth] = doi; 996 /* 997 * We may have to set the Vendor ID for the 998 * authentication method we're using. 999 */ 1000 switch ($2) { 1001 case algtype_gssapikrb: 1002 if (prhead->spspec->vendorid != 1003 VENDORID_UNKNOWN) { 1004 yyerror("Vendor ID mismatch " 1005 "for auth method"); 1006 return -1; 1007 } 1008 /* 1009 * For interoperability with Win2k, 1010 * we set the Vendor ID to "GSSAPI". 1011 */ 1012 prhead->spspec->vendorid = 1013 VENDORID_GSSAPI; 1014 break; 1015 default: 1016 break; 1017 } 1018 break; 1019 default: 1020 yyerror("algorithm mismatched 2"); 1021 return -1; 1022 } 1023 } 1024 EOS 1025 ; 1026 1027unittype_time 1028 : UNITTYPE_SEC { $$ = 1; } 1029 | UNITTYPE_MIN { $$ = 60; } 1030 | UNITTYPE_HOUR { $$ = (60 * 60); } 1031 ; 1032unittype_byte 1033 : UNITTYPE_BYTE { $$ = 1; } 1034 | UNITTYPE_KBYTES { $$ = 1024; } 1035 | UNITTYPE_MBYTES { $$ = (1024 * 1024); } 1036 | UNITTYPE_TBYTES { $$ = (1024 * 1024 * 1024); } 1037 ; 1038%% 1039 1040static struct proposalspec * 1041newprspec() 1042{ 1043 struct proposalspec *new; 1044 1045 new = racoon_calloc(1, sizeof(*new)); 1046 if (new == NULL) 1047 yyerror("failed to allocate proposal"); 1048 1049 return new; 1050} 1051 1052static void 1053cleanprhead() 1054{ 1055 struct proposalspec *p, *next; 1056 1057 if (prhead == NULL) 1058 return; 1059 1060 for (p = prhead; p != NULL; p = next) { 1061 next = p->next; 1062 racoon_free(p); 1063 } 1064 1065 prhead = NULL; 1066} 1067 1068/* 1069 * insert into head of list. 1070 */ 1071static void 1072insprspec(prspec, head) 1073 struct proposalspec *prspec; 1074 struct proposalspec **head; 1075{ 1076 if (*head != NULL) 1077 (*head)->prev = prspec; 1078 prspec->next = *head; 1079 *head = prspec; 1080} 1081 1082static struct secprotospec * 1083newspspec() 1084{ 1085 struct secprotospec *new; 1086 1087 new = racoon_calloc(1, sizeof(*new)); 1088 if (new == NULL) { 1089 yyerror("failed to allocate spproto"); 1090 return NULL; 1091 } 1092 1093 new->encklen = 0; /*XXX*/ 1094 1095 /* 1096 * Default to "uknown" vendor -- we will override this 1097 * as necessary. When we send a Vendor ID payload, an 1098 * "unknown" will be translated to a KAME/racoon ID. 1099 */ 1100 new->vendorid = VENDORID_UNKNOWN; 1101 1102 return new; 1103} 1104 1105/* 1106 * insert into head of list. 1107 */ 1108static void 1109insspspec(spspec, head) 1110 struct secprotospec *spspec; 1111 struct proposalspec **head; 1112{ 1113 spspec->back = *head; 1114 1115 if ((*head)->spspec != NULL) 1116 (*head)->spspec->prev = spspec; 1117 spspec->next = (*head)->spspec; 1118 (*head)->spspec = spspec; 1119} 1120 1121/* set final acceptable proposal */ 1122static int 1123set_isakmp_proposal(rmconf, prspec) 1124 struct remoteconf *rmconf; 1125 struct proposalspec *prspec; 1126{ 1127 struct proposalspec *p; 1128 struct secprotospec *s; 1129 int prop_no = 1; 1130 int trns_no = 1; 1131 u_int32_t types[MAXALGCLASS]; 1132 1133 p = prspec; 1134 if (p->next != 0) { 1135 plog(LLV_ERROR, LOCATION, NULL, 1136 "multiple proposal definition.\n"); 1137 return -1; 1138 } 1139 1140 /* mandatory check */ 1141 if (p->spspec == NULL) { 1142 yyerror("no remote specification found: %s.\n", 1143 rm2str(rmconf)); 1144 return -1; 1145 } 1146 for (s = p->spspec; s != NULL; s = s->next) { 1147 /* XXX need more to check */ 1148 if (s->algclass[algclass_isakmp_enc] == 0) { 1149 yyerror("encryption algorithm required."); 1150 return -1; 1151 } 1152 if (s->algclass[algclass_isakmp_hash] == 0) { 1153 yyerror("hash algorithm required."); 1154 return -1; 1155 } 1156 if (s->algclass[algclass_isakmp_dh] == 0) { 1157 yyerror("DH group required."); 1158 return -1; 1159 } 1160 if (s->algclass[algclass_isakmp_ameth] == 0) { 1161 yyerror("authentication method required."); 1162 return -1; 1163 } 1164 } 1165 1166 /* skip to last part */ 1167 for (s = p->spspec; s->next != NULL; s = s->next) 1168 ; 1169 1170 while (s != NULL) { 1171 plog(LLV_DEBUG2, LOCATION, NULL, 1172 "lifetime = %ld\n", (long) 1173 (s->lifetime ? s->lifetime : p->lifetime)); 1174 plog(LLV_DEBUG2, LOCATION, NULL, 1175 "lifebyte = %d\n", 1176 s->lifebyte ? s->lifebyte : p->lifebyte); 1177 plog(LLV_DEBUG2, LOCATION, NULL, 1178 "encklen=%d\n", s->encklen); 1179 1180 memset(types, 0, ARRAYLEN(types)); 1181 types[algclass_isakmp_enc] = s->algclass[algclass_isakmp_enc]; 1182 types[algclass_isakmp_hash] = s->algclass[algclass_isakmp_hash]; 1183 types[algclass_isakmp_dh] = s->algclass[algclass_isakmp_dh]; 1184 types[algclass_isakmp_ameth] = 1185 s->algclass[algclass_isakmp_ameth]; 1186 1187 /* expanding spspec */ 1188 clean_tmpalgtype(); 1189 trns_no = expand_isakmpspec(prop_no, trns_no, types, 1190 algclass_isakmp_enc, algclass_isakmp_ameth + 1, 1191 s->lifetime ? s->lifetime : p->lifetime, 1192 s->lifebyte ? s->lifebyte : p->lifebyte, 1193 s->encklen, s->vendorid, s->gssid, 1194 rmconf); 1195 if (trns_no == -1) { 1196 plog(LLV_ERROR, LOCATION, NULL, 1197 "failed to expand isakmp proposal.\n"); 1198 return -1; 1199 } 1200 1201 s = s->prev; 1202 } 1203 1204 if (rmconf->proposal == NULL) { 1205 plog(LLV_ERROR, LOCATION, NULL, 1206 "no proposal found.\n"); 1207 return -1; 1208 } 1209 1210 return 0; 1211} 1212 1213static void 1214clean_tmpalgtype() 1215{ 1216 int i; 1217 for (i = 0; i < MAXALGCLASS; i++) 1218 tmpalgtype[i] = 0; /* means algorithm undefined. */ 1219} 1220 1221static int 1222expand_isakmpspec(prop_no, trns_no, types, 1223 class, last, lifetime, lifebyte, encklen, vendorid, gssid, 1224 rmconf) 1225 int prop_no, trns_no; 1226 int *types, class, last; 1227 time_t lifetime; 1228 int lifebyte; 1229 int encklen; 1230 int vendorid; 1231 char *gssid; 1232 struct remoteconf *rmconf; 1233{ 1234 struct isakmpsa *new; 1235 1236 /* debugging */ 1237 { 1238 int j; 1239 char tb[10]; 1240 plog(LLV_DEBUG2, LOCATION, NULL, 1241 "p:%d t:%d\n", prop_no, trns_no); 1242 for (j = class; j < MAXALGCLASS; j++) { 1243 snprintf(tb, sizeof(tb), "%d", types[j]); 1244 plog(LLV_DEBUG2, LOCATION, NULL, 1245 "%s%s%s%s\n", 1246 s_algtype(j, types[j]), 1247 types[j] ? "(" : "", 1248 tb[0] == '0' ? "" : tb, 1249 types[j] ? ")" : ""); 1250 } 1251 plog(LLV_DEBUG2, LOCATION, NULL, "\n"); 1252 } 1253 1254#define TMPALGTYPE2STR(n) \ 1255 s_algtype(algclass_isakmp_##n, types[algclass_isakmp_##n]) 1256 /* check mandatory values */ 1257 if (types[algclass_isakmp_enc] == 0 1258 || types[algclass_isakmp_ameth] == 0 1259 || types[algclass_isakmp_hash] == 0 1260 || types[algclass_isakmp_dh] == 0) { 1261 yyerror("few definition of algorithm " 1262 "enc=%s ameth=%s hash=%s dhgroup=%s.\n", 1263 TMPALGTYPE2STR(enc), 1264 TMPALGTYPE2STR(ameth), 1265 TMPALGTYPE2STR(hash), 1266 TMPALGTYPE2STR(dh)); 1267 return -1; 1268 } 1269#undef TMPALGTYPE2STR 1270 1271 /* set new sa */ 1272 new = newisakmpsa(); 1273 if (new == NULL) { 1274 yyerror("failed to allocate isakmp sa"); 1275 return -1; 1276 } 1277 new->prop_no = prop_no; 1278 new->trns_no = trns_no++; 1279 new->lifetime = lifetime; 1280 new->lifebyte = lifebyte; 1281 new->enctype = types[algclass_isakmp_enc]; 1282 new->encklen = encklen; 1283 new->authmethod = types[algclass_isakmp_ameth]; 1284 new->hashtype = types[algclass_isakmp_hash]; 1285 new->dh_group = types[algclass_isakmp_dh]; 1286 new->vendorid = vendorid; 1287#ifdef HAVE_GSSAPI 1288 if (gssid != NULL) { 1289 new->gssid = vmalloc(strlen(gssid) + 1); 1290 memcpy(new->gssid->v, gssid, new->gssid->l); 1291 racoon_free(gssid); 1292 } else 1293 new->gssid = NULL; 1294#endif 1295 insisakmpsa(new, rmconf); 1296 1297 return trns_no; 1298} 1299 1300#if 0 1301/* 1302 * fix lifebyte. 1303 * Must be more than 1024B because its unit is kilobytes. 1304 * That is defined RFC2407. 1305 */ 1306static int 1307fix_lifebyte(t) 1308 unsigned long t; 1309{ 1310 if (t < 1024) { 1311 yyerror("byte size should be more than 1024B."); 1312 return 0; 1313 } 1314 1315 return(t / 1024); 1316} 1317#endif 1318 1319int 1320cfparse() 1321{ 1322 int error; 1323 1324 yycf_init_buffer(); 1325 1326 if (yycf_set_buffer(lcconf->racoon_conf) != 0) 1327 return -1; 1328 1329 prhead = NULL; 1330 1331 error = yyparse(); 1332 if (error != 0) { 1333 if (yyerrorcount) { 1334 plog(LLV_ERROR, LOCATION, NULL, 1335 "fatal parse failure (%d errors)\n", 1336 yyerrorcount); 1337 } else { 1338 plog(LLV_ERROR, LOCATION, NULL, 1339 "fatal parse failure.\n"); 1340 } 1341 return -1; 1342 } 1343 1344 if (error == 0 && yyerrorcount) { 1345 plog(LLV_ERROR, LOCATION, NULL, 1346 "parse error is nothing, but yyerrorcount is %d.\n", 1347 yyerrorcount); 1348 exit(1); 1349 } 1350 1351 yycf_clean_buffer(); 1352 1353 plog(LLV_DEBUG2, LOCATION, NULL, "parse successed.\n"); 1354 1355 return 0; 1356} 1357 1358int 1359cfreparse() 1360{ 1361 flushph2(); 1362 flushph1(); 1363 flushrmconf(); 1364 cleanprhead(); 1365 clean_tmpalgtype(); 1366 yycf_init_buffer(); 1367 1368 if (yycf_set_buffer(lcconf->racoon_conf) != 0) 1369 return -1; 1370 1371 return(cfparse()); 1372} 1373 1374