From: Apple Date: Thu, 12 Nov 2009 17:57:22 +0000 (+0000) Subject: ipsec-92.4.tar.gz X-Git-Tag: mac-os-x-1062^0 X-Git-Url: https://git.saurik.com/apple/ipsec.git/commitdiff_plain/476121220b14176dcbf5f70f47b9ef8e38f8b389 ipsec-92.4.tar.gz --- diff --git a/ipsec-tools/Common/pfkey.c b/ipsec-tools/Common/pfkey.c index f4bcb4f..026ccd8 100644 --- a/ipsec-tools/Common/pfkey.c +++ b/ipsec-tools/Common/pfkey.c @@ -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) diff --git a/ipsec-tools/racoon/admin.c b/ipsec-tools/racoon/admin.c index ea11b4e..d8e16b9 100644 --- a/ipsec-tools/racoon/admin.c +++ b/ipsec-tools/racoon/admin.c @@ -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); diff --git a/ipsec-tools/racoon/crypto_openssl.c b/ipsec-tools/racoon/crypto_openssl.c index ae184d7..c32f636 100644 --- a/ipsec-tools/racoon/crypto_openssl.c +++ b/ipsec-tools/racoon/crypto_openssl.c @@ -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 diff --git a/ipsec-tools/racoon/handler.c b/ipsec-tools/racoon/handler.c index a070970..9dc7f92 100644 --- a/ipsec-tools/racoon/handler.c +++ b/ipsec-tools/racoon/handler.c @@ -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 diff --git a/ipsec-tools/racoon/handler.h b/ipsec-tools/racoon/handler.h index 9dcfdbd..9523316 100644 --- a/ipsec-tools/racoon/handler.h +++ b/ipsec-tools/racoon/handler.h @@ -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; diff --git a/ipsec-tools/racoon/ike_session.c b/ipsec-tools/racoon/ike_session.c index 4f688bf..3bb62d7 100644 --- a/ipsec-tools/racoon/ike_session.c +++ b/ipsec-tools/racoon/ike_session.c @@ -47,13 +47,15 @@ #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 diff --git a/ipsec-tools/racoon/ike_session.h b/ipsec-tools/racoon/ike_session.h index ba91e0f..e840c37 100644 --- a/ipsec-tools/racoon/ike_session.h +++ b/ipsec-tools/racoon/ike_session.h @@ -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 */ diff --git a/ipsec-tools/racoon/ipsec_doi.c b/ipsec-tools/racoon/ipsec_doi.c index 713ec4c..56cb6b7 100644 --- a/ipsec-tools/racoon/ipsec_doi.c +++ b/ipsec-tools/racoon/ipsec_doi.c @@ -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)); diff --git a/ipsec-tools/racoon/isakmp.c b/ipsec-tools/racoon/isakmp.c index 7d8e24e..7bcf121 100644 --- a/ipsec-tools/racoon/isakmp.c +++ b/ipsec-tools/racoon/isakmp.c @@ -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; } diff --git a/ipsec-tools/racoon/isakmp_cfg.c b/ipsec-tools/racoon/isakmp_cfg.c index c72600a..9672fd1 100644 --- a/ipsec-tools/racoon/isakmp_cfg.c +++ b/ipsec-tools/racoon/isakmp_cfg.c @@ -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; } diff --git a/ipsec-tools/racoon/isakmp_frag.c b/ipsec-tools/racoon/isakmp_frag.c index 6422823..af19b91 100644 --- a/ipsec-tools/racoon/isakmp_frag.c +++ b/ipsec-tools/racoon/isakmp_frag.c @@ -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; } diff --git a/ipsec-tools/racoon/isakmp_inf.c b/ipsec-tools/racoon/isakmp_inf.c index af7d93b..9ed13ef 100644 --- a/ipsec-tools/racoon/isakmp_inf.c +++ b/ipsec-tools/racoon/isakmp_inf.c @@ -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; } diff --git a/ipsec-tools/racoon/isakmp_quick.c b/ipsec-tools/racoon/isakmp_quick.c index 005ca95..44f8fed 100644 --- a/ipsec-tools/racoon/isakmp_quick.c +++ b/ipsec-tools/racoon/isakmp_quick.c @@ -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) { diff --git a/ipsec-tools/racoon/isakmp_xauth.c b/ipsec-tools/racoon/isakmp_xauth.c index aeb5aa8..4cf6c49 100644 --- a/ipsec-tools/racoon/isakmp_xauth.c +++ b/ipsec-tools/racoon/isakmp_xauth.c @@ -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; } diff --git a/ipsec-tools/racoon/main.c b/ipsec-tools/racoon/main.c index 82057e7..7d4827e 100644 --- a/ipsec-tools/racoon/main.c +++ b/ipsec-tools/racoon/main.c @@ -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 (); diff --git a/ipsec-tools/racoon/nattraversal.c b/ipsec-tools/racoon/nattraversal.c index 4bd1f1f..3a57fdb 100644 --- a/ipsec-tools/racoon/nattraversal.c +++ b/ipsec-tools/racoon/nattraversal.c @@ -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 */ diff --git a/ipsec-tools/racoon/oakley.c b/ipsec-tools/racoon/oakley.c index 9ab26f9..139c3db 100644 --- a/ipsec-tools/racoon/oakley.c +++ b/ipsec-tools/racoon/oakley.c @@ -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; diff --git a/ipsec-tools/racoon/remoteconf.c b/ipsec-tools/racoon/remoteconf.c index c7790da..e2ca900 100644 --- a/ipsec-tools/racoon/remoteconf.c +++ b/ipsec-tools/racoon/remoteconf.c @@ -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); diff --git a/ipsec-tools/setkey/setkey.c b/ipsec-tools/setkey/setkey.c index 5afba1b..0cb3a85 100644 --- a/ipsec-tools/setkey/setkey.c +++ b/ipsec-tools/setkey/setkey.c @@ -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';