]> git.saurik.com Git - apple/ipsec.git/commitdiff
ipsec-34.0.1.tar.gz mac-os-x-1054 v34.0.1
authorApple <opensource@apple.com>
Sat, 7 Jun 2008 03:22:58 +0000 (03:22 +0000)
committerApple <opensource@apple.com>
Sat, 7 Jun 2008 03:22:58 +0000 (03:22 +0000)
ipsec-tools/racoon/cfparse.y
ipsec-tools/racoon/isakmp_quick.c
ipsec-tools/racoon/localconf.c
ipsec-tools/racoon/localconf.h
ipsec-tools/racoon/pfkey_racoon.c
ipsec-tools/racoon/sainfo.c
ipsec-tools/racoon/sainfo.h

index d9ac8a4f12300fd448b8887804ce7d0fcf0428b3..e19032a0bae4c21bbb67396be0ffe0c79d2f8b1b 100644 (file)
@@ -758,7 +758,7 @@ sainfo_statement
                        /* duplicate check */
                        check = getsainfo(cur_sainfo->idsrc,
                                          cur_sainfo->iddst,
-                                         cur_sainfo->id_i);
+                                         cur_sainfo->id_i, 0);
                        if (check && (!check->idsrc && !cur_sainfo->idsrc)) {
                                yyerror("duplicated sainfo: %s",
                                        sainfo2str(cur_sainfo));
index fc3c2594f326bd10a48054b76e17e3adc3053591..a872904dead2ee84b14f653b44895ccb2343ec8e 100644 (file)
@@ -88,7 +88,7 @@
 /* quick mode */
 static vchar_t *quick_ir1mx __P((struct ph2handle *, vchar_t *, vchar_t *));
 static int get_sainfo_r __P((struct ph2handle *));
-static int get_proposal_r __P((struct ph2handle *));
+static int get_proposal_r __P((struct ph2handle *, int));
 
 /* \f%%%
  * Quick Mode
@@ -470,43 +470,56 @@ quick_i2recv(iph2, msg0)
 
                case ISAKMP_NPTYPE_ID:
                    {
-                       vchar_t *vp;
-
-                       /* check ID value */
-                       if (f_id == 0) {
-                               /* for IDci */
-                               f_id = 1;
-                               vp = iph2->id;
-                       } else {
-                               /* for IDcr */
-                               vp = iph2->id_p;
-                       }
-
-                       /* These ids may not match when natt is used with some devices.
-                        * RFC 2407 says that the protocol and port fields should be ignored
-                        * if they are zero, therefore they need to be checked individually.
-                        */
-                       struct ipsecdoi_id_b *id_ptr = (struct ipsecdoi_id_b *)vp->v;
-                       struct ipsecdoi_pl_id *idp_ptr = (struct ipsecdoi_pl_id *)pa->ptr;
-                       
-                       if (id_ptr->type != idp_ptr->b.type
-                               || (idp_ptr->b.proto_id != 0 && idp_ptr->b.proto_id != id_ptr->proto_id)
-                               || (idp_ptr->b.port != 0 && idp_ptr->b.port != id_ptr->port)
-                               || memcmp(vp->v + sizeof(struct ipsecdoi_id_b), (caddr_t)pa->ptr + sizeof(struct ipsecdoi_pl_id), 
-                                               vp->l - sizeof(struct ipsecdoi_id_b))) {
-                               //%%% BUG_FIX - to support some servers
-                               if (iph2->ph1->natt_flags & NAT_DETECTED) {
-                                       plog(LLV_WARNING, LOCATION, NULL,
-                                               "mismatched ID was returned - ignored because nat traversal is being used.\n");
-                                       break;
+                               vchar_t *vp;
+
+                               /* check ID value */
+                               if (f_id == 0) {
+                                       /* for IDci */
+                                       vp = iph2->id;
+                               } else {
+                                       /* for IDcr */
+                                       vp = iph2->id_p;
                                }
-                               plog(LLV_ERROR, LOCATION, NULL,
-                                       "mismatched ID was returned.\n");
-                               error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
-                               goto end;
+
+                               /* These ids may not match when natt is used with some devices.
+                                * RFC 2407 says that the protocol and port fields should be ignored
+                                * if they are zero, therefore they need to be checked individually.
+                                */
+                               struct ipsecdoi_id_b *id_ptr = (struct ipsecdoi_id_b *)vp->v;
+                               struct ipsecdoi_pl_id *idp_ptr = (struct ipsecdoi_pl_id *)pa->ptr;
+                               
+                               if (id_ptr->type != idp_ptr->b.type
+                                       || (idp_ptr->b.proto_id != 0 && idp_ptr->b.proto_id != id_ptr->proto_id)
+                                       || (idp_ptr->b.port != 0 && idp_ptr->b.port != id_ptr->port)
+                                       || memcmp(vp->v + sizeof(struct ipsecdoi_id_b), (caddr_t)pa->ptr + sizeof(struct ipsecdoi_pl_id), 
+                                                       vp->l - sizeof(struct ipsecdoi_id_b))) {
+                                       // to support servers that use our external nat address as our ID
+                                       if (iph2->ph1->natt_flags & NAT_DETECTED) {
+                                               plog(LLV_WARNING, LOCATION, NULL,
+                                                       "mismatched ID was returned - ignored because nat traversal is being used.\n");
+                                               /* If I'm behind a nat and the ID is type address - save the address
+                                                * and port for when the peer rekeys.
+                                                */
+                                               if (f_id == 0 && (iph2->ph1->natt_flags & NAT_DETECTED_ME)) {
+                                                       if (lcconf->ext_nat_id)
+                                                               vfree(lcconf->ext_nat_id);
+                                                       lcconf->ext_nat_id = vmalloc(idp_ptr->h.len - sizeof(struct isakmp_gen));
+                                                       if (lcconf->ext_nat_id == NULL) {
+                                                               plog(LLV_ERROR, LOCATION, NULL, "memory error while allocating external nat id.\n");
+                                                               goto end;
+                                                       }
+                                                       memcpy(lcconf->ext_nat_id->v, &(idp_ptr->b), lcconf->ext_nat_id->l);
+                                                       plog(LLV_DEBUG, LOCATION, NULL, "external nat address saved.\n");
+                                               } 
+                                       } else {
+                                               plog(LLV_ERROR, LOCATION, NULL, "mismatched ID was returned.\n");
+                                               error = ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED;
+                                               goto end;
+                                       }
                                }
+                               if (f_id == 0)
+                                       f_id = 1;
                        }
-
                        break;
 
                case ISAKMP_NPTYPE_N:
@@ -1130,7 +1143,10 @@ quick_r1recv(iph2, msg0)
        }
 
        /* check the existence of ID payload and create responder's proposal */
-       error = get_proposal_r(iph2);
+       error = get_proposal_r(iph2, 0);
+       if (error != -2 && error != 0 && (iph2->ph1->natt_flags & NAT_DETECTED_ME) && lcconf->ext_nat_id != NULL)
+               error = get_proposal_r(iph2, 1);
+               
        switch (error) {
        case -2:
                /* generate a policy template from peer's proposal */
@@ -1953,7 +1969,10 @@ get_sainfo_r(iph2)
                goto end;
        }
 
-       iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p);
+       iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, 0);
+       if (iph2->sainfo == NULL)
+               if ((iph2->ph1->natt_flags & NAT_DETECTED_ME) && lcconf->ext_nat_id != NULL)
+                       iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, 1);
        if (iph2->sainfo == NULL) {
                plog(LLV_ERROR, LOCATION, NULL,
                        "failed to get sainfo.\n");
@@ -1984,8 +2003,9 @@ end:
  * NOTE: This function is only for responder.
  */
 static int
-get_proposal_r(iph2)
+get_proposal_r(iph2, use_remote_addr)
        struct ph2handle *iph2;
+       int use_remote_addr;
 {
        struct policyindex spidx;
        struct secpolicy *sp_in, *sp_out;
@@ -2018,8 +2038,11 @@ get_proposal_r(iph2)
        /*
         * make destination address in spidx from either ID payload
         * or phase 1 address into a address in spidx.
+        * If behind a nat - use phase1 address because server's
+        * use the nat's address in the ID payload.
         */
        if (iph2->id != NULL
+        && use_remote_addr == 0
         && (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR
          || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR
          || _XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR_SUBNET
@@ -2066,7 +2089,11 @@ get_proposal_r(iph2)
                memcpy(&spidx.dst, iph2->src, sysdep_sa_len(iph2->src));
                switch (spidx.dst.ss_family) {
                case AF_INET:
-                       spidx.prefd = sizeof(struct in_addr) << 3;
+                       {
+                               struct sockaddr_in *s = (struct sockaddr_in *)&spidx.dst;
+                               spidx.prefd = sizeof(struct in_addr) << 3;                      
+                               s->sin_port = htons(0);
+                       }
                        break;
 #ifdef INET6
                case AF_INET6:
@@ -2081,6 +2108,7 @@ get_proposal_r(iph2)
 
        /* make source address in spidx */
        if (iph2->id_p != NULL
+        && use_remote_addr == 0
         && (_XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR
          || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV6_ADDR
          || _XIDT(iph2->id_p) == IPSECDOI_ID_IPV4_ADDR_SUBNET
@@ -2123,7 +2151,11 @@ get_proposal_r(iph2)
                memcpy(&spidx.src, iph2->dst, sysdep_sa_len(iph2->dst));
                switch (spidx.src.ss_family) {
                case AF_INET:
-                       spidx.prefs = sizeof(struct in_addr) << 3;
+                       {
+                               struct sockaddr_in *s = (struct sockaddr_in *)&spidx.src;
+                               spidx.prefs = sizeof(struct in_addr) << 3;
+                               s->sin_port = htons(0);
+                       }
                        break;
 #ifdef INET6
                case AF_INET6:
index 73f01f9f7fa6f9d722aa3eb87b936e0191143b32..381d1e8d3f57a3dafc2c3617f30cf4d14e311ba8 100644 (file)
@@ -101,6 +101,10 @@ flushlcconf()
                        vfree(lcconf->ident[i]);
                lcconf->ident[i] = NULL;
        }
+       if (lcconf->ext_nat_id) {
+               vfree(lcconf->ext_nat_id);
+               lcconf->ext_nat_id = NULL;
+       }
 }
 
 static void
index f99d1a7ade67b31109b6bfd76761efb23c6b8da6..b206492810587910a7cbbe4632548096242ca73e 100644 (file)
@@ -132,6 +132,7 @@ struct localconf {
        int wait_ph2complete;
 
        int natt_ka_interval;           /* NAT-T keepalive interval. */
+       vchar_t *ext_nat_id;            /* our address id for our nat address */
 
        int secret_size;
        int strict_address;             /* strictly check addresses. */
index 7152a4ee406261df9ee508287796d365e07dc7c1..76ecbc387c5d69fab8c6072b5045ae8127023656 100644 (file)
@@ -1969,7 +1969,7 @@ pk_recvacquire(mhp)
                delph2(iph2[n]);
                return -1;
        }
-       iph2[n]->sainfo = getsainfo(idsrc, iddst, NULL);
+       iph2[n]->sainfo = getsainfo(idsrc, iddst, NULL, 0);
        vfree(idsrc);
        vfree(iddst);
        if (iph2[n]->sainfo == NULL) {
@@ -2747,43 +2747,35 @@ pk_checkalg(class, calg, keylen)
  */
 static struct sadb_msg *
 pk_recv(so, lenp)
-       int so;
-       int *lenp;
+int so;
+int *lenp;
 {
-       struct sadb_msg buf, *newmsg;
-       int reallen;
-
-       *lenp = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK);
-       if (*lenp < 0)
+       struct sadb_msg *newmsg;
+       int reallen = 0; 
+       socklen_t optlen = sizeof(reallen);
+       
+       if (getsockopt(so, SOL_SOCKET, SO_NREAD, &reallen, &optlen) < 0)
                return NULL;    /*fatal*/
-       else if (*lenp < sizeof(buf))
+       
+       if (reallen == 0)
                return NULL;
-
-       reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
+       
        if ((newmsg = racoon_calloc(1, reallen)) == NULL)
                return NULL;
-
-       *lenp = recv(so, (caddr_t)newmsg, reallen, MSG_PEEK);
-       if (*lenp < 0) {
-               racoon_free(newmsg);
-               return NULL;    /*fatal*/
-       } else if (*lenp != reallen) {
-               racoon_free(newmsg);
-               return NULL;
-       }
-
+       
        *lenp = recv(so, (caddr_t)newmsg, reallen, 0);
        if (*lenp < 0) {
                racoon_free(newmsg);
                return NULL;    /*fatal*/
-       } else if (*lenp != reallen) {
+       } else if (*lenp != reallen || *lenp < sizeof(struct sadb_msg)) {
                racoon_free(newmsg);
                return NULL;
        }
-
+       
        return newmsg;
 }
 
+
 /* see handler.h */
 u_int32_t
 pk_getseq()
index 2ad87975cd0910e0ef91c76b7162ae4e362cd4c0..502914b981ab58a8f9db41a22267586707a82ee7 100644 (file)
@@ -79,12 +79,16 @@ static LIST_HEAD(_sitree, sainfo) sitree;
  * First pass is for sainfo from a specified peer, second for others.
  */
 struct sainfo *
-getsainfo(src, dst, peer)
+getsainfo(src, dst, peer, use_nat_addr)
        const vchar_t *src, *dst, *peer;
+       int use_nat_addr;
 {
        struct sainfo *s = NULL;
        struct sainfo *anonymous = NULL;
        int pass = 1;
+       
+       if (use_nat_addr && lcconf->ext_nat_id == NULL)
+               return NULL;
 
        if (peer == NULL)
                pass = 2;
@@ -109,9 +113,13 @@ getsainfo(src, dst, peer)
                        continue;
                }
 
-               if (memcmp(src->v, s->idsrc->v, s->idsrc->l) == 0
-                && memcmp(dst->v, s->iddst->v, s->iddst->l) == 0)
-                       return s;
+               if (memcmp(src->v, s->idsrc->v, s->idsrc->l) == 0) {
+                       if (use_nat_addr) {
+                               if (memcmp(lcconf->ext_nat_id->v, s->iddst->v, s->iddst->l) == 0)
+                                       return s;
+                       } else if (memcmp(dst->v, s->iddst->v, s->iddst->l) == 0)
+                               return s;
+               }
        }
 
        if (anonymous) {
index ec2a72f29808da3352d354ad8bf382ab8faf6238..77fff23006cde1818aef3155826acb7e8c55bcaa 100644 (file)
@@ -61,7 +61,7 @@ struct sainfoalg {
 };
 
 extern struct sainfo *getsainfo __P((const vchar_t *,
-       const vchar_t *, const vchar_t *));
+       const vchar_t *, const vchar_t *, int));
 extern struct sainfo *newsainfo __P((void));
 extern void delsainfo __P((struct sainfo *));
 extern void inssainfo __P((struct sainfo *));