]> git.saurik.com Git - apple/ipsec.git/commitdiff
ipsec-92.4.tar.gz mac-os-x-1062 v92.4
authorApple <opensource@apple.com>
Thu, 12 Nov 2009 17:57:22 +0000 (17:57 +0000)
committerApple <opensource@apple.com>
Thu, 12 Nov 2009 17:57:22 +0000 (17:57 +0000)
19 files changed:
ipsec-tools/Common/pfkey.c
ipsec-tools/racoon/admin.c
ipsec-tools/racoon/crypto_openssl.c
ipsec-tools/racoon/handler.c
ipsec-tools/racoon/handler.h
ipsec-tools/racoon/ike_session.c
ipsec-tools/racoon/ike_session.h
ipsec-tools/racoon/ipsec_doi.c
ipsec-tools/racoon/isakmp.c
ipsec-tools/racoon/isakmp_cfg.c
ipsec-tools/racoon/isakmp_frag.c
ipsec-tools/racoon/isakmp_inf.c
ipsec-tools/racoon/isakmp_quick.c
ipsec-tools/racoon/isakmp_xauth.c
ipsec-tools/racoon/main.c
ipsec-tools/racoon/nattraversal.c
ipsec-tools/racoon/oakley.c
ipsec-tools/racoon/remoteconf.c
ipsec-tools/setkey/setkey.c

index f4bcb4f493d81adc84cf24f88ffa2409ed4391a4..026ccd835efa85035232e1f5dd0f80ae9612f836 100644 (file)
@@ -1771,7 +1771,11 @@ pfkey_send_x2(so, type, satype, mode, src, dst, spi)
 
        /* create new sadb_msg to reply. */
        len = sizeof(struct sadb_msg)
+#ifdef __APPLE__
+               + sizeof(struct sadb_sa_2)
+#else
                + sizeof(struct sadb_sa)
+#endif
                + sizeof(struct sadb_address)
                + PFKEY_ALIGN8(sysdep_sa_len(src))
                + sizeof(struct sadb_address)
