X-Git-Url: https://git.saurik.com/apple/network_cmds.git/blobdiff_plain/7ba0088d6898d7fd2873f736f1f556673a8be855..c688725629e05b86c13cf47e9756dd332fa510c6:/racoon.tproj/ipsec_doi.c diff --git a/racoon.tproj/ipsec_doi.c b/racoon.tproj/ipsec_doi.c index 2b039c5..26567af 100644 --- a/racoon.tproj/ipsec_doi.c +++ b/racoon.tproj/ipsec_doi.c @@ -1,4 +1,4 @@ -/* $KAME: ipsec_doi.c,v 1.154 2001/12/31 20:13:40 thorpej Exp $ */ +/* $KAME: ipsec_doi.c,v 1.158 2002/09/27 05:55:52 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -80,6 +80,7 @@ #include "crypto_openssl.h" #include "strnames.h" #include "gcmalloc.h" +#include "isakmp_natd.h" #ifdef HAVE_GSSAPI #include "gssapi.h" @@ -315,9 +316,7 @@ get_ph1approvalx(p, proposal, sap) struct prop_pair *p; struct isakmpsa *proposal, *sap; { -#ifdef YIPS_DEBUG struct isakmp_pl_p *prop = p->prop; -#endif struct isakmp_pl_t *trns = p->trns; struct isakmpsa sa, *s, *tsap; @@ -736,6 +735,7 @@ ipsecdoi_selectph2proposal(iph2) /* make a SA to be replayed. */ /* SPI must be updated later. */ iph2->sa_ret = get_sabyproppair(ret, iph2->ph1); + free_proppair0(ret); if (iph2->sa_ret == NULL) return -1; @@ -2085,6 +2085,10 @@ check_attr_ipsec(proto_id, trns) switch (lorv) { case IPSECDOI_ATTR_ENC_MODE_TUNNEL: case IPSECDOI_ATTR_ENC_MODE_TRNS: + case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC: + case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC: + case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT: + case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT: break; default: plog(LLV_ERROR, LOCATION, NULL, @@ -2260,6 +2264,10 @@ check_attr_ipcomp(trns) switch (lorv) { case IPSECDOI_ATTR_ENC_MODE_TUNNEL: case IPSECDOI_ATTR_ENC_MODE_TRNS: + case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC: + case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC: + case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT: + case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT: break; default: plog(LLV_ERROR, LOCATION, NULL, @@ -2797,6 +2805,37 @@ ipsecdoi_setph2proposal(iph2) propoff = 0; for (a = proposal; a; a = a->next) { for (b = a->head; b; b = b->next) { +#ifdef IKE_NAT_T + /* + * Hack to fix encmode, we may have detected a nat since + * we last set pr->encmode. We need to fix this if + * we now have a NAT. NAT-T doesn't work with AH. + */ + int nattype; + if (iph2->ph1 && (nattype = natd_hasnat(iph2->ph1)) && + b->proto_id != IPSECDOI_PROTO_IPSEC_AH) + { + switch (b->encmode) + { + + case IPSECDOI_ATTR_ENC_MODE_TUNNEL: + if (nattype == natt_type_rfc || + nattype == natt_type_apple) + b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC; + else + b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT; + break; + case IPSECDOI_ATTR_ENC_MODE_TRNS: + if (nattype == natt_type_rfc || + nattype == natt_type_apple) + b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC; + else + b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT; + break; + } + } +#endif + q = setph2proposal0(iph2, a, b); if (q == NULL) { vfree(iph2->sa); @@ -2826,6 +2865,28 @@ ipsecdoi_setph2proposal(iph2) return 0; } +/* + * return 1 if all of the proposed protocols are tunnel mode. + */ +int +ipsecdoi_tunnelmode(iph2) + struct ph2handle *iph2; +{ + struct saprop *pp; + struct saproto *pr = NULL; + + for (pp = iph2->proposal; pp; pp = pp->next) { + for (pr = pp->head; pr; pr = pr->next) { + if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TUNNEL && + pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC && + pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT) + return 0; + } + } + + return 1; +} + /* * return 1 if all of the proposed protocols are transport mode. */ @@ -2838,7 +2899,9 @@ ipsecdoi_transportmode(iph2) for (pp = iph2->proposal; pp; pp = pp->next) { for (pr = pp->head; pr; pr = pr->next) { - if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS) + if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS && + pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC && + pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT) return 0; } } @@ -2846,6 +2909,7 @@ ipsecdoi_transportmode(iph2) return 1; } + int ipsecdoi_get_defaultlifetime() { @@ -2945,6 +3009,8 @@ ipsecdoi_checkid1(iph1) struct ph1handle *iph1; { struct ipsecdoi_id_b *id_b; + struct sockaddr *sa; + caddr_t sa1, sa2; if (iph1->id_p == NULL) { plog(LLV_ERROR, LOCATION, NULL, @@ -2960,9 +3026,11 @@ ipsecdoi_checkid1(iph1) id_b = (struct ipsecdoi_id_b *)iph1->id_p->v; - /* In main mode with pre-shared key, only address type can be used. */ + /* In main mode with pre-shared key, only address type can be used. + If NAT Traversal draft 02 being used - allow this. */ if (iph1->etype == ISAKMP_ETYPE_IDENT - && iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) { + && iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY + && !natd_hasnat(iph1)) { if (id_b->type != IPSECDOI_ID_IPV4_ADDR && id_b->type != IPSECDOI_ID_IPV6_ADDR) { plog(LLV_ERROR, LOCATION, NULL, @@ -3049,19 +3117,43 @@ ipsecdoi_checkid1(iph1) case IDTYPE_ASN1DN: ident.v = (caddr_t)(id_b + 1); ident.l = ident0->l; - if (eay_cmp_asn1dn(ident0, &ident)) { - plog(LLV_WARNING, LOCATION, NULL, - "ID value mismatched.\n"); - if (iph1->rmconf->verify_identifier) - return ISAKMP_NTYPE_INVALID_ID_INFORMATION; + if (eay_cmp_asn1dn(ident0, &ident)) + goto err; + break; + case IDTYPE_ADDRESS: + sa = (struct sockaddr *)ident0->v; + sa2 = (caddr_t)(id_b + 1); + switch (sa->sa_family) { + case AF_INET: + if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr)) + goto err; + + sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr; + if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0) + goto err; + break; +#ifdef INET6 + case AF_INET6: + if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr)) + goto err; + sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr; + if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0) + goto err; + break; +#endif + default: + goto err; } break; default: if (memcmp(ident0->v, id_b + 1, ident0->l)) { +err: plog(LLV_WARNING, LOCATION, NULL, "ID value mismatched.\n"); - if (iph1->rmconf->verify_identifier) + if (iph1->rmconf->verify_identifier) { + vfree(ident0); return ISAKMP_NTYPE_INVALID_ID_INFORMATION; + } } break; } @@ -3100,6 +3192,7 @@ ipsecdoi_setid1(iph1) ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv); break; case IDTYPE_KEYID: + case IDTYPE_KEYIDUSE: id_b.type = IPSECDOI_ID_KEY_ID; ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv); break; @@ -3227,6 +3320,7 @@ set_identifier(vpp, type, value) switch (type) { case IDTYPE_FQDN: case IDTYPE_USERFQDN: + case IDTYPE_KEYIDUSE: /* length is adjusted since QUOTEDSTRING teminates NULL. */ new = vmalloc(value->l - 1); if (new == NULL) @@ -3327,6 +3421,11 @@ ipsecdoi_setid2(iph2) vchar_t *ident; id_b.type = idtype2doi(iph2->sainfo->idvtype); + if (id_b.type == 255) { + plog(LLV_ERROR, LOCATION, NULL, + "failed to convert ID type to DOI.\n"); + return -1; + } id_b.proto_id = 0; id_b.port = 0; @@ -3862,14 +3961,14 @@ static int rm_idtype2doi[] = { IPSECDOI_ID_FQDN, IPSECDOI_ID_USER_FQDN, IPSECDOI_ID_KEY_ID, - -1, /* it's type of "address" + 255, /* it's type of "address" * it expands into 4 types by another function. */ IPSECDOI_ID_DER_ASN1_DN, }; /* * convert idtype to DOI value. - * OUT -1 : NG + * OUT 255 : NG * other: converted. */ int @@ -3878,7 +3977,7 @@ idtype2doi(idtype) { if (ARRAYLEN(rm_idtype2doi) > idtype) return rm_idtype2doi[idtype]; - return -1; + return 255; } int