]> git.saurik.com Git - apple/ipsec.git/commitdiff
ipsec-93.8.tar.gz mac-os-x-1064 v93.8
authorApple <opensource@apple.com>
Thu, 17 Jun 2010 16:16:37 +0000 (16:16 +0000)
committerApple <opensource@apple.com>
Thu, 17 Jun 2010 16:16:37 +0000 (16:16 +0000)
13 files changed:
ipsec-tools/racoon/handler.c
ipsec-tools/racoon/ike_session.c
ipsec-tools/racoon/ike_session.h
ipsec-tools/racoon/isakmp.c
ipsec-tools/racoon/isakmp_agg.c
ipsec-tools/racoon/isakmp_base.c
ipsec-tools/racoon/isakmp_ident.c
ipsec-tools/racoon/isakmp_inf.c
ipsec-tools/racoon/isakmp_quick.c
ipsec-tools/racoon/nattraversal.c
ipsec-tools/racoon/pfkey_racoon.c
ipsec-tools/racoon/proposal.c
ipsec-tools/racoon/proposal.h

index 9dc7f92da8216d3db08009d5e5d3e5a02d87dd19..3eb3a0b9b5a14eeec39f78a3872050c779d54af5 100644 (file)
@@ -780,7 +780,9 @@ flushph2(int ignore_established_handles)
 
        for (p = LIST_FIRST(&ph2tree); p; p = next) {
                next = LIST_NEXT(p, chain);
-               
+               if (p->is_dying || p->status == PHASE2ST_EXPIRED) {
+                       continue;
+               }
                if (p->status == PHASE2ST_ESTABLISHED){
                        if (ignore_established_handles) {
                                plog(LLV_DEBUG2, LOCATION, NULL,
@@ -820,6 +822,9 @@ deleteallph2(src, dst, proto_id)
 
        for (iph2 = LIST_FIRST(&ph2tree); iph2 != NULL; iph2 = next) {
                next = LIST_NEXT(iph2, chain);
+               if (iph2->is_dying || iph2->status == PHASE2ST_EXPIRED) {
+                       continue;
+               }
                if (iph2->proposal == NULL && iph2->approval == NULL)
                        continue;
                if (cmpsaddrwop(src, iph2->src) != 0 ||
@@ -1325,12 +1330,15 @@ purgephXbyspid(u_int32_t spid,
     // do ph2's first... we need the ph1s for notifications
        LIST_FOREACH(iph2, &ph2tree, chain) {
                if (spid == iph2->spid) {
+                       if (iph2->is_dying || iph2->status == PHASE2ST_EXPIRED) {
+                               continue;
+                       }
             if (iph2->status == PHASE2ST_ESTABLISHED) {
                 isakmp_info_send_d2(iph2);
             }
-            isakmp_ph2expire(iph2); // iph2 will go down 1 second later.
             ike_session_stopped_by_controller(iph2->parent_session,
                                               ike_session_stopped_by_flush);
+            isakmp_ph2expire(iph2); // iph2 will go down 1 second later.
         }
     }
 
@@ -1339,6 +1347,9 @@ purgephXbyspid(u_int32_t spid,
                if (spid == iph2->spid) {
             if (del_boundph1 && iph2->parent_session) {
                 for (iph1 = LIST_FIRST(&iph2->parent_session->ikev1_state.ph1tree); iph1; iph1 = LIST_NEXT(iph1, ph1ofsession_chain)) {
+                                       if (iph1->is_dying || iph1->status == PHASE1ST_EXPIRED) {
+                                               continue;
+                                       }
                     if (iph1->status == PHASE1ST_ESTABLISHED) {
                         isakmp_info_send_d1(iph1);
                     }
index ffc1516d50a03c223f20029b51e7e5f563591121..97e5be73f7c5e5cf1bc411f4ceba6aeab2ba3357 100644 (file)
@@ -904,7 +904,7 @@ ike_session_cleanup_other_established_ph1s (ike_session_t    *session,
                 * TODO: currently, most recently established SA wins. Need to revisit to see if 
                 * alternative selections is better (e.g. largest p->index stays).
                 */
-               if (p != new_iph1) {
+               if (p != new_iph1 && !p->is_dying) {
                        SCHED_KILL(p->sce);
                        SCHED_KILL(p->sce_rekey);
                        p->is_dying = 1;
@@ -943,6 +943,10 @@ ike_session_cleanup_ph2 (struct ph2handle *iph2)
 
     SCHED_KILL(iph2->sce);
 
+       plog(LLV_ERROR, LOCATION, NULL,
+                "about to cleanup ph2: status %d, seq %d dying %d\n",
+                iph2->status, iph2->seq, iph2->is_dying);
+       
        /* send delete information */
        if (iph2->status == PHASE2ST_ESTABLISHED) {
                isakmp_info_send_d2(iph2);
@@ -993,7 +997,7 @@ ike_session_cleanup_other_established_ph2s (ike_session_t    *session,
                 * TODO: currently, most recently established SA wins. Need to revisit to see if 
                 * alternative selections is better.
                 */
-               if (p != new_iph2 && p->spid == new_iph2->spid) {
+               if (p != new_iph2 && p->spid == new_iph2->spid && !p->is_dying) {
                        SCHED_KILL(p->sce);
                        p->is_dying = 1;
                        
@@ -1067,6 +1071,9 @@ ike_session_purge_ph2s_by_ph1 (struct ph1handle *iph1)
        for (p = LIST_FIRST(&iph1->parent_session->ikev1_state.ph2tree); p; p = next) {
                // take next pointer now, since delete change the underlying ph2tree list
                next = LIST_NEXT(p, ph2ofsession_chain);
+               if (p->is_dying) {
+                       continue;
+               }
         SCHED_KILL(p->sce);
         p->is_dying = 1;
                        
@@ -1401,6 +1408,47 @@ ike_session_is_id_ipany (vchar_t *ext_id)
        return 0;
 }
 
+static int
+ike_session_is_id_portany (vchar_t *ext_id)
+{
+       struct id {
+               u_int8_t type;          /* ID Type */
+               u_int8_t proto_id;      /* Protocol ID */
+               u_int16_t port;         /* Port */
+               u_int32_t addr;         /* IPv4 address */
+               u_int32_t mask;
+       } *id_ptr;
+       
+       /* ignore addr */
+       id_ptr = (struct id *)ext_id->v;
+       if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR &&
+           id_ptr->port == 0) {
+               return 1;
+       }
+       plog(LLV_DEBUG2, LOCATION, NULL, "not portany_ids in %s: type %d, port %x.\n",
+                __FUNCTION__, id_ptr->type, id_ptr->port);
+       return 0;
+}
+
+static void
+ike_session_set_id_portany (vchar_t *ext_id)
+{
+       struct id {
+               u_int8_t type;          /* ID Type */
+               u_int8_t proto_id;      /* Protocol ID */
+               u_int16_t port;         /* Port */
+               u_int32_t addr;         /* IPv4 address */
+               u_int32_t mask;
+       } *id_ptr;
+       
+       /* ignore addr */
+       id_ptr = (struct id *)ext_id->v;
+       if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR) {
+           id_ptr->port = 0;
+               return;
+       }
+}
+
 static int
 ike_session_cmp_ph2_ids_ipany (vchar_t *ext_id,
                                                           vchar_t *ext_id_p)
@@ -1412,10 +1460,19 @@ ike_session_cmp_ph2_ids_ipany (vchar_t *ext_id,
        return 0;
 }
 
-static int
+/*
+ * ipsec rekeys for l2tp-over-ipsec fail particularly when client is behind nat because the client's configs and policies don't 
+ * match the server's view of the client's address and port.
+ * servers behave differently when using this address-port info to generate ids during phase2 rekeys, so try to match the incoming id to 
+ * a variety of info saved in the older phase2.
+ */
+int
 ike_session_cmp_ph2_ids (struct ph2handle *iph2,
                                                 struct ph2handle *older_ph2)
 {
+       vchar_t *portany_id = NULL;
+       vchar_t *portany_id_p = NULL;
+
        if (iph2->id && older_ph2->id &&
            iph2->id->l == older_ph2->id->l &&
            memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 &&
@@ -1440,6 +1497,82 @@ ike_session_cmp_ph2_ids (struct ph2handle *iph2,
            memcmp(iph2->id_p->v, older_ph2->ext_nat_id_p->v, iph2->id_p->l) == 0) {
                return 0;
        }
+       if (iph2->id && older_ph2->ext_nat_id &&
+           iph2->id->l == older_ph2->ext_nat_id->l &&
+           memcmp(iph2->id->v, older_ph2->ext_nat_id->v, iph2->id->l) == 0 &&
+           iph2->id_p && older_ph2->id_p &&
+           iph2->id_p->l == older_ph2->id_p->l &&
+           memcmp(iph2->id_p->v, older_ph2->id_p->v, iph2->id_p->l) == 0) {
+               return 0;
+       }
+       if (iph2->id && older_ph2->id &&
+           iph2->id->l == older_ph2->id->l &&
+           memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 &&
+           iph2->id_p && older_ph2->ext_nat_id_p &&
+           iph2->id_p->l == older_ph2->ext_nat_id_p->l &&
+           memcmp(iph2->id_p->v, older_ph2->ext_nat_id_p->v, iph2->id_p->l) == 0) {
+               return 0;
+       }
+
+       /* check if the external id has a wildcard port and compare ids accordingly */
+       if ((older_ph2->ext_nat_id && ike_session_is_id_portany(older_ph2->ext_nat_id)) ||
+               (older_ph2->ext_nat_id_p && ike_session_is_id_portany(older_ph2->ext_nat_id_p))) {
+               // try ignoring ports in iph2->id and iph2->id
+               if (iph2->id && (portany_id = vdup(iph2->id))) {
+                       ike_session_set_id_portany(portany_id);
+               }
+               if (iph2->id_p && (portany_id_p = vdup(iph2->id_p))) {
+                       ike_session_set_id_portany(portany_id_p);
+               }
+               if (portany_id && older_ph2->ext_nat_id &&
+                       portany_id->l == older_ph2->ext_nat_id->l &&
+                       memcmp(portany_id->v, older_ph2->ext_nat_id->v, portany_id->l) == 0 &&
+                       portany_id_p && older_ph2->ext_nat_id_p &&
+                       portany_id_p->l == older_ph2->ext_nat_id_p->l &&
+                       memcmp(portany_id_p->v, older_ph2->ext_nat_id_p->v, portany_id_p->l) == 0) {
+                       if (portany_id) {
+                               vfree(portany_id);
+                       }
+                       if (portany_id_p) {
+                               vfree(portany_id_p);
+                       }
+                       return 0;
+               }
+               if (iph2->id && older_ph2->ext_nat_id &&
+                       iph2->id->l == older_ph2->ext_nat_id->l &&
+                       memcmp(portany_id->v, older_ph2->ext_nat_id->v, portany_id->l) == 0 &&
+                       iph2->id_p && older_ph2->id_p &&
+                       iph2->id_p->l == older_ph2->id_p->l &&
+                       memcmp(iph2->id_p->v, older_ph2->id_p->v, iph2->id_p->l) == 0) {
+                       if (portany_id) {
+                               vfree(portany_id);
+                       }
+                       if (portany_id_p) {
+                               vfree(portany_id_p);
+                       }
+                       return 0;
+               }
+               if (iph2->id && older_ph2->id &&
+                       iph2->id->l == older_ph2->id->l &&
+                       memcmp(iph2->id->v, older_ph2->id->v, iph2->id->l) == 0 &&
+                       iph2->id_p && older_ph2->ext_nat_id_p &&
+                       iph2->id_p->l == older_ph2->ext_nat_id_p->l &&
+                       memcmp(portany_id_p->v, older_ph2->ext_nat_id_p->v, portany_id_p->l) == 0) {
+                       if (portany_id) {
+                               vfree(portany_id);
+                       }
+                       if (portany_id_p) {
+                               vfree(portany_id_p);
+                       }
+                       return 0;
+               }
+               if (portany_id) {
+                       vfree(portany_id);
+               }
+               if (portany_id_p) {
+                       vfree(portany_id_p);
+               }
+       }
        return -1;
 }
 
@@ -1461,6 +1594,18 @@ ike_session_get_sainfo_r (struct ph2handle *iph2)
                                    ike_session_cmp_ph2_ids(iph2, p) == 0) {
                                        plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 matched in %s.\n", __FUNCTION__);
                                        iph2->sainfo = p->sainfo;
+                                       if (p->ext_nat_id) {
+                                               if (iph2->ext_nat_id) {
+                                                       vfree(iph2->ext_nat_id);
+                                               }
+                                               iph2->ext_nat_id = vdup(p->ext_nat_id);
+                                       }
+                                       if (p->ext_nat_id_p) {
+                                               if (iph2->ext_nat_id_p) {
+                                                       vfree(iph2->ext_nat_id_p);
+                                               }
+                                               iph2->ext_nat_id_p = vdup(p->ext_nat_id_p);
+                                       }
                                        return 0;
                                }
                        }
@@ -1469,6 +1614,53 @@ ike_session_get_sainfo_r (struct ph2handle *iph2)
        return -1;
 }
 
+int
+ike_session_get_proposal_r (struct ph2handle *iph2)
+{
+       if (iph2->parent_session &&
+           iph2->parent_session->is_client &&
+           iph2->id && iph2->id_p) {
+               struct ph2handle *p;
+               int ipany_ids = ike_session_cmp_ph2_ids_ipany(iph2->id, iph2->id_p);
+               plog(LLV_DEBUG2, LOCATION, NULL, "ipany_ids %d in %s.\n", ipany_ids, __FUNCTION__);
+
+               for (p = LIST_FIRST(&iph2->parent_session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) {
+                       if (iph2 != p && !p->is_dying && p->status >= PHASE2ST_ESTABLISHED &&
+                           p->approval) {
+                               plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 found in %s.\n", __FUNCTION__);
+                               if (ipany_ids ||
+                                   ike_session_cmp_ph2_ids(iph2, p) == 0) {
+                                       plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 matched in %s.\n", __FUNCTION__);
+                                       iph2->proposal = dupsaprop(p->approval, 1);
+                                       return 0;
+                               }
+                       }
+               }
+       }
+       return -1;
+}
+
+void
+ike_session_update_natt_version (struct ph1handle *iph1)
+{
+       if (iph1->parent_session) {
+               if (iph1->natt_options) {
+                       iph1->parent_session->natt_version = iph1->natt_options->version;
+               } else {
+                       iph1->parent_session->natt_version = 0;
+               }
+       }
+}
+
+int
+ike_session_get_natt_version (struct ph1handle *iph1)
+{
+       if (iph1->parent_session) {
+               return(iph1->parent_session->natt_version);
+       }
+       return 0;
+}
+
 int
 ike_session_drop_rekey (ike_session_t *session)
 {
index 4d4854c7d6ae335e1958ed74d64ea92e94212e8a..bc018d62f6699d71c2857c0cab9b113113d1c03e 100644 (file)
@@ -98,6 +98,7 @@ struct ike_session {
     int                                         is_client:1;
     time_t                               last_time_data_sc_detected;
     u_int32_t                            natt_flags;
+       u_int32_t                            natt_version;
        char                                *term_reason;
 
        struct timeval                                           start_timestamp;
@@ -153,6 +154,9 @@ extern int                ike_session_is_client_ph1_rekey __P((struct ph1handle
 extern void               ike_session_start_xauth_timer __P((struct ph1handle *));
 extern void               ike_session_stop_xauth_timer __P((struct ph1handle *));
 extern int                ike_session_get_sainfo_r __P((struct ph2handle *));
+extern int                ike_session_get_proposal_r __P((struct ph2handle *));
+extern void               ike_session_update_natt_version __P((struct ph1handle *));
+extern int                ike_session_get_natt_version __P((struct ph1handle *));
 extern int                ike_session_drop_rekey __P((ike_session_t *));
 extern void               ike_session_ph2_retransmits __P((struct ph2handle *));
 
index f499850197acc2aa69f4335d20b2a0d9de6182ce..050ca4216a127b169a9e06491de39006802bae2b 100644 (file)
@@ -2618,6 +2618,10 @@ isakmp_ph2expire(iph2)
 {
        char *src, *dst;
 
+       if (iph2->status == PHASE2ST_EXPIRED) {
+               return;
+       }
+
        SCHED_KILL(iph2->sce);
 
        src = racoon_strdup(saddrwop2str(iph2->src));
index 7dddea3de5e4d679781b032ef3c3c849fdbd65c4..d2c59b729f21dbfefad4b62d8c5f1bbf235cfa01 100644 (file)
@@ -631,6 +631,7 @@ agg_i2recv(iph1, msg)
 
                if (iph1->natt_flags & NAT_DETECTED)
                        natt_float_ports (iph1);
+               ike_session_update_natt_version(iph1);
        }
 #endif
 
@@ -1106,10 +1107,12 @@ agg_r1recv(iph1, msg)
        }
 
 #ifdef ENABLE_NATT
-       if (NATT_AVAILABLE(iph1))
+       if (NATT_AVAILABLE(iph1)) {
                plog(LLV_INFO, LOCATION, iph1->remote,
                     "Selected NAT-T version: %s\n",
                     vid_string_by_id(iph1->natt_options->version));
+               ike_session_update_natt_version(iph1);
+       }
 #endif
 
        /* check SA payload and set approval SA for use */
index 3ac9e7c7f32878d9ba075dec900cc8e47f010360..5a26c509b0c7af567d0aa7efd378f56447107a1d 100644 (file)
@@ -397,10 +397,12 @@ base_i2recv(iph1, msg)
        }
 
 #ifdef ENABLE_NATT
-       if (NATT_AVAILABLE(iph1))
+       if (NATT_AVAILABLE(iph1)) {
                plog(LLV_INFO, LOCATION, iph1->remote,
                     "Selected NAT-T version: %s\n",
                     vid_string_by_id(iph1->natt_options->version));
+               ike_session_update_natt_version(iph1);
+       }
 #endif
 
        /* check SA payload and set approval SA for use */
@@ -938,10 +940,12 @@ base_r1recv(iph1, msg)
        }
 
 #ifdef ENABLE_NATT
-       if (NATT_AVAILABLE(iph1))
+       if (NATT_AVAILABLE(iph1)) {
                plog(LLV_INFO, LOCATION, iph1->remote,
                     "Selected NAT-T version: %s\n",
                     vid_string_by_id(iph1->natt_options->version));
+               ike_session_update_natt_version(iph1);
+       }
 #endif
 
        /* check SA payload and set approval SA for use */
index 6488207f5b613f48d844371af74c430626584a01..ff155e617e53b7415decc79cc6ffbaff6a234981 100644 (file)
@@ -364,10 +364,12 @@ ident_i2recv(iph1, msg)
        }
 
 #ifdef ENABLE_NATT
-       if (NATT_AVAILABLE(iph1))
+       if (NATT_AVAILABLE(iph1)) {
                plog(LLV_INFO, LOCATION, iph1->remote,
                     "Selected NAT-T version: %s\n",
                     vid_string_by_id(iph1->natt_options->version));
+               ike_session_update_natt_version(iph1);
+       }
 #endif
 
        /* check SA payload and set approval SA for use */
@@ -1190,10 +1192,12 @@ ident_r1recv(iph1, msg)
        }
 
 #ifdef ENABLE_NATT
-       if (NATT_AVAILABLE(iph1))
+       if (NATT_AVAILABLE(iph1)) {
                plog(LLV_INFO, LOCATION, iph1->remote,
                     "Selected NAT-T version: %s\n",
                     vid_string_by_id(iph1->natt_options->version));
+               ike_session_update_natt_version(iph1);
+       }
 #endif
 
        /* check SA payload and set approval SA for use */
index 44fa30f951ae04f2222fb2d64c9c9aeb29a40cbc..003e3ce9e848913feb5b19753af0c2095af39744 100644 (file)
@@ -1447,7 +1447,7 @@ purge_isakmp_spi(proto, spi, n)
 
        for (i = 0; i < n; i++) {
                iph1 = getph1byindex(&spi[i]);
-               if (!iph1)
+               if (!iph1 || iph1->is_dying || iph1->status == PHASE1ST_EXPIRED)
                        continue;
 
                plog(LLV_INFO, LOCATION, NULL,
index 44f8fed04c0059ea180b394599724c34556045fa..2b73f65f41b4721690240ccc2f5399fc3ebacd35 100644 (file)
@@ -97,7 +97,8 @@
 /* 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 *, int));
+static int get_proposal_r __P((struct ph2handle *));
+static int get_proposal_r_remote __P((struct ph2handle *, int));
 
 /* \f%%%
  * Quick Mode
@@ -568,6 +569,7 @@ quick_i2recv(iph2, msg0)
                                                                goto end;
                                                        }
                                                        plog(LLV_DEBUG, LOCATION, NULL, "external nat address saved.\n");
+                                                       plogdump(LLV_DEBUG, iph2->ext_nat_id->v, iph2->ext_nat_id->l);
                                                } else if (f_id && (iph2->ph1->natt_flags & NAT_DETECTED_PEER)) {
                                                        if (iph2->ext_nat_id_p)
                                                                vfree(iph2->ext_nat_id_p);
@@ -578,6 +580,7 @@ quick_i2recv(iph2, msg0)
                                                        }
                                                        memcpy(iph2->ext_nat_id_p->v, &(idp_ptr->b), iph2->ext_nat_id_p->l);
                                                        plog(LLV_DEBUG, LOCATION, NULL, "peer's external nat address saved.\n");
+                                                       plogdump(LLV_DEBUG, iph2->ext_nat_id_p->v, iph2->ext_nat_id_p->l);
                                                } 
                                        } else {
                                                plog(LLV_ERROR, LOCATION, NULL, "mismatched ID was returned.\n");
@@ -1369,12 +1372,7 @@ quick_r1recv(iph2, msg0)
        }
 
     /* check the existence of ID payload and create responder's proposal */
-    error = get_proposal_r(iph2, 0);
-    if (error != -2 && error != 0 && 
-               (((iph2->ph1->natt_flags & NAT_DETECTED_ME) && lcconf->ext_nat_id != NULL) ||
-                (iph2->parent_session && iph2->parent_session->is_client)))
-        error = get_proposal_r(iph2, 1);
-               
+       error = get_proposal_r(iph2);
        switch (error) {
        case -2:
                /* generate a policy template from peer's proposal */
@@ -1602,6 +1600,8 @@ quick_r2send(iph2, msg)
        }
 #endif
 
+       plog(LLV_DEBUG, LOCATION, NULL, "Approved SA\n");
+       printsaprop0(LLV_DEBUG, iph2->approval);
 
        body = vmalloc(tlen);
        if (body == NULL) { 
@@ -1634,9 +1634,13 @@ quick_r2send(iph2, msg)
        if (iph2->id_p != NULL) {
                /* IDci */
                p = set_isakmp_payload(p, iph2->id_p, ISAKMP_NPTYPE_ID);
+               plog(LLV_DEBUG, LOCATION, NULL, "sending IDci2:\n");
+               plogdump(LLV_DEBUG, iph2->id_p->v, iph2->id_p->l);
                /* IDcr */
                np_p = &((struct isakmp_gen *)p)->np;   /* XXX */
                p = set_isakmp_payload(p, iph2->id, (natoa_type ? natoa_type : ISAKMP_NPTYPE_NONE));
+               plog(LLV_DEBUG, LOCATION, NULL, "sending IDcr2:\n");
+               plogdump(LLV_DEBUG, iph2->id->v, iph2->id->l);
        }
 
        /* add a RESPONDER-LIFETIME notify payload if needed */
@@ -2369,6 +2373,22 @@ end:
        return error;
 }
 
+static int
+get_proposal_r(iph2)
+       struct ph2handle *iph2;
+{
+       int error = get_proposal_r_remote(iph2, 0);
+       if (error != -2 && error != 0 && 
+               (((iph2->ph1->natt_flags & NAT_DETECTED_ME) && lcconf->ext_nat_id != NULL) ||
+                (iph2->parent_session && iph2->parent_session->is_client))) {
+               if (iph2->parent_session && iph2->parent_session->is_client)
+                       error = ike_session_get_proposal_r(iph2);
+               if (error != -2 && error != 0)
+                       error = get_proposal_r_remote(iph2, 1);                                 
+       }
+       return error;
+}
+
 /*
  * Copy both IP addresses in ID payloads into [src,dst]_id if both ID types
  * are IP address and same address family.
@@ -2380,7 +2400,7 @@ end:
  * NOTE: This function is only for responder.
  */
 static int
-get_proposal_r(iph2, use_remote_addr)
+get_proposal_r_remote(iph2, use_remote_addr)
        struct ph2handle *iph2;
        int use_remote_addr;
 {
index 3a57fdb716dca3a0340246ed8db89d5b290c18e1..4dfd089fc93f006cc38fab103a0c7652ad0aed57 100644 (file)
@@ -496,6 +496,8 @@ natt_float_ports (struct ph1handle *iph1)
 void
 natt_handle_vendorid (struct ph1handle *iph1, int vid_numeric)
 {
+  int version;
+
   if (! iph1->natt_options)
     iph1->natt_options = racoon_calloc (1, sizeof (*iph1->natt_options));
 
@@ -504,7 +506,13 @@ natt_handle_vendorid (struct ph1handle *iph1, int vid_numeric)
          "Allocating memory for natt_options failed!\n");
     return;
   }
-  
+
+  // stick to the version we already selected on a previous phase1
+  version = ike_session_get_natt_version(iph1);
+  if (version) {
+    vid_numeric = version;
+  }
+
   if (iph1->natt_options->version < vid_numeric)
     if (natt_fill_options (iph1->natt_options, vid_numeric) == 0)
       iph1->natt_flags |= NAT_ANNOUNCED;
index 4ff5db301eb76796a336843028cbc0f32d502fb6..ef64f6078fc96db1bf10cb75d36a1296dd7fa326 100644 (file)
@@ -998,6 +998,13 @@ pk_recvgetspi(mhp)
                return -1;
        }
 
+       if (iph2->is_dying) {
+               plog(LLV_ERROR, LOCATION, NULL,
+                        "status mismatch phase2 dying (db:%d msg:%d)\n",
+                        iph2->status, PHASE2ST_GETSPISENT);
+               return -1;
+       }
+
        if (iph2->status != PHASE2ST_GETSPISENT) {
                plog(LLV_ERROR, LOCATION, NULL,
                        "status mismatch (db:%d msg:%d)\n",
@@ -1340,6 +1347,13 @@ pk_recvupdate(mhp)
                return -1;
        }
 
+       if (iph2->is_dying) {
+               plog(LLV_ERROR, LOCATION, NULL,
+                        "status mismatch phase2 dying (db:%d msg:%d)\n",
+                        iph2->status, PHASE2ST_ADDSA);
+               return -1;
+       }
+
        if (iph2->status != PHASE2ST_ADDSA) {
                plog(LLV_ERROR, LOCATION, NULL,
                        "status mismatch (db:%d msg:%d)\n",
@@ -1809,7 +1823,7 @@ pk_recvexpire(mhp)
                            sa_mode));
                return 0;
        }
-       if (iph2->status != PHASE2ST_ESTABLISHED) {
+       if (iph2->is_dying || iph2->status != PHASE2ST_ESTABLISHED) {
                /*
                 * If the status is not equal to PHASE2ST_ESTABLISHED,
                 * racoon ignores this expire message.  There are two reason.
@@ -1820,7 +1834,7 @@ pk_recvexpire(mhp)
                 */
                plog(LLV_WARNING, LOCATION, NULL,
                        "the expire message is received "
-                       "but the handler has not been established.\n");
+                       "but the handler is dying or has not been established.\n");
                return 0;
        }
 
index 7ade8874dadb8c6a1d3f08dd0f3f1e9298425406..7a299e00eea7b18dc11f4bc3eacab02cb1e4bbf8 100644 (file)
@@ -180,6 +180,50 @@ inssatrns(pr, new)
        return;
 }
 
+#ifdef ENABLE_NATT
+static void
+saprop_udp_encap (struct saproto *pr)
+{
+       switch (pr->encmode) {
+               case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
+               case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
+                       pr->encmode = IPSECDOI_ATTR_ENC_MODE_TUNNEL;
+                       pr->udp_encap = 1;
+                       break;
+               case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
+               case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
+                       pr->encmode = IPSECDOI_ATTR_ENC_MODE_TRNS;
+                       pr->udp_encap = 1;
+                       break;
+       }
+}
+
+static void
+saprop_adjust_encmode (struct saproto *pr2, struct saproto *pr1)
+{
+       int prev;
+
+       if (natt_udp_encap(pr2->encmode)) {
+               prev = pr2->encmode;
+               saprop_udp_encap(pr2);
+               plog(LLV_INFO, LOCATION, NULL, "Adjusting my encmode %s(%d)->%s(%d)\n",
+                        s_ipsecdoi_encmode(prev),
+                        prev,
+                        s_ipsecdoi_encmode(pr2->encmode),
+                        pr2->encmode);
+       }
+       if (natt_udp_encap(pr1->encmode)) {
+               prev = pr1->encmode;
+               saprop_udp_encap(pr1);
+               plog(LLV_INFO, LOCATION, NULL, "Adjusting peer's encmode %s(%d)->%s(%d)\n",
+                        s_ipsecdoi_encmode(prev),
+                        prev,
+                        s_ipsecdoi_encmode(pr1->encmode),
+                        pr1->encmode);
+       }       
+}
+#endif // ENABLE_NATT
+
 /*
  * take a single match between saprop.  allocate a new proposal and return it
  * for future use (like picking single proposal from a bundle).
@@ -388,27 +432,9 @@ cmpsaprop_alloc(ph1, pp1, pp2, side)
                        goto err;
                }
 
-#ifdef ENABLE_NATT
-               if ((ph1->natt_flags & NAT_DETECTED) && 
-                   natt_udp_encap (pr2->encmode))
-               {
-                       plog(LLV_INFO, LOCATION, NULL, "Adjusting my encmode %s->%s\n",
-                            s_ipsecdoi_encmode(pr2->encmode),
-                            s_ipsecdoi_encmode(pr2->encmode - ph1->natt_options->mode_udp_diff));
-                       pr2->encmode -= ph1->natt_options->mode_udp_diff;
-                       pr2->udp_encap = 1;
-               }
-
-               if ((ph1->natt_flags & NAT_DETECTED) &&
-                   natt_udp_encap (pr1->encmode))
-               {
-                       plog(LLV_INFO, LOCATION, NULL, "Adjusting peer's encmode %s(%d)->%s(%d)\n",
-                            s_ipsecdoi_encmode(pr1->encmode),
-                            pr1->encmode,
-                            s_ipsecdoi_encmode(pr1->encmode - ph1->natt_options->mode_udp_diff),
-                            pr1->encmode - ph1->natt_options->mode_udp_diff);
-                       pr1->encmode -= ph1->natt_options->mode_udp_diff;
-                       pr1->udp_encap = 1;
+#ifdef ENABLE_NATT             
+               if (ph1->natt_flags & NAT_DETECTED) {
+                       saprop_adjust_encmode(pr2, pr1);
                }
 #endif
 
@@ -1208,3 +1234,84 @@ tunnel_mode_prop(p)
                        return 1;
        return 0;
 }
+
+void
+dupsatrns(newpr, head)
+       struct saproto *newpr;
+       struct satrns *head;
+{
+       struct satrns *p, *newtr;
+
+       for (p = head; p != NULL; p = p->next) {
+               newtr = newsatrns();
+               if (newtr) {
+                       newtr->trns_no = p->trns_no;
+                       newtr->trns_id = p->trns_id;
+                       newtr->encklen = p->encklen;
+                       newtr->authtype = p->authtype;
+                       inssatrns(newpr, newtr);
+               } else {
+                       break;
+               }
+
+       }
+
+       return;
+}
+       
+void
+dupsaproto(newpp, head, ignore_spis)
+       struct saprop  *newpp;
+       struct saproto *head;
+       int ignore_spis;
+{
+       struct saproto *p, *newpr;
+
+       for (p = head; p != NULL; p = p->next) {
+               newpr = newsaproto();
+               if (newpr) {
+                       newpr->proto_id = p->proto_id;
+                       newpr->spisize = p->spisize;
+                       newpr->encmode = p->encmode;
+                       newpr->udp_encap = p->udp_encap;
+                       if (!ignore_spis) {
+                               newpr->spi = p->spi;
+                               newpr->spi_p = p->spi_p;
+                               newpr->reqid_in = p->reqid_in;
+                               newpr->reqid_out = p->reqid_out;
+                       }
+                       dupsatrns(newpr, p->head);
+                       inssaproto(newpp, newpr);
+               } else {
+                       break;
+               }
+
+       }
+
+       return;
+}
+
+struct saprop *
+dupsaprop(head, ignore_spis)
+       struct saprop *head;
+       int ignore_spis;
+{
+       struct saprop *p, *newpp;
+
+       for (p = head, newpp = NULL; p != NULL; p = p->next) {
+               struct saprop *tmp = newsaprop();
+               if (tmp) {
+                       tmp->prop_no = p->prop_no;
+                       tmp->lifetime = p->lifetime;
+                       tmp->lifebyte = p->lifebyte;
+                       tmp->pfs_group = p->pfs_group;
+                       tmp->claim = p->claim;
+                       dupsaproto(tmp, p->head, ignore_spis);
+                       inssaprop(&newpp, tmp);
+               } else {
+                       break;
+               }
+       }
+
+       return newpp;
+}
index 72df73ae851048b6a28ff01d7cd712936871c4d9..a9cc8da110f23060ce5261b842062edac3aedfb0 100644 (file)
@@ -207,5 +207,6 @@ extern int set_proposal_from_policy __P((struct ph2handle *,
        struct secpolicy *, struct secpolicy *));
 extern int set_proposal_from_proposal __P((struct ph2handle *));
 extern int tunnel_mode_prop __P((struct saprop *));
+extern struct saprop *dupsaprop __P((struct saprop *, int));
 
 #endif /* _PROPOSAL_H */