index ea11b4e462a7117cbe1b0a75637ea5bf78f0a230..d8e16b984967bca6e438c1788ce5ae54a2f48fcc 100644 (file)
@@ -316,16 +316,18 @@ out2:
 #ifdef ENABLE_HYBRID
        case ADMIN_LOGOUT_USER: {
                struct ph1handle *iph1;
-               char *user;
-               int found = 0;
+               char user[LOGINLEN+1];
+               int found = 0, len = com->ac_len - sizeof(com);
 
-               if (com->ac_len > sizeof(com) + LOGINLEN + 1) {
+               if (len > LOGINLEN) {
                        plog(LLV_ERROR, LOCATION, NULL,
                            "malformed message (login too long)\n");
                        break;
                }
 
-               user = (char *)(com + 1);
+               memcpy(user, (char *)(com + 1), len);
+               user[len] = 0;
+
                found = purgeph1bylogin(user);
                plog(LLV_INFO, LOCATION, NULL, 
                    "deleted %d SA for user \"%s\"\n", found, user);
index ae184d7976aacd029a27a2ac843d2f06049767cf..c32f636f34a1feac2cad6bd728936e2346878ffc 100644 (file)
@@ -497,7 +497,7 @@ eay_check_x509cert(cert, CApath, CAfile, local)
        X509_STORE_CTX_set_flags (csc, X509_V_FLAG_CRL_CHECK_ALL);
 #endif
        error = X509_verify_cert(csc);
-       X509_STORE_CTX_cleanup(csc);
+       X509_STORE_CTX_free(csc);
 
        /*
         * if x509_verify_cert() is successful then the value of error is
index a070970d3d8e7c3a5450340bcdcc539cce5bf382..9dc7f92da8216d3db08009d5e5d3e5a02d87dd19 100644 (file)
@@ -732,6 +732,14 @@ delph2(iph2)
                unlink_sainfo_from_ph2(iph2->sainfo);
                iph2->sainfo = NULL;
        }
+       if (iph2->ext_nat_id) {
+               vfree(iph2->ext_nat_id);
+               iph2->ext_nat_id = NULL;
+       }
+       if (iph2->ext_nat_id_p) {
+               vfree(iph2->ext_nat_id_p);
+               iph2->ext_nat_id_p = NULL;
+       }
 #endif
 
        racoon_free(iph2);
@@ -1195,7 +1203,7 @@ sweep_recvdpkt(dummy)
                }
        }
 
-       sched_new(lt, sweep_recvdpkt, NULL);
+       sched_new(lt, sweep_recvdpkt, &rcptree);
 }
 
 void
@@ -1208,6 +1216,7 @@ clear_recvdpkt()
                rem_recvdpkt(r);
                del_recvdpkt(r);
        }
+       sched_scrub_param(&rcptree);
 }
 
 void
@@ -1217,7 +1226,7 @@ init_recvdpkt()
 
        LIST_INIT(&rcptree);
 
-       sched_new(lt, sweep_recvdpkt, NULL);
+       sched_new(lt, sweep_recvdpkt, &rcptree);
 }
 
 #ifdef ENABLE_HYBRID
index 9dcfdbd341c4b818772e74dd778ea31071f24db6..9523316a52afa69b5abf79a9104160786ee85dc3 100644 (file)
@@ -339,6 +339,8 @@ struct ph2handle {
        int                    is_dying:1;
        ike_session_t         *parent_session;
        LIST_ENTRY(ph2handle)  ph2ofsession_chain;
+       vchar_t               *ext_nat_id;
+       vchar_t               *ext_nat_id_p;
 #endif
        
        LIST_ENTRY(ph2handle) chain;
index 4f688bfb8de8975f1acd96a6f912cfe2c5c59776..3bb62d7cc449df4537629d6cf7e152720fc92530 100644 (file)
 #include "localconf.h"
 #include "remoteconf.h"
 #include "vpn_control.h"
+#include "proposal.h"
+#include "sainfo.h"
 
 const char *ike_session_stopped_by_vpn_disconnect = "Stopped by VPN disconnect";
 const char *ike_session_stopped_by_flush          = "Stopped by Flush";
 const char *ike_session_stopped_by_idle           = "Stopped by Idle";
 const char *ike_session_stopped_by_xauth_timeout  = "Stopped by XAUTH timeout";
 
-static LIST_HEAD(_ike_session_tree_, ike_session) ike_session_tree;
+static LIST_HEAD(_ike_session_tree_, ike_session) ike_session_tree = { NULL };
 
 static ike_session_t *
 new_ike_session (ike_session_id_t *id)
@@ -88,7 +90,7 @@ free_ike_session (ike_session_t *session)
         SCHED_KILL(session->traffic_monitor.sc_idle);
         SCHED_KILL(session->sc_xauth);
                if (session->start_timestamp.tv_sec || session->start_timestamp.tv_usec) {
-                       if (!(session->stop_timestamp.tv_sec || session->start_timestamp.tv_usec)) {
+                       if (!(session->stop_timestamp.tv_sec || session->stop_timestamp.tv_usec)) {
                                gettimeofday(&session->stop_timestamp, NULL);
                        }
             if (session->term_reason != ike_session_stopped_by_vpn_disconnect ||
@@ -314,17 +316,17 @@ ike_session_init_traffic_cop_params (struct ph1handle *iph1)
             min_period = MIN(iph1->rmconf->dpd_interval, iph1->rmconf->idle_timeout);
             max_period = MAX(iph1->rmconf->dpd_interval, iph1->rmconf->idle_timeout);
         } else if (iph1->rmconf->idle_timeout) {
-            min_period = max_period = MIN(0, iph1->rmconf->idle_timeout);
+            min_period = max_period = iph1->rmconf->idle_timeout;
         } else {
             // DPD_ALGO_DEFAULT is configured and there's no idle timeout... we don't need to monitor traffic
             return;
         }
         if (min_period) {
-            sample_period = min_period >> 1;
+            sample_period = min_period / 20;
             if (!sample_period)
                 sample_period = 1; // bad
         } else {
-            sample_period = max_period >> 1;
+            sample_period = max_period / 20;
             if (!sample_period)
                 sample_period = 1; // bad
         }
@@ -791,15 +793,24 @@ ike_session_traffic_cop (void *arg)
 static void
 ike_session_cleanup_idle (void *arg)
 {
-    ike_session_t *session = (ike_session_t *)arg;
+    ike_session_cleanup((ike_session_t *)arg, ike_session_stopped_by_idle);
+}
+
+static void
+ike_session_monitor_idle (ike_session_t *session)
+{
+       if (!session)
+               return;
 
     if (session->traffic_monitor.dir_idle == IPSEC_DIR_INBOUND ||
         session->traffic_monitor.dir_idle == IPSEC_DIR_ANY) {
         if (session->peer_sent_data_sc_idle) {
             SCHED_KILL(session->traffic_monitor.sc_idle);
-            session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle,
-                                                         ike_session_cleanup_idle,
-                                                         session);
+                       if (session->traffic_monitor.interv_idle) {
+                               session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle,
+                                                                                                                        ike_session_cleanup_idle,
+                                                                                                                        session);
+                       }
             session->peer_sent_data_sc_idle = 0;
             session->i_sent_data_sc_idle = 0;
             return;
@@ -809,16 +820,16 @@ ike_session_cleanup_idle (void *arg)
         session->traffic_monitor.dir_idle == IPSEC_DIR_ANY) {
         if (session->i_sent_data_sc_idle) {
             SCHED_KILL(session->traffic_monitor.sc_idle);
-            session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle,
-                                                         ike_session_cleanup_idle,
-                                                         session);
+                       if (session->traffic_monitor.interv_idle) {
+                               session->traffic_monitor.sc_idle = sched_new(session->traffic_monitor.interv_idle,
+                                                                                                                        ike_session_cleanup_idle,
+                                                                                                                        session);
+                       }
             session->peer_sent_data_sc_idle = 0;
             session->i_sent_data_sc_idle = 0;
             return;
         }
     }
-
-    ike_session_cleanup((ike_session_t *)arg, ike_session_stopped_by_idle);
 }
 
 void
@@ -1140,6 +1151,11 @@ ike_session_update_traffic_idle_status (ike_session_t *session,
         return;
     }
 
+    if (!session->established || session->stopped_by_vpn_controller || session->stop_timestamp.tv_sec || session->stop_timestamp.tv_usec) {
+        plog(LLV_DEBUG2, LOCATION, NULL, "dropping update on invalid session.\n", __FUNCTION__);
+        return;
+    }
+
     for (i = 0; i < max_stats; i++) {
         if (dir == IPSEC_DIR_INBOUND) {
             for (j = 0; j < session->traffic_monitor.num_in_last_poll; j++) {
@@ -1191,6 +1207,8 @@ ike_session_update_traffic_idle_status (ike_session_t *session,
             session->i_sent_data_sc_idle = 1;
         }
     }
+
+       ike_session_monitor_idle(session);
 }
 
 void
@@ -1203,6 +1221,7 @@ ike_session_cleanup (ike_session_t *session,
     if (!session)
         return;
 
+       SCHED_KILL(session->traffic_monitor.sc_idle);
     // do ph2's first... we need the ph1s for notifications
     for (iph2 = LIST_FIRST(&session->ikev1_state.ph2tree); iph2; iph2 = LIST_NEXT(iph2, ph2ofsession_chain)) {
         if (iph2->status == PHASE2ST_ESTABLISHED) {
@@ -1352,4 +1371,98 @@ ike_session_stop_xauth_timer (struct ph1handle *iph1)
     if (iph1->parent_session) {
         SCHED_KILL(iph1->parent_session->sc_xauth);
     }
+}
+
+static int
+ike_session_is_id_ipany (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 protocol and port */
+       id_ptr = (struct id *)ext_id->v;
+       if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR &&
+           id_ptr->addr == 0) {
+               return 1;
+       } else if (id_ptr->type == IPSECDOI_ID_IPV4_ADDR_SUBNET &&
+                          id_ptr->mask == 0 &&
+                          id_ptr->addr == 0) {
+               return 1;
+       }
+       plog(LLV_DEBUG2, LOCATION, NULL, "not ipany_ids in %s: type %d, addr %x, mask %x.\n",
+                __FUNCTION__, id_ptr->type, id_ptr->addr, id_ptr->mask);
+       return 0;
+}
+
+static int
+ike_session_cmp_ph2_ids_ipany (vchar_t *ext_id,
+                                                          vchar_t *ext_id_p)
+{
+       if (ike_session_is_id_ipany(ext_id) &&
+           ike_session_is_id_ipany(ext_id_p)) {
+               return 1;
+       }
+       return 0;
+}
+
+static int
+ike_session_cmp_ph2_ids (struct ph2handle *iph2,
+                                                struct ph2handle *older_ph2)
+{
+       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->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->ext_nat_id && older_ph2->ext_nat_id &&
+           iph2->ext_nat_id->l == older_ph2->ext_nat_id->l &&
+           memcmp(iph2->ext_nat_id->v, older_ph2->ext_nat_id->v, iph2->ext_nat_id->l) == 0 &&
+           iph2->ext_nat_id_p && older_ph2->ext_nat_id_p &&
+           iph2->ext_nat_id_p->l == older_ph2->ext_nat_id_p->l &&
+           memcmp(iph2->ext_nat_id_p->v, older_ph2->ext_nat_id_p->v, iph2->ext_nat_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->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;
+       }
+       return -1;
+}
+
+int
+ike_session_get_sainfo_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->sainfo && !p->sainfo->to_delete && !p->sainfo->to_remove) {
+                               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->sainfo = p->sainfo;
+                                       return 0;
+                               }
+                       }
+               }
+       }
+       return -1;
 }
