Return to remoteconf.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
1.1 ! misho 1: /* $NetBSD: remoteconf.c,v 1.26 2011/03/14 15:50:36 vanhu Exp $ */ ! 2: ! 3: /* Id: remoteconf.c,v 1.38 2006/05/06 15:52:44 manubsd Exp */ ! 4: ! 5: /* ! 6: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. Neither the name of the project nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: */ ! 33: ! 34: #include "config.h" ! 35: ! 36: #include <sys/types.h> ! 37: #include <sys/param.h> ! 38: #include <sys/socket.h> ! 39: #include <sys/queue.h> ! 40: ! 41: #include <netinet/in.h> ! 42: #include <netinet/in_systm.h> ! 43: #include <netinet/ip.h> ! 44: ! 45: #include PATH_IPSEC_H ! 46: ! 47: #include <stdlib.h> ! 48: #include <stdio.h> ! 49: #include <string.h> ! 50: #include <errno.h> ! 51: ! 52: #include "var.h" ! 53: #include "misc.h" ! 54: #include "vmbuf.h" ! 55: #include "plog.h" ! 56: #include "sockmisc.h" ! 57: #include "genlist.h" ! 58: #include "debug.h" ! 59: ! 60: #include "isakmp_var.h" ! 61: #ifdef ENABLE_HYBRID ! 62: #include "isakmp_xauth.h" ! 63: #endif ! 64: #include "isakmp.h" ! 65: #include "ipsec_doi.h" ! 66: #include "crypto_openssl.h" ! 67: #include "oakley.h" ! 68: #include "remoteconf.h" ! 69: #include "localconf.h" ! 70: #include "grabmyaddr.h" ! 71: #include "policy.h" ! 72: #include "proposal.h" ! 73: #include "vendorid.h" ! 74: #include "gcmalloc.h" ! 75: #include "strnames.h" ! 76: #include "algorithm.h" ! 77: #include "nattraversal.h" ! 78: #include "isakmp_frag.h" ! 79: #include "handler.h" ! 80: #include "genlist.h" ! 81: #include "rsalist.h" ! 82: ! 83: typedef TAILQ_HEAD(_rmtree, remoteconf) remoteconf_tailq_head_t; ! 84: static remoteconf_tailq_head_t rmtree, rmtree_save; ! 85: ! 86: /* ! 87: * Script hook names and script hook paths ! 88: */ ! 89: char *script_names[SCRIPT_MAX + 1] = { ! 90: "phase1_up", "phase1_down", "phase1_dead" }; ! 91: ! 92: /*%%%*/ ! 93: ! 94: int ! 95: rmconf_match_identity(rmconf, id_p) ! 96: struct remoteconf *rmconf; ! 97: vchar_t *id_p; ! 98: { ! 99: struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *) id_p->v; ! 100: struct sockaddr *sa; ! 101: caddr_t sa1, sa2; ! 102: vchar_t ident; ! 103: struct idspec *id; ! 104: struct genlist_entry *gpb; ! 105: ! 106: /* compare with the ID if specified. */ ! 107: if (!genlist_next(rmconf->idvl_p, 0)) ! 108: return 0; ! 109: ! 110: for (id = genlist_next(rmconf->idvl_p, &gpb); id; id = genlist_next(0, &gpb)) { ! 111: /* No ID specified in configuration, so it is ok */ ! 112: if (id->id == 0) ! 113: return 0; ! 114: ! 115: /* check the type of both IDs */ ! 116: if (id->idtype != doi2idtype(id_b->type)) ! 117: continue; /* ID type mismatch */ ! 118: ! 119: /* compare defined ID with the ID sent by peer. */ ! 120: switch (id->idtype) { ! 121: case IDTYPE_ASN1DN: ! 122: ident.v = id_p->v + sizeof(*id_b); ! 123: ident.l = id_p->l - sizeof(*id_b); ! 124: if (eay_cmp_asn1dn(id->id, &ident) == 0) ! 125: return 0; ! 126: break; ! 127: case IDTYPE_ADDRESS: ! 128: sa = (struct sockaddr *)id->id->v; ! 129: sa2 = (caddr_t)(id_b + 1); ! 130: switch (sa->sa_family) { ! 131: case AF_INET: ! 132: if (id_p->l - sizeof(*id_b) != sizeof(struct in_addr)) ! 133: continue; /* ID value mismatch */ ! 134: sa1 = (caddr_t) &((struct sockaddr_in *)sa)->sin_addr; ! 135: if (memcmp(sa1, sa2, sizeof(struct in_addr)) == 0) ! 136: return 0; ! 137: break; ! 138: #ifdef INET6 ! 139: case AF_INET6: ! 140: if (id_p->l - sizeof(*id_b) != sizeof(struct in6_addr)) ! 141: continue; /* ID value mismatch */ ! 142: sa1 = (caddr_t) &((struct sockaddr_in6 *)sa)->sin6_addr; ! 143: if (memcmp(sa1, sa2, sizeof(struct in6_addr)) == 0) ! 144: return 0; ! 145: break; ! 146: #endif ! 147: default: ! 148: break; ! 149: } ! 150: break; ! 151: default: ! 152: if (memcmp(id->id->v, id_b + 1, id->id->l) == 0) ! 153: return 0; ! 154: break; ! 155: } ! 156: } ! 157: ! 158: plog(LLV_WARNING, LOCATION, NULL, "No ID match.\n"); ! 159: if (rmconf->verify_identifier) ! 160: return ISAKMP_NTYPE_INVALID_ID_INFORMATION; ! 161: ! 162: return 0; ! 163: } ! 164: ! 165: static int ! 166: rmconf_match_etype_and_approval(rmconf, etype, approval) ! 167: struct remoteconf *rmconf; ! 168: int etype; ! 169: struct isakmpsa *approval; ! 170: { ! 171: struct isakmpsa *p; ! 172: ! 173: if (check_etypeok(rmconf, (void *) (intptr_t) etype) == 0) ! 174: return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN; ! 175: ! 176: if (approval == NULL) ! 177: return 0; ! 178: ! 179: if (etype == ISAKMP_ETYPE_AGG && ! 180: approval->dh_group != rmconf->dh_group) ! 181: return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN; ! 182: ! 183: if (checkisakmpsa(rmconf->pcheck_level, approval, ! 184: rmconf->proposal) == NULL) ! 185: return ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN; ! 186: ! 187: return 0; ! 188: } ! 189: ! 190: enum rmconf_match_t { ! 191: MATCH_NONE = 0, ! 192: MATCH_BASIC = 0x0000001, ! 193: MATCH_ADDRESS = 0x0000002, ! 194: MATCH_SA = 0x0000004, ! 195: MATCH_IDENTITY = 0x0000008, ! 196: MATCH_AUTH_IDENTITY = 0x0000010, ! 197: }; ! 198: ! 199: static int ! 200: rmconf_match_type(rmsel, rmconf) ! 201: struct rmconfselector *rmsel; ! 202: struct remoteconf *rmconf; ! 203: { ! 204: int ret = MATCH_NONE, tmp; ! 205: ! 206: /* No match at all: unwanted anonymous */ ! 207: if ((rmsel->flags & GETRMCONF_F_NO_ANONYMOUS) && ! 208: rmconf->remote->sa_family == AF_UNSPEC){ ! 209: plog(LLV_DEBUG2, LOCATION, rmsel->remote, ! 210: "Not matched: Anonymous conf.\n"); ! 211: return MATCH_NONE; ! 212: } ! 213: ! 214: if ((rmsel->flags & GETRMCONF_F_NO_PASSIVE) && rmconf->passive){ ! 215: plog(LLV_DEBUG2, LOCATION, rmsel->remote, ! 216: "Not matched: passive conf.\n"); ! 217: return MATCH_NONE; ! 218: } ! 219: ! 220: ret |= MATCH_BASIC; ! 221: ! 222: /* Check address */ ! 223: if (rmsel->remote != NULL) { ! 224: if (rmconf->remote->sa_family != AF_UNSPEC) { ! 225: if (cmpsaddr(rmsel->remote, rmconf->remote) == CMPSADDR_MISMATCH){ ! 226: plog(LLV_DEBUG2, LOCATION, rmsel->remote, ! 227: "Not matched: address mismatch.\n"); ! 228: return MATCH_NONE; ! 229: } ! 230: ! 231: /* Address matched */ ! 232: ret |= MATCH_ADDRESS; ! 233: } ! 234: } ! 235: ! 236: /* Check etype and approval */ ! 237: if (rmsel->etype != ISAKMP_ETYPE_NONE) { ! 238: tmp=rmconf_match_etype_and_approval(rmconf, rmsel->etype, ! 239: rmsel->approval); ! 240: if (tmp != 0){ ! 241: plog(LLV_DEBUG2, LOCATION, rmsel->remote, ! 242: "Not matched: etype (%d)/approval mismatch (%d).\n", rmsel->etype, tmp); ! 243: return MATCH_NONE; ! 244: } ! 245: ret |= MATCH_SA; ! 246: } ! 247: ! 248: /* Check identity */ ! 249: if (rmsel->identity != NULL && rmconf->verify_identifier) { ! 250: if (rmconf_match_identity(rmconf, rmsel->identity) != 0){ ! 251: plog(LLV_DEBUG2, LOCATION, rmsel->remote, ! 252: "Not matched: identity mismatch.\n"); ! 253: return MATCH_NONE; ! 254: } ! 255: ret |= MATCH_IDENTITY; ! 256: } ! 257: ! 258: /* Check certificate request */ ! 259: if (rmsel->certificate_request != NULL) { ! 260: if (oakley_get_certtype(rmsel->certificate_request) != ! 261: oakley_get_certtype(rmconf->mycert)){ ! 262: plog(LLV_DEBUG2, LOCATION, rmsel->remote, ! 263: "Not matched: cert type mismatch.\n"); ! 264: return MATCH_NONE; ! 265: } ! 266: ! 267: if (rmsel->certificate_request->l > 1) { ! 268: vchar_t *issuer; ! 269: ! 270: issuer = eay_get_x509asn1issuername(rmconf->mycert); ! 271: if (rmsel->certificate_request->l - 1 != issuer->l || ! 272: memcmp(rmsel->certificate_request->v + 1, ! 273: issuer->v, issuer->l) != 0) { ! 274: vfree(issuer); ! 275: plog(LLV_DEBUG2, LOCATION, rmsel->remote, ! 276: "Not matched: cert issuer mismatch.\n"); ! 277: return MATCH_NONE; ! 278: } ! 279: vfree(issuer); ! 280: } else { ! 281: if (!rmconf->match_empty_cr){ ! 282: plog(LLV_DEBUG2, LOCATION, rmsel->remote, ! 283: "Not matched: empty certificate request.\n"); ! 284: return MATCH_NONE; ! 285: } ! 286: } ! 287: ! 288: ret |= MATCH_AUTH_IDENTITY; ! 289: } ! 290: ! 291: return ret; ! 292: } ! 293: ! 294: void rmconf_selector_from_ph1(rmsel, iph1) ! 295: struct rmconfselector *rmsel; ! 296: struct ph1handle *iph1; ! 297: { ! 298: memset(rmsel, 0, sizeof(*rmsel)); ! 299: rmsel->flags = 0; ! 300: rmsel->remote = iph1->remote; ! 301: rmsel->etype = iph1->etype; ! 302: rmsel->approval = iph1->approval; ! 303: rmsel->identity = iph1->id_p; ! 304: rmsel->certificate_request = iph1->cr_p; ! 305: } ! 306: ! 307: int ! 308: enumrmconf(rmsel, enum_func, enum_arg) ! 309: struct rmconfselector *rmsel; ! 310: int (* enum_func)(struct remoteconf *rmconf, void *arg); ! 311: void *enum_arg; ! 312: { ! 313: struct remoteconf *p; ! 314: int ret = 0; ! 315: ! 316: RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) { ! 317: plog(LLV_DEBUG2, LOCATION, rmsel->remote, ! 318: "Checking remote conf \"%s\" %s.\n", p->name, ! 319: p->remote->sa_family == AF_UNSPEC ? ! 320: "anonymous" : saddr2str(p->remote)); ! 321: ! 322: if (rmsel != NULL) { ! 323: if (rmconf_match_type(rmsel, p) == MATCH_NONE){ ! 324: plog(LLV_DEBUG2, LOCATION, rmsel->remote, ! 325: "Not matched.\n"); ! 326: continue; ! 327: } ! 328: } ! 329: ! 330: plog(LLV_DEBUG2, LOCATION, NULL, ! 331: "enumrmconf: \"%s\" matches.\n", p->name); ! 332: ! 333: ret = (*enum_func)(p, enum_arg); ! 334: if (ret) ! 335: break; ! 336: } ! 337: ! 338: return ret; ! 339: } ! 340: ! 341: struct rmconf_find_context { ! 342: struct rmconfselector sel; ! 343: ! 344: struct remoteconf *rmconf; ! 345: int match_type; ! 346: int num_found; ! 347: }; ! 348: ! 349: static int ! 350: rmconf_find(rmconf, ctx) ! 351: struct remoteconf *rmconf; ! 352: void *ctx; ! 353: { ! 354: struct rmconf_find_context *fctx = (struct rmconf_find_context *) ctx; ! 355: int match_type; ! 356: ! 357: /* First matching remote conf? */ ! 358: match_type = rmconf_match_type(&fctx->sel, rmconf); ! 359: ! 360: if (fctx->rmconf != NULL) { ! 361: /* More ambiguous matches are ignored. */ ! 362: if (match_type < fctx->match_type) ! 363: return 0; ! 364: ! 365: if (match_type == fctx->match_type) { ! 366: /* Ambiguous match */ ! 367: fctx->num_found++; ! 368: return 0; ! 369: } ! 370: } ! 371: ! 372: /* More exact match found */ ! 373: fctx->match_type = match_type; ! 374: fctx->num_found = 1; ! 375: fctx->rmconf = rmconf; ! 376: ! 377: return 0; ! 378: } ! 379: ! 380: /* ! 381: * search remote configuration. ! 382: * don't use port number to search if its value is either IPSEC_PORT_ANY. ! 383: * If matching anonymous entry, then new entry is copied from anonymous entry. ! 384: * If no anonymous entry found, then return NULL. ! 385: * OUT: NULL: NG ! 386: * Other: remote configuration entry. ! 387: */ ! 388: ! 389: struct remoteconf * ! 390: getrmconf(remote, flags) ! 391: struct sockaddr *remote; ! 392: int flags; ! 393: { ! 394: struct rmconf_find_context ctx; ! 395: int n = 0; ! 396: ! 397: memset(&ctx, 0, sizeof(ctx)); ! 398: ctx.sel.flags = flags; ! 399: ctx.sel.remote = remote; ! 400: ! 401: if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) { ! 402: plog(LLV_ERROR, LOCATION, remote, ! 403: "multiple exact configurations.\n"); ! 404: return NULL; ! 405: } ! 406: ! 407: if (ctx.rmconf == NULL) { ! 408: plog(LLV_DEBUG, LOCATION, remote, ! 409: "no remote configuration found.\n"); ! 410: return NULL; ! 411: } ! 412: ! 413: if (ctx.num_found != 1) { ! 414: plog(LLV_DEBUG, LOCATION, remote, ! 415: "multiple non-exact configurations found.\n"); ! 416: return NULL; ! 417: } ! 418: ! 419: plog(LLV_DEBUG, LOCATION, remote, ! 420: "configuration \"%s\" selected.\n", ! 421: ctx.rmconf->name); ! 422: ! 423: return ctx.rmconf; ! 424: } ! 425: ! 426: struct remoteconf * ! 427: getrmconf_by_ph1(iph1) ! 428: struct ph1handle *iph1; ! 429: { ! 430: struct rmconf_find_context ctx; ! 431: ! 432: memset(&ctx, 0, sizeof(ctx)); ! 433: rmconf_selector_from_ph1(&ctx.sel, iph1); ! 434: if (loglevel >= LLV_DEBUG) { ! 435: char *idstr = NULL; ! 436: ! 437: if (iph1->id_p != NULL) ! 438: idstr = ipsecdoi_id2str(iph1->id_p); ! 439: ! 440: plog(LLV_DEBUG, LOCATION, iph1->remote, ! 441: "getrmconf_by_ph1: remote %s, identity %s.\n", ! 442: saddr2str(iph1->remote), idstr ? idstr : "<any>"); ! 443: ! 444: if (idstr) ! 445: racoon_free(idstr); ! 446: } ! 447: ! 448: if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) { ! 449: plog(LLV_ERROR, LOCATION, iph1->remote, ! 450: "multiple exact configurations.\n"); ! 451: return RMCONF_ERR_MULTIPLE; ! 452: } ! 453: ! 454: if (ctx.rmconf == NULL) { ! 455: plog(LLV_DEBUG, LOCATION, iph1->remote, ! 456: "no remote configuration found\n"); ! 457: return NULL; ! 458: } ! 459: ! 460: if (ctx.num_found != 1) { ! 461: plog(LLV_DEBUG, LOCATION, iph1->remote, ! 462: "multiple non-exact configurations found.\n"); ! 463: return RMCONF_ERR_MULTIPLE; ! 464: } ! 465: ! 466: plog(LLV_DEBUG, LOCATION, iph1->remote, ! 467: "configuration \"%s\" selected.\n", ! 468: ctx.rmconf->name); ! 469: ! 470: return ctx.rmconf; ! 471: } ! 472: ! 473: struct remoteconf * ! 474: getrmconf_by_name(name) ! 475: const char *name; ! 476: { ! 477: struct remoteconf *p; ! 478: ! 479: plog(LLV_DEBUG, LOCATION, NULL, ! 480: "getrmconf_by_name: remote \"%s\".\n", ! 481: name); ! 482: ! 483: RACOON_TAILQ_FOREACH_REVERSE(p, &rmtree, _rmtree, chain) { ! 484: if (p->name == NULL) ! 485: continue; ! 486: ! 487: if (strcmp(name, p->name) == 0) ! 488: return p; ! 489: } ! 490: ! 491: return NULL; ! 492: } ! 493: ! 494: struct remoteconf * ! 495: newrmconf() ! 496: { ! 497: struct remoteconf *new; ! 498: int i; ! 499: ! 500: new = racoon_calloc(1, sizeof(*new)); ! 501: if (new == NULL) ! 502: return NULL; ! 503: ! 504: new->proposal = NULL; ! 505: ! 506: /* set default */ ! 507: new->doitype = IPSEC_DOI; ! 508: new->sittype = IPSECDOI_SIT_IDENTITY_ONLY; ! 509: new->idvtype = IDTYPE_UNDEFINED; ! 510: new->idvl_p = genlist_init(); ! 511: new->nonce_size = DEFAULT_NONCE_SIZE; ! 512: new->passive = FALSE; ! 513: new->ike_frag = FALSE; ! 514: new->esp_frag = IP_MAXPACKET; ! 515: new->ini_contact = TRUE; ! 516: new->mode_cfg = FALSE; ! 517: new->pcheck_level = PROP_CHECK_STRICT; ! 518: new->verify_identifier = FALSE; ! 519: new->verify_cert = TRUE; ! 520: new->cacertfile = NULL; ! 521: new->send_cert = TRUE; ! 522: new->send_cr = TRUE; ! 523: new->match_empty_cr = FALSE; ! 524: new->support_proxy = FALSE; ! 525: for (i = 0; i <= SCRIPT_MAX; i++) ! 526: new->script[i] = NULL; ! 527: new->gen_policy = FALSE; ! 528: new->nat_traversal = FALSE; ! 529: new->rsa_private = genlist_init(); ! 530: new->rsa_public = genlist_init(); ! 531: new->idv = NULL; ! 532: new->key = NULL; ! 533: ! 534: new->dpd = TRUE; /* Enable DPD support by default */ ! 535: new->dpd_interval = 0; /* Disable DPD checks by default */ ! 536: new->dpd_retry = 5; ! 537: new->dpd_maxfails = 5; ! 538: ! 539: new->rekey = REKEY_ON; ! 540: ! 541: new->weak_phase1_check = 0; ! 542: ! 543: #ifdef ENABLE_HYBRID ! 544: new->xauth = NULL; ! 545: #endif ! 546: ! 547: new->lifetime = oakley_get_defaultlifetime(); ! 548: ! 549: return new; ! 550: } ! 551: ! 552: void * ! 553: dupidvl(entry, arg) ! 554: void *entry; ! 555: void *arg; ! 556: { ! 557: struct idspec *id; ! 558: struct idspec *old = (struct idspec *) entry; ! 559: id = newidspec(); ! 560: if (!id) return (void *) -1; ! 561: ! 562: if (set_identifier(&id->id, old->idtype, old->id) != 0) { ! 563: racoon_free(id); ! 564: return (void *) -1; ! 565: } ! 566: ! 567: id->idtype = old->idtype; ! 568: ! 569: genlist_append(arg, id); ! 570: return NULL; ! 571: } ! 572: ! 573: void * ! 574: duprsa(entry, arg) ! 575: void *entry; ! 576: void *arg; ! 577: { ! 578: struct rsa_key *new; ! 579: ! 580: new = rsa_key_dup((struct rsa_key *)entry); ! 581: if (new == NULL) ! 582: return (void *) -1; ! 583: genlist_append(arg, new); ! 584: ! 585: /* keep genlist_foreach going */ ! 586: return NULL; ! 587: } ! 588: ! 589: /* Creates shallow copy of a remote config. Used for "inherit" keyword. */ ! 590: struct remoteconf * ! 591: duprmconf_shallow (rmconf) ! 592: struct remoteconf *rmconf; ! 593: { ! 594: struct remoteconf *new; ! 595: struct proposalspec *prspec; ! 596: ! 597: new = racoon_calloc(1, sizeof(*new)); ! 598: if (new == NULL) ! 599: return NULL; ! 600: ! 601: memcpy(new, rmconf, sizeof(*new)); ! 602: new->name = NULL; ! 603: new->inherited_from = rmconf; ! 604: ! 605: new->proposal = NULL; /* will be filled by set_isakmp_proposal() */ ! 606: ! 607: return new; ! 608: } ! 609: ! 610: /* Copies pointer structures of an inherited remote config. ! 611: * Used by "inherit" mechanism in a two step copy method, necessary to ! 612: * prevent both double free() and memory leak during config reload. ! 613: */ ! 614: int ! 615: duprmconf_finish (new) ! 616: struct remoteconf *new; ! 617: { ! 618: struct remoteconf *rmconf; ! 619: int i; ! 620: ! 621: if (new->inherited_from == NULL) ! 622: return 0; /* nothing todo, no inheritance */ ! 623: ! 624: rmconf = new->inherited_from; ! 625: ! 626: /* duplicate dynamic structures unless value overridden */ ! 627: if (new->etypes != NULL && new->etypes == rmconf->etypes) ! 628: new->etypes = dupetypes(new->etypes); ! 629: if (new->idvl_p == rmconf->idvl_p) { ! 630: new->idvl_p = genlist_init(); ! 631: genlist_foreach(rmconf->idvl_p, dupidvl, new->idvl_p); ! 632: } ! 633: ! 634: if (new->rsa_private == rmconf->rsa_private) { ! 635: new->rsa_private = genlist_init(); ! 636: genlist_foreach(rmconf->rsa_private, duprsa, new->rsa_private); ! 637: } ! 638: if (new->rsa_public == rmconf->rsa_public) { ! 639: new->rsa_public = genlist_init(); ! 640: genlist_foreach(rmconf->rsa_public, duprsa, new->rsa_public); ! 641: } ! 642: if (new->remote != NULL && new->remote == rmconf->remote) { ! 643: new->remote = racoon_malloc(sizeof(*new->remote)); ! 644: if (new->remote == NULL) { ! 645: plog(LLV_ERROR, LOCATION, NULL, ! 646: "duprmconf_finish: malloc failed (remote)\n"); ! 647: exit(1); ! 648: } ! 649: memcpy(new->remote, rmconf->remote, sizeof(*new->remote)); ! 650: } ! 651: if (new->spspec != NULL && new->spspec == rmconf->spspec) { ! 652: dupspspec_list(new, rmconf); ! 653: } ! 654: ! 655: /* proposal has been deep copied already from spspec's, see ! 656: * cfparse.y:set_isakmp_proposal, which in turn calls ! 657: * cfparse.y:expand_isakmpspec where the copying happens. ! 658: */ ! 659: ! 660: #ifdef ENABLE_HYBRID ! 661: if (new->xauth != NULL && new->xauth == rmconf->xauth) { ! 662: new->xauth = xauth_rmconf_dup(new->xauth); ! 663: if (new->xauth == NULL) ! 664: exit(1); ! 665: } ! 666: #endif ! 667: ! 668: /* duplicate strings unless value overridden */ ! 669: if (new->mycertfile != NULL && new->mycertfile == rmconf->mycertfile) { ! 670: new->mycertfile = racoon_strdup(new->mycertfile); ! 671: STRDUP_FATAL(new->mycertfile); ! 672: } ! 673: if (new->myprivfile != NULL && new->myprivfile == rmconf->myprivfile) { ! 674: new->myprivfile = racoon_strdup(new->myprivfile); ! 675: STRDUP_FATAL(new->myprivfile); ! 676: } ! 677: if (new->peerscertfile != NULL && new->peerscertfile == rmconf->peerscertfile) { ! 678: new->peerscertfile = racoon_strdup(new->peerscertfile); ! 679: STRDUP_FATAL(new->peerscertfile); ! 680: } ! 681: if (new->cacertfile != NULL && new->cacertfile == rmconf->cacertfile) { ! 682: new->cacertfile = racoon_strdup(new->cacertfile); ! 683: STRDUP_FATAL(new->cacertfile); ! 684: } ! 685: if (new->idv != NULL && new->idv == rmconf->idv) { ! 686: new->idv = vdup(new->idv); ! 687: STRDUP_FATAL(new->idv); ! 688: } ! 689: if (new->key != NULL && new->key == rmconf->key) { ! 690: new->key = vdup(new->key); ! 691: STRDUP_FATAL(new->key); ! 692: } ! 693: if (new->mycert != NULL && new->mycert == rmconf->mycert) { ! 694: new->mycert = vdup(new->mycert); ! 695: STRDUP_FATAL(new->mycert); ! 696: } ! 697: if (new->peerscert != NULL && new->peerscert == rmconf->peerscert) { ! 698: new->peerscert = vdup(new->peerscert); ! 699: STRDUP_FATAL(new->peerscert); ! 700: } ! 701: if (new->cacert != NULL && new->cacert == rmconf->cacert) { ! 702: new->cacert = vdup(new->cacert); ! 703: STRDUP_FATAL(new->cacert); ! 704: } ! 705: for (i = 0; i <= SCRIPT_MAX; i++) ! 706: if (new->script[i] != NULL && new->script[i] == rmconf->script[i]) { ! 707: new->script[i] = vdup(new->script[i]); ! 708: STRDUP_FATAL(new->script[i]); ! 709: } ! 710: ! 711: return 0; ! 712: } ! 713: ! 714: static void ! 715: idspec_free(void *data) ! 716: { ! 717: vfree (((struct idspec *)data)->id); ! 718: free (data); ! 719: } ! 720: ! 721: void ! 722: delrmconf(rmconf) ! 723: struct remoteconf *rmconf; ! 724: { ! 725: int i; ! 726: ! 727: #ifdef ENABLE_HYBRID ! 728: if (rmconf->xauth) ! 729: xauth_rmconf_delete(&rmconf->xauth); ! 730: #endif ! 731: if (rmconf->etypes){ ! 732: deletypes(rmconf->etypes); ! 733: rmconf->etypes=NULL; ! 734: } ! 735: if (rmconf->idv) ! 736: vfree(rmconf->idv); ! 737: if (rmconf->key) ! 738: vfree(rmconf->key); ! 739: if (rmconf->idvl_p) ! 740: genlist_free(rmconf->idvl_p, idspec_free); ! 741: if (rmconf->dhgrp) ! 742: oakley_dhgrp_free(rmconf->dhgrp); ! 743: if (rmconf->proposal) ! 744: delisakmpsa(rmconf->proposal); ! 745: flushspspec(rmconf); ! 746: if (rmconf->mycert) ! 747: vfree(rmconf->mycert); ! 748: if (rmconf->mycertfile) ! 749: racoon_free(rmconf->mycertfile); ! 750: if (rmconf->myprivfile) ! 751: racoon_free(rmconf->myprivfile); ! 752: if (rmconf->peerscert) ! 753: vfree(rmconf->peerscert); ! 754: if (rmconf->peerscertfile) ! 755: racoon_free(rmconf->peerscertfile); ! 756: if (rmconf->cacert) ! 757: vfree(rmconf->cacert); ! 758: if (rmconf->cacertfile) ! 759: racoon_free(rmconf->cacertfile); ! 760: if (rmconf->rsa_private) ! 761: genlist_free(rmconf->rsa_private, rsa_key_free); ! 762: if (rmconf->rsa_public) ! 763: genlist_free(rmconf->rsa_public, rsa_key_free); ! 764: if (rmconf->name) ! 765: racoon_free(rmconf->name); ! 766: if (rmconf->remote) ! 767: racoon_free(rmconf->remote); ! 768: for (i = 0; i <= SCRIPT_MAX; i++) ! 769: if (rmconf->script[i]) ! 770: vfree(rmconf->script[i]); ! 771: ! 772: racoon_free(rmconf); ! 773: } ! 774: ! 775: void ! 776: delisakmpsa(sa) ! 777: struct isakmpsa *sa; ! 778: { ! 779: if (sa->dhgrp) ! 780: oakley_dhgrp_free(sa->dhgrp); ! 781: if (sa->next) ! 782: delisakmpsa(sa->next); ! 783: #ifdef HAVE_GSSAPI ! 784: if (sa->gssid) ! 785: vfree(sa->gssid); ! 786: #endif ! 787: racoon_free(sa); ! 788: } ! 789: ! 790: struct etypes * ! 791: dupetypes(orig) ! 792: struct etypes *orig; ! 793: { ! 794: struct etypes *new; ! 795: ! 796: if (!orig) ! 797: return NULL; ! 798: ! 799: new = racoon_malloc(sizeof(struct etypes)); ! 800: if (new == NULL) ! 801: return NULL; ! 802: ! 803: new->type = orig->type; ! 804: new->next = NULL; ! 805: ! 806: if (orig->next) ! 807: new->next=dupetypes(orig->next); ! 808: ! 809: return new; ! 810: } ! 811: ! 812: void ! 813: deletypes(e) ! 814: struct etypes *e; ! 815: { ! 816: if (e->next) ! 817: deletypes(e->next); ! 818: racoon_free(e); ! 819: } ! 820: ! 821: /* ! 822: * insert into head of list. ! 823: */ ! 824: void ! 825: insrmconf(new) ! 826: struct remoteconf *new; ! 827: { ! 828: if (new->name == NULL) { ! 829: new->name = racoon_strdup(saddr2str(new->remote)); ! 830: } ! 831: if (new->remote == NULL) { ! 832: new->remote = newsaddr(sizeof(struct sockaddr)); ! 833: new->remote->sa_family = AF_UNSPEC; ! 834: } ! 835: ! 836: TAILQ_INSERT_HEAD(&rmtree, new, chain); ! 837: } ! 838: ! 839: void ! 840: remrmconf(rmconf) ! 841: struct remoteconf *rmconf; ! 842: { ! 843: TAILQ_REMOVE(&rmtree, rmconf, chain); ! 844: } ! 845: ! 846: void ! 847: flushrmconf() ! 848: { ! 849: struct remoteconf *p, *next; ! 850: ! 851: for (p = TAILQ_FIRST(&rmtree); p; p = next) { ! 852: next = TAILQ_NEXT(p, chain); ! 853: remrmconf(p); ! 854: delrmconf(p); ! 855: } ! 856: } ! 857: ! 858: void ! 859: initrmconf() ! 860: { ! 861: TAILQ_INIT(&rmtree); ! 862: } ! 863: ! 864: void ! 865: rmconf_start_reload() ! 866: { ! 867: rmtree_save=rmtree; ! 868: initrmconf(); ! 869: } ! 870: ! 871: void ! 872: rmconf_finish_reload() ! 873: { ! 874: remoteconf_tailq_head_t rmtree_tmp; ! 875: ! 876: rmtree_tmp=rmtree; ! 877: rmtree=rmtree_save; ! 878: flushrmconf(); ! 879: initrmconf(); ! 880: rmtree=rmtree_tmp; ! 881: } ! 882: ! 883: ! 884: ! 885: /* check exchange type to be acceptable */ ! 886: int ! 887: check_etypeok(rmconf, ctx) ! 888: struct remoteconf *rmconf; ! 889: void *ctx; ! 890: { ! 891: u_int8_t etype = (u_int8_t) (intptr_t) ctx; ! 892: struct etypes *e; ! 893: ! 894: for (e = rmconf->etypes; e != NULL; e = e->next) { ! 895: if (e->type == etype) ! 896: return 1; ! 897: plog(LLV_DEBUG2, LOCATION, NULL, ! 898: "Etype mismatch: got %d, expected %d.\n", e->type, etype); ! 899: } ! 900: ! 901: return 0; ! 902: } ! 903: ! 904: /*%%%*/ ! 905: struct isakmpsa * ! 906: newisakmpsa() ! 907: { ! 908: struct isakmpsa *new; ! 909: ! 910: new = racoon_calloc(1, sizeof(*new)); ! 911: if (new == NULL) ! 912: return NULL; ! 913: ! 914: /* ! 915: * Just for sanity, make sure this is initialized. This is ! 916: * filled in for real when the ISAKMP proposal is configured. ! 917: */ ! 918: new->vendorid = VENDORID_UNKNOWN; ! 919: ! 920: new->next = NULL; ! 921: #ifdef HAVE_GSSAPI ! 922: new->gssid = NULL; ! 923: #endif ! 924: ! 925: return new; ! 926: } ! 927: ! 928: /* ! 929: * insert into tail of list. ! 930: */ ! 931: void ! 932: insisakmpsa(new, rmconf) ! 933: struct isakmpsa *new; ! 934: struct remoteconf *rmconf; ! 935: { ! 936: struct isakmpsa *p; ! 937: ! 938: if (rmconf->proposal == NULL) { ! 939: rmconf->proposal = new; ! 940: return; ! 941: } ! 942: ! 943: for (p = rmconf->proposal; p->next != NULL; p = p->next) ! 944: ; ! 945: p->next = new; ! 946: } ! 947: ! 948: static void * ! 949: dump_peers_identifiers (void *entry, void *arg) ! 950: { ! 951: struct idspec *id = (struct idspec*) entry; ! 952: char buf[1024], *pbuf; ! 953: pbuf = buf; ! 954: pbuf += sprintf (pbuf, "\tpeers_identifier %s", ! 955: s_idtype (id->idtype)); ! 956: if (id->id) ! 957: pbuf += sprintf (pbuf, " \"%s\"", id->id->v); ! 958: plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf); ! 959: return NULL; ! 960: } ! 961: ! 962: static int ! 963: dump_rmconf_single (struct remoteconf *p, void *data) ! 964: { ! 965: struct etypes *etype = p->etypes; ! 966: struct isakmpsa *prop = p->proposal; ! 967: char buf[1024], *pbuf; ! 968: ! 969: pbuf = buf; ! 970: ! 971: pbuf += sprintf(pbuf, "remote \"%s\"", p->name); ! 972: if (p->inherited_from) ! 973: pbuf += sprintf(pbuf, " inherit \"%s\"", ! 974: p->inherited_from->name); ! 975: plog(LLV_INFO, LOCATION, NULL, "%s {\n", buf); ! 976: pbuf = buf; ! 977: pbuf += sprintf(pbuf, "\texchange_type "); ! 978: while (etype) { ! 979: pbuf += sprintf (pbuf, "%s%s", s_etype(etype->type), ! 980: etype->next != NULL ? ", " : ";\n"); ! 981: etype = etype->next; ! 982: } ! 983: plog(LLV_INFO, LOCATION, NULL, "%s", buf); ! 984: plog(LLV_INFO, LOCATION, NULL, "\tdoi %s;\n", s_doi(p->doitype)); ! 985: pbuf = buf; ! 986: pbuf += sprintf(pbuf, "\tmy_identifier %s", s_idtype (p->idvtype)); ! 987: if (p->idvtype == IDTYPE_ASN1DN) { ! 988: plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf); ! 989: plog(LLV_INFO, LOCATION, NULL, ! 990: "\tcertificate_type %s \"%s\" \"%s\";\n", ! 991: oakley_get_certtype(p->mycert) == ISAKMP_CERT_X509SIGN ! 992: ? "x509" : "*UNKNOWN*", ! 993: p->mycertfile, p->myprivfile); ! 994: ! 995: switch (oakley_get_certtype(p->peerscert)) { ! 996: case ISAKMP_CERT_NONE: ! 997: plog(LLV_INFO, LOCATION, NULL, ! 998: "\t/* peers certificate from payload */\n"); ! 999: break; ! 1000: case ISAKMP_CERT_X509SIGN: ! 1001: plog(LLV_INFO, LOCATION, NULL, ! 1002: "\tpeers_certfile \"%s\";\n", p->peerscertfile); ! 1003: break; ! 1004: case ISAKMP_CERT_DNS: ! 1005: plog(LLV_INFO, LOCATION, NULL, ! 1006: "\tpeers_certfile dnssec;\n"); ! 1007: break; ! 1008: default: ! 1009: plog(LLV_INFO, LOCATION, NULL, ! 1010: "\tpeers_certfile *UNKNOWN* (%d)\n", ! 1011: oakley_get_certtype(p->peerscert)); ! 1012: break; ! 1013: } ! 1014: } ! 1015: else { ! 1016: if (p->idv) ! 1017: pbuf += sprintf (pbuf, " \"%s\"", p->idv->v); ! 1018: plog(LLV_INFO, LOCATION, NULL, "%s;\n", buf); ! 1019: genlist_foreach(p->idvl_p, &dump_peers_identifiers, NULL); ! 1020: } ! 1021: ! 1022: plog(LLV_INFO, LOCATION, NULL, "\trekey %s;\n", ! 1023: p->rekey == REKEY_FORCE ? "force" : s_switch (p->rekey)); ! 1024: plog(LLV_INFO, LOCATION, NULL, "\tsend_cert %s;\n", ! 1025: s_switch (p->send_cert)); ! 1026: plog(LLV_INFO, LOCATION, NULL, "\tsend_cr %s;\n", ! 1027: s_switch (p->send_cr)); ! 1028: plog(LLV_INFO, LOCATION, NULL, "\tmatch_empty_cr %s;\n", ! 1029: s_switch (p->match_empty_cr)); ! 1030: plog(LLV_INFO, LOCATION, NULL, "\tverify_cert %s;\n", ! 1031: s_switch (p->verify_cert)); ! 1032: plog(LLV_INFO, LOCATION, NULL, "\tverify_identifier %s;\n", ! 1033: s_switch (p->verify_identifier)); ! 1034: plog(LLV_INFO, LOCATION, NULL, "\tnat_traversal %s;\n", ! 1035: p->nat_traversal == NATT_FORCE ? ! 1036: "force" : s_switch (p->nat_traversal)); ! 1037: plog(LLV_INFO, LOCATION, NULL, "\tnonce_size %d;\n", ! 1038: p->nonce_size); ! 1039: plog(LLV_INFO, LOCATION, NULL, "\tpassive %s;\n", ! 1040: s_switch (p->passive)); ! 1041: plog(LLV_INFO, LOCATION, NULL, "\tike_frag %s;\n", ! 1042: p->ike_frag == ISAKMP_FRAG_FORCE ? ! 1043: "force" : s_switch (p->ike_frag)); ! 1044: plog(LLV_INFO, LOCATION, NULL, "\tesp_frag %d;\n", p->esp_frag); ! 1045: plog(LLV_INFO, LOCATION, NULL, "\tinitial_contact %s;\n", ! 1046: s_switch (p->ini_contact)); ! 1047: plog(LLV_INFO, LOCATION, NULL, "\tgenerate_policy %s;\n", ! 1048: s_switch (p->gen_policy)); ! 1049: plog(LLV_INFO, LOCATION, NULL, "\tsupport_proxy %s;\n", ! 1050: s_switch (p->support_proxy)); ! 1051: ! 1052: while (prop) { ! 1053: plog(LLV_INFO, LOCATION, NULL, "\n"); ! 1054: plog(LLV_INFO, LOCATION, NULL, ! 1055: "\t/* prop_no=%d, trns_no=%d */\n", ! 1056: prop->prop_no, prop->trns_no); ! 1057: plog(LLV_INFO, LOCATION, NULL, "\tproposal {\n"); ! 1058: plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime time %lu sec;\n", ! 1059: (long)prop->lifetime); ! 1060: plog(LLV_INFO, LOCATION, NULL, "\t\tlifetime bytes %zd;\n", ! 1061: prop->lifebyte); ! 1062: plog(LLV_INFO, LOCATION, NULL, "\t\tdh_group %s;\n", ! 1063: alg_oakley_dhdef_name(prop->dh_group)); ! 1064: plog(LLV_INFO, LOCATION, NULL, "\t\tencryption_algorithm %s;\n", ! 1065: alg_oakley_encdef_name(prop->enctype)); ! 1066: plog(LLV_INFO, LOCATION, NULL, "\t\thash_algorithm %s;\n", ! 1067: alg_oakley_hashdef_name(prop->hashtype)); ! 1068: plog(LLV_INFO, LOCATION, NULL, "\t\tauthentication_method %s;\n", ! 1069: alg_oakley_authdef_name(prop->authmethod)); ! 1070: plog(LLV_INFO, LOCATION, NULL, "\t}\n"); ! 1071: prop = prop->next; ! 1072: } ! 1073: plog(LLV_INFO, LOCATION, NULL, "}\n"); ! 1074: plog(LLV_INFO, LOCATION, NULL, "\n"); ! 1075: ! 1076: return 0; ! 1077: } ! 1078: ! 1079: void ! 1080: dumprmconf() ! 1081: { ! 1082: enumrmconf(NULL, dump_rmconf_single, NULL); ! 1083: } ! 1084: ! 1085: struct idspec * ! 1086: newidspec() ! 1087: { ! 1088: struct idspec *new; ! 1089: ! 1090: new = racoon_calloc(1, sizeof(*new)); ! 1091: if (new == NULL) ! 1092: return NULL; ! 1093: new->idtype = IDTYPE_ADDRESS; ! 1094: ! 1095: return new; ! 1096: } ! 1097: ! 1098: vchar_t * ! 1099: script_path_add(path) ! 1100: vchar_t *path; ! 1101: { ! 1102: char *script_dir; ! 1103: vchar_t *new_path; ! 1104: vchar_t *new_storage; ! 1105: vchar_t **sp; ! 1106: size_t len; ! 1107: size_t size; ! 1108: ! 1109: script_dir = lcconf->pathinfo[LC_PATHTYPE_SCRIPT]; ! 1110: ! 1111: /* Try to find the script in the script directory */ ! 1112: if ((path->v[0] != '/') && (script_dir != NULL)) { ! 1113: len = strlen(script_dir) + sizeof("/") + path->l + 1; ! 1114: ! 1115: if ((new_path = vmalloc(len)) == NULL) { ! 1116: plog(LLV_ERROR, LOCATION, NULL, ! 1117: "Cannot allocate memory: %s\n", strerror(errno)); ! 1118: return NULL; ! 1119: } ! 1120: ! 1121: new_path->v[0] = '\0'; ! 1122: (void)strlcat(new_path->v, script_dir, len); ! 1123: (void)strlcat(new_path->v, "/", len); ! 1124: (void)strlcat(new_path->v, path->v, len); ! 1125: ! 1126: vfree(path); ! 1127: path = new_path; ! 1128: } ! 1129: ! 1130: return path; ! 1131: } ! 1132: ! 1133: ! 1134: struct isakmpsa * ! 1135: dupisakmpsa(struct isakmpsa *sa) ! 1136: { ! 1137: struct isakmpsa *res = NULL; ! 1138: ! 1139: if(sa == NULL) ! 1140: return NULL; ! 1141: ! 1142: res = newisakmpsa(); ! 1143: if(res == NULL) ! 1144: return NULL; ! 1145: ! 1146: *res = *sa; ! 1147: #ifdef HAVE_GSSAPI ! 1148: if (sa->gssid != NULL) ! 1149: res->gssid = vdup(sa->gssid); ! 1150: #endif ! 1151: res->next = NULL; ! 1152: ! 1153: if(sa->dhgrp != NULL) ! 1154: oakley_setdhgroup(sa->dh_group, &res->dhgrp); ! 1155: ! 1156: return res; ! 1157: ! 1158: } ! 1159: ! 1160: #ifdef ENABLE_HYBRID ! 1161: int ! 1162: isakmpsa_switch_authmethod(authmethod) ! 1163: int authmethod; ! 1164: { ! 1165: switch(authmethod) { ! 1166: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R: ! 1167: authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I; ! 1168: break; ! 1169: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R: ! 1170: authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I; ! 1171: break; ! 1172: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R: ! 1173: authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I; ! 1174: break; ! 1175: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R: ! 1176: authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I; ! 1177: break; ! 1178: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R: ! 1179: authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I; ! 1180: break; ! 1181: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R: ! 1182: authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I; ! 1183: break; ! 1184: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R: ! 1185: authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I; ! 1186: break; ! 1187: default: ! 1188: break; ! 1189: } ! 1190: ! 1191: return authmethod; ! 1192: } ! 1193: #endif ! 1194: ! 1195: /* ! 1196: * Given a proposed ISAKMP SA, and a list of acceptable ! 1197: * ISAKMP SAs, it compares using pcheck_level policy and ! 1198: * returns first match (if any). ! 1199: */ ! 1200: struct isakmpsa * ! 1201: checkisakmpsa(pcheck_level, proposal, acceptable) ! 1202: int pcheck_level; ! 1203: struct isakmpsa *proposal, *acceptable; ! 1204: { ! 1205: struct isakmpsa *p; ! 1206: ! 1207: for (p = acceptable; p != NULL; p = p->next){ ! 1208: plog(LLV_DEBUG2, LOCATION, NULL, ! 1209: "checkisakmpsa:\nauthmethod: %d / %d\n", ! 1210: isakmpsa_switch_authmethod(proposal->authmethod), isakmpsa_switch_authmethod(p->authmethod)); ! 1211: if (isakmpsa_switch_authmethod(proposal->authmethod) != isakmpsa_switch_authmethod(p->authmethod) || ! 1212: proposal->enctype != p->enctype || ! 1213: proposal->dh_group != p->dh_group || ! 1214: proposal->hashtype != p->hashtype) ! 1215: continue; ! 1216: ! 1217: switch (pcheck_level) { ! 1218: case PROP_CHECK_OBEY: ! 1219: break; ! 1220: ! 1221: case PROP_CHECK_CLAIM: ! 1222: case PROP_CHECK_STRICT: ! 1223: if (proposal->encklen < p->encklen || ! 1224: #if 0 ! 1225: proposal->lifebyte > p->lifebyte || ! 1226: #endif ! 1227: proposal->lifetime > p->lifetime) ! 1228: continue; ! 1229: break; ! 1230: ! 1231: case PROP_CHECK_EXACT: ! 1232: if (proposal->encklen != p->encklen || ! 1233: #if 0 ! 1234: proposal->lifebyte != p->lifebyte || ! 1235: #endif ! 1236: proposal->lifetime != p->lifetime) ! 1237: continue; ! 1238: break; ! 1239: ! 1240: default: ! 1241: continue; ! 1242: } ! 1243: ! 1244: return p; ! 1245: } ! 1246: ! 1247: return NULL; ! 1248: }