1/* $Id: ipsec_doi.c,v 1.26.2.16 2006/02/02 14:37:17 vanhu Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include "config.h" 33 34#include <sys/types.h> 35#include <sys/param.h> 36#include <sys/socket.h> 37 38#include <netinet/in.h> 39 40#ifndef HAVE_NETINET6_IPSEC 41#include <netinet/ipsec.h> 42#else 43#include <netinet6/ipsec.h> 44#endif 45 46#include <stdlib.h> 47#include <stdio.h> 48#include <string.h> 49#include <errno.h> 50#include <netdb.h> 51#if TIME_WITH_SYS_TIME 52# include <sys/time.h> 53# include <time.h> 54#else 55# if HAVE_SYS_TIME_H 56# include <sys/time.h> 57# else 58# include <time.h> 59# endif 60#endif 61 62#include "var.h" 63#include "vmbuf.h" 64#include "misc.h" 65#include "plog.h" 66#include "debug.h" 67 68#include "cfparse_proto.h" 69#include "isakmp_var.h" 70#include "isakmp.h" 71#include "ipsec_doi.h" 72#include "oakley.h" 73#include "remoteconf.h" 74#include "localconf.h" 75#include "sockmisc.h" 76#include "handler.h" 77#include "policy.h" 78#include "algorithm.h" 79#include "sainfo.h" 80#include "proposal.h" 81#include "crypto_openssl.h" 82#include "crypto_cssm.h" 83#include "strnames.h" 84#include "gcmalloc.h" 85 86#ifdef ENABLE_NATT 87#include "nattraversal.h" 88#endif 89 90#ifdef ENABLE_HYBRID 91static int switch_authmethod(int); 92#endif 93 94int verbose_proposal_check = 1; 95 96static vchar_t *get_ph1approval (phase1_handle_t *, struct prop_pair **); 97void print_ph1mismatched (struct prop_pair *, struct isakmpsa *); 98static int t2isakmpsa (struct isakmp_pl_t *, struct isakmpsa *); 99static int cmp_aproppair_i (struct prop_pair *, struct prop_pair *); 100static struct prop_pair *get_ph2approval (phase2_handle_t *, 101 struct prop_pair **); 102static struct prop_pair *get_ph2approvalx (phase2_handle_t *, 103 struct prop_pair *); 104static void free_proppair0 (struct prop_pair *); 105 106static int get_transform (struct isakmp_pl_p *, struct prop_pair **, int *); 107static u_int32_t ipsecdoi_set_ld (vchar_t *); 108 109static int check_doi (u_int32_t); 110static int check_situation (u_int32_t); 111 112static int check_prot_main (int); 113static int check_prot_quick (int); 114static int (*check_protocol[]) (int) = { 115 check_prot_main, /* IPSECDOI_TYPE_PH1 */ 116 check_prot_quick, /* IPSECDOI_TYPE_PH2 */ 117 NULL, /* IPSECDOI_TYPE_IKEV2_PH1 */ 118 NULL, /* IPSECDOI_TYPE_IKEV2_PH2 */ 119}; 120 121int check_spi_size (int, int); 122 123static int check_trns_isakmp (int); 124static int check_trns_ah (int); 125static int check_trns_esp (int); 126static int check_trns_ipcomp (int); 127static int (*check_transform[]) (int) = { 128 0, 129 check_trns_isakmp, /* IPSECDOI_PROTO_ISAKMP */ 130 check_trns_ah, /* IPSECDOI_PROTO_IPSEC_AH */ 131 check_trns_esp, /* IPSECDOI_PROTO_IPSEC_ESP */ 132 check_trns_ipcomp, /* IPSECDOI_PROTO_IPCOMP */ 133}; 134 135static int check_attr_isakmp (struct isakmp_pl_t *); 136static int check_attr_ah (struct isakmp_pl_t *); 137static int check_attr_esp (struct isakmp_pl_t *); 138static int check_attr_ipsec (int, struct isakmp_pl_t *); 139static int check_attr_ipcomp (struct isakmp_pl_t *); 140static int (*check_attributes[]) (struct isakmp_pl_t *) = { 141 0, 142 check_attr_isakmp, /* IPSECDOI_PROTO_ISAKMP */ 143 check_attr_ah, /* IPSECDOI_PROTO_IPSEC_AH */ 144 check_attr_esp, /* IPSECDOI_PROTO_IPSEC_ESP */ 145 check_attr_ipcomp, /* IPSECDOI_PROTO_IPCOMP */ 146}; 147 148int setph1prop (phase1_handle_t *, caddr_t); 149static int setph1trns (struct isakmpsa *, caddr_t); 150static int setph1attr (struct isakmpsa *, caddr_t); 151static vchar_t *setph2proposal0 (const phase2_handle_t *, 152 const struct saprop *, const struct saproto *); 153 154static vchar_t *getidval (int, vchar_t *); 155 156 157/*%%%*/ 158/* 159 * check phase 1 SA payload. 160 * make new SA payload to be replyed not including general header. 161 * the pointer to one of isakmpsa in proposal is set into iph1->approval. 162 * OUT: 163 * positive: the pointer to new buffer of SA payload. 164 * network byte order. 165 * NULL : error occurd. 166 */ 167int 168ipsecdoi_checkph1proposal(sa, iph1) 169 vchar_t *sa; 170 phase1_handle_t *iph1; 171{ 172 vchar_t *newsa; /* new SA payload approved. */ 173 struct prop_pair **pair; 174 175 /* get proposal pair */ 176 pair = get_proppair(sa, IPSECDOI_TYPE_PH1); 177 if (pair == NULL) 178 return -1; 179 180 /* check and get one SA for use */ 181 newsa = get_ph1approval(iph1, pair); 182 183 free_proppair(pair); 184 185 if (newsa == NULL) 186 return -1; 187 188 iph1->sa_ret = newsa; 189 190 return 0; 191} 192 193/* 194 * acceptable check for remote configuration. 195 * return a new SA payload to be reply to peer. 196 */ 197static vchar_t * 198get_ph1approval(iph1, pair) 199 phase1_handle_t *iph1; 200 struct prop_pair **pair; 201{ 202 vchar_t *newsa; 203 struct isakmpsa *sa, tsa; 204 struct prop_pair *s, *p; 205 int prophlen; 206 int i; 207 208 if (iph1->approval) { 209 delisakmpsa(iph1->approval); 210 iph1->approval = NULL; 211 } 212 213 for (i = 0; i < MAXPROPPAIRLEN; i++) { 214 if (pair[i] == NULL) 215 continue; 216 for (s = pair[i]; s; s = s->next) { 217 prophlen = 218 sizeof(struct isakmp_pl_p) + s->prop->spi_size; 219 220 /* compare proposal and select one */ 221 for (p = s; p; p = p->tnext) { 222 if ((sa = get_ph1approvalx(p, 223 iph1->rmconf->proposal, &tsa, 224 iph1->rmconf->pcheck_level)) != NULL) 225 goto found; 226 } 227 } 228 } 229 230 /* 231 * if there is no suitable proposal, racoon complains about all of 232 * mismatched items in those proposal. 233 */ 234 if (verbose_proposal_check) { 235 for (i = 0; i < MAXPROPPAIRLEN; i++) { 236 if (pair[i] == NULL) 237 continue; 238 for (s = pair[i]; s; s = s->next) { 239 prophlen = sizeof(struct isakmp_pl_p) 240 + s->prop->spi_size; 241 for (p = s; p; p = p->tnext) { 242 print_ph1mismatched(p, 243 iph1->rmconf->proposal); 244 } 245 } 246 } 247 } 248 plog(ASL_LEVEL_ERR, "no suitable proposal found.\n"); 249 250 return NULL; 251 252found: 253 plog(ASL_LEVEL_DEBUG, "an acceptable proposal found.\n"); 254 255 /* check DH group settings */ 256 if (sa->dhgrp) { 257 if (sa->dhgrp->prime && sa->dhgrp->gen1) { 258 /* it's ok */ 259 goto saok; 260 } 261 plog(ASL_LEVEL_WARNING, 262 "invalid DH parameter found, use default.\n"); 263 oakley_dhgrp_free(sa->dhgrp); 264 sa->dhgrp=NULL; 265 } 266 267 if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) { 268 sa->dhgrp = NULL; 269 racoon_free(sa); 270 return NULL; 271 } 272 273saok: 274 iph1->approval = sa; 275 if(iph1->approval) { 276 plog(ASL_LEVEL_DEBUG, "agreed on %s auth.\n", 277 s_oakley_attr_method(iph1->approval->authmethod)); 278 } 279 280 newsa = get_sabyproppair(p, iph1); 281 if (newsa == NULL) { 282 delisakmpsa(iph1->approval); 283 iph1->approval = NULL; 284 } 285 286 return newsa; 287} 288 289/* 290 * compare peer's single proposal and all of my proposal. 291 * and select one if suiatable. 292 * p : one of peer's proposal. 293 * proposal: my proposals. 294 */ 295struct isakmpsa * 296get_ph1approvalx(p, proposal, sap, check_level) 297 struct prop_pair *p; 298 struct isakmpsa *proposal, *sap; 299 int check_level; 300{ 301 struct isakmp_pl_p *prop = p->prop; 302 struct isakmp_pl_t *trns = p->trns; 303 struct isakmpsa sa, *s, *tsap; 304 int authmethod; 305 int tsap_authmethod; 306 307 plog(ASL_LEVEL_DEBUG, 308 "prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n", 309 prop->p_no, s_ipsecdoi_proto(prop->proto_id), 310 prop->spi_size, prop->num_t); 311 312 plog(ASL_LEVEL_DEBUG, 313 "trns#=%d, trns-id=%s\n", 314 trns->t_no, 315 s_ipsecdoi_trns(prop->proto_id, trns->t_id)); 316 317 tsap = sap != NULL ? sap : &sa; 318 319 memset(tsap, 0, sizeof(*tsap)); 320 if (t2isakmpsa(trns, tsap) < 0) 321 return NULL; 322 for (s = proposal; s != NULL; s = s->next) { 323#ifdef ENABLE_HYBRID 324 authmethod = switch_authmethod(s->authmethod); 325 tsap_authmethod = switch_authmethod(tsap->authmethod); 326#else 327 authmethod = s->authmethod; 328 tsap_authmethod = tsap->authmethod; 329#endif 330 plog(ASL_LEVEL_DEBUG, "Compared: DB:Peer\n"); 331 plog(ASL_LEVEL_DEBUG, "(version = %d:%d)\n", 332 s->version, tsap->version); 333 plog(ASL_LEVEL_DEBUG, "(lifetime = %ld:%ld)\n", 334 (long)s->lifetime, (long)tsap->lifetime); 335 plog(ASL_LEVEL_DEBUG, "(lifebyte = %zu:%zu)\n", 336 s->lifebyte, tsap->lifebyte); 337 plog(ASL_LEVEL_DEBUG, "enctype = %s:%s\n", 338 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, 339 s->enctype), 340 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, 341 tsap->enctype)); 342 plog(ASL_LEVEL_DEBUG, "(encklen = %d:%d)\n", 343 s->encklen, tsap->encklen); 344 plog(ASL_LEVEL_DEBUG, "hashtype = %s:%s\n", 345 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, 346 s->hashtype), 347 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, 348 tsap->hashtype)); 349 plog(ASL_LEVEL_DEBUG, "authmethod = %s:%s\n", 350 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, 351 s->authmethod), 352 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, 353 tsap->authmethod)); 354 plog(ASL_LEVEL_DEBUG, "dh_group = %s:%s\n", 355 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, 356 s->dh_group), 357 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, 358 tsap->dh_group)); 359#if 0 360 /* XXX to be considered ? */ 361 if (tsap->lifebyte > s->lifebyte) ; 362#endif 363 /* 364 * if responder side and peer's key length in proposal 365 * is bigger than mine, it might be accepted. 366 */ 367 if(tsap->enctype == s->enctype && 368 (tsap->authmethod == authmethod || tsap_authmethod == authmethod) && 369 tsap->hashtype == s->hashtype && 370 tsap->dh_group == s->dh_group && 371 tsap->encklen == s->encklen && 372 tsap->version == s->version) { 373 switch(check_level) { 374 case PROP_CHECK_OBEY: 375 goto found; 376 break; 377 378 case PROP_CHECK_STRICT: 379 if ((tsap->lifetime > s->lifetime) || 380 (tsap->lifebyte > s->lifebyte)) 381 continue; 382 goto found; 383 break; 384 385 case PROP_CHECK_CLAIM: 386 if (tsap->lifetime < s->lifetime) 387 s->lifetime = tsap->lifetime; 388 if (tsap->lifebyte < s->lifebyte) 389 s->lifebyte = tsap->lifebyte; 390 goto found; 391 break; 392 393 case PROP_CHECK_EXACT: 394 if ((tsap->lifetime != s->lifetime) || 395 (tsap->lifebyte != s->lifebyte)) 396 continue; 397 goto found; 398 break; 399 400 default: 401 plog(ASL_LEVEL_ERR, 402 "Unexpected proposal_check value\n"); 403 continue; 404 break; 405 } 406 } 407 } 408 409found: 410 if (tsap->dhgrp != NULL){ 411 oakley_dhgrp_free(tsap->dhgrp); 412 tsap->dhgrp = NULL; 413 } 414 415 if ((s = dupisakmpsa(s)) != NULL) { 416 switch(check_level) { 417 case PROP_CHECK_OBEY: 418 s->lifetime = tsap->lifetime; 419 s->lifebyte = tsap->lifebyte; 420 break; 421 422 case PROP_CHECK_STRICT: 423 s->lifetime = tsap->lifetime; 424 s->lifebyte = tsap->lifebyte; 425 break; 426 427 case PROP_CHECK_CLAIM: 428 if (tsap->lifetime < s->lifetime) 429 s->lifetime = tsap->lifetime; 430 if (tsap->lifebyte < s->lifebyte) 431 s->lifebyte = tsap->lifebyte; 432 break; 433 434 default: 435 break; 436 } 437 // hack to get around cisco rekeys 438 if (tsap->authmethod != authmethod && tsap_authmethod == authmethod) { 439 s->authmethod = tsap->authmethod; 440 } 441 } 442 return s; 443} 444 445/* 446 * print all of items in peer's proposal which are mismatched to my proposal. 447 * p : one of peer's proposal. 448 * proposal: my proposals. 449 */ 450void 451print_ph1mismatched(p, proposal) 452 struct prop_pair *p; 453 struct isakmpsa *proposal; 454{ 455 struct isakmpsa sa, *s; 456 457 memset(&sa, 0, sizeof(sa)); 458 if (t2isakmpsa(p->trns, &sa) < 0) 459 return; 460 for (s = proposal; s ; s = s->next) { 461 if (sa.enctype != s->enctype) { 462 plog(ASL_LEVEL_ERR, 463 "rejected enctype: " 464 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = " 465 "%s:%s\n", 466 s->prop_no, s->trns_no, 467 p->prop->p_no, p->trns->t_no, 468 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, 469 s->enctype), 470 s_oakley_attr_v(OAKLEY_ATTR_ENC_ALG, 471 sa.enctype)); 472 } 473 if (sa.authmethod != s->authmethod) { 474 plog(ASL_LEVEL_ERR, 475 "rejected authmethod: " 476 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = " 477 "%s:%s\n", 478 s->prop_no, s->trns_no, 479 p->prop->p_no, p->trns->t_no, 480 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, 481 s->authmethod), 482 s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD, 483 sa.authmethod)); 484 } 485 if (sa.hashtype != s->hashtype) { 486 plog(ASL_LEVEL_ERR, 487 "rejected hashtype: " 488 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = " 489 "%s:%s\n", 490 s->prop_no, s->trns_no, 491 p->prop->p_no, p->trns->t_no, 492 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, 493 s->hashtype), 494 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, 495 sa.hashtype)); 496 } 497 if (sa.prf != s->prf || 498 sa.prfklen != s->prfklen) { 499 plog(ASL_LEVEL_ERR, 500 "rejected prf: " 501 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = " 502 "%s.%d:%s.%d\n", 503 s->prop_no, s->trns_no, 504 p->prop->p_no, p->trns->t_no, 505 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, 506 s->prf), 507 s->prfklen, 508 s_oakley_attr_v(OAKLEY_ATTR_HASH_ALG, 509 sa.prf), 510 sa.prfklen); 511 } 512 if (sa.dh_group != s->dh_group) { 513 plog(ASL_LEVEL_ERR, 514 "rejected dh_group: " 515 "DB(prop#%d:trns#%d):Peer(prop#%d:trns#%d) = " 516 "%s:%s\n", 517 s->prop_no, s->trns_no, 518 p->prop->p_no, p->trns->t_no, 519 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, 520 s->dh_group), 521 s_oakley_attr_v(OAKLEY_ATTR_GRP_DESC, 522 sa.dh_group)); 523 } 524 } 525 526 if (sa.dhgrp != NULL){ 527 oakley_dhgrp_free(sa.dhgrp); 528 sa.dhgrp=NULL; 529 } 530} 531 532/* 533 * get ISAKMP data attributes 534 */ 535static int 536t2isakmpsa(trns, sa) 537 struct isakmp_pl_t *trns; 538 struct isakmpsa *sa; 539{ 540 struct isakmp_data *d, *prev; 541 int flag, type; 542 int error = -1; 543 int life_t; 544 int keylen = 0; 545 vchar_t *val = NULL; 546 int len, tlen; 547 u_char *p; 548 549 tlen = ntohs(trns->h.len) - sizeof(*trns); 550 prev = (struct isakmp_data *)NULL; 551 d = (struct isakmp_data *)(trns + 1); 552 553 /* default */ 554 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT; 555 sa->lifetime = OAKLEY_ATTR_SA_LD_SEC_DEFAULT; 556 sa->lifebyte = 0; 557 sa->dhgrp = racoon_calloc(1, sizeof(struct dhgroup)); 558 if (!sa->dhgrp) 559 goto err; 560 561 while (tlen > 0) { 562 563 type = ntohs(d->type) & ~ISAKMP_GEN_MASK; 564 flag = ntohs(d->type) & ISAKMP_GEN_MASK; 565 566 plog(ASL_LEVEL_DEBUG, 567 "type=%s, flag=0x%04x, lorv=%s\n", 568 s_oakley_attr(type), flag, 569 s_oakley_attr_v(type, ntohs(d->lorv))); 570 571 /* get variable-sized item */ 572 switch (type) { 573 case OAKLEY_ATTR_GRP_PI: 574 case OAKLEY_ATTR_GRP_GEN_ONE: 575 case OAKLEY_ATTR_GRP_GEN_TWO: 576 case OAKLEY_ATTR_GRP_CURVE_A: 577 case OAKLEY_ATTR_GRP_CURVE_B: 578 case OAKLEY_ATTR_SA_LD: 579 case OAKLEY_ATTR_GRP_ORDER: 580 if (flag) { /*TV*/ 581 len = 2; 582 p = (u_char *)&d->lorv; 583 } else { /*TLV*/ 584 len = ntohs(d->lorv); 585 if (len > tlen) { 586 plog(ASL_LEVEL_ERR, 587 "invalid ISAKMP-SA attr, attr-len %d, overall-len %d\n", 588 len, tlen); 589 return -1; 590 } 591 p = (u_char *)(d + 1); 592 } 593 val = vmalloc(len); 594 if (!val) 595 return -1; 596 memcpy(val->v, p, len); 597 break; 598 599 default: 600 break; 601 } 602 603 switch (type) { 604 case OAKLEY_ATTR_ENC_ALG: 605 sa->enctype = (u_int16_t)ntohs(d->lorv); 606 break; 607 608 case OAKLEY_ATTR_HASH_ALG: 609 sa->hashtype = (u_int16_t)ntohs(d->lorv); 610 break; 611 612 case OAKLEY_ATTR_AUTH_METHOD: 613 sa->authmethod = ntohs(d->lorv); 614 break; 615 616 case OAKLEY_ATTR_GRP_DESC: 617 sa->dh_group = (u_int16_t)ntohs(d->lorv); 618 break; 619 620 case OAKLEY_ATTR_GRP_TYPE: 621 { 622 int type = (int)ntohs(d->lorv); 623 if (type == OAKLEY_ATTR_GRP_TYPE_MODP) 624 sa->dhgrp->type = type; 625 else 626 return -1; 627 break; 628 } 629 case OAKLEY_ATTR_GRP_PI: 630 sa->dhgrp->prime = val; 631 break; 632 633 case OAKLEY_ATTR_GRP_GEN_ONE: 634 vfree(val); 635 if (!flag) 636 sa->dhgrp->gen1 = ntohs(d->lorv); 637 else { 638 int len = ntohs(d->lorv); 639 sa->dhgrp->gen1 = 0; 640 if (len > 4) 641 return -1; 642 memcpy(&sa->dhgrp->gen1, d + 1, len); 643 sa->dhgrp->gen1 = ntohl(sa->dhgrp->gen1); 644 } 645 break; 646 647 case OAKLEY_ATTR_GRP_GEN_TWO: 648 vfree(val); 649 if (!flag) 650 sa->dhgrp->gen2 = ntohs(d->lorv); 651 else { 652 int len = ntohs(d->lorv); 653 sa->dhgrp->gen2 = 0; 654 if (len > 4) 655 return -1; 656 memcpy(&sa->dhgrp->gen2, d + 1, len); 657 sa->dhgrp->gen2 = ntohl(sa->dhgrp->gen2); 658 } 659 break; 660 661 case OAKLEY_ATTR_GRP_CURVE_A: 662 sa->dhgrp->curve_a = val; 663 break; 664 665 case OAKLEY_ATTR_GRP_CURVE_B: 666 sa->dhgrp->curve_b = val; 667 break; 668 669 case OAKLEY_ATTR_SA_LD_TYPE: 670 { 671 int type = (int)ntohs(d->lorv); 672 switch (type) { 673 case OAKLEY_ATTR_SA_LD_TYPE_SEC: 674 case OAKLEY_ATTR_SA_LD_TYPE_KB: 675 life_t = type; 676 break; 677 default: 678 life_t = OAKLEY_ATTR_SA_LD_TYPE_DEFAULT; 679 break; 680 } 681 break; 682 } 683 case OAKLEY_ATTR_SA_LD: 684 if (!prev 685 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) != 686 OAKLEY_ATTR_SA_LD_TYPE) { 687 plog(ASL_LEVEL_ERR, 688 "life duration must follow ltype\n"); 689 break; 690 } 691 692 switch (life_t) { 693 case IPSECDOI_ATTR_SA_LD_TYPE_SEC: 694 sa->lifetime = ipsecdoi_set_ld(val); 695 vfree(val); 696 if (sa->lifetime == 0) { 697 plog(ASL_LEVEL_ERR, 698 "invalid life duration.\n"); 699 goto err; 700 } 701 break; 702 case IPSECDOI_ATTR_SA_LD_TYPE_KB: 703 sa->lifebyte = ipsecdoi_set_ld(val); 704 vfree(val); 705 if (sa->lifebyte == 0) { 706 plog(ASL_LEVEL_ERR, 707 "invalid life duration.\n"); 708 goto err; 709 } 710 break; 711 default: 712 vfree(val); 713 plog(ASL_LEVEL_ERR, 714 "invalid life type: %d\n", life_t); 715 goto err; 716 } 717 break; 718 719 case OAKLEY_ATTR_KEY_LEN: 720 { 721 int len = ntohs(d->lorv); 722 if (len % 8 != 0) { 723 plog(ASL_LEVEL_ERR, 724 "keylen %d: not multiple of 8\n", 725 len); 726 goto err; 727 } 728 sa->encklen = (u_int16_t)len; 729 keylen++; 730 break; 731 } 732 case OAKLEY_ATTR_PRF: 733 case OAKLEY_ATTR_FIELD_SIZE: 734 /* unsupported */ 735 break; 736 737 case OAKLEY_ATTR_GRP_ORDER: 738 sa->dhgrp->order = val; 739 break; 740 741 default: 742 break; 743 } 744 745 prev = d; 746 if (flag) { 747 tlen -= sizeof(*d); 748 d = (struct isakmp_data *)((char *)d + sizeof(*d)); 749 } else { 750 tlen -= (sizeof(*d) + ntohs(d->lorv)); 751 d = (struct isakmp_data *)((char *)d + sizeof(*d) + ntohs(d->lorv)); 752 } 753 } 754 755 /* key length must not be specified on some algorithms */ 756 if (keylen) { 757 if (sa->enctype == OAKLEY_ATTR_ENC_ALG_DES 758 || sa->enctype == OAKLEY_ATTR_ENC_ALG_3DES) { 759 plog(ASL_LEVEL_ERR, 760 "keylen must not be specified " 761 "for encryption algorithm %d\n", 762 sa->enctype); 763 return -1; 764 } 765 } 766 767 return 0; 768err: 769 return error; 770} 771 772/*%%%*/ 773/* 774 * check phase 2 SA payload and select single proposal. 775 * make new SA payload to be replyed not including general header. 776 * This function is called by responder only. 777 * OUT: 778 * 0: succeed. 779 * -1: error occured. 780 */ 781int 782ipsecdoi_selectph2proposal(iph2) 783 phase2_handle_t *iph2; 784{ 785 struct prop_pair **pair; 786 struct prop_pair *ret; 787 788 /* get proposal pair */ 789 pair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2); 790 if (pair == NULL) 791 return -1; 792 793 /* check and select a proposal. */ 794 ret = get_ph2approval(iph2, pair); 795 free_proppair(pair); 796 if (ret == NULL) 797 return -1; 798 799 /* make a SA to be replayed. */ 800 /* SPI must be updated later. */ 801 iph2->sa_ret = get_sabyproppair(ret, iph2->ph1); 802 free_proppair0(ret); 803 if (iph2->sa_ret == NULL) 804 return -1; 805 806 return 0; 807} 808 809/* 810 * check phase 2 SA payload returned from responder. 811 * This function is called by initiator only. 812 * OUT: 813 * 0: valid. 814 * -1: invalid. 815 */ 816int 817ipsecdoi_checkph2proposal(iph2) 818 phase2_handle_t *iph2; 819{ 820 struct prop_pair **rpair = NULL, **spair = NULL; 821 struct prop_pair *p; 822 int i, n, num; 823 int error = -1; 824 vchar_t *sa_ret = NULL; 825 826 /* get proposal pair of SA sent. */ 827 spair = get_proppair(iph2->sa, IPSECDOI_TYPE_PH2); 828 if (spair == NULL) { 829 plog(ASL_LEVEL_ERR, 830 "failed to get prop pair.\n"); 831 goto end; 832 } 833 834 /* XXX should check the number of transform */ 835 836 /* get proposal pair of SA replayed */ 837 rpair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2); 838 if (rpair == NULL) { 839 plog(ASL_LEVEL_ERR, 840 "failed to get prop pair.\n"); 841 goto end; 842 } 843 844 /* check proposal is only one ? */ 845 n = 0; 846 num = 0; 847 for (i = 0; i < MAXPROPPAIRLEN; i++) { 848 if (rpair[i]) { 849 n = i; 850 num++; 851 } 852 } 853 if (num == 0) { 854 plog(ASL_LEVEL_ERR, 855 "no proposal received.\n"); 856 goto end; 857 } 858 if (num != 1) { 859 plog(ASL_LEVEL_ERR, 860 "some proposals received.\n"); 861 goto end; 862 } 863 864 if (spair[n] == NULL) { 865 plog(ASL_LEVEL_WARNING, 866 "invalid proposal number:%d received.\n", i); 867 } 868 869 870 if (rpair[n]->tnext != NULL) { 871 plog(ASL_LEVEL_ERR, 872 "multi transforms replyed.\n"); 873 goto end; 874 } 875 876 if (cmp_aproppair_i(rpair[n], spair[n])) { 877 plog(ASL_LEVEL_ERR, 878 "proposal mismathed.\n"); 879 goto end; 880 } 881 882 /* 883 * check and select a proposal. 884 * ensure that there is no modification of the proposal by 885 * cmp_aproppair_i() 886 */ 887 p = get_ph2approval(iph2, rpair); 888 if (p == NULL) 889 goto end; 890 891 /* make a SA to be replayed. */ 892 sa_ret = iph2->sa_ret; 893 iph2->sa_ret = get_sabyproppair(p, iph2->ph1); 894 free_proppair0(p); 895 if (iph2->sa_ret == NULL) 896 goto end; 897 898 error = 0; 899 900end: 901 if (rpair) 902 free_proppair(rpair); 903 if (spair) 904 free_proppair(spair); 905 if (sa_ret) 906 vfree(sa_ret); 907 908 return error; 909} 910 911/* 912 * compare two prop_pair which is assumed to have same proposal number. 913 * the case of bundle or single SA, NOT multi transforms. 914 * a: a proposal that is multi protocols and single transform, usually replyed. 915 * b: a proposal that is multi protocols and multi transform, usually sent. 916 * NOTE: this function is for initiator. 917 * OUT 918 * 0: equal 919 * 1: not equal 920 * XXX cannot understand the comment! 921 */ 922static int 923cmp_aproppair_i(a, b) 924 struct prop_pair *a, *b; 925{ 926 struct prop_pair *p, *q, *r; 927 int len; 928 929 for (p = a, q = b; p && q; p = p->next, q = q->next) { 930 for (r = q; r; r = r->tnext) { 931 /* compare trns */ 932 if (p->trns->t_no == r->trns->t_no) 933 break; 934 } 935 if (!r) { 936 /* no suitable transform found */ 937 plog(ASL_LEVEL_ERR, 938 "no suitable transform found.\n"); 939 return -1; 940 } 941 942 /* compare prop */ 943 if (p->prop->p_no != r->prop->p_no) { 944 plog(ASL_LEVEL_WARNING, 945 "proposal #%d mismatched, " 946 "expected #%d.\n", 947 r->prop->p_no, p->prop->p_no); 948 /*FALLTHROUGH*/ 949 } 950 951 if (p->prop->proto_id != r->prop->proto_id) { 952 plog(ASL_LEVEL_ERR, 953 "proto_id mismathed: my:%d peer:%d\n", 954 r->prop->proto_id, p->prop->proto_id); 955 return -1; 956 } 957 958 if (p->prop->proto_id != r->prop->proto_id) { 959 plog(ASL_LEVEL_ERR, 960 "invalid spi size: %d.\n", 961 p->prop->proto_id); 962 return -1; 963 } 964 965 /* check #of transforms */ 966 if (p->prop->num_t != 1) { 967 plog(ASL_LEVEL_WARNING, 968 "#of transform is %d, " 969 "but expected 1.\n", p->prop->num_t); 970 /*FALLTHROUGH*/ 971 } 972 973 if (p->trns->t_id != r->trns->t_id) { 974 plog(ASL_LEVEL_WARNING, 975 "transform number has been modified.\n"); 976 /*FALLTHROUGH*/ 977 } 978 if (p->trns->reserved != r->trns->reserved) { 979 plog(ASL_LEVEL_WARNING, 980 "reserved field should be zero.\n"); 981 /*FALLTHROUGH*/ 982 } 983 984 /* compare attribute */ 985 len = ntohs(r->trns->h.len) - sizeof(*p->trns); 986 if (memcmp(p->trns + 1, r->trns + 1, len) != 0) { 987 plog(ASL_LEVEL_WARNING, 988 "attribute has been modified.\n"); 989 /*FALLTHROUGH*/ 990 } 991 } 992 if ((p && !q) || (!p && q)) { 993 /* # of protocols mismatched */ 994 plog(ASL_LEVEL_ERR, 995 "#of protocols mismatched.\n"); 996 return -1; 997 } 998 999 return 0; 1000} 1001 1002/* 1003 * acceptable check for policy configuration. 1004 * return a new SA payload to be reply to peer. 1005 */ 1006static struct prop_pair * 1007get_ph2approval(iph2, pair) 1008 phase2_handle_t *iph2; 1009 struct prop_pair **pair; 1010{ 1011 struct prop_pair *ret; 1012 int i; 1013 1014 iph2->approval = NULL; 1015 1016 plog(ASL_LEVEL_DEBUG, 1017 "begin compare proposals.\n"); 1018 1019 for (i = 0; i < MAXPROPPAIRLEN; i++) { 1020 if (pair[i] == NULL) 1021 continue; 1022 plog(ASL_LEVEL_DEBUG, 1023 "pair[%d]: %p\n", i, pair[i]); 1024 print_proppair(ASL_LEVEL_DEBUG, pair[i]);; 1025 1026 /* compare proposal and select one */ 1027 ret = get_ph2approvalx(iph2, pair[i]); 1028 if (ret != NULL) { 1029 /* found */ 1030 return ret; 1031 } 1032 } 1033 1034 plog(ASL_LEVEL_ERR, "no suitable policy found.\n"); 1035 1036 return NULL; 1037} 1038 1039/* 1040 * compare my proposal and peers just one proposal. 1041 * set a approval. 1042 */ 1043static struct prop_pair * 1044get_ph2approvalx(iph2, pp) 1045 phase2_handle_t *iph2; 1046 struct prop_pair *pp; 1047{ 1048 struct prop_pair *ret = NULL; 1049 struct saprop *pr0, *pr = NULL; 1050 struct saprop *q1, *q2; 1051 1052 pr0 = aproppair2saprop(pp); 1053 if (pr0 == NULL) 1054 return NULL; 1055 1056 for (q1 = pr0; q1; q1 = q1->next) { 1057 for (q2 = iph2->proposal; q2; q2 = q2->next) { 1058 plog(ASL_LEVEL_DEBUG, 1059 "peer's single bundle:\n"); 1060 printsaprop0(ASL_LEVEL_DEBUG, q1); 1061 plog(ASL_LEVEL_DEBUG, 1062 "my single bundle:\n"); 1063 printsaprop0(ASL_LEVEL_DEBUG, q2); 1064 1065 pr = cmpsaprop_alloc(iph2->ph1, q1, q2, iph2->side); 1066 if (pr != NULL) 1067 goto found; 1068 1069 plog(ASL_LEVEL_ERR, 1070 "not matched\n"); 1071 } 1072 } 1073 /* no proposal matching */ 1074err: 1075 if (pr0 != NULL) { 1076 flushsaprop(pr0); 1077 pr0 = NULL; 1078 } 1079 return NULL; 1080 1081found: 1082 if (pr0 != NULL) { 1083 flushsaprop(pr0); 1084 pr0 = NULL; 1085 } 1086 plog(ASL_LEVEL_DEBUG, "matched\n"); 1087 iph2->approval = pr; 1088 1089 { 1090 struct saproto *sp; 1091 struct prop_pair *p, *x; 1092 struct prop_pair *n = NULL; 1093 1094 ret = NULL; 1095 1096 for (p = pp; p; p = p->next) { 1097 /* 1098 * find a proposal with matching proto_id. 1099 * we have analyzed validity already, in cmpsaprop_alloc(). 1100 */ 1101 for (sp = pr->head; sp; sp = sp->next) { 1102 if (sp->proto_id == p->prop->proto_id) 1103 break; 1104 } 1105 if (!sp) 1106 goto err; 1107 if (sp->head->next) 1108 goto err; /* XXX */ 1109 1110 for (x = p; x; x = x->tnext) 1111 if (sp->head->trns_no == x->trns->t_no) 1112 break; 1113 if (!x) 1114 goto err; /* XXX */ 1115 1116 n = racoon_calloc(1, sizeof(struct prop_pair)); 1117 if (n == NULL) { 1118 plog(ASL_LEVEL_ERR, 1119 "failed to get buffer.\n"); 1120 goto err; 1121 } 1122 1123 n->prop = x->prop; 1124 n->trns = x->trns; 1125 1126 /* need to preserve the order */ 1127 for (x = ret; x && x->next; x = x->next) 1128 ; 1129 if (x && x->prop == n->prop) { 1130 for (/*nothing*/; x && x->tnext; x = x->tnext) 1131 ; 1132 x->tnext = n; 1133 } else { 1134 if (x) 1135 x->next = n; 1136 else { 1137 ret = n; 1138 } 1139 } 1140 1141 /* #of transforms should be updated ? */ 1142 } 1143 } 1144 1145 return ret; 1146} 1147 1148void 1149free_proppair(pair) 1150 struct prop_pair **pair; 1151{ 1152 int i; 1153 1154 for (i = 0; i < MAXPROPPAIRLEN; i++) { 1155 free_proppair0(pair[i]); 1156 pair[i] = NULL; 1157 } 1158 racoon_free(pair); 1159} 1160 1161static void 1162free_proppair0(pair) 1163 struct prop_pair *pair; 1164{ 1165 struct prop_pair *p, *q, *r, *s; 1166 1167 p = pair; 1168 while (p) { 1169 q = p->next; 1170 r = p; 1171 while (r) { 1172 s = r->tnext; 1173 racoon_free(r); 1174 r = s; 1175 } 1176 p = q; 1177 } 1178} 1179 1180/* 1181 * get proposal pairs from SA payload. 1182 * tiny check for proposal payload. 1183 */ 1184struct prop_pair ** 1185get_proppair(sa, mode) 1186 vchar_t *sa; 1187 int mode; 1188{ 1189 struct prop_pair **pair = NULL; 1190 int num_p = 0; /* number of proposal for use */ 1191 int tlen; 1192 caddr_t bp; 1193 int i; 1194 1195 //plogdump(ASL_LEVEL_DEBUG, sa->v, sa->l, "total SA len=%zu\n", sa->l); 1196 1197 if (mode == IPSECDOI_TYPE_PH1 || mode == IPSECDOI_TYPE_PH2) { 1198 // IKEv1 1199 struct ipsecdoi_sa_b *sab = ALIGNED_CAST(__typeof__(sab))sa->v; 1200 1201 1202 /* check SA payload size */ 1203 if (sa->l < sizeof(*sab)) { 1204 plog(ASL_LEVEL_ERR, 1205 "Invalid SA length = %zu.\n", sa->l); 1206 goto bad; 1207 } 1208 1209 /* check DOI */ 1210 if (check_doi(ntohl(sab->doi)) < 0) 1211 goto bad; 1212 1213 /* check SITUATION */ 1214 if (check_situation(ntohl(sab->sit)) < 0) 1215 goto bad; 1216 1217 bp = (caddr_t)(sab + 1); 1218 tlen = sa->l - sizeof(*sab); 1219 } else { 1220 bp = (__typeof__(bp))sa->v; 1221 tlen = sa->l; 1222 } 1223 1224 pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair)); 1225 if (pair == NULL) { 1226 plog(ASL_LEVEL_ERR, 1227 "failed to get buffer.\n"); 1228 goto bad; 1229 } 1230 1231 { 1232 struct isakmp_pl_p *prop; 1233 int proplen; 1234 vchar_t *pbuf = NULL; 1235 struct isakmp_parse_t *pa; 1236 1237 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen); 1238 if (pbuf == NULL) 1239 goto bad; 1240 1241 for (pa = ALIGNED_CAST(struct isakmp_parse_t *)pbuf->v; 1242 pa->type != ISAKMP_NPTYPE_NONE; 1243 pa++) { 1244 /* check the value of next payload */ 1245 if (pa->type != ISAKMP_NPTYPE_P) { 1246 plog(ASL_LEVEL_ERR, 1247 "Invalid payload type=%u\n", pa->type); 1248 vfree(pbuf); 1249 goto bad; 1250 } 1251 1252 prop = (struct isakmp_pl_p *)pa->ptr; 1253 proplen = pa->len; 1254 1255 plog(ASL_LEVEL_DEBUG, 1256 "proposal #%u len=%d\n", prop->p_no, proplen); 1257 1258 if (proplen == 0) { 1259 plog(ASL_LEVEL_ERR, 1260 "invalid proposal with length %d\n", proplen); 1261 vfree(pbuf); 1262 goto bad; 1263 } 1264 1265 /* check Protocol ID */ 1266 if (!check_protocol[mode]) { 1267 plog(ASL_LEVEL_ERR, 1268 "unsupported mode %d\n", mode); 1269 continue; 1270 } 1271 1272 if (check_protocol[mode](prop->proto_id) < 0) 1273 continue; 1274 1275 /* check SPI length when IKE. */ 1276 if (check_spi_size(prop->proto_id, prop->spi_size) < 0) 1277 continue; 1278 1279 /* get transform */ 1280 if (get_transform(prop, pair, &num_p) < 0) { 1281 vfree(pbuf); 1282 goto bad; 1283 } 1284 } 1285 vfree(pbuf); 1286 pbuf = NULL; 1287 } 1288 1289 { 1290 int notrans, nprop; 1291 struct prop_pair *p, *q; 1292 1293 /* check for proposals with no transforms */ 1294 for (i = 0; i < MAXPROPPAIRLEN; i++) { 1295 if (!pair[i]) 1296 continue; 1297 1298 plog(ASL_LEVEL_DEBUG, "pair %d:\n", i); 1299 print_proppair(ASL_LEVEL_DEBUG, pair[i]); 1300 1301 notrans = nprop = 0; 1302 for (p = pair[i]; p; p = p->next) { 1303 if (p->trns == NULL) { 1304 notrans++; 1305 break; 1306 } 1307 for (q = p; q; q = q->tnext) 1308 nprop++; 1309 } 1310 1311#if 0 1312 /* 1313 * XXX at this moment, we cannot accept proposal group 1314 * with multiple proposals. this should be fixed. 1315 */ 1316 if (pair[i]->next) { 1317 plog(ASL_LEVEL_WARNING, 1318 "proposal #%u ignored " 1319 "(multiple proposal not supported)\n", 1320 pair[i]->prop->p_no); 1321 notrans++; 1322 } 1323#endif 1324 1325 if (notrans) { 1326 for (p = pair[i]; p; p = q) { 1327 q = p->next; 1328 racoon_free(p); 1329 } 1330 pair[i] = NULL; 1331 num_p--; 1332 } else { 1333 plog(ASL_LEVEL_DEBUG, 1334 "proposal #%u: %d transform\n", 1335 pair[i]->prop->p_no, nprop); 1336 } 1337 } 1338 } 1339 1340 /* bark if no proposal is found. */ 1341 if (num_p <= 0) { 1342 plog(ASL_LEVEL_ERR, 1343 "no Proposal found.\n"); 1344 goto bad; 1345 } 1346 1347 return pair; 1348bad: 1349 if (pair != NULL) 1350 racoon_free(pair); 1351 return NULL; 1352} 1353 1354/* 1355 * check transform payload. 1356 * OUT: 1357 * positive: return the pointer to the payload of valid transform. 1358 * 0 : No valid transform found. 1359 */ 1360static int 1361get_transform(prop, pair, num_p) 1362 struct isakmp_pl_p *prop; 1363 struct prop_pair **pair; 1364 int *num_p; 1365{ 1366 int tlen; /* total length of all transform in a proposal */ 1367 caddr_t bp; 1368 struct isakmp_pl_t *trns; 1369 int trnslen; 1370 vchar_t *pbuf = NULL; 1371 struct isakmp_parse_t *pa; 1372 struct prop_pair *p = NULL, *q; 1373 int num_t; 1374 1375 bp = (caddr_t)prop + sizeof(struct isakmp_pl_p) + prop->spi_size; 1376 tlen = ntohs(prop->h.len) 1377 - (sizeof(struct isakmp_pl_p) + prop->spi_size); 1378 pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_T, (struct isakmp_gen *)bp, tlen); 1379 if (pbuf == NULL) 1380 return -1; 1381 1382 /* check and get transform for use */ 1383 num_t = 0; 1384 for (pa = ALIGNED_CAST(struct isakmp_parse_t *)pbuf->v; 1385 pa->type != ISAKMP_NPTYPE_NONE; 1386 pa++) { 1387 1388 num_t++; 1389 1390 /* check the value of next payload */ 1391 if (pa->type != ISAKMP_NPTYPE_T) { 1392 plog(ASL_LEVEL_ERR, 1393 "Invalid payload type=%u\n", pa->type); 1394 break; 1395 } 1396 1397 trns = (struct isakmp_pl_t *)pa->ptr; 1398 trnslen = pa->len; 1399 1400 plog(ASL_LEVEL_DEBUG, 1401 "transform #%u len=%u\n", trns->t_no, trnslen); 1402 1403 /* check transform ID */ 1404 if (prop->proto_id >= ARRAYLEN(check_transform)) { 1405 plog(ASL_LEVEL_WARNING, 1406 "unsupported proto_id %u\n", 1407 prop->proto_id); 1408 continue; 1409 } 1410 if (prop->proto_id >= ARRAYLEN(check_attributes)) { 1411 plog(ASL_LEVEL_WARNING, 1412 "unsupported proto_id %u\n", 1413 prop->proto_id); 1414 continue; 1415 } 1416 1417 if (!check_transform[prop->proto_id] 1418 || !check_attributes[prop->proto_id]) { 1419 plog(ASL_LEVEL_WARNING, 1420 "unsupported proto_id %u\n", 1421 prop->proto_id); 1422 continue; 1423 } 1424 if (check_transform[prop->proto_id](trns->t_id) < 0) 1425 continue; 1426 1427 /* check data attributes */ 1428 if (check_attributes[prop->proto_id](trns) != 0) 1429 continue; 1430 1431 p = racoon_calloc(1, sizeof(*p)); 1432 if (p == NULL) { 1433 plog(ASL_LEVEL_ERR, 1434 "failed to get buffer.\n"); 1435 vfree(pbuf); 1436 return -1; 1437 } 1438 p->prop = prop; 1439 p->trns = trns; 1440 1441 /* need to preserve the order */ 1442 for (q = pair[prop->p_no]; q && q->next; q = q->next) 1443 ; 1444 if (q && q->prop == p->prop) { 1445 for (/*nothing*/; q && q->tnext; q = q->tnext) 1446 ; 1447 q->tnext = p; 1448 } else { 1449 if (q) 1450 q->next = p; 1451 else { 1452 pair[prop->p_no] = p; 1453 (*num_p)++; 1454 } 1455 } 1456 } 1457 1458 vfree(pbuf); 1459 1460 return 0; 1461} 1462 1463/* 1464 * make a new SA payload from prop_pair. 1465 * NOTE: this function clears the spi value. 1466 */ 1467vchar_t * 1468get_sabyproppair(pair, iph1) 1469 struct prop_pair *pair; 1470 phase1_handle_t *iph1; 1471{ 1472 vchar_t *newsa; 1473 int newtlen; 1474 u_int8_t *np_p = NULL; 1475 struct prop_pair *p; 1476 int prophlen, trnslen; 1477 caddr_t bp; 1478 1479 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) { 1480 newtlen = sizeof(struct ipsecdoi_sa_b); 1481 } else { 1482 newtlen = 0; 1483 } 1484 for (p = pair; p; p = p->next) { 1485 newtlen += sizeof(struct isakmp_pl_p); 1486 newtlen += p->prop->spi_size; 1487 newtlen += ntohs(p->trns->h.len); 1488 } 1489 1490 newsa = vmalloc(newtlen); 1491 if (newsa == NULL) { 1492 plog(ASL_LEVEL_ERR, "failed to get newsa.\n"); 1493 return NULL; 1494 } 1495 bp = newsa->v; 1496 1497 ((struct isakmp_gen *)bp)->len = htons(newtlen); 1498 1499 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) { 1500 /* update some of values in SA header */ 1501 (ALIGNED_CAST(struct ipsecdoi_sa_b *)bp)->doi = htonl(iph1->rmconf->doitype); 1502 (ALIGNED_CAST(struct ipsecdoi_sa_b *)bp)->sit = htonl(iph1->rmconf->sittype); 1503 bp += sizeof(struct ipsecdoi_sa_b); 1504 } 1505 1506 /* create proposal payloads */ 1507 for (p = pair; p; p = p->next) { 1508 prophlen = sizeof(struct isakmp_pl_p) 1509 + p->prop->spi_size; 1510 trnslen = ntohs(p->trns->h.len); 1511 1512 if (np_p) 1513 *np_p = ISAKMP_NPTYPE_P; 1514 1515 /* create proposal */ 1516 1517 memcpy(bp, p->prop, prophlen); 1518 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE; 1519 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen); 1520 ((struct isakmp_pl_p *)bp)->num_t = 1; 1521 np_p = &((struct isakmp_pl_p *)bp)->h.np; 1522 memset(bp + sizeof(struct isakmp_pl_p), 0, p->prop->spi_size); 1523 bp += prophlen; 1524 1525 /* create transform */ 1526 memcpy(bp, p->trns, trnslen); 1527 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE; 1528 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen); 1529 bp += trnslen; 1530 } 1531 1532 return newsa; 1533} 1534 1535/* 1536 * update responder's spi 1537 */ 1538int 1539ipsecdoi_updatespi(iph2) 1540 phase2_handle_t *iph2; 1541{ 1542 struct prop_pair **pair, *p; 1543 struct saprop *pp; 1544 struct saproto *pr; 1545 int i; 1546 int error = -1; 1547 u_int8_t *spi; 1548 1549 pair = get_proppair(iph2->sa_ret, IPSECDOI_TYPE_PH2); 1550 if (pair == NULL) 1551 return -1; 1552 for (i = 0; i < MAXPROPPAIRLEN; i++) { 1553 if (pair[i]) 1554 break; 1555 } 1556 if (i == MAXPROPPAIRLEN || pair[i]->tnext) { 1557 /* multiple transform must be filtered by selectph2proposal.*/ 1558 goto end; 1559 } 1560 1561 pp = iph2->approval; 1562 1563 /* create proposal payloads */ 1564 for (p = pair[i]; p; p = p->next) { 1565 /* 1566 * find a proposal/transform with matching proto_id/t_id. 1567 * we have analyzed validity already, in cmpsaprop_alloc(). 1568 */ 1569 for (pr = pp->head; pr; pr = pr->next) { 1570 if (p->prop->proto_id == pr->proto_id && 1571 p->trns->t_id == pr->head->trns_id) { 1572 break; 1573 } 1574 } 1575 if (!pr) 1576 goto end; 1577 1578 /* 1579 * XXX SPI bits are left-filled, for use with IPComp. 1580 * we should be switching to variable-length spi field... 1581 */ 1582 spi = (u_int8_t *)&pr->spi; 1583 spi += sizeof(pr->spi); 1584 spi -= pr->spisize; 1585 memcpy((caddr_t)p->prop + sizeof(*p->prop), spi, pr->spisize); 1586 } 1587 1588 error = 0; 1589end: 1590 free_proppair(pair); 1591 return error; 1592} 1593 1594/* 1595 * make a new SA payload from prop_pair. 1596 */ 1597vchar_t * 1598get_sabysaprop(pp0, sa0) 1599 struct saprop *pp0; 1600 vchar_t *sa0; 1601{ 1602 struct prop_pair **pair = NULL; 1603 vchar_t *newsa = NULL; 1604 int newtlen; 1605 u_int8_t *np_p = NULL; 1606 struct prop_pair *p = NULL; 1607 struct saprop *pp; 1608 struct saproto *pr; 1609 struct satrns *tr; 1610 int prophlen, trnslen; 1611 caddr_t bp; 1612 int error = -1; 1613 1614 /* get proposal pair */ 1615 pair = get_proppair(sa0, IPSECDOI_TYPE_PH2); 1616 if (pair == NULL) 1617 goto out; 1618 1619 newtlen = sizeof(struct ipsecdoi_sa_b); 1620 for (pp = pp0; pp; pp = pp->next) { 1621 1622 if (pair[pp->prop_no] == NULL) 1623 goto out; 1624 1625 for (pr = pp->head; pr; pr = pr->next) { 1626 newtlen += (sizeof(struct isakmp_pl_p) 1627 + pr->spisize); 1628 1629 for (tr = pr->head; tr; tr = tr->next) { 1630 for (p = pair[pp->prop_no]; p; p = p->tnext) { 1631 if (tr->trns_no == p->trns->t_no) 1632 break; 1633 } 1634 if (p == NULL) 1635 goto out; 1636 1637 newtlen += ntohs(p->trns->h.len); 1638 } 1639 } 1640 } 1641 1642 newsa = vmalloc(newtlen); 1643 if (newsa == NULL) { 1644 plog(ASL_LEVEL_ERR, "failed to get newsa.\n"); 1645 goto out; 1646 } 1647 bp = newsa->v; 1648 1649 /* some of values of SA must be updated in the out of this function */ 1650 ((struct isakmp_gen *)bp)->len = htons(newtlen); 1651 bp += sizeof(struct ipsecdoi_sa_b); 1652 1653 /* create proposal payloads */ 1654 for (pp = pp0; pp; pp = pp->next) { 1655 1656 for (pr = pp->head; pr; pr = pr->next) { 1657 prophlen = sizeof(struct isakmp_pl_p) 1658 + p->prop->spi_size; 1659 1660 for (tr = pr->head; tr; tr = tr->next) { 1661 for (p = pair[pp->prop_no]; p; p = p->tnext) { 1662 if (tr->trns_no == p->trns->t_no) 1663 break; 1664 } 1665 if (p == NULL) 1666 goto out; 1667 1668 trnslen = ntohs(p->trns->h.len); 1669 1670 if (np_p) 1671 *np_p = ISAKMP_NPTYPE_P; 1672 1673 /* create proposal */ 1674 1675 memcpy(bp, p->prop, prophlen); 1676 ((struct isakmp_pl_p *)bp)->h.np = ISAKMP_NPTYPE_NONE; 1677 ((struct isakmp_pl_p *)bp)->h.len = htons(prophlen + trnslen); 1678 ((struct isakmp_pl_p *)bp)->num_t = 1; 1679 np_p = &((struct isakmp_pl_p *)bp)->h.np; 1680 bp += prophlen; 1681 1682 /* create transform */ 1683 memcpy(bp, p->trns, trnslen); 1684 ((struct isakmp_pl_t *)bp)->h.np = ISAKMP_NPTYPE_NONE; 1685 ((struct isakmp_pl_t *)bp)->h.len = htons(trnslen); 1686 bp += trnslen; 1687 } 1688 } 1689 } 1690 1691 error = 0; 1692out: 1693 if (pair != NULL) 1694 racoon_free(pair); 1695 1696 if (error != 0) { 1697 if (newsa != NULL) { 1698 vfree(newsa); 1699 newsa = NULL; 1700 } 1701 } 1702 1703 return newsa; 1704} 1705 1706/* 1707 * If some error happens then return 0. Although 0 means that lifetime is zero, 1708 * such a value should not be accepted. 1709 * Also 0 of lifebyte should not be included in a packet although 0 means not 1710 * to care of it. 1711 */ 1712static u_int32_t 1713ipsecdoi_set_ld(buf) 1714 vchar_t *buf; 1715{ 1716 u_int32_t ld; 1717 1718 if (buf == 0) 1719 return 0; 1720 1721 switch (buf->l) { 1722 case 2: 1723 ld = ntohs(*ALIGNED_CAST(u_int16_t *)buf->v); 1724 break; 1725 case 4: 1726 ld = ntohl(*ALIGNED_CAST(u_int32_t *)buf->v); 1727 break; 1728 default: 1729 plog(ASL_LEVEL_ERR, 1730 "length %zu of life duration " 1731 "isn't supported.\n", buf->l); 1732 return 0; 1733 } 1734 1735 return ld; 1736} 1737 1738/*%%%*/ 1739/* 1740 * check DOI 1741 */ 1742static int 1743check_doi(doi) 1744 u_int32_t doi; 1745{ 1746 switch (doi) { 1747 case IPSEC_DOI: 1748 return 0; 1749 default: 1750 plog(ASL_LEVEL_ERR, 1751 "invalid value of DOI 0x%08x.\n", doi); 1752 return -1; 1753 } 1754 /* NOT REACHED */ 1755} 1756 1757/* 1758 * check situation 1759 */ 1760static int 1761check_situation(sit) 1762 u_int32_t sit; 1763{ 1764 switch (sit) { 1765 case IPSECDOI_SIT_IDENTITY_ONLY: 1766 return 0; 1767 1768 case IPSECDOI_SIT_SECRECY: 1769 case IPSECDOI_SIT_INTEGRITY: 1770 plog(ASL_LEVEL_ERR, 1771 "situation 0x%08x unsupported yet.\n", sit); 1772 return -1; 1773 1774 default: 1775 plog(ASL_LEVEL_ERR, 1776 "invalid situation 0x%08x.\n", sit); 1777 return -1; 1778 } 1779 /* NOT REACHED */ 1780} 1781 1782/* 1783 * check protocol id in main mode 1784 */ 1785static int 1786check_prot_main(proto_id) 1787 int proto_id; 1788{ 1789 switch (proto_id) { 1790 case IPSECDOI_PROTO_ISAKMP: 1791 return 0; 1792 1793 default: 1794 plog(ASL_LEVEL_ERR, 1795 "Illegal protocol id=%u.\n", proto_id); 1796 return -1; 1797 } 1798 /* NOT REACHED */ 1799} 1800 1801/* 1802 * check protocol id in quick mode 1803 */ 1804static int 1805check_prot_quick(proto_id) 1806 int proto_id; 1807{ 1808 switch (proto_id) { 1809 case IPSECDOI_PROTO_IPSEC_AH: 1810 case IPSECDOI_PROTO_IPSEC_ESP: 1811 return 0; 1812 1813 case IPSECDOI_PROTO_IPCOMP: 1814 return 0; 1815 1816 default: 1817 plog(ASL_LEVEL_ERR, 1818 "invalid protocol id %d.\n", proto_id); 1819 return -1; 1820 } 1821 /* NOT REACHED */ 1822} 1823 1824int 1825check_spi_size(proto_id, size) 1826 int proto_id, size; 1827{ 1828 switch (proto_id) { 1829 case IPSECDOI_PROTO_ISAKMP: 1830 if (size != 0) { 1831 /* WARNING */ 1832 plog(ASL_LEVEL_WARNING, 1833 "SPI size isn't zero, but IKE proposal.\n"); 1834 } 1835 return 0; 1836 1837 case IPSECDOI_PROTO_IPSEC_AH: 1838 case IPSECDOI_PROTO_IPSEC_ESP: 1839 if (size != 4) { 1840 plog(ASL_LEVEL_ERR, 1841 "invalid SPI size=%d for IPSEC proposal.\n", 1842 size); 1843 return -1; 1844 } 1845 return 0; 1846 1847 case IPSECDOI_PROTO_IPCOMP: 1848 if (size != 2 && size != 4) { 1849 plog(ASL_LEVEL_ERR, 1850 "invalid SPI size=%d for IPCOMP proposal.\n", 1851 size); 1852 return -1; 1853 } 1854 return 0; 1855 1856 default: 1857 /* ??? */ 1858 return -1; 1859 } 1860 /* NOT REACHED */ 1861} 1862 1863/* 1864 * check transform ID in ISAKMP. 1865 */ 1866static int 1867check_trns_isakmp(t_id) 1868 int t_id; 1869{ 1870 switch (t_id) { 1871 case IPSECDOI_KEY_IKE: 1872 return 0; 1873 default: 1874 plog(ASL_LEVEL_ERR, 1875 "invalid transform-id=%u in proto_id=%u.\n", 1876 t_id, IPSECDOI_KEY_IKE); 1877 return -1; 1878 } 1879 /* NOT REACHED */ 1880} 1881 1882/* 1883 * check transform ID in AH. 1884 */ 1885static int 1886check_trns_ah(t_id) 1887 int t_id; 1888{ 1889 switch (t_id) { 1890 case IPSECDOI_AH_MD5: 1891 case IPSECDOI_AH_SHA: 1892 case IPSECDOI_AH_SHA256: 1893 case IPSECDOI_AH_SHA384: 1894 case IPSECDOI_AH_SHA512: 1895 return 0; 1896 case IPSECDOI_AH_DES: 1897 plog(ASL_LEVEL_ERR, 1898 "not support transform-id=%u in AH.\n", t_id); 1899 return -1; 1900 default: 1901 plog(ASL_LEVEL_ERR, 1902 "invalid transform-id=%u in AH.\n", t_id); 1903 return -1; 1904 } 1905 /* NOT REACHED */ 1906} 1907 1908/* 1909 * check transform ID in ESP. 1910 */ 1911static int 1912check_trns_esp(t_id) 1913 int t_id; 1914{ 1915 switch (t_id) { 1916 case IPSECDOI_ESP_DES: 1917 case IPSECDOI_ESP_3DES: 1918 case IPSECDOI_ESP_NULL: 1919 case IPSECDOI_ESP_RC5: 1920 case IPSECDOI_ESP_CAST: 1921 case IPSECDOI_ESP_BLOWFISH: 1922 case IPSECDOI_ESP_AES: 1923 case IPSECDOI_ESP_TWOFISH: 1924 return 0; 1925 case IPSECDOI_ESP_DES_IV32: 1926 case IPSECDOI_ESP_DES_IV64: 1927 case IPSECDOI_ESP_IDEA: 1928 case IPSECDOI_ESP_3IDEA: 1929 case IPSECDOI_ESP_RC4: 1930 plog(ASL_LEVEL_ERR, 1931 "not support transform-id=%u in ESP.\n", t_id); 1932 return -1; 1933 default: 1934 plog(ASL_LEVEL_ERR, 1935 "invalid transform-id=%u in ESP.\n", t_id); 1936 return -1; 1937 } 1938 /* NOT REACHED */ 1939} 1940 1941/* 1942 * check transform ID in IPCOMP. 1943 */ 1944static int 1945check_trns_ipcomp(t_id) 1946 int t_id; 1947{ 1948 switch (t_id) { 1949 case IPSECDOI_IPCOMP_OUI: 1950 case IPSECDOI_IPCOMP_DEFLATE: 1951 case IPSECDOI_IPCOMP_LZS: 1952 return 0; 1953 default: 1954 plog(ASL_LEVEL_ERR, 1955 "invalid transform-id=%u in IPCOMP.\n", t_id); 1956 return -1; 1957 } 1958 /* NOT REACHED */ 1959} 1960 1961/* 1962 * check data attributes in IKE. 1963 */ 1964static int 1965check_attr_isakmp(trns) 1966 struct isakmp_pl_t *trns; 1967{ 1968 struct isakmp_data *d; 1969 int tlen; 1970 int flag, type; 1971 u_int16_t lorv; 1972 1973 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t); 1974 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t)); 1975 1976 while (tlen > 0) { 1977 type = ntohs(d->type) & ~ISAKMP_GEN_MASK; 1978 flag = ntohs(d->type) & ISAKMP_GEN_MASK; 1979 lorv = ntohs(d->lorv); 1980 1981 plog(ASL_LEVEL_DEBUG, 1982 "type=%s, flag=0x%04x, lorv=%s\n", 1983 s_oakley_attr(type), flag, 1984 s_oakley_attr_v(type, lorv)); 1985 1986 /* 1987 * some of the attributes must be encoded in TV. 1988 * see RFC2409 Appendix A "Attribute Classes". 1989 */ 1990 switch (type) { 1991 case OAKLEY_ATTR_ENC_ALG: 1992 case OAKLEY_ATTR_HASH_ALG: 1993 case OAKLEY_ATTR_AUTH_METHOD: 1994 case OAKLEY_ATTR_GRP_DESC: 1995 case OAKLEY_ATTR_GRP_TYPE: 1996 case OAKLEY_ATTR_SA_LD_TYPE: 1997 case OAKLEY_ATTR_PRF: 1998 case OAKLEY_ATTR_KEY_LEN: 1999 case OAKLEY_ATTR_FIELD_SIZE: 2000 if (!flag) { /* TLV*/ 2001 plog(ASL_LEVEL_ERR, 2002 "oakley attribute %d must be TV.\n", 2003 type); 2004 return -1; 2005 } 2006 break; 2007 } 2008 2009 /* sanity check for TLV. length must be specified. */ 2010 if (!flag && lorv == 0) { /*TLV*/ 2011 plog(ASL_LEVEL_ERR, 2012 "invalid length %d for TLV attribute %d.\n", 2013 lorv, type); 2014 return -1; 2015 } 2016 2017 switch (type) { 2018 case OAKLEY_ATTR_ENC_ALG: 2019 if (!alg_oakley_encdef_ok(lorv)) { 2020 plog(ASL_LEVEL_ERR, 2021 "invalied encryption algorithm=%d.\n", 2022 lorv); 2023 return -1; 2024 } 2025 break; 2026 2027 case OAKLEY_ATTR_HASH_ALG: 2028 if (!alg_oakley_hashdef_ok(lorv)) { 2029 plog(ASL_LEVEL_ERR, 2030 "invalied hash algorithm=%d.\n", 2031 lorv); 2032 return -1; 2033 } 2034 break; 2035 2036 case OAKLEY_ATTR_AUTH_METHOD: 2037 switch (lorv) { 2038 case OAKLEY_ATTR_AUTH_METHOD_PSKEY: 2039 case OAKLEY_ATTR_AUTH_METHOD_RSASIG: 2040#ifdef ENABLE_HYBRID 2041 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I: 2042 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I: 2043#if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */ 2044 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I: 2045#endif 2046 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: 2047#endif 2048 case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB: 2049 break; 2050 case OAKLEY_ATTR_AUTH_METHOD_DSSSIG: 2051#ifdef ENABLE_HYBRID 2052 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: 2053 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: 2054 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I: 2055 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: 2056 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I: 2057 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: 2058 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I: 2059 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: 2060 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I: 2061 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: 2062#endif 2063 case OAKLEY_ATTR_AUTH_METHOD_RSAENC: 2064 case OAKLEY_ATTR_AUTH_METHOD_RSAREV: 2065 plog(ASL_LEVEL_ERR, 2066 "auth method %s isn't supported.\n", 2067 s_oakley_attr_method(lorv)); 2068 return -1; 2069 default: 2070 plog(ASL_LEVEL_ERR, 2071 "invalid auth method %d.\n", 2072 lorv); 2073 return -1; 2074 } 2075 break; 2076 2077 case OAKLEY_ATTR_GRP_DESC: 2078 if (!alg_oakley_dhdef_ok(lorv)) { 2079 plog(ASL_LEVEL_ERR, 2080 "invalid DH group %d.\n", 2081 lorv); 2082 return -1; 2083 } 2084 break; 2085 2086 case OAKLEY_ATTR_GRP_TYPE: 2087 switch (lorv) { 2088 case OAKLEY_ATTR_GRP_TYPE_MODP: 2089 break; 2090 default: 2091 plog(ASL_LEVEL_ERR, 2092 "unsupported DH group type %d.\n", 2093 lorv); 2094 return -1; 2095 } 2096 break; 2097 2098 case OAKLEY_ATTR_GRP_PI: 2099 case OAKLEY_ATTR_GRP_GEN_ONE: 2100 /* sanity checks? */ 2101 break; 2102 2103 case OAKLEY_ATTR_GRP_GEN_TWO: 2104 case OAKLEY_ATTR_GRP_CURVE_A: 2105 case OAKLEY_ATTR_GRP_CURVE_B: 2106 plog(ASL_LEVEL_ERR, 2107 "attr type=%u isn't supported.\n", type); 2108 return -1; 2109 2110 case OAKLEY_ATTR_SA_LD_TYPE: 2111 switch (lorv) { 2112 case OAKLEY_ATTR_SA_LD_TYPE_SEC: 2113 case OAKLEY_ATTR_SA_LD_TYPE_KB: 2114 break; 2115 default: 2116 plog(ASL_LEVEL_ERR, 2117 "invalid life type %d.\n", lorv); 2118 return -1; 2119 } 2120 break; 2121 2122 case OAKLEY_ATTR_SA_LD: 2123 /* should check the value */ 2124 break; 2125 2126 case OAKLEY_ATTR_PRF: 2127 case OAKLEY_ATTR_KEY_LEN: 2128 break; 2129 2130 case OAKLEY_ATTR_FIELD_SIZE: 2131 plog(ASL_LEVEL_ERR, 2132 "attr type=%u isn't supported.\n", type); 2133 return -1; 2134 2135 case OAKLEY_ATTR_GRP_ORDER: 2136 break; 2137 2138 case OAKLEY_ATTR_GSS_ID: 2139 break; 2140 2141 default: 2142 plog(ASL_LEVEL_ERR, 2143 "invalid attribute type %d.\n", type); 2144 return -1; 2145 } 2146 2147 if (flag) { 2148 tlen -= sizeof(*d); 2149 d = (struct isakmp_data *)((char *)d 2150 + sizeof(*d)); 2151 } else { 2152 tlen -= (sizeof(*d) + lorv); 2153 d = (struct isakmp_data *)((char *)d 2154 + sizeof(*d) + lorv); 2155 } 2156 } 2157 2158 return 0; 2159} 2160 2161/* 2162 * check data attributes in IPSEC AH/ESP. 2163 */ 2164static int 2165check_attr_ah(trns) 2166 struct isakmp_pl_t *trns; 2167{ 2168 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_AH, trns); 2169} 2170 2171static int 2172check_attr_esp(trns) 2173 struct isakmp_pl_t *trns; 2174{ 2175 return check_attr_ipsec(IPSECDOI_PROTO_IPSEC_ESP, trns); 2176} 2177 2178static int 2179check_attr_ipsec(proto_id, trns) 2180 int proto_id; 2181 struct isakmp_pl_t *trns; 2182{ 2183 struct isakmp_data *d; 2184 int tlen; 2185 int flag, type = 0; 2186 u_int16_t lorv; 2187 int attrseen[16]; /* XXX magic number */ 2188 2189 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t); 2190 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t)); 2191 memset(attrseen, 0, sizeof(attrseen)); 2192 2193 while (tlen > 0) { 2194 type = ntohs(d->type) & ~ISAKMP_GEN_MASK; 2195 flag = ntohs(d->type) & ISAKMP_GEN_MASK; 2196 lorv = ntohs(d->lorv); 2197 2198 plog(ASL_LEVEL_DEBUG, 2199 "type=%s, flag=0x%04x, lorv=%s\n", 2200 s_ipsecdoi_attr(type), flag, 2201 s_ipsecdoi_attr_v(type, lorv)); 2202 2203 if (type < sizeof(attrseen)/sizeof(attrseen[0])) 2204 attrseen[type]++; 2205 2206 switch (type) { 2207 case IPSECDOI_ATTR_ENC_MODE: 2208 if (! flag) { 2209 plog(ASL_LEVEL_ERR, 2210 "must be TV when ENC_MODE.\n"); 2211 return -1; 2212 } 2213 2214 switch (lorv) { 2215 case IPSECDOI_ATTR_ENC_MODE_TUNNEL: 2216 case IPSECDOI_ATTR_ENC_MODE_TRNS: 2217 break; 2218#ifdef ENABLE_NATT 2219 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC: 2220 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC: 2221 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT: 2222 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT: 2223 plog(ASL_LEVEL_DEBUG, 2224 "UDP encapsulation requested\n"); 2225 break; 2226#endif 2227 default: 2228 plog(ASL_LEVEL_ERR, 2229 "invalid encryption mode=%u.\n", 2230 lorv); 2231 return -1; 2232 } 2233 break; 2234 2235 case IPSECDOI_ATTR_AUTH: 2236 if (! flag) { 2237 plog(ASL_LEVEL_ERR, 2238 "must be TV when AUTH.\n"); 2239 return -1; 2240 } 2241 2242 switch (lorv) { 2243 case IPSECDOI_ATTR_AUTH_HMAC_MD5: 2244 if (proto_id == IPSECDOI_PROTO_IPSEC_AH && 2245 trns->t_id != IPSECDOI_AH_MD5) { 2246ahmismatch: 2247 plog(ASL_LEVEL_ERR, 2248 "auth algorithm %u conflicts " 2249 "with transform %u.\n", 2250 lorv, trns->t_id); 2251 return -1; 2252 } 2253 break; 2254 case IPSECDOI_ATTR_AUTH_HMAC_SHA1: 2255 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) { 2256 if (trns->t_id != IPSECDOI_AH_SHA) 2257 goto ahmismatch; 2258 } 2259 break; 2260 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256: 2261 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) { 2262 if (trns->t_id != IPSECDOI_AH_SHA256) 2263 goto ahmismatch; 2264 } 2265 break; 2266 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384: 2267 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) { 2268 if (trns->t_id != IPSECDOI_AH_SHA384) 2269 goto ahmismatch; 2270 } 2271 break; 2272 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512: 2273 if (proto_id == IPSECDOI_PROTO_IPSEC_AH) { 2274 if (trns->t_id != IPSECDOI_AH_SHA512) 2275 goto ahmismatch; 2276 } 2277 break; 2278 case IPSECDOI_ATTR_AUTH_DES_MAC: 2279 case IPSECDOI_ATTR_AUTH_KPDK: 2280 plog(ASL_LEVEL_ERR, 2281 "auth algorithm %u isn't supported.\n", 2282 lorv); 2283 return -1; 2284 default: 2285 plog(ASL_LEVEL_ERR, 2286 "invalid auth algorithm=%u.\n", 2287 lorv); 2288 return -1; 2289 } 2290 break; 2291 2292 case IPSECDOI_ATTR_SA_LD_TYPE: 2293 if (! flag) { 2294 plog(ASL_LEVEL_ERR, 2295 "must be TV when LD_TYPE.\n"); 2296 return -1; 2297 } 2298 2299 switch (lorv) { 2300 case IPSECDOI_ATTR_SA_LD_TYPE_SEC: 2301 case IPSECDOI_ATTR_SA_LD_TYPE_KB: 2302 break; 2303 default: 2304 plog(ASL_LEVEL_ERR, 2305 "invalid life type %d.\n", lorv); 2306 return -1; 2307 } 2308 break; 2309 2310 case IPSECDOI_ATTR_SA_LD: 2311 if (flag) { 2312 /* i.e. ISAKMP_GEN_TV */ 2313 plog(ASL_LEVEL_DEBUG, 2314 "life duration was in TLV.\n"); 2315 } else { 2316 /* i.e. ISAKMP_GEN_TLV */ 2317 if (lorv == 0) { 2318 plog(ASL_LEVEL_ERR, 2319 "invalid length of LD\n"); 2320 return -1; 2321 } 2322 } 2323 break; 2324 2325 case IPSECDOI_ATTR_GRP_DESC: 2326 if (! flag) { 2327 plog(ASL_LEVEL_ERR, 2328 "must be TV when GRP_DESC.\n"); 2329 return -1; 2330 } 2331 2332 if (!alg_oakley_dhdef_ok(lorv)) { 2333 plog(ASL_LEVEL_ERR, 2334 "invalid group description=%u.\n", 2335 lorv); 2336 return -1; 2337 } 2338 break; 2339 2340 case IPSECDOI_ATTR_KEY_LENGTH: 2341 if (! flag) { 2342 plog(ASL_LEVEL_ERR, 2343 "must be TV when KEY_LENGTH.\n"); 2344 return -1; 2345 } 2346 break; 2347 2348 case IPSECDOI_ATTR_KEY_ROUNDS: 2349 case IPSECDOI_ATTR_COMP_DICT_SIZE: 2350 case IPSECDOI_ATTR_COMP_PRIVALG: 2351 plog(ASL_LEVEL_ERR, 2352 "attr type=%u isn't supported.\n", type); 2353 return -1; 2354 2355 default: 2356 plog(ASL_LEVEL_ERR, 2357 "invalid attribute type %d.\n", type); 2358 return -1; 2359 } 2360 2361 if (flag) { 2362 tlen -= sizeof(*d); 2363 d = (struct isakmp_data *)((char *)d 2364 + sizeof(*d)); 2365 } else { 2366 tlen -= (sizeof(*d) + lorv); 2367 d = (struct isakmp_data *)((caddr_t)d 2368 + sizeof(*d) + lorv); 2369 } 2370 } 2371 2372 if (proto_id == IPSECDOI_PROTO_IPSEC_AH && 2373 !attrseen[IPSECDOI_ATTR_AUTH]) { 2374 plog(ASL_LEVEL_ERR, 2375 "attr AUTH must be present for AH.\n"); 2376 return -1; 2377 } 2378 2379 if (proto_id == IPSECDOI_PROTO_IPSEC_ESP && 2380 trns->t_id == IPSECDOI_ESP_NULL && 2381 !attrseen[IPSECDOI_ATTR_AUTH]) { 2382 plog(ASL_LEVEL_ERR, 2383 "attr AUTH must be present for ESP NULL encryption.\n"); 2384 return -1; 2385 } 2386 2387 return 0; 2388} 2389 2390static int 2391check_attr_ipcomp(trns) 2392 struct isakmp_pl_t *trns; 2393{ 2394 struct isakmp_data *d; 2395 int tlen; 2396 int flag, type = 0; 2397 u_int16_t lorv; 2398 int attrseen[16]; /* XXX magic number */ 2399 2400 tlen = ntohs(trns->h.len) - sizeof(struct isakmp_pl_t); 2401 d = (struct isakmp_data *)((caddr_t)trns + sizeof(struct isakmp_pl_t)); 2402 memset(attrseen, 0, sizeof(attrseen)); 2403 2404 while (tlen > 0) { 2405 type = ntohs(d->type) & ~ISAKMP_GEN_MASK; 2406 flag = ntohs(d->type) & ISAKMP_GEN_MASK; 2407 lorv = ntohs(d->lorv); 2408 2409 plog(ASL_LEVEL_DEBUG, 2410 "type=%d, flag=0x%04x, lorv=0x%04x\n", 2411 type, flag, lorv); 2412 2413 if (type < sizeof(attrseen)/sizeof(attrseen[0])) 2414 attrseen[type]++; 2415 2416 switch (type) { 2417 case IPSECDOI_ATTR_ENC_MODE: 2418 if (! flag) { 2419 plog(ASL_LEVEL_ERR, 2420 "must be TV when ENC_MODE.\n"); 2421 return -1; 2422 } 2423 2424 switch (lorv) { 2425 case IPSECDOI_ATTR_ENC_MODE_TUNNEL: 2426 case IPSECDOI_ATTR_ENC_MODE_TRNS: 2427 break; 2428#ifdef ENABLE_NATT 2429 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC: 2430 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC: 2431 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT: 2432 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT: 2433 plog(ASL_LEVEL_DEBUG, 2434 "UDP encapsulation requested\n"); 2435 break; 2436#endif 2437 default: 2438 plog(ASL_LEVEL_ERR, 2439 "invalid encryption mode=%u.\n", 2440 lorv); 2441 return -1; 2442 } 2443 break; 2444 2445 case IPSECDOI_ATTR_SA_LD_TYPE: 2446 if (! flag) { 2447 plog(ASL_LEVEL_ERR, 2448 "must be TV when LD_TYPE.\n"); 2449 return -1; 2450 } 2451 2452 switch (lorv) { 2453 case IPSECDOI_ATTR_SA_LD_TYPE_SEC: 2454 case IPSECDOI_ATTR_SA_LD_TYPE_KB: 2455 break; 2456 default: 2457 plog(ASL_LEVEL_ERR, 2458 "invalid life type %d.\n", lorv); 2459 return -1; 2460 } 2461 break; 2462 2463 case IPSECDOI_ATTR_SA_LD: 2464 if (flag) { 2465 /* i.e. ISAKMP_GEN_TV */ 2466 plog(ASL_LEVEL_DEBUG, 2467 "life duration was in TLV.\n"); 2468 } else { 2469 /* i.e. ISAKMP_GEN_TLV */ 2470 if (lorv == 0) { 2471 plog(ASL_LEVEL_ERR, 2472 "invalid length of LD\n"); 2473 return -1; 2474 } 2475 } 2476 break; 2477 2478 case IPSECDOI_ATTR_GRP_DESC: 2479 if (! flag) { 2480 plog(ASL_LEVEL_ERR, 2481 "must be TV when GRP_DESC.\n"); 2482 return -1; 2483 } 2484 2485 if (!alg_oakley_dhdef_ok(lorv)) { 2486 plog(ASL_LEVEL_ERR, 2487 "invalid group description=%u.\n", 2488 lorv); 2489 return -1; 2490 } 2491 break; 2492 2493 case IPSECDOI_ATTR_AUTH: 2494 plog(ASL_LEVEL_ERR, 2495 "invalid attr type=%u.\n", type); 2496 return -1; 2497 2498 case IPSECDOI_ATTR_KEY_LENGTH: 2499 case IPSECDOI_ATTR_KEY_ROUNDS: 2500 case IPSECDOI_ATTR_COMP_DICT_SIZE: 2501 case IPSECDOI_ATTR_COMP_PRIVALG: 2502 plog(ASL_LEVEL_ERR, 2503 "attr type=%u isn't supported.\n", type); 2504 return -1; 2505 2506 default: 2507 plog(ASL_LEVEL_ERR, 2508 "invalid attribute type %d.\n", type); 2509 return -1; 2510 } 2511 2512 if (flag) { 2513 tlen -= sizeof(*d); 2514 d = (struct isakmp_data *)((char *)d 2515 + sizeof(*d)); 2516 } else { 2517 tlen -= (sizeof(*d) + lorv); 2518 d = (struct isakmp_data *)((caddr_t)d 2519 + sizeof(*d) + lorv); 2520 } 2521 } 2522 2523#if 0 2524 if (proto_id == IPSECDOI_PROTO_IPCOMP && 2525 !attrseen[IPSECDOI_ATTR_AUTH]) { 2526 plog(ASL_LEVEL_ERR, 2527 "attr AUTH must be present for AH.\n", type); 2528 return -1; 2529 } 2530#endif 2531 2532 return 0; 2533} 2534 2535/* %%% */ 2536/* 2537 * create phase1 proposal from remote configuration. 2538 * NOT INCLUDING isakmp general header of SA payload 2539 */ 2540vchar_t * 2541ipsecdoi_setph1proposal (phase1_handle_t *iph1) 2542{ 2543 vchar_t *mysa; 2544 int sablen; 2545 2546 if (!iph1) return NULL; 2547 2548 struct isakmpsa *props = iph1->rmconf->proposal; 2549 unsigned int version = iph1->version; 2550 2551 /* count total size of SA minus isakmp general header */ 2552 /* not including isakmp general header of SA payload */ 2553 if (version == ISAKMP_VERSION_NUMBER_IKEV1) { 2554 sablen = sizeof(struct ipsecdoi_sa_b); 2555 } else { 2556 sablen = 0; 2557 } 2558 sablen += setph1prop(iph1, NULL); 2559 2560 mysa = vmalloc(sablen); 2561 if (mysa == NULL) { 2562 plog(ASL_LEVEL_ERR, 2563 "failed to allocate my sa buffer\n"); 2564 return NULL; 2565 } 2566 2567 /* create SA payload */ 2568 if (version == ISAKMP_VERSION_NUMBER_IKEV1) { 2569 /* not including isakmp general header */ 2570 (ALIGNED_CAST(struct ipsecdoi_sa_b *)mysa->v)->doi = htonl(props->rmconf->doitype); 2571 (ALIGNED_CAST(struct ipsecdoi_sa_b *)mysa->v)->sit = htonl(props->rmconf->sittype); 2572 2573 (void)setph1prop(iph1, mysa->v + sizeof(struct ipsecdoi_sa_b)); 2574 } 2575 2576 return mysa; 2577} 2578 2579int 2580setph1prop (phase1_handle_t *iph1, 2581 caddr_t buf) 2582{ 2583 struct isakmpsa *props = iph1->rmconf->proposal; 2584 2585 struct isakmp_pl_p *prop = NULL; 2586 struct isakmpsa *s = NULL; 2587 int proplen, trnslen; 2588 u_int8_t *np_t; /* pointer next trns type in previous header */ 2589 int trns_num; 2590 caddr_t p = buf; 2591 int spi_size = 0; 2592 2593 proplen = sizeof(*prop) + spi_size; 2594 if (buf) { 2595 /* create proposal */ 2596 prop = (struct isakmp_pl_p *)p; 2597 prop->h.np = ISAKMP_NPTYPE_NONE; 2598 prop->h.reserved = 0; 2599 prop->p_no = props->prop_no; 2600 prop->proto_id = IPSECDOI_PROTO_ISAKMP; 2601 prop->spi_size = spi_size; 2602 p += sizeof(*prop); 2603 } 2604 2605 np_t = NULL; 2606 trns_num = 0; 2607 2608 for (s = props; s != NULL; s = s->next) { 2609 { 2610 if (np_t) 2611 *np_t = ISAKMP_NPTYPE_T; 2612 2613 trnslen = setph1trns(s, p); 2614 proplen += trnslen; 2615 if (buf) { 2616 /* save buffer to pre-next payload */ 2617 np_t = &((struct isakmp_pl_t *)p)->h.np; 2618 p += trnslen; 2619 2620 /* count up transform length */ 2621 trns_num++; 2622 } 2623 } 2624 } 2625 2626 /* update proposal length */ 2627 if (buf) { 2628 prop->h.len = htons(proplen); 2629 prop->num_t = trns_num; 2630 } 2631 2632 return proplen; 2633} 2634 2635static int 2636setph1trns (struct isakmpsa *sa, 2637 caddr_t buf) 2638{ 2639 struct isakmp_pl_t *trns = NULL; 2640 int trnslen, attrlen; 2641 caddr_t p = buf; 2642 2643 trnslen = sizeof(*trns); 2644 if (buf) { 2645 /* create transform */ 2646 trns = (struct isakmp_pl_t *)p; 2647 trns->h.np = ISAKMP_NPTYPE_NONE; 2648 trns->t_no = sa->trns_no; 2649 trns->t_id = IPSECDOI_KEY_IKE; 2650 p += sizeof(*trns); 2651 } 2652 2653 attrlen = setph1attr(sa, p); 2654 trnslen += attrlen; 2655 if (buf) 2656 p += attrlen; 2657 2658 if (buf) 2659 trns->h.len = htons(trnslen); 2660 2661 return trnslen; 2662} 2663 2664static int 2665setph1attr (struct isakmpsa *sa, 2666 caddr_t buf) 2667{ 2668 caddr_t p = buf; 2669 int attrlen = 0; 2670 2671 if (sa->lifetime) { 2672 u_int32_t lifetime = htonl((u_int32_t)sa->lifetime); 2673 2674 attrlen += sizeof(struct isakmp_data) 2675 + sizeof(struct isakmp_data); 2676 if (sa->lifetime > 0xffff) 2677 attrlen += sizeof(lifetime); 2678 if (buf) { 2679 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE, 2680 OAKLEY_ATTR_SA_LD_TYPE_SEC); 2681 if (sa->lifetime > 0xffff) { 2682 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD, 2683 (caddr_t)&lifetime, 2684 sizeof(lifetime)); 2685 } else { 2686 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD, 2687 sa->lifetime); 2688 } 2689 } 2690 } 2691 2692 if (sa->lifebyte) { 2693 u_int32_t lifebyte = htonl((u_int32_t)sa->lifebyte); 2694 2695 attrlen += sizeof(struct isakmp_data) 2696 + sizeof(struct isakmp_data); 2697 if (sa->lifebyte > 0xffff) 2698 attrlen += sizeof(lifebyte); 2699 if (buf) { 2700 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD_TYPE, 2701 OAKLEY_ATTR_SA_LD_TYPE_KB); 2702 if (sa->lifebyte > 0xffff) { 2703 p = isakmp_set_attr_v(p, OAKLEY_ATTR_SA_LD, 2704 (caddr_t)&lifebyte, 2705 sizeof(lifebyte)); 2706 } else { 2707 p = isakmp_set_attr_l(p, OAKLEY_ATTR_SA_LD, 2708 sa->lifebyte); 2709 } 2710 } 2711 } 2712 2713 if (sa->enctype) { 2714 attrlen += sizeof(struct isakmp_data); 2715 if (buf) 2716 p = isakmp_set_attr_l(p, OAKLEY_ATTR_ENC_ALG, sa->enctype); 2717 } 2718 if (sa->encklen) { 2719 attrlen += sizeof(struct isakmp_data); 2720 if (buf) 2721 p = isakmp_set_attr_l(p, OAKLEY_ATTR_KEY_LEN, sa->encklen); 2722 } 2723 if (sa->authmethod) { 2724 int authmethod; 2725 2726#ifdef ENABLE_HYBRID 2727 authmethod = switch_authmethod(sa->authmethod); 2728#else 2729 authmethod = sa->authmethod; 2730#endif 2731 attrlen += sizeof(struct isakmp_data); 2732 if (buf) 2733 p = isakmp_set_attr_l(p, OAKLEY_ATTR_AUTH_METHOD, authmethod); 2734 } 2735 if (sa->hashtype) { 2736 attrlen += sizeof(struct isakmp_data); 2737 if (buf) 2738 p = isakmp_set_attr_l(p, OAKLEY_ATTR_HASH_ALG, sa->hashtype); 2739 } 2740 switch (sa->dh_group) { 2741 case OAKLEY_ATTR_GRP_DESC_MODP768: 2742 case OAKLEY_ATTR_GRP_DESC_MODP1024: 2743 case OAKLEY_ATTR_GRP_DESC_MODP1536: 2744 case OAKLEY_ATTR_GRP_DESC_MODP2048: 2745 case OAKLEY_ATTR_GRP_DESC_MODP3072: 2746 case OAKLEY_ATTR_GRP_DESC_MODP4096: 2747 case OAKLEY_ATTR_GRP_DESC_MODP6144: 2748 case OAKLEY_ATTR_GRP_DESC_MODP8192: 2749 /* don't attach group type for known groups */ 2750 attrlen += sizeof(struct isakmp_data); 2751 if (buf) { 2752 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_DESC, 2753 sa->dh_group); 2754 } 2755 break; 2756 case OAKLEY_ATTR_GRP_DESC_EC2N155: 2757 case OAKLEY_ATTR_GRP_DESC_EC2N185: 2758 /* don't attach group type for known groups */ 2759 attrlen += sizeof(struct isakmp_data); 2760 if (buf) { 2761 p = isakmp_set_attr_l(p, OAKLEY_ATTR_GRP_TYPE, 2762 OAKLEY_ATTR_GRP_TYPE_EC2N); 2763 } 2764 break; 2765 case 0: 2766 default: 2767 break; 2768 } 2769 2770 return attrlen; 2771} 2772 2773static vchar_t * 2774setph2proposal0(iph2, pp, pr) 2775 const phase2_handle_t *iph2; 2776 const struct saprop *pp; 2777 const struct saproto *pr; 2778{ 2779 vchar_t *p; 2780 struct isakmp_pl_p *prop; 2781 struct isakmp_pl_t *trns; 2782 struct satrns *tr; 2783 int attrlen; 2784 size_t trnsoff; 2785 caddr_t x0, x; 2786 u_int8_t *np_t; /* pointer next trns type in previous header */ 2787 const u_int8_t *spi; 2788 2789 p = vmalloc(sizeof(*prop) + sizeof(pr->spi)); 2790 if (p == NULL) 2791 return NULL; 2792 2793 /* create proposal */ 2794 prop = (struct isakmp_pl_p *)p->v; 2795 prop->h.np = ISAKMP_NPTYPE_NONE; 2796 prop->p_no = pp->prop_no; 2797 prop->proto_id = pr->proto_id; 2798 prop->num_t = 1; 2799 2800 spi = (const u_int8_t *)&pr->spi; 2801 switch (pr->proto_id) { 2802 case IPSECDOI_PROTO_IPCOMP: 2803 /* 2804 * draft-shacham-ippcp-rfc2393bis-05.txt: 2805 * construct 16bit SPI (CPI). 2806 * XXX we may need to provide a configuration option to 2807 * generate 32bit SPI. otherwise we cannot interoeprate 2808 * with nodes that uses 32bit SPI, in case we are initiator. 2809 */ 2810 prop->spi_size = sizeof(u_int16_t); 2811 spi += sizeof(pr->spi) - sizeof(u_int16_t); 2812 p->l -= sizeof(pr->spi); 2813 p->l += sizeof(u_int16_t); 2814 break; 2815 default: 2816 prop->spi_size = sizeof(pr->spi); 2817 break; 2818 } 2819 memcpy(prop + 1, spi, prop->spi_size); 2820 2821 /* create transform */ 2822 trnsoff = sizeof(*prop) + prop->spi_size; 2823 np_t = NULL; 2824 2825 for (tr = pr->head; tr; tr = tr->next) { 2826 2827 switch (pr->proto_id) { 2828 case IPSECDOI_PROTO_IPSEC_ESP: 2829 /* 2830 * don't build a null encryption 2831 * with no authentication transform. 2832 */ 2833 if (tr->trns_id == IPSECDOI_ESP_NULL && 2834 tr->authtype == IPSECDOI_ATTR_AUTH_NONE) 2835 continue; 2836 break; 2837 } 2838 2839 if (np_t) { 2840 *np_t = ISAKMP_NPTYPE_T; 2841 prop->num_t++; 2842 } 2843 2844 /* get attribute length */ 2845 attrlen = 0; 2846 if (pp->lifetime) { 2847 attrlen += sizeof(struct isakmp_data) 2848 + sizeof(struct isakmp_data); 2849 if (pp->lifetime > 0xffff) 2850 attrlen += sizeof(u_int32_t); 2851 } 2852 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) { 2853 attrlen += sizeof(struct isakmp_data) 2854 + sizeof(struct isakmp_data); 2855 if (pp->lifebyte > 0xffff) 2856 attrlen += sizeof(u_int32_t); 2857 } 2858 attrlen += sizeof(struct isakmp_data); /* enc mode */ 2859 if (tr->encklen) 2860 attrlen += sizeof(struct isakmp_data); 2861 2862 switch (pr->proto_id) { 2863 case IPSECDOI_PROTO_IPSEC_ESP: 2864 /* non authentication mode ? */ 2865 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) 2866 attrlen += sizeof(struct isakmp_data); 2867 break; 2868 case IPSECDOI_PROTO_IPSEC_AH: 2869 if (tr->authtype == IPSECDOI_ATTR_AUTH_NONE) { 2870 plog(ASL_LEVEL_ERR, 2871 "no authentication algorithm found " 2872 "but protocol is AH.\n"); 2873 vfree(p); 2874 return NULL; 2875 } 2876 attrlen += sizeof(struct isakmp_data); 2877 break; 2878 case IPSECDOI_PROTO_IPCOMP: 2879 break; 2880 default: 2881 plog(ASL_LEVEL_ERR, 2882 "invalid protocol: %d\n", pr->proto_id); 2883 vfree(p); 2884 return NULL; 2885 } 2886 2887 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group)) 2888 attrlen += sizeof(struct isakmp_data); 2889 2890 p = vrealloc(p, p->l + sizeof(*trns) + attrlen); 2891 if (p == NULL) 2892 return NULL; 2893 prop = (struct isakmp_pl_p *)p->v; 2894 2895 /* set transform's values */ 2896 trns = (struct isakmp_pl_t *)(p->v + trnsoff); 2897 trns->h.np = ISAKMP_NPTYPE_NONE; 2898 trns->t_no = tr->trns_no; 2899 trns->t_id = tr->trns_id; 2900 2901 /* set attributes */ 2902 x = x0 = p->v + trnsoff + sizeof(*trns); 2903 2904 if (pp->lifetime) { 2905 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE, 2906 IPSECDOI_ATTR_SA_LD_TYPE_SEC); 2907 if (pp->lifetime > 0xffff) { 2908 u_int32_t v = htonl((u_int32_t)pp->lifetime); 2909 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD, 2910 (caddr_t)&v, sizeof(v)); 2911 } else { 2912 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD, 2913 pp->lifetime); 2914 } 2915 } 2916 2917 if (pp->lifebyte && pp->lifebyte != IPSECDOI_ATTR_SA_LD_KB_MAX) { 2918 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD_TYPE, 2919 IPSECDOI_ATTR_SA_LD_TYPE_KB); 2920 if (pp->lifebyte > 0xffff) { 2921 u_int32_t v = htonl((u_int32_t)pp->lifebyte); 2922 x = isakmp_set_attr_v(x, IPSECDOI_ATTR_SA_LD, 2923 (caddr_t)&v, sizeof(v)); 2924 } else { 2925 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_SA_LD, 2926 pp->lifebyte); 2927 } 2928 } 2929 2930 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_ENC_MODE, pr->encmode); 2931 2932 if (tr->encklen) 2933 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_KEY_LENGTH, tr->encklen); 2934 2935 /* mandatory check has done above. */ 2936 if ((pr->proto_id == IPSECDOI_PROTO_IPSEC_ESP && tr->authtype != IPSECDOI_ATTR_AUTH_NONE) 2937 || pr->proto_id == IPSECDOI_PROTO_IPSEC_AH) 2938 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_AUTH, tr->authtype); 2939 2940 if (alg_oakley_dhdef_ok(iph2->sainfo->pfs_group)) 2941 x = isakmp_set_attr_l(x, IPSECDOI_ATTR_GRP_DESC, 2942 iph2->sainfo->pfs_group); 2943 2944 /* update length of this transform. */ 2945 trns = (struct isakmp_pl_t *)(p->v + trnsoff); 2946 trns->h.len = htons(sizeof(*trns) + attrlen); 2947 2948 /* save buffer to pre-next payload */ 2949 np_t = &trns->h.np; 2950 2951 trnsoff += (sizeof(*trns) + attrlen); 2952 } 2953 2954 if (np_t == NULL) { 2955 plog(ASL_LEVEL_ERR, 2956 "no suitable proposal was created.\n"); 2957 return NULL; 2958 } 2959 2960 /* update length of this protocol. */ 2961 prop->h.len = htons(p->l); 2962 2963 return p; 2964} 2965 2966/* 2967 * create phase2 proposal from policy configuration. 2968 * NOT INCLUDING isakmp general header of SA payload. 2969 * This function is called by initiator only. 2970 */ 2971int 2972ipsecdoi_setph2proposal(phase2_handle_t *iph2, int return_sa) 2973{ 2974 struct saprop *proposal, *a; 2975 struct saproto *b = NULL; 2976 vchar_t *q, *sa = NULL; 2977 struct isakmp_pl_p *prop; 2978 size_t propoff; /* for previous field of type of next payload. */ 2979 2980 if (return_sa) 2981 proposal = iph2->approval; 2982 else 2983 proposal = iph2->proposal; 2984 2985 if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) { 2986 struct ipsecdoi_sa_b *sab; 2987 2988 sa = vmalloc(sizeof(*sab)); 2989 if (sa == NULL) { 2990 plog(ASL_LEVEL_ERR, 2991 "failed to allocate my sa buffer\n"); 2992 return -1; 2993 } 2994 2995 /* create SA payload */ 2996 sab = ALIGNED_CAST(struct ipsecdoi_sa_b *)sa->v; 2997 sab->doi = htonl(IPSEC_DOI); 2998 sab->sit = htonl(IPSECDOI_SIT_IDENTITY_ONLY); /* XXX configurable ? */ 2999 3000 } 3001 3002 prop = NULL; 3003 propoff = 0; 3004 for (a = proposal; a; a = a->next) { 3005 for (b = a->head; b; b = b->next) { 3006 if (b->proto_id == IPSECDOI_PROTO_IPCOMP) { 3007 // skip this - not specified in the SA 3008 // Need to set this in iph2 ??? 3009 continue; 3010 } 3011 // IKEv1 sends encode mode in SA - uses diferent codes when NATT being used 3012#ifdef ENABLE_NATT 3013 if (iph2->ph1->natt_flags & NAT_DETECTED) { 3014 plog (ASL_LEVEL_INFO, "NAT detected -> UDP encapsulation\n"); 3015 b->udp_encap = 1; 3016 if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) { 3017 int udp_diff = iph2->ph1->natt_options->mode_udp_diff; 3018 /* Tunnel -> UDP-Tunnel, Transport -> UDP_Transport */ 3019 b->encmode += udp_diff; 3020 } 3021 } 3022#endif 3023 switch (iph2->version) { 3024 case ISAKMP_VERSION_NUMBER_IKEV1: 3025 q = setph2proposal0(iph2, a, b); 3026 break; 3027 default: 3028 plog(ASL_LEVEL_ERR, "Invalid IKE version detected\n"); 3029 q = NULL; 3030 break; 3031 } 3032 if (q == NULL) { 3033 VPTRINIT(sa); 3034 return -1; 3035 } 3036 if (sa != NULL) 3037 sa = vrealloc(sa, sa->l + q->l); 3038 else 3039 sa = vmalloc(q->l); 3040 3041 if (sa == NULL) { 3042 plog(ASL_LEVEL_ERR, 3043 "failed to allocate my sa buffer\n"); 3044 if (q) 3045 vfree(q); 3046 return -1; 3047 } 3048 memcpy(sa->v + sa->l - q->l, q->v, q->l); 3049 if (propoff != 0) { 3050 prop = (struct isakmp_pl_p *)(sa->v + 3051 propoff); 3052 if (iph2->version == ISAKMP_VERSION_NUMBER_IKEV1) 3053 prop->h.np = ISAKMP_NPTYPE_P; 3054 } 3055 propoff = sa->l - q->l; 3056 3057 vfree(q); 3058 } 3059 } 3060 if (return_sa) 3061 iph2->sa_ret = sa; 3062 else 3063 iph2->sa = sa; 3064 return 0; 3065} 3066 3067/* 3068 * return 1 if all of the given protocols are tunnel mode. 3069 */ 3070int 3071ipsecdoi_tunnelmode(iph2) 3072 phase2_handle_t *iph2; 3073{ 3074 struct saprop *pp; 3075 struct saproto *pr = NULL; 3076 3077 for (pp = iph2->proposal; pp; pp = pp->next) { 3078 for (pr = pp->head; pr; pr = pr->next) { 3079 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TUNNEL && 3080 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC && 3081 pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT) 3082 return 0; 3083 } 3084 } 3085 3086 return 1; 3087} 3088 3089/* 3090 * return 1 if any of the given protocols are transport mode. 3091 */ 3092int 3093ipsecdoi_any_transportmode(pp) 3094struct saprop *pp; 3095{ 3096 struct saproto *pr = NULL; 3097 3098 for (; pp; pp = pp->next) { 3099 for (pr = pp->head; pr; pr = pr->next) { 3100 if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TRNS || 3101 pr->encmode == IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC || 3102 pr->encmode == IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT) 3103 return 1; 3104 } 3105 } 3106 3107 return 0; 3108} 3109 3110/* 3111 * return 1 if all of the given protocols are transport mode. 3112 */ 3113int 3114ipsecdoi_transportmode(pp) 3115 struct saprop *pp; 3116{ 3117 struct saproto *pr = NULL; 3118 3119 for (; pp; pp = pp->next) { 3120 for (pr = pp->head; pr; pr = pr->next) { 3121 if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS) 3122 return 0; 3123 } 3124 } 3125 3126 return 1; 3127} 3128 3129int 3130ipsecdoi_get_defaultlifetime() 3131{ 3132 return IPSECDOI_ATTR_SA_LD_SEC_DEFAULT; 3133} 3134 3135int 3136ipsecdoi_checkalgtypes(proto_id, enc, auth, comp) 3137 int proto_id, enc, auth, comp; 3138{ 3139#define TMPALGTYPE2STR(n) s_algtype(algclass_ipsec_##n, n) 3140 switch (proto_id) { 3141 case IPSECDOI_PROTO_IPSEC_ESP: 3142 if (enc == 0 || comp != 0) { 3143 plog(ASL_LEVEL_ERR, 3144 "illegal algorithm defined " 3145 "ESP enc=%s auth=%s comp=%s.\n", 3146 TMPALGTYPE2STR(enc), 3147 TMPALGTYPE2STR(auth), 3148 TMPALGTYPE2STR(comp)); 3149 return -1; 3150 } 3151 break; 3152 case IPSECDOI_PROTO_IPSEC_AH: 3153 if (enc != 0 || auth == 0 || comp != 0) { 3154 plog(ASL_LEVEL_ERR, 3155 "illegal algorithm defined " 3156 "AH enc=%s auth=%s comp=%s.\n", 3157 TMPALGTYPE2STR(enc), 3158 TMPALGTYPE2STR(auth), 3159 TMPALGTYPE2STR(comp)); 3160 return -1; 3161 } 3162 break; 3163 case IPSECDOI_PROTO_IPCOMP: 3164 if (enc != 0 || auth != 0 || comp == 0) { 3165 plog(ASL_LEVEL_ERR, 3166 "illegal algorithm defined " 3167 "IPcomp enc=%s auth=%s comp=%s.\n", 3168 TMPALGTYPE2STR(enc), 3169 TMPALGTYPE2STR(auth), 3170 TMPALGTYPE2STR(comp)); 3171 return -1; 3172 } 3173 break; 3174 default: 3175 plog(ASL_LEVEL_ERR, 3176 "invalid ipsec protocol %d\n", proto_id); 3177 return -1; 3178 } 3179#undef TMPALGTYPE2STR 3180 return 0; 3181} 3182 3183int 3184ipproto2doi(proto) 3185 int proto; 3186{ 3187 switch (proto) { 3188 case IPPROTO_AH: 3189 return IPSECDOI_PROTO_IPSEC_AH; 3190 case IPPROTO_ESP: 3191 return IPSECDOI_PROTO_IPSEC_ESP; 3192 case IPPROTO_IPCOMP: 3193 return IPSECDOI_PROTO_IPCOMP; 3194 } 3195 return -1; /* XXX */ 3196} 3197 3198int 3199doi2ipproto(proto) 3200 int proto; 3201{ 3202 switch (proto) { 3203 case IPSECDOI_PROTO_IPSEC_AH: 3204 return IPPROTO_AH; 3205 case IPSECDOI_PROTO_IPSEC_ESP: 3206 return IPPROTO_ESP; 3207 case IPSECDOI_PROTO_IPCOMP: 3208 return IPPROTO_IPCOMP; 3209 } 3210 return -1; /* XXX */ 3211} 3212 3213/* 3214 * Check if a subnet id is valid for comparison 3215 * with an address id ( address length mask ) 3216 * and compare them 3217 * Return value 3218 * = 0 for match 3219 * = 1 for mismatch 3220 */ 3221 3222int 3223ipsecdoi_subnetisaddr_v4( subnet, address ) 3224 const vchar_t *subnet; 3225 const vchar_t *address; 3226{ 3227 struct in_addr *mask; 3228 3229 if (address->l != sizeof(struct in_addr)) 3230 return 1; 3231 3232 if (subnet->l != (sizeof(struct in_addr)*2)) 3233 return 1; 3234 3235 mask = ALIGNED_CAST(struct in_addr*)(subnet->v + sizeof(struct in_addr)); 3236 3237 if (mask->s_addr!=0xffffffff) 3238 return 1; 3239 3240 return memcmp(subnet->v,address->v,address->l); 3241} 3242 3243#ifdef INET6 3244 3245int 3246ipsecdoi_subnetisaddr_v6( subnet, address ) 3247 const vchar_t *subnet; 3248 const vchar_t *address; 3249{ 3250 struct in6_addr *mask; 3251 int i; 3252 3253 if (address->l != sizeof(struct in6_addr)) 3254 return 1; 3255 3256 if (subnet->l != (sizeof(struct in6_addr)*2)) 3257 return 1; 3258 3259 mask = ALIGNED_CAST(struct in6_addr*)(subnet->v + sizeof(struct in6_addr)); 3260 3261 for (i=0; i<16; i++) 3262 if(mask->s6_addr[i]!=0xff) 3263 return 1; 3264 3265 return memcmp(subnet->v,address->v,address->l); 3266} 3267 3268#endif 3269 3270#ifdef NOT_USED 3271/* 3272 * Check and Compare two IDs 3273 * - specify 0 for exact if wildcards are allowed 3274 * Return value 3275 * = 0 for match 3276 * = 1 for misatch 3277 * = -1 for integrity error 3278 */ 3279 3280int 3281ipsecdoi_chkcmpids( idt, ids, exact ) 3282 const vchar_t *idt; /* id cmp target */ 3283 const vchar_t *ids; /* id cmp source */ 3284 int exact; 3285{ 3286 struct ipsecdoi_id_b *id_bt; 3287 struct ipsecdoi_id_b *id_bs; 3288 vchar_t ident_t; 3289 vchar_t ident_s; 3290 int result; 3291 3292 /* handle wildcard IDs */ 3293 3294 if (idt == NULL || ids == NULL) 3295 { 3296 if( !exact ) 3297 { 3298 plog(ASL_LEVEL_DEBUG, 3299 "check and compare ids : values matched (ANONYMOUS)\n" ); 3300 return 0; 3301 } 3302 else 3303 { 3304 plog(ASL_LEVEL_DEBUG, 3305 "check and compare ids : value mismatch (ANONYMOUS)\n" ); 3306 return -1; 3307 } 3308 } 3309 3310 /* make sure the ids are of the same type */ 3311 3312 id_bt = (struct ipsecdoi_id_b *) idt->v; 3313 id_bs = (struct ipsecdoi_id_b *) ids->v; 3314 3315 ident_t.v = idt->v + sizeof(*id_bt); 3316 ident_t.l = idt->l - sizeof(*id_bt); 3317 ident_s.v = ids->v + sizeof(*id_bs); 3318 ident_s.l = ids->l - sizeof(*id_bs); 3319 3320 if (id_bs->type != id_bt->type) 3321 { 3322 /* 3323 * special exception for comparing 3324 * address to subnet id types when 3325 * the netmask is address length 3326 */ 3327 3328 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&& 3329 (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) { 3330 result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s); 3331 goto cmpid_result; 3332 } 3333 3334 if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&& 3335 (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) { 3336 result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t); 3337 goto cmpid_result; 3338 } 3339 3340#ifdef INET6 3341 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&& 3342 (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) { 3343 result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s); 3344 goto cmpid_result; 3345 } 3346 3347 if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&& 3348 (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) { 3349 result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t); 3350 goto cmpid_result; 3351 } 3352#endif 3353 plog(ASL_LEVEL_DEBUG, 3354 "check and compare ids : id type mismatch %s != %s\n", 3355 s_ipsecdoi_ident(id_bs->type), 3356 s_ipsecdoi_ident(id_bt->type)); 3357 3358 return 1; 3359 } 3360 3361 if(id_bs->proto_id != id_bt->proto_id){ 3362 plog(ASL_LEVEL_DEBUG, 3363 "check and compare ids : proto_id mismatch %d != %d\n", 3364 id_bs->proto_id, id_bt->proto_id); 3365 3366 return 1; 3367 } 3368 3369 /* compare the ID data. */ 3370 3371 switch (id_bt->type) { 3372 case IPSECDOI_ID_DER_ASN1_DN: 3373 case IPSECDOI_ID_DER_ASN1_GN: 3374 /* compare asn1 ids */ 3375 result = eay_cmp_asn1dn(&ident_t, &ident_s); 3376 goto cmpid_result; 3377 3378 case IPSECDOI_ID_IPV4_ADDR: 3379 /* validate lengths */ 3380 if ((ident_t.l != sizeof(struct in_addr))|| 3381 (ident_s.l != sizeof(struct in_addr))) 3382 goto cmpid_invalid; 3383 break; 3384 3385 case IPSECDOI_ID_IPV4_ADDR_SUBNET: 3386 case IPSECDOI_ID_IPV4_ADDR_RANGE: 3387 /* validate lengths */ 3388 if ((ident_t.l != (sizeof(struct in_addr)*2))|| 3389 (ident_s.l != (sizeof(struct in_addr)*2))) 3390 goto cmpid_invalid; 3391 break; 3392 3393#ifdef INET6 3394 case IPSECDOI_ID_IPV6_ADDR: 3395 /* validate lengths */ 3396 if ((ident_t.l != sizeof(struct in6_addr))|| 3397 (ident_s.l != sizeof(struct in6_addr))) 3398 goto cmpid_invalid; 3399 break; 3400 3401 case IPSECDOI_ID_IPV6_ADDR_SUBNET: 3402 case IPSECDOI_ID_IPV6_ADDR_RANGE: 3403 /* validate lengths */ 3404 if ((ident_t.l != (sizeof(struct in6_addr)*2))|| 3405 (ident_s.l != (sizeof(struct in6_addr)*2))) 3406 goto cmpid_invalid; 3407 break; 3408#endif 3409 case IPSECDOI_ID_FQDN: 3410 case IPSECDOI_ID_USER_FQDN: 3411 case IPSECDOI_ID_KEY_ID: 3412 break; 3413 3414 default: 3415 plog(ASL_LEVEL_ERR, 3416 "Unhandled id type %i specified for comparison\n", 3417 id_bt->type); 3418 return -1; 3419 } 3420 3421 /* validate matching data and length */ 3422 if (ident_t.l == ident_s.l) 3423 result = memcmp(ident_t.v,ident_s.v,ident_t.l); 3424 else 3425 result = 1; 3426 3427cmpid_result: 3428 3429 /* debug level output */ 3430 if(loglevel >= ASL_LEVEL_DEBUG) { 3431 char *idstrt = ipsecdoi_id2str(idt); 3432 char *idstrs = ipsecdoi_id2str(ids); 3433 3434 if (!result) 3435 plog(ASL_LEVEL_DEBUG, 3436 "check and compare ids : values matched (%s)\n", 3437 s_ipsecdoi_ident(id_bs->type) ); 3438 else 3439 plog(ASL_LEVEL_DEBUG, 3440 "check and compare ids : value mismatch (%s)\n", 3441 s_ipsecdoi_ident(id_bs->type)); 3442 3443 plog(ASL_LEVEL_DEBUG, "cmpid target: \'%s\'\n", idstrt ); 3444 plog(ASL_LEVEL_DEBUG, "cmpid source: \'%s\'\n", idstrs ); 3445 3446 racoon_free(idstrs); 3447 racoon_free(idstrt); 3448 } 3449 3450 /* return result */ 3451 if( !result ) 3452 return 0; 3453 else 3454 return 1; 3455 3456cmpid_invalid: 3457 3458 /* id integrity error */ 3459 plog(ASL_LEVEL_DEBUG, "check and compare ids : %s integrity error\n", 3460 s_ipsecdoi_ident(id_bs->type)); 3461 plog(ASL_LEVEL_DEBUG, "cmpid target: length = \'%zu\'\n", ident_t.l ); 3462 plog(ASL_LEVEL_DEBUG, "cmpid source: length = \'%zu\'\n", ident_s.l ); 3463 3464 return -1; 3465} 3466#endif 3467 3468/* 3469 * check the following: 3470 * - In main mode with pre-shared key, only address type can be used. 3471 * - if proper type for phase 1 ? 3472 * - if phase 1 ID payload conformed RFC2407 4.6.2. 3473 * (proto, port) must be (0, 0), (udp, 500) or (udp, [specified]). 3474 * - if ID payload sent from peer is equal to the ID expected by me. 3475 * 3476 * both of "id" and "id_p" should be ID payload without general header, 3477 */ 3478int 3479ipsecdoi_checkid1(iph1) 3480 phase1_handle_t *iph1; 3481{ 3482 struct ipsecdoi_id_b *id_b; 3483 struct sockaddr_storage *sa; 3484 caddr_t sa1, sa2; 3485 3486 if (iph1->id_p == NULL) { 3487 plog(ASL_LEVEL_ERR, 3488 "invalid iph1 passed id_p == NULL\n"); 3489 return ISAKMP_INTERNAL_ERROR; 3490 } 3491 if (iph1->id_p->l < sizeof(*id_b)) { 3492 plog(ASL_LEVEL_ERR, 3493 "invalid value passed as \"ident\" (len=%lu)\n", 3494 (u_long)iph1->id_p->l); 3495 return ISAKMP_NTYPE_INVALID_ID_INFORMATION; 3496 } 3497 3498 id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)iph1->id_p->v; 3499 3500 /* In main mode with pre-shared key, only address type can be used. 3501 * If NAT Traversal being used and peer is behind nat and 3502 * natt version = 02 - allow non-address ID type. 3503 */ 3504 if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1 3505 && iph1->etype == ISAKMP_ETYPE_IDENT 3506 && iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY 3507#ifdef ENABLE_NATT 3508 && (iph1->natt_flags & NAT_DETECTED_PEER) == 0 3509#endif 3510 ) { 3511 if (id_b->type != IPSECDOI_ID_IPV4_ADDR 3512 && id_b->type != IPSECDOI_ID_IPV6_ADDR) { 3513 plog(ASL_LEVEL_ERR, 3514 "Expecting IP address type in main mode, " 3515 "but %s.\n", s_ipsecdoi_ident(id_b->type)); 3516 return ISAKMP_NTYPE_INVALID_ID_INFORMATION; 3517 } 3518 } 3519 3520 /* if proper type for phase 1 ? */ 3521 switch (id_b->type) { 3522 case IPSECDOI_ID_IPV4_ADDR_SUBNET: 3523 case IPSECDOI_ID_IPV6_ADDR_SUBNET: 3524 case IPSECDOI_ID_IPV4_ADDR_RANGE: 3525 case IPSECDOI_ID_IPV6_ADDR_RANGE: 3526 plog(ASL_LEVEL_WARNING, 3527 "such ID type %s is not proper.\n", 3528 s_ipsecdoi_ident(id_b->type)); 3529 /*FALLTHROUGH*/ 3530 } 3531 3532 /* if phase 1 ID payload conformed RFC2407 4.6.2. */ 3533 if (id_b->type == IPSECDOI_ID_IPV4_ADDR || 3534 id_b->type == IPSECDOI_ID_IPV6_ADDR) { 3535 3536 if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) { 3537 plog(ASL_LEVEL_WARNING, 3538 "protocol ID and Port mismatched. " 3539 "proto_id:%d port:%d\n", 3540 id_b->proto_id, ntohs(id_b->port)); 3541 /*FALLTHROUGH*/ 3542 3543 } else if (id_b->proto_id == IPPROTO_UDP) { 3544 /* 3545 * copmaring with expected port. 3546 * always permit if port is equal to PORT_ISAKMP 3547 */ 3548 if (ntohs(id_b->port) != PORT_ISAKMP) { 3549 3550 u_int16_t port; 3551 3552 switch (iph1->remote->ss_family) { 3553 case AF_INET: 3554 port = ((struct sockaddr_in *)iph1->remote)->sin_port; 3555 break; 3556#ifdef INET6 3557 case AF_INET6: 3558 port = ((struct sockaddr_in6 *)iph1->remote)->sin6_port; 3559 break; 3560#endif 3561 default: 3562 plog(ASL_LEVEL_ERR, 3563 "invalid family: %d\n", 3564 iph1->remote->ss_family); 3565 return ISAKMP_NTYPE_INVALID_ID_INFORMATION; 3566 } 3567 if (ntohs(id_b->port) != port) { 3568 plog(ASL_LEVEL_WARNING, 3569 "port %d expected, but %d\n", 3570 port, ntohs(id_b->port)); 3571 /*FALLTHROUGH*/ 3572 } 3573 } 3574 } 3575 } 3576 3577 /* compare with the ID if specified. */ 3578 if (genlist_next(iph1->rmconf->idvl_p, 0)) { 3579 vchar_t *ident0 = NULL; 3580#ifdef HAVE_OPENSSL 3581 vchar_t ident; 3582#endif 3583 struct idspec *id; 3584 struct genlist_entry *gpb; 3585 3586 for (id = genlist_next (iph1->rmconf->idvl_p, &gpb); id; id = genlist_next (0, &gpb)) { 3587 /* check the type of both IDs */ 3588 if (id->idtype != doi2idtype(id_b->type)) 3589 continue; /* ID type mismatch */ 3590 if (id->id == 0) 3591 goto matched; 3592 3593 /* compare defined ID with the ID sent by peer. */ 3594 if (ident0 != NULL) 3595 vfree(ident0); 3596 ident0 = getidval(id->idtype, id->id); 3597 3598 switch (id->idtype) { 3599 case IDTYPE_ASN1DN: 3600#ifdef HAVE_OPENSSL 3601 ident.v = iph1->id_p->v + sizeof(*id_b); 3602 ident.l = iph1->id_p->l - sizeof(*id_b); 3603 if (eay_cmp_asn1dn(ident0, &ident) == 0) 3604 goto matched; 3605#else 3606 plog(ASL_LEVEL_WARNING, "ASN1DN ID matching not implemented - passed.\n"); 3607 goto matched; //%%%%%% hack for now until we have code to do this. 3608#endif 3609 break; 3610 case IDTYPE_ADDRESS: 3611 sa = ALIGNED_CAST(struct sockaddr_storage *)ident0->v; 3612 sa2 = (caddr_t)(id_b + 1); 3613 switch (sa->ss_family) { 3614 case AF_INET: 3615 if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr)) 3616 continue; /* ID value mismatch */ 3617 sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr; 3618 if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0) 3619 goto matched; 3620 break; 3621#ifdef INET6 3622 case AF_INET6: 3623 if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr)) 3624 continue; /* ID value mismatch */ 3625 sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr; 3626 if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0) 3627 goto matched; 3628 break; 3629#endif 3630 default: 3631 break; 3632 } 3633 break; 3634 default: 3635 if (memcmp(ident0->v, id_b + 1, ident0->l) == 0) 3636 goto matched; 3637 break; 3638 } 3639 } 3640 if (ident0 != NULL) { 3641 vfree(ident0); 3642 ident0 = NULL; 3643 } 3644 plog(ASL_LEVEL_DEBUG, "No ID match.\n"); 3645 if (iph1->rmconf->verify_identifier) 3646 return ISAKMP_NTYPE_INVALID_ID_INFORMATION; 3647matched: /* ID value match */ 3648 if (ident0 != NULL) 3649 vfree(ident0); 3650 } 3651 3652 return 0; 3653} 3654 3655/* HACK!!! - temporary until this prototype gets moved */ 3656extern CFDataRef SecCertificateCopySubjectSequence( SecCertificateRef certificate); 3657 3658/* 3659 * create ID payload for phase 1 and set into iph1->id. 3660 * NOT INCLUDING isakmp general header. 3661 * see, RFC2407 4.6.2.1 3662 */ 3663int 3664ipsecdoi_setid1(iph1) 3665 phase1_handle_t *iph1; 3666{ 3667 vchar_t *ret = NULL; 3668 struct ipsecdoi_id_b id_b; 3669 vchar_t *ident = NULL; 3670 struct sockaddr_storage *ipid = NULL; 3671 3672 /* init */ 3673 bzero(&id_b, sizeof(id_b)); 3674 ident = NULL; 3675 switch (iph1->rmconf->idvtype) { 3676 case IDTYPE_FQDN: 3677 id_b.type = IPSECDOI_ID_FQDN; 3678 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv); 3679 break; 3680 case IDTYPE_USERFQDN: 3681 id_b.type = IPSECDOI_ID_USER_FQDN; 3682 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv); 3683 break; 3684 case IDTYPE_KEYID: 3685 case IDTYPE_KEYIDUSE: 3686 id_b.type = IPSECDOI_ID_KEY_ID; 3687 ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv); 3688 break; 3689 case IDTYPE_ASN1DN: 3690 id_b.type = IPSECDOI_ID_DER_ASN1_DN; 3691 if (iph1->rmconf->idv) { 3692 /* XXX it must be encoded to asn1dn. */ 3693 ident = vdup(iph1->rmconf->idv); 3694 } else { 3695 if (oakley_getmycert(iph1) < 0) { 3696 plog(ASL_LEVEL_ERR, 3697 "failed to get own CERT.\n"); 3698 goto err; 3699 } 3700 3701 SecCertificateRef certificate; 3702 CFDataRef subject; 3703 UInt8* namePtr; 3704 int len; 3705 3706 certificate = crypto_cssm_x509cert_CreateSecCertificateRef(&iph1->cert->cert); 3707 if (certificate == NULL) { 3708 plog(ASL_LEVEL_ERR, 3709 "failed to get SecCertificateRef\n"); 3710 break; 3711 } 3712 subject = crypto_cssm_CopySubjectSequence(certificate); 3713 if (subject == NULL) { 3714 plog(ASL_LEVEL_ERR, 3715 "failed to get subjectName\n"); 3716 CFRelease(certificate); 3717 break; 3718 } 3719 len = CFDataGetLength(subject); 3720 namePtr = (UInt8*)CFDataGetBytePtr(subject); 3721 ident = vmalloc(len); 3722 if (ident == NULL) { 3723 plog(ASL_LEVEL_ERR, 3724 "failed to get subjectName\n"); 3725 CFRelease(certificate); 3726 CFRelease(subject); 3727 break; 3728 } 3729 memcpy(ident->v, namePtr, len); 3730 CFRelease(certificate); 3731 CFRelease(subject); 3732 } 3733 break; 3734 case IDTYPE_ADDRESS: 3735 /* 3736 * if the value of the id type was set by the configuration 3737 * file, then use it. otherwise the value is get from local 3738 * ip address by using ike negotiation. 3739 */ 3740 if (iph1->rmconf->idv) 3741 ipid = ALIGNED_CAST(struct sockaddr_storage *)iph1->rmconf->idv->v; 3742 /*FALLTHROUGH*/ 3743 default: 3744 { 3745 int l; 3746 caddr_t p; 3747 3748 if (ipid == NULL) 3749 ipid = iph1->local; 3750 3751 /* use IP address */ 3752 switch (ipid->ss_family) { 3753 case AF_INET: 3754 id_b.type = IPSECDOI_ID_IPV4_ADDR; 3755 l = sizeof(struct in_addr); 3756 p = (caddr_t)&((struct sockaddr_in *)ipid)->sin_addr; 3757 break; 3758#ifdef INET6 3759 case AF_INET6: 3760 id_b.type = IPSECDOI_ID_IPV6_ADDR; 3761 l = sizeof(struct in6_addr); 3762 p = (caddr_t)&((struct sockaddr_in6 *)ipid)->sin6_addr; 3763 break; 3764#endif 3765 default: 3766 plog(ASL_LEVEL_ERR, 3767 "invalid address family.\n"); 3768 goto err; 3769 } 3770 if(iph1->version == ISAKMP_VERSION_NUMBER_IKEV1){ 3771 id_b.proto_id = IPPROTO_UDP; 3772 id_b.port = htons(PORT_ISAKMP); 3773 3774 } 3775 ident = vmalloc(l); 3776 if (!ident) { 3777 plog(ASL_LEVEL_ERR, 3778 "failed to get ID buffer.\n"); 3779 return 0; 3780 } 3781 memcpy(ident->v, p, ident->l); 3782 } 3783 } 3784 if (!ident) { 3785 plog(ASL_LEVEL_ERR, 3786 "failed to get ID buffer.\n"); 3787 return 0; 3788 } 3789 3790 ret = vmalloc(sizeof(id_b) + ident->l); 3791 if (ret == NULL) { 3792 plog(ASL_LEVEL_ERR, 3793 "failed to get ID buffer.\n"); 3794 goto err; 3795 } 3796 3797 memcpy(ret->v, &id_b, sizeof(id_b)); 3798 memcpy(ret->v + sizeof(id_b), ident->v, ident->l); 3799 3800 iph1->id = ret; 3801 3802 plogdump(ASL_LEVEL_DEBUG, iph1->id->v, iph1->id->l, "use ID type of %s\n", s_ipsecdoi_ident(id_b.type)); 3803 if (ident) 3804 vfree(ident); 3805 return 0; 3806 3807err: 3808 if (ident) 3809 vfree(ident); 3810 plog(ASL_LEVEL_ERR, "failed get my ID\n"); 3811 return -1; 3812} 3813 3814static vchar_t * 3815getidval(type, val) 3816 int type; 3817 vchar_t *val; 3818{ 3819 vchar_t *new = NULL; 3820 3821 if (val) 3822 new = vdup(val); 3823 else if (lcconf->ident[type]) 3824 new = vdup(lcconf->ident[type]); 3825 3826 return new; 3827} 3828 3829/* it's only called by cfparse.y. */ 3830int 3831set_identifier(vpp, type, value) 3832 vchar_t **vpp, *value; 3833 int type; 3834{ 3835 return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC); 3836} 3837 3838int 3839set_identifier_qual(vpp, type, value, qual) 3840 vchar_t **vpp, *value; 3841 int type; 3842 int qual; 3843{ 3844 vchar_t *new = NULL; 3845 3846 /* simply return if value is null. */ 3847 if (!value){ 3848 if( type == IDTYPE_FQDN || type == IDTYPE_USERFQDN){ 3849 plog(ASL_LEVEL_ERR, 3850 "No %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn"); 3851 return -1; 3852 } 3853 return 0; 3854 } 3855 3856 switch (type) { 3857 case IDTYPE_FQDN: 3858 case IDTYPE_USERFQDN: 3859 if(value->l <= 1){ 3860 plog(ASL_LEVEL_ERR, 3861 "Empty %s\n", type == IDTYPE_FQDN ? "fqdn":"user fqdn"); 3862 return -1; 3863 } 3864 case IDTYPE_KEYIDUSE: 3865#ifdef ENABLE_HYBRID 3866 case IDTYPE_LOGIN: 3867#endif 3868 /* length is adjusted since QUOTEDSTRING teminates NULL. */ 3869 new = vmalloc(value->l - 1); 3870 if (new == NULL) 3871 return -1; 3872 memcpy(new->v, value->v, new->l); 3873 break; 3874 case IDTYPE_KEYID: 3875 /* 3876 * If no qualifier is specified: IDQUAL_UNSPEC. It means 3877 * to use a file for backward compatibility sake. 3878 */ 3879 switch(qual) { 3880 case IDQUAL_FILE: 3881 case IDQUAL_UNSPEC: { 3882 FILE *fp; 3883 char b[512]; 3884 int tlen, len; 3885 3886 fp = fopen(value->v, "r"); 3887 if (fp == NULL) { 3888 plog(ASL_LEVEL_ERR, 3889 "can not open %s\n", value->v); 3890 return -1; 3891 } 3892 tlen = 0; 3893 while ((len = fread(b, 1, sizeof(b), fp)) != 0) { 3894 new = vrealloc(new, tlen + len); 3895 if (!new) { 3896 fclose(fp); 3897 return -1; 3898 } 3899 memcpy(new->v + tlen, b, len); 3900 tlen += len; 3901 } 3902 fclose(fp); 3903 break; 3904 } 3905 3906 case IDQUAL_TAG: 3907 new = vmalloc(value->l - 1); 3908 if (new == NULL) { 3909 plog(ASL_LEVEL_ERR, 3910 "can not allocate memory"); 3911 return -1; 3912 } 3913 memcpy(new->v, value->v, new->l); 3914 break; 3915 3916 default: 3917 plog(ASL_LEVEL_ERR, 3918 "unknown qualifier"); 3919 return -1; 3920 } 3921 break; 3922 3923 case IDTYPE_ADDRESS: { 3924 struct sockaddr_storage *sa; 3925 3926 /* length is adjusted since QUOTEDSTRING teminates NULL. */ 3927 if (value->l == 0) 3928 break; 3929 3930 sa = str2saddr(value->v, NULL); 3931 if (sa == NULL) { 3932 plog(ASL_LEVEL_ERR, 3933 "invalid ip address %s\n", value->v); 3934 return -1; 3935 } 3936 3937 new = vmalloc(sysdep_sa_len((struct sockaddr *)sa)); 3938 if (new == NULL) { 3939 racoon_free(sa); 3940 return -1; 3941 } 3942 memcpy(new->v, sa, new->l); 3943 racoon_free(sa); 3944 break; 3945 } 3946 case IDTYPE_ASN1DN: 3947 plog(ASL_LEVEL_DEBUG, "Setting ID type ASN1DN from string not supported\n"); 3948 return -1; 3949 3950 break; 3951 } 3952 3953 *vpp = new; 3954 3955 return 0; 3956} 3957 3958/* 3959 * create ID payload for phase 2, and set into iph2->id and id_p. There are 3960 * NOT INCLUDING isakmp general header. 3961 * this function is for initiator. responder will get to copy from payload. 3962 * responder ID type is always address type. 3963 * see, RFC2407 4.6.2.1 3964 */ 3965int 3966ipsecdoi_setid2(iph2) 3967 phase2_handle_t *iph2; 3968{ 3969 struct secpolicy *sp; 3970 3971 /* check there is phase 2 handler ? */ 3972 sp = getspbyspid(iph2->spid); 3973 if (sp == NULL) { 3974 plog(ASL_LEVEL_ERR, 3975 "no policy found for spid:%u.\n", iph2->spid); 3976 return -1; 3977 } 3978 3979 iph2->id = ipsecdoi_sockaddr2id(&sp->spidx.src, 3980 sp->spidx.prefs, sp->spidx.ul_proto); 3981 if (iph2->id == NULL) { 3982 plog(ASL_LEVEL_ERR, 3983 "failed to get ID for %s\n", 3984 spidx2str(&sp->spidx)); 3985 return -1; 3986 } 3987#ifdef ENABLE_NATT 3988 if (((ALIGNED_CAST(struct ipsecdoi_id_b *)iph2->id->v)->type == IPSECDOI_ID_IPV4_ADDR || 3989 (ALIGNED_CAST(struct ipsecdoi_id_b *)iph2->id->v)->type == IPSECDOI_ID_IPV4_ADDR_SUBNET) && 3990 iph2->side == RESPONDER && 3991 iph2->ph1 && (iph2->ph1->natt_flags & NAT_DETECTED_ME) && 3992 lcconf->ext_nat_id) { 3993 vfree(iph2->id); 3994 if (!(iph2->id = vdup(lcconf->ext_nat_id))) { 3995 return -1; 3996 } 3997 } 3998#endif 3999 plogdump(ASL_LEVEL_DEBUG, iph2->id->v, iph2->id->l, "use local ID type %s\n", 4000 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b *)iph2->id->v)->type)); 4001 4002 /* remote side */ 4003 iph2->id_p = ipsecdoi_sockaddr2id(&sp->spidx.dst, 4004 sp->spidx.prefd, sp->spidx.ul_proto); 4005 if (iph2->id_p == NULL) { 4006 plog(ASL_LEVEL_ERR, 4007 "failed to get ID for %s\n", 4008 spidx2str(&sp->spidx)); 4009 VPTRINIT(iph2->id); 4010 return -1; 4011 } 4012 plogdump(ASL_LEVEL_DEBUG, iph2->id->v, iph2->id->l, "use remote ID type %s\n", 4013 s_ipsecdoi_ident((ALIGNED_CAST(struct ipsecdoi_id_b *)iph2->id_p->v)->type)); 4014 4015 return 0; 4016} 4017 4018/* 4019 * set address type of ID. 4020 * NOT INCLUDING general header. 4021 */ 4022vchar_t * 4023ipsecdoi_sockaddr2id(saddr, prefixlen, ul_proto) 4024 struct sockaddr_storage *saddr; 4025 u_int prefixlen; 4026 u_int ul_proto; 4027{ 4028 vchar_t *new; 4029 int type, len1, len2; 4030 caddr_t sa; 4031 u_short port; 4032 4033 /* 4034 * Q. When type is SUBNET, is it allowed to be ::1/128. 4035 * A. Yes. (consensus at bake-off) 4036 */ 4037 switch (saddr->ss_family) { 4038 case AF_INET: 4039 len1 = sizeof(struct in_addr); 4040 if (prefixlen == (sizeof(struct in_addr) << 3)) { 4041 type = IPSECDOI_ID_IPV4_ADDR; 4042 len2 = 0; 4043 } else { 4044 type = IPSECDOI_ID_IPV4_ADDR_SUBNET; 4045 len2 = sizeof(struct in_addr); 4046 } 4047 sa = (caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr; 4048 port = ((struct sockaddr_in *)(saddr))->sin_port; 4049 break; 4050#ifdef INET6 4051 case AF_INET6: 4052 len1 = sizeof(struct in6_addr); 4053 if (prefixlen == (sizeof(struct in6_addr) << 3)) { 4054 type = IPSECDOI_ID_IPV6_ADDR; 4055 len2 = 0; 4056 } else { 4057 type = IPSECDOI_ID_IPV6_ADDR_SUBNET; 4058 len2 = sizeof(struct in6_addr); 4059 } 4060 sa = (caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr; 4061 port = ((struct sockaddr_in6 *)(saddr))->sin6_port; 4062 break; 4063#endif 4064 default: 4065 plog(ASL_LEVEL_ERR, 4066 "invalid family: %d.\n", saddr->ss_family); 4067 return NULL; 4068 } 4069 4070 /* get ID buffer */ 4071 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2); 4072 if (new == NULL) { 4073 plog(ASL_LEVEL_ERR, 4074 "failed to get ID buffer.\n"); 4075 return NULL; 4076 } 4077 4078 memset(new->v, 0, new->l); 4079 4080 /* set the part of header. */ 4081 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->type = type; 4082 4083 /* set ul_proto and port */ 4084 /* 4085 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card 4086 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY. 4087 */ 4088 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->proto_id = 4089 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto; 4090 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->port = 4091 port == IPSEC_PORT_ANY ? 0 : port; 4092 memcpy(new->v + sizeof(struct ipsecdoi_id_b), sa, len1); 4093 4094 /* set address */ 4095 4096 /* set prefix */ 4097 if (len2) { 4098 u_char *p = (unsigned char *) new->v + 4099 sizeof(struct ipsecdoi_id_b) + len1; 4100 u_int bits = prefixlen; 4101 4102 while (bits >= 8) { 4103 *p++ = 0xff; 4104 bits -= 8; 4105 } 4106 4107 if (bits > 0) 4108 *p = ~((1 << (8 - bits)) - 1); 4109 } 4110 4111 return new; 4112} 4113 4114vchar_t * 4115ipsecdoi_sockrange2id(laddr, haddr, ul_proto) 4116 struct sockaddr_storage *laddr, *haddr; 4117 u_int ul_proto; 4118{ 4119 vchar_t *new; 4120 int type, len1, len2; 4121 u_short port; 4122 4123 if (laddr->ss_family != haddr->ss_family) { 4124 plog(ASL_LEVEL_ERR, "Address family mismatch\n"); 4125 return NULL; 4126 } 4127 4128 switch (laddr->ss_family) { 4129 case AF_INET: 4130 type = IPSECDOI_ID_IPV4_ADDR_RANGE; 4131 len1 = sizeof(struct in_addr); 4132 len2 = sizeof(struct in_addr); 4133 break; 4134#ifdef INET6 4135 case AF_INET6: 4136 type = IPSECDOI_ID_IPV6_ADDR_RANGE; 4137 len1 = sizeof(struct in6_addr); 4138 len2 = sizeof(struct in6_addr); 4139 break; 4140#endif 4141 default: 4142 plog(ASL_LEVEL_ERR, 4143 "invalid family: %d.\n", laddr->ss_family); 4144 return NULL; 4145 } 4146 4147 /* get ID buffer */ 4148 new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2); 4149 if (new == NULL) { 4150 plog(ASL_LEVEL_ERR, 4151 "failed to get ID buffer.\n"); 4152 return NULL; 4153 } 4154 4155 memset(new->v, 0, new->l); 4156 /* set the part of header. */ 4157 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->type = type; 4158 4159 /* set ul_proto and port */ 4160 /* 4161 * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card 4162 * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY. 4163 */ 4164 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->proto_id = 4165 ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto; 4166 port = ((struct sockaddr_in *)(laddr))->sin_port; 4167 (ALIGNED_CAST(struct ipsecdoi_id_b *)new->v)->port = 4168 port == IPSEC_PORT_ANY ? 0 : port; 4169 memcpy(new->v + sizeof(struct ipsecdoi_id_b), 4170 (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr, 4171 len1); 4172 memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1, 4173 (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr, 4174 len2); 4175 return new; 4176} 4177 4178 4179/* 4180 * create sockaddr_storage structure from ID payload (buf). 4181 * buffers (saddr, prefixlen, ul_proto) must be allocated. 4182 * see, RFC2407 4.6.2.1 4183 */ 4184int 4185ipsecdoi_id2sockaddr(vchar_t *buf, 4186 struct sockaddr_storage *saddr, 4187 u_int8_t *prefixlen, 4188 u_int16_t *ul_proto, 4189 int version) 4190{ 4191 struct ipsecdoi_id_b *id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)buf->v; 4192 u_int plen = 0; 4193 4194 /* 4195 * When a ID payload of subnet type with a IP address of full bit 4196 * masked, it has to be processed as host address. 4197 * e.g. below 2 type are same. 4198 * type = ipv6 subnet, data = 2001::1/128 4199 * type = ipv6 address, data = 2001::1 4200 */ 4201 switch (id_b->type) { 4202 case IPSECDOI_ID_IPV4_ADDR: 4203 case IPSECDOI_ID_IPV4_ADDR_SUBNET: 4204 saddr->ss_len = sizeof(struct sockaddr_in); 4205 saddr->ss_family = AF_INET; 4206 ((struct sockaddr_in *)saddr)->sin_port = 4207 (id_b->port == 0 4208 ? IPSEC_PORT_ANY 4209 : id_b->port); /* see sockaddr2id() */ 4210 memcpy(&((struct sockaddr_in *)saddr)->sin_addr, 4211 buf->v + sizeof(*id_b), sizeof(struct in_addr)); 4212 break; 4213#ifdef INET6 4214 case IPSECDOI_ID_IPV6_ADDR: 4215 case IPSECDOI_ID_IPV6_ADDR_SUBNET: 4216 saddr->ss_len = sizeof(struct sockaddr_in6); 4217 saddr->ss_family = AF_INET6; 4218 ((struct sockaddr_in6 *)saddr)->sin6_port = 4219 (id_b->port == 0 4220 ? IPSEC_PORT_ANY 4221 : id_b->port); /* see sockaddr2id() */ 4222 memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr, 4223 buf->v + sizeof(*id_b), sizeof(struct in6_addr)); 4224 break; 4225#endif 4226 default: 4227 plog(ASL_LEVEL_ERR, 4228 "unsupported ID type %d\n", id_b->type); 4229 return ISAKMP_NTYPE_INVALID_ID_INFORMATION; 4230 } 4231 4232 /* get prefix length */ 4233 switch (id_b->type) { 4234 case IPSECDOI_ID_IPV4_ADDR: 4235 plen = sizeof(struct in_addr) << 3; 4236 break; 4237#ifdef INET6 4238 case IPSECDOI_ID_IPV6_ADDR: 4239 plen = sizeof(struct in6_addr) << 3; 4240 break; 4241#endif 4242 case IPSECDOI_ID_IPV4_ADDR_SUBNET: 4243#ifdef INET6 4244 case IPSECDOI_ID_IPV6_ADDR_SUBNET: 4245#endif 4246 { 4247 u_char *p; 4248 u_int max; 4249 int alen = sizeof(struct in_addr); 4250 4251 switch (id_b->type) { 4252 case IPSECDOI_ID_IPV4_ADDR_SUBNET: 4253 alen = sizeof(struct in_addr); 4254 break; 4255#ifdef INET6 4256 case IPSECDOI_ID_IPV6_ADDR_SUBNET: 4257 alen = sizeof(struct in6_addr); 4258 break; 4259#endif 4260 } 4261 4262 /* sanity check */ 4263 if (buf->l < alen) 4264 return ISAKMP_INTERNAL_ERROR; 4265 4266 /* get subnet mask length */ 4267 plen = 0; 4268 max = alen <<3; 4269 4270 p = (unsigned char *) buf->v 4271 + sizeof(struct ipsecdoi_id_b) 4272 + alen; 4273 4274 for (; *p == 0xff; p++) { 4275 plen += 8; 4276 if (plen >= max) 4277 break; 4278 } 4279 4280 if (plen < max) { 4281 u_int l = 0; 4282 u_char b = ~(*p); 4283 4284 while (b) { 4285 b >>= 1; 4286 l++; 4287 } 4288 4289 l = 8 - l; 4290 plen += l; 4291 } 4292 } 4293 break; 4294 } 4295 4296 *prefixlen = plen; 4297 if (version == ISAKMP_VERSION_NUMBER_IKEV1) { 4298 *ul_proto = id_b->proto_id == 0 ? IPSEC_ULPROTO_ANY : id_b->proto_id; /* see sockaddr2id() */ 4299 } 4300 4301 return 0; 4302} 4303 4304/* 4305 * make printable string from ID payload except of general header. 4306 */ 4307char * 4308ipsecdoi_id2str(id) 4309 const vchar_t *id; 4310{ 4311#define BUFLEN 512 4312 char * ret = NULL; 4313 int len = 0; 4314 char *dat; 4315 static char buf[BUFLEN]; 4316 struct ipsecdoi_id_b *id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)id->v; 4317 struct sockaddr_storage saddr; 4318 u_int plen = 0; 4319 4320 bzero(&saddr, sizeof(saddr)); 4321 4322 switch (id_b->type) { 4323 case IPSECDOI_ID_IPV4_ADDR: 4324 case IPSECDOI_ID_IPV4_ADDR_SUBNET: 4325 case IPSECDOI_ID_IPV4_ADDR_RANGE: 4326 4327 saddr.ss_len = sizeof(struct sockaddr_in); 4328 saddr.ss_family = AF_INET; 4329 ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY; 4330 memcpy(&((struct sockaddr_in *)&saddr)->sin_addr, 4331 id->v + sizeof(*id_b), sizeof(struct in_addr)); 4332 break; 4333#ifdef INET6 4334 case IPSECDOI_ID_IPV6_ADDR: 4335 case IPSECDOI_ID_IPV6_ADDR_SUBNET: 4336 case IPSECDOI_ID_IPV6_ADDR_RANGE: 4337 saddr.ss_len = sizeof(struct sockaddr_in6); 4338 saddr.ss_family = AF_INET6; 4339 ((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY; 4340 memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr, 4341 id->v + sizeof(*id_b), sizeof(struct in6_addr)); 4342 ((struct sockaddr_in6 *)&saddr)->sin6_scope_id = 4343 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)&saddr)->sin6_addr) 4344 ? (ALIGNED_CAST(struct sockaddr_in6 *)id_b)->sin6_scope_id 4345 : 0); 4346 break; 4347#endif 4348 } 4349 4350 switch (id_b->type) { 4351 case IPSECDOI_ID_IPV4_ADDR: 4352#ifdef INET6 4353 case IPSECDOI_ID_IPV6_ADDR: 4354#endif 4355 len = snprintf( buf, sizeof(buf), "%s", saddrwop2str((struct sockaddr *)&saddr)); 4356 break; 4357 4358 case IPSECDOI_ID_IPV4_ADDR_SUBNET: 4359#ifdef INET6 4360 case IPSECDOI_ID_IPV6_ADDR_SUBNET: 4361#endif 4362 { 4363 u_char *p; 4364 u_int max; 4365 int alen = sizeof(struct in_addr); 4366 4367 switch (id_b->type) { 4368 case IPSECDOI_ID_IPV4_ADDR_SUBNET: 4369 alen = sizeof(struct in_addr); 4370 break; 4371#ifdef INET6 4372 case IPSECDOI_ID_IPV6_ADDR_SUBNET: 4373 alen = sizeof(struct in6_addr); 4374 break; 4375#endif 4376 } 4377 4378 /* sanity check */ 4379 if (id->l < alen) { 4380 len = 0; 4381 break; 4382 } 4383 4384 /* get subnet mask length */ 4385 plen = 0; 4386 max = alen <<3; 4387 4388 p = (unsigned char *) id->v 4389 + sizeof(struct ipsecdoi_id_b) 4390 + alen; 4391 4392 for (; *p == 0xff; p++) { 4393 plen += 8; 4394 if (plen >= max) 4395 break; 4396 } 4397 4398 if (plen < max) { 4399 u_int l = 0; 4400 u_char b = ~(*p); 4401 4402 while (b) { 4403 b >>= 1; 4404 l++; 4405 } 4406 4407 l = 8 - l; 4408 plen += l; 4409 } 4410 4411 len = snprintf( buf, sizeof(buf), "%s/%i", saddrwop2str((struct sockaddr *)&saddr), plen); 4412 } 4413 break; 4414 4415 case IPSECDOI_ID_IPV4_ADDR_RANGE: 4416 4417 len = snprintf( buf, sizeof(buf), "%s-", saddrwop2str((struct sockaddr *)&saddr)); 4418 4419 saddr.ss_len = sizeof(struct sockaddr_in); 4420 saddr.ss_family = AF_INET; 4421 ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY; 4422 memcpy(&((struct sockaddr_in *)&saddr)->sin_addr, 4423 id->v + sizeof(*id_b) + sizeof(struct in_addr), 4424 sizeof(struct in_addr)); 4425 4426 if (len >= 0) { 4427 len += snprintf( buf + len, sizeof(buf) - len, "%s", saddrwop2str((struct sockaddr *)&saddr)); 4428 } 4429 4430 break; 4431 4432#ifdef INET6 4433 case IPSECDOI_ID_IPV6_ADDR_RANGE: 4434 4435 len = snprintf( buf, sizeof(buf), "%s-", saddrwop2str((struct sockaddr *)&saddr)); 4436 4437 saddr.ss_len = sizeof(struct sockaddr_in6); 4438 saddr.ss_family = AF_INET6; 4439 ((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY; 4440 memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr, 4441 id->v + sizeof(*id_b) + sizeof(struct in6_addr), 4442 sizeof(struct in6_addr)); 4443 ((struct sockaddr_in6 *)&saddr)->sin6_scope_id = 4444 (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)&saddr)->sin6_addr) 4445 ? (ALIGNED_CAST(struct sockaddr_in6 *)id_b)->sin6_scope_id 4446 : 0); 4447 4448 if (len >= 0) { 4449 len += snprintf( buf + len, sizeof(buf) - len, "%s", saddrwop2str((struct sockaddr *)&saddr)); 4450 } 4451 4452 break; 4453#endif 4454 4455 case IPSECDOI_ID_FQDN: 4456 case IPSECDOI_ID_USER_FQDN: 4457 len = id->l - sizeof(*id_b); 4458 if (len > BUFLEN) 4459 len = BUFLEN; 4460 memcpy(buf, id->v + sizeof(*id_b), len); 4461 break; 4462 4463 case IPSECDOI_ID_DER_ASN1_DN: 4464 case IPSECDOI_ID_DER_ASN1_GN: 4465 { 4466#ifdef HAVE_OPENSSL 4467 X509_NAME *xn = NULL; 4468#endif 4469 4470 dat = id->v + sizeof(*id_b); 4471 len = id->l - sizeof(*id_b); 4472#ifdef HAVE_OPENSSL 4473 if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) { 4474 BIO *bio = BIO_new(BIO_s_mem()); 4475 X509_NAME_print_ex(bio, xn, 0, 0); 4476 len = BIO_get_mem_data(bio, &dat); 4477 if (len > BUFLEN) 4478 len = BUFLEN; 4479 memcpy(buf,dat,len); 4480 BIO_free(bio); 4481 X509_NAME_free(xn); 4482 } else 4483#endif 4484 { 4485 4486 plog(ASL_LEVEL_ERR, 4487 "unable to extract asn1dn from id\n"); 4488 4489 len = snprintf(buf, sizeof(buf), "<ASN1-DN>"); 4490 } 4491 4492 break; 4493 } 4494 4495 /* currently unhandled id types */ 4496 case IPSECDOI_ID_KEY_ID: 4497 len = snprintf( buf, sizeof(buf), "<KEY-ID>"); 4498 break; 4499 4500 default: 4501 plog(ASL_LEVEL_ERR, 4502 "unknown ID type %d\n", id_b->type); 4503 } 4504 4505 if (!len) 4506 len = snprintf( buf, sizeof(buf), "<?>"); 4507 4508 ret = racoon_malloc(len+1); 4509 if (ret != NULL) { 4510 memcpy(ret,buf,len); 4511 ret[len]=0; 4512 } 4513 4514 return ret; 4515} 4516 4517/* 4518 * set IPsec data attributes into a proposal. 4519 * NOTE: MUST called per a transform. 4520 */ 4521int 4522ipsecdoi_t2satrns(t, pp, pr, tr) 4523 struct isakmp_pl_t *t; 4524 struct saprop *pp; 4525 struct saproto *pr; 4526 struct satrns *tr; 4527{ 4528 struct isakmp_data *d, *prev; 4529 int flag, type; 4530 int error = -1; 4531 int life_t; 4532 int tlen; 4533 4534 tr->trns_no = t->t_no; 4535 tr->trns_id = t->t_id; 4536 4537 tlen = ntohs(t->h.len) - sizeof(*t); 4538 prev = (struct isakmp_data *)NULL; 4539 d = (struct isakmp_data *)(t + 1); 4540 4541 /* default */ 4542 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT; 4543 pp->lifetime = IPSECDOI_ATTR_SA_LD_SEC_DEFAULT; 4544 pp->lifebyte = 0; 4545 tr->authtype = IPSECDOI_ATTR_AUTH_NONE; 4546 4547 while (tlen > 0) { 4548 4549 type = ntohs(d->type) & ~ISAKMP_GEN_MASK; 4550 flag = ntohs(d->type) & ISAKMP_GEN_MASK; 4551 4552 plog(ASL_LEVEL_DEBUG, 4553 "type=%s, flag=0x%04x, lorv=%s\n", 4554 s_ipsecdoi_attr(type), flag, 4555 s_ipsecdoi_attr_v(type, ntohs(d->lorv))); 4556 4557 switch (type) { 4558 case IPSECDOI_ATTR_SA_LD_TYPE: 4559 { 4560 int type = ntohs(d->lorv); 4561 switch (type) { 4562 case IPSECDOI_ATTR_SA_LD_TYPE_SEC: 4563 case IPSECDOI_ATTR_SA_LD_TYPE_KB: 4564 life_t = type; 4565 break; 4566 default: 4567 plog(ASL_LEVEL_WARNING, 4568 "invalid life duration type. " 4569 "use default\n"); 4570 life_t = IPSECDOI_ATTR_SA_LD_TYPE_DEFAULT; 4571 break; 4572 } 4573 break; 4574 } 4575 case IPSECDOI_ATTR_SA_LD: 4576 if (prev == NULL 4577 || (ntohs(prev->type) & ~ISAKMP_GEN_MASK) != 4578 IPSECDOI_ATTR_SA_LD_TYPE) { 4579 plog(ASL_LEVEL_ERR, 4580 "life duration must follow ltype\n"); 4581 break; 4582 } 4583 4584 { 4585 u_int32_t t; 4586 vchar_t *ld_buf = NULL; 4587 4588 if (flag) { 4589 /* i.e. ISAKMP_GEN_TV */ 4590 ld_buf = vmalloc(sizeof(d->lorv)); 4591 if (ld_buf == NULL) { 4592 plog(ASL_LEVEL_ERR, 4593 "failed to get LD buffer.\n"); 4594 goto end; 4595 } 4596 memcpy(ld_buf->v, &d->lorv, sizeof(d->lorv)); 4597 } else { 4598 int len = ntohs(d->lorv); 4599 /* i.e. ISAKMP_GEN_TLV */ 4600 ld_buf = vmalloc(len); 4601 if (ld_buf == NULL) { 4602 plog(ASL_LEVEL_ERR, 4603 "failed to get LD buffer.\n"); 4604 goto end; 4605 } 4606 memcpy(ld_buf->v, d + 1, len); 4607 } 4608 switch (life_t) { 4609 case IPSECDOI_ATTR_SA_LD_TYPE_SEC: 4610 t = ipsecdoi_set_ld(ld_buf); 4611 vfree(ld_buf); 4612 if (t == 0) { 4613 plog(ASL_LEVEL_ERR, 4614 "invalid life duration.\n"); 4615 goto end; 4616 } 4617 /* lifetime must be equal in a proposal. */ 4618 if (pp->lifetime == IPSECDOI_ATTR_SA_LD_SEC_DEFAULT) 4619 pp->lifetime = t; 4620 else if (pp->lifetime != t) { 4621 plog(ASL_LEVEL_ERR, 4622 "lifetime mismatched " 4623 "in a proposal, " 4624 "prev:%ld curr:%u.\n", 4625 (long)pp->lifetime, t); 4626 goto end; 4627 } 4628 break; 4629 case IPSECDOI_ATTR_SA_LD_TYPE_KB: 4630 t = ipsecdoi_set_ld(ld_buf); 4631 vfree(ld_buf); 4632 if (t == 0) { 4633 plog(ASL_LEVEL_ERR, 4634 "invalid life duration.\n"); 4635 goto end; 4636 } 4637 /* lifebyte must be equal in a proposal. */ 4638 if (pp->lifebyte == 0) 4639 pp->lifebyte = t; 4640 else if (pp->lifebyte != t) { 4641 plog(ASL_LEVEL_ERR, 4642 "lifebyte mismatched " 4643 "in a proposal, " 4644 "prev:%d curr:%u.\n", 4645 pp->lifebyte, t); 4646 goto end; 4647 } 4648 break; 4649 default: 4650 vfree(ld_buf); 4651 plog(ASL_LEVEL_ERR, 4652 "invalid life type: %d\n", life_t); 4653 goto end; 4654 } 4655 } 4656 break; 4657 4658 case IPSECDOI_ATTR_GRP_DESC: 4659 /* 4660 * RFC2407: 4.5 IPSEC Security Association Attributes 4661 * Specifies the Oakley Group to be used in a PFS QM 4662 * negotiation. For a list of supported values, see 4663 * Appendix A of [IKE]. 4664 */ 4665 if (pp->pfs_group == 0) 4666 pp->pfs_group = (u_int16_t)ntohs(d->lorv); 4667 else if (pp->pfs_group != (u_int16_t)ntohs(d->lorv)) { 4668 plog(ASL_LEVEL_ERR, 4669 "pfs_group mismatched " 4670 "in a proposal.\n"); 4671 goto end; 4672 } 4673 break; 4674 4675 case IPSECDOI_ATTR_ENC_MODE: 4676 if (pr->encmode && 4677 pr->encmode != (u_int16_t)ntohs(d->lorv)) { 4678 plog(ASL_LEVEL_ERR, 4679 "multiple encmode exist " 4680 "in a transform.\n"); 4681 goto end; 4682 } 4683 pr->encmode = (u_int16_t)ntohs(d->lorv); 4684 break; 4685 4686 case IPSECDOI_ATTR_AUTH: 4687 if (tr->authtype != IPSECDOI_ATTR_AUTH_NONE) { 4688 plog(ASL_LEVEL_ERR, 4689 "multiple authtype exist " 4690 "in a transform.\n"); 4691 goto end; 4692 } 4693 tr->authtype = (u_int16_t)ntohs(d->lorv); 4694 break; 4695 4696 case IPSECDOI_ATTR_KEY_LENGTH: 4697 if (pr->proto_id != IPSECDOI_PROTO_IPSEC_ESP) { 4698 plog(ASL_LEVEL_ERR, 4699 "key length defined but not ESP"); 4700 goto end; 4701 } 4702 tr->encklen = ntohs(d->lorv); 4703 break; 4704 4705 case IPSECDOI_ATTR_KEY_ROUNDS: 4706 case IPSECDOI_ATTR_COMP_DICT_SIZE: 4707 case IPSECDOI_ATTR_COMP_PRIVALG: 4708 default: 4709 break; 4710 } 4711 4712 prev = d; 4713 if (flag) { 4714 tlen -= sizeof(*d); 4715 d = (struct isakmp_data *)((char *)d + sizeof(*d)); 4716 } else { 4717 tlen -= (sizeof(*d) + ntohs(d->lorv)); 4718 d = (struct isakmp_data *)((caddr_t)d + sizeof(*d) + ntohs(d->lorv)); 4719 } 4720 } 4721 4722 error = 0; 4723end: 4724 return error; 4725} 4726 4727int 4728ipsecdoi_authalg2trnsid(alg) 4729 int alg; 4730{ 4731 switch (alg) { 4732 case IPSECDOI_ATTR_AUTH_HMAC_MD5: 4733 return IPSECDOI_AH_MD5; 4734 case IPSECDOI_ATTR_AUTH_HMAC_SHA1: 4735 return IPSECDOI_AH_SHA; 4736 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256: 4737 return IPSECDOI_AH_SHA256; 4738 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384: 4739 return IPSECDOI_AH_SHA384; 4740 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512: 4741 return IPSECDOI_AH_SHA512; 4742 case IPSECDOI_ATTR_AUTH_DES_MAC: 4743 return IPSECDOI_AH_DES; 4744 case IPSECDOI_ATTR_AUTH_KPDK: 4745 return IPSECDOI_AH_MD5; /* XXX */ 4746 default: 4747 plog(ASL_LEVEL_ERR, 4748 "invalid authentication algorithm:%d\n", alg); 4749 } 4750 return -1; 4751} 4752 4753static int rm_idtype2doi[] = { 4754 255, /* IDTYPE_UNDEFINED, 0 */ 4755 IPSECDOI_ID_FQDN, /* IDTYPE_FQDN, 1 */ 4756 IPSECDOI_ID_USER_FQDN, /* IDTYPE_USERFQDN, 2 */ 4757 IPSECDOI_ID_KEY_ID, /* IDTYPE_KEYID, 3 */ 4758 255, /* IDTYPE_ADDRESS, 4 4759 * it expands into 4 types by another function. */ 4760 IPSECDOI_ID_DER_ASN1_DN, /* IDTYPE_ASN1DN, 5 */ 4761}; 4762 4763/* 4764 * convert idtype to DOI value. 4765 * OUT 255 : NG 4766 * other: converted. 4767 */ 4768int 4769idtype2doi(idtype) 4770 int idtype; 4771{ 4772 if (ARRAYLEN(rm_idtype2doi) > idtype) 4773 return rm_idtype2doi[idtype]; 4774 return 255; 4775} 4776 4777int 4778doi2idtype(doi) 4779 int doi; 4780{ 4781 switch(doi) { 4782 case IPSECDOI_ID_FQDN: 4783 return(IDTYPE_FQDN); 4784 case IPSECDOI_ID_USER_FQDN: 4785 return(IDTYPE_USERFQDN); 4786 case IPSECDOI_ID_KEY_ID: 4787 return(IDTYPE_KEYID); 4788 case IPSECDOI_ID_DER_ASN1_DN: 4789 return(IDTYPE_ASN1DN); 4790 case IPSECDOI_ID_IPV4_ADDR: 4791 case IPSECDOI_ID_IPV4_ADDR_SUBNET: 4792 case IPSECDOI_ID_IPV6_ADDR: 4793 case IPSECDOI_ID_IPV6_ADDR_SUBNET: 4794 return(IDTYPE_ADDRESS); 4795 default: 4796 plog(ASL_LEVEL_WARNING, 4797 "Inproper idtype:%s in this function.\n", 4798 s_ipsecdoi_ident(doi)); 4799 return(IDTYPE_ADDRESS); /* XXX */ 4800 } 4801 /*NOTREACHED*/ 4802} 4803 4804#ifdef ENABLE_HYBRID 4805static int 4806switch_authmethod(authmethod) 4807 int authmethod; 4808{ 4809 switch(authmethod) { 4810 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: 4811 authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I; 4812 break; 4813 case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: 4814 authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I; 4815 break; 4816 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: 4817 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I; 4818 break; 4819 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: 4820 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I; 4821 break; 4822 /* Those are not implemented */ 4823 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: 4824 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I; 4825 break; 4826 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: 4827 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I; 4828 break; 4829 case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: 4830 authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I; 4831 break; 4832 default: 4833 break; 4834 } 4835 4836 return authmethod; 4837} 4838#endif 4839