\ No newline at end of file
index ba91e0fe4140a147a24792522205d154d1e32193..e840c37106a8ccf409843df959e35199a4aab7c5 100644 (file)
@@ -151,5 +151,6 @@ extern int                ike_session_is_client_ph2_rekey __P((struct ph2handle
 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 *));
 
 #endif /* _IKE_SESSION_H */
index 713ec4cf854d490f41fccb62ba20d1efc046e78b..56cb6b7d4d29ce6790c4ab87915f536dde69d57d 100644 (file)
@@ -4463,6 +4463,10 @@ ipsecdoi_id2str(id)
                ((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY;
                memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
                        id->v + sizeof(*id_b), sizeof(struct in6_addr));
+               ((struct sockaddr_in6 *)&saddr)->sin6_scope_id =
+                       (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)&saddr)->sin6_addr) 
+                        ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id 
+                        : 0);
                break;
 #endif
        }
@@ -4564,6 +4568,10 @@ ipsecdoi_id2str(id)
                memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
                        id->v + sizeof(*id_b) + sizeof(struct in6_addr),
                        sizeof(struct in6_addr));
+               ((struct sockaddr_in6 *)&saddr)->sin6_scope_id = 
+                       (IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)&saddr)->sin6_addr) 
+                        ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id 
+                        : 0);
 
                if (len >= 0) {
                    len += snprintf( buf + len, sizeof(buf) - len, "%s", saddrwop2str((struct sockaddr *)&saddr));
index 7d8e24ea4be92e1895060f099527bc776dfdd3da..7bcf121a70a9b28fb5559e25b27aba34ad5a2c03 100644 (file)
@@ -770,6 +770,18 @@ isakmp_main(msg, remote, local)
                if (ISSET(isakmp->flags, ISAKMP_FLAG_C))
                        iph2->flags |= ISAKMP_FLAG_C;
 
+               if (ISSET(isakmp->flags, ISAKMP_FLAG_E) &&
+                       (iph2->ph1 == NULL || iph2->ph1->approval == NULL)) {
+                       IPSECSESSIONTRACEREVENT(iph2->parent_session,
+                                                                       IPSECSESSIONEVENTCODE_IKEV1_PH2_INIT_DROP,
+                                                                       CONSTSTR("can't continue phase2 without valid phase1"),
+                                                                       CONSTSTR("Failed to continue phase2 resonder (invalid linked phase1"));
+                       plog(LLV_ERROR, LOCATION, remote,
+                                "can't start the quick mode, "
+                                "invalid linked ISAKMP-SA\n");
+                       return -1;                      
+               }
+
                /* call main process of quick mode */
                if (quick_main(iph2, msg) < 0) {
                        plog(LLV_ERROR, LOCATION, iph1->remote,
@@ -1210,7 +1222,7 @@ isakmp_ph1begin_i(rmconf, remote, local, started_by_api)
        /* XXX copy remote address */
        if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
                /* don't call remph1(iph1) until after insph1(iph1) is called */
-               delph1(iph1);
+               iph1 = NULL; /* deleted in copy_ph1addresses */
                return -1;
        }
 
@@ -1358,7 +1370,7 @@ isakmp_ph1begin_r(msg, remote, local, etype)
        /* copy remote address */
        if (copy_ph1addresses(iph1, rmconf, remote, local) < 0) {
                /* don't call remph1(iph1) until after insph1(iph1) is called */
-               delph1(iph1);
+               iph1 = NULL; /* deleted in copy_ph1addresses */
                return -1;
        }
        (void)insph1(iph1);
@@ -1763,7 +1775,6 @@ isakmp_init()
        initph2tree();
        initctdtree();
        init_recvdpkt();
-       ike_session_init();
 
        if (isakmp_open() < 0)
                goto err;
@@ -1978,6 +1989,7 @@ isakmp_open()
                                "failed to bind to address %s (%s).\n",
                                saddr2str(p->addr), strerror(errno));
                        close(p->sock);
+                       p->sock = -1;
                        goto err_and_next;
                }
                
@@ -3437,6 +3449,7 @@ copy_ph1addresses(iph1, rmconf, remote, local)
        default:
                plog(LLV_ERROR, LOCATION, NULL,
                        "invalid family: %d\n", iph1->remote->sa_family);
+               delph1(iph1);
                return -1;
        }
 
index c72600ac82abd29453a0c91a41fb3e06a5454c37..9672fd1bf02b34a1addd22e51ec31c973ff23972 100644 (file)
@@ -839,8 +839,7 @@ isakmp_cfg_set(iph1, attrpl, msg)
        if (iph1->mode_cfg->flags & ISAKMP_CFG_DELETE_PH1) {
                if (iph1->status == PHASE1ST_ESTABLISHED)
                        isakmp_info_send_d1(iph1);
-               remph1(iph1);
-               delph1(iph1);
+               isakmp_ph1expire(iph1);
                iph1 = NULL;
        }
        vfree(payload);
@@ -2265,7 +2264,7 @@ isakmp_cfg_resize_pool(size)
        /* If a pool already exists, check if we can shrink it */
        if ((isakmp_cfg_config.port_pool != NULL) &&
            (size < isakmp_cfg_config.pool_size)) {
-               for (i = isakmp_cfg_config.pool_size; i >= size; --i) {
+               for (i = isakmp_cfg_config.pool_size-1; i >= size; --i) {
                        if (isakmp_cfg_config.port_pool[i].used) {
                                plog(LLV_ERROR, LOCATION, NULL, 
                                    "resize pool from %zu to %d impossible "
@@ -2361,10 +2360,12 @@ isakmp_cfg_init(cold)
        isakmp_cfg_config.splitdns_list = NULL;
        isakmp_cfg_config.splitdns_len = 0;
 
+#if 0
        if (cold == ISAKMP_CFG_INIT_COLD) {
                if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
                        return error;
        }
+#endif
 
        return 0;
 }
index 64228239e9484478975df488bf4c6b09e1732c35..af19b91a286057ef72b6cf04b3d5d7e6a675a443 100644 (file)
@@ -199,7 +199,8 @@ isakmp_frag_extract(iph1, msg)
         * frag->len is the frag payload data plus the frag payload header,
         * whose size is sizeof(*frag) 
         */
-       if (msg->l < sizeof(*isakmp) + ntohs(frag->len)) {
+       if (msg->l < sizeof(*isakmp) + ntohs(frag->len) ||
+               ntohs(frag->len) < sizeof(*frag) + 1) {
                plog(LLV_ERROR, LOCATION, NULL, "Fragment too short\n");
                return -1;
        }
index af7d93b116efb4edfdb8732a0a6e22980248b5f4..9ed13efc24f716e2d43a736dca1de11b10b9ea92 100644 (file)
@@ -953,6 +953,7 @@ isakmp_info_send_nx(isakmp, remote, local, type, data)
                plog(LLV_ERROR, LOCATION, NULL,
                         "failed to copy ph1 addresses");
                error = -1;
+               iph1 = NULL; /* deleted in copy_ph1addresses */
                goto end;
        }
 
index 005ca95d2eea47bd6a526fdf81192d4ba098954d..44f8fed04c0059ea180b394599724c34556045fa 100644 (file)
@@ -554,13 +554,30 @@ quick_i2recv(iph2, msg0)
                                                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));
+                                                       lcconf->ext_nat_id = vmalloc(ntohs(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);
+                                                       if (iph2->ext_nat_id)
+                                                               vfree(iph2->ext_nat_id);
+                                                       iph2->ext_nat_id = vdup(lcconf->ext_nat_id);
+                                                       if (iph2->ext_nat_id == NULL) {
+                                                               plog(LLV_ERROR, LOCATION, NULL, "memory error while allocating ph2's external nat id.\n");
+                                                               goto end;
+                                                       }
                                                        plog(LLV_DEBUG, LOCATION, NULL, "external nat address saved.\n");
+                                               } else if (f_id && (iph2->ph1->natt_flags & NAT_DETECTED_PEER)) {
+                                                       if (iph2->ext_nat_id_p)
+                                                               vfree(iph2->ext_nat_id_p);
+                                                       iph2->ext_nat_id_p = vmalloc(ntohs(idp_ptr->h.len) - sizeof(struct isakmp_gen));
+                                                       if (iph2->ext_nat_id_p == NULL) {
+                                                               plog(LLV_ERROR, LOCATION, NULL, "memory error while allocating peers ph2's external nat id.\n");
+                                                               goto end;
+                                                       }
+                                                       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");
                                                } 
                                        } else {
                                                plog(LLV_ERROR, LOCATION, NULL, "mismatched ID was returned.\n");
@@ -1353,7 +1370,9 @@ 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 || ike_session_is_client_ph2_rekey(iph2)))
+    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);
                
        switch (error) {
@@ -2237,10 +2256,9 @@ get_sainfo_r(iph2)
        vchar_t *idsrc = NULL, *iddst = NULL;
        int prefixlen;
        int error = ISAKMP_INTERNAL_ERROR;
-       int remoteid = 0;
+       struct sainfo *anonymous = NULL;
 
-       if (iph2->id == NULL ||
-        ((iph2->ph1->natt_flags & NAT_DETECTED_ME) && ike_session_is_client_ph2_rekey(iph2))) {
+       if (iph2->id == NULL) {
                switch (iph2->src->sa_family) {
                case AF_INET:
                        prefixlen = sizeof(struct in_addr) << 3;
@@ -2264,8 +2282,7 @@ get_sainfo_r(iph2)
                goto end;
        }
 
-       if (iph2->id_p == NULL ||
-        ((iph2->ph1->natt_flags & NAT_DETECTED_PEER) && ike_session_is_client_ph2_rekey(iph2))) {
+       if (iph2->id_p == NULL) {
                switch (iph2->dst->sa_family) {
                case AF_INET:
                        prefixlen = sizeof(struct in_addr) << 3;
@@ -2290,13 +2307,35 @@ get_sainfo_r(iph2)
        }
 
        iph2->sainfo = getsainfo(idsrc, iddst, iph2->ph1->id_p, 0);
-       if (iph2->sainfo == NULL)
+       // track anonymous sainfo, because we'll try to find a better sainfo if this is a client
+       if (iph2->sainfo && iph2->sainfo->idsrc == NULL)
+               anonymous = iph2->sainfo;
+
+       if (iph2->sainfo == NULL ||
+               (anonymous &&  iph2->parent_session && iph2->parent_session->is_client)) {
                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) {
+                       plog(LLV_DEBUG2, LOCATION, NULL,
+                                "get_sainfo_r case 1.\n");
+               }
+               // still no sainfo (or anonymous): for client, fallback to sainfo used by a previous established phase2
+               if (iph2->sainfo == NULL ||
+                       (iph2->sainfo->idsrc == NULL && iph2->parent_session && iph2->parent_session->is_client)) {
+                       ike_session_get_sainfo_r(iph2);
+                       if (iph2->sainfo) {
+                               plog(LLV_DEBUG2, LOCATION, NULL,
+                                        "get_sainfo_r case 2.\n");
+                       }
+               }
+       }
        if (iph2->sainfo == NULL) {
-               plog(LLV_ERROR, LOCATION, NULL,
-                       "failed to get sainfo.\n");
-               goto end;
+               if (anonymous == NULL) {
+                       plog(LLV_ERROR, LOCATION, NULL,
+                                "failed to get sainfo.\n");
+                       goto end;
+               }
+               iph2->sainfo = anonymous;
        }
 #ifdef __APPLE__
        if (link_sainfo_to_ph2(iph2->sainfo) != 0) {
index aeb5aa869debe582b5d56c216430d534edc5a90b..4cf6c49f10384557a22f12b40749338f83e5edca 100644 (file)
@@ -395,8 +395,7 @@ xauth_reply(iph1, port, id, res)
                /* Delete Phase 1 SA */
                if (iph1->status == PHASE1ST_ESTABLISHED)
                        isakmp_info_send_d1(iph1);
-               remph1(iph1);
-               delph1(iph1);
+               isakmp_ph1expire(iph1);
 
                return -1;
        }
index 82057e7d9c8a925e1f65503f59da5259e3ac4295..7d4827e6d67668a7cc666eab68b73c256a4e3b0d 100644 (file)
@@ -301,6 +301,12 @@ skip:
        }
 #endif
 
+#ifdef ENABLE_HYBRID
+       if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
+               if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
+                       return error;
+#endif
+
        if (dump_config)
                dumprmconf ();
 
index 4bd1f1ff6db13975d08246c52c43ce96d34d0a5c..3a57fdb716dca3a0340246ed8db89d5b290c18e1 100644 (file)
@@ -464,7 +464,7 @@ void
 natt_float_ports (struct ph1handle *iph1)
 {
        
-       if (! (iph1->natt_flags && NAT_DETECTED) )
+       if (! (iph1->natt_flags & NAT_DETECTED) )
                return;
        if (! iph1->natt_options->float_port){
                /* Drafts 00 / 01, just schedule keepalive */
index 9ab26f91405f1fe519701f6efbe14c69dd9d5115..139c3db032d0d6d7e01bba474e29666bdb9e5ae9 100644 (file)
@@ -3510,7 +3510,7 @@ oakley_do_decrypt(iph1, msg, ivdp, ivep)
        /* do decrypt */
        new = alg_oakley_encdef_decrypt(iph1->approval->enctype,
                                        buf, iph1->key, ivdp);
-       if (new == NULL) {
+       if (new == NULL || new->v == NULL || new->l == 0) {
                plog(LLV_ERROR, LOCATION, NULL,
                        "decryption %d failed.\n", iph1->approval->enctype);
                goto end;
index c7790da4d62b923ee10d7ffa49bda07d3eb4b19b..e2ca9004a31355f41ab2d71fd22c04c9044fd976 100644 (file)
@@ -104,6 +104,7 @@ getrmconf_strict(remote, allow_anon)
        int allow_anon;
 {
        struct remoteconf *p;
+       struct remoteconf *p_withport_besteffort = NULL;
        struct remoteconf *anon = NULL;
        int withport;
        char buf[NI_MAXHOST + NI_MAXSERV + 10];
@@ -111,12 +112,11 @@ getrmconf_strict(remote, allow_anon)
 
        withport = 0;
 
-#ifndef ENABLE_NATT
        /* 
         * We never have ports set in our remote configurations, but when
         * NAT-T is enabled, the kernel can have policies with ports and
         * send us an acquire message for a destination that has a port set.
-        * If we do this port check here, we don't find the remote config.
+        * If we do this port check here, we have to fallback to a best-effort result (without the port).
         *
         * In an ideal world, we would be able to have remote conf with
         * port, and the port could be a wildcard. That test could be used.
@@ -138,9 +138,8 @@ getrmconf_strict(remote, allow_anon)
        default:
                plog(LLV_ERROR2, LOCATION, NULL,
                        "invalid ip address family: %d\n", remote->sa_family);
-               exit(1);
+               return NULL;
        }
-#endif /* ENABLE_NATT */
 
        if (remote->sa_family == AF_UNSPEC)
                snprintf (buf, sizeof(buf), "%s", "anonymous");
@@ -165,6 +164,9 @@ getrmconf_strict(remote, allow_anon)
                        plog(LLV_DEBUG, LOCATION, NULL,
                                "configuration found for %s.\n", buf);
                        return p;
+               } else if (withport && cmpsaddrwop(remote, p->remote) == 0) {
+                       // for withport: save the pointer for the best-effort search
+                       p_withport_besteffort = p;
                }
 
                /* save the pointer to the anonymous configuration */
@@ -172,6 +174,12 @@ getrmconf_strict(remote, allow_anon)
                        anon = p;
        }
 
+       if (p_withport_besteffort) {
+               plog(LLV_DEBUG, LOCATION, NULL,
+                        "configuration found for %s.\n", buf);
+               return p_withport_besteffort;
+       }
+       
        if (allow_anon && anon != NULL) {
                plog(LLV_DEBUG, LOCATION, NULL,
                        "anonymous configuration selected for %s.\n", buf);
index 5afba1b4768d7a50e5215ace7345d3325c7089ba..0cb3a852ea2fdcd35115976a11da24e81d36d3a9 100644 (file)
@@ -337,8 +337,7 @@ stdin_loop()
 #else
                char rbuf[1024];
                rbuf[0] = '\0';
-               fgets (rbuf, sizeof(rbuf), stdin);
-               if (!rbuf[0])
+               if (fgets(rbuf, sizeof(rbuf), stdin) == NULL)
                        break;
                if (rbuf[strlen(rbuf)-1] == '\n')
                        rbuf[strlen(rbuf)-1] = '\0';