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