]> git.saurik.com Git - apple/network_cmds.git/blobdiff - racoon.tproj/ipsec_doi.c
network_cmds-245.12.tar.gz
[apple/network_cmds.git] / racoon.tproj / ipsec_doi.c
index 2b039c59a2e40e6c8a0c4a38b378f535f1de8ae2..26567af5760ff725d16e1ff92c79e1d515e68cc5 100644 (file)
@@ -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