From b8c3779817a9fa91e6b7b4457680cb64775c25cf Mon Sep 17 00:00:00 2001 From: Apple Date: Fri, 24 Jun 2011 13:58:53 +0000 Subject: [PATCH] ipsec-93.15.tar.gz --- ipsec-tools/racoon/ike_session.c | 31 +++++++++++++++-- ipsec-tools/racoon/isakmp.c | 40 ++++++++++++++++++++++ ipsec-tools/racoon/isakmp_ident.c | 7 ++++ ipsec-tools/racoon/isakmp_quick.c | 27 +++++++++++---- ipsec-tools/racoon/isakmp_var.h | 2 ++ ipsec-tools/racoon/sainfo.c | 55 +++++++++++++++++++++++++++++++ ipsec-tools/racoon/sainfo.h | 1 + 7 files changed, 155 insertions(+), 8 deletions(-) diff --git a/ipsec-tools/racoon/ike_session.c b/ipsec-tools/racoon/ike_session.c index 97e5be7..3d4608d 100644 --- a/ipsec-tools/racoon/ike_session.c +++ b/ipsec-tools/racoon/ike_session.c @@ -620,8 +620,9 @@ ike_session_has_other_negoing_ph2 (ike_session_t *session, struct ph2handle *iph } for (p = LIST_FIRST(&session->ikev1_state.ph2tree); p; p = LIST_NEXT(p, ph2ofsession_chain)) { + plog(LLV_DEBUG2, LOCATION, NULL, "%s: ph2 sub spid %d, db spid %d\n", __FUNCTION__, iph2->spid, p->spid); if (iph2 != p && !p->is_dying && iph2->spid == p->spid) { - if (p->status >= PHASE2ST_START && p->status < PHASE2ST_ESTABLISHED) { + if (p->status >= PHASE2ST_START && p->status <= PHASE2ST_ESTABLISHED) { return 1; } } @@ -859,6 +860,7 @@ ike_session_ph2_established (struct ph2handle *iph2) iph2->parent_session->term_reason = NULL; ike_session_update_mode(iph2); + plog(LLV_DEBUG2, LOCATION, NULL, "%s phase2 established, spid %d.\n", __FUNCTION__, iph2->spid); } void @@ -897,6 +899,13 @@ ike_session_cleanup_other_established_ph1s (ike_session_t *session, return; } + /* + * if we are responder, then we should wait until the server sends a delete notification. + */ + if (session->is_client && new_iph1->side == RESPONDER) { + return; + } + for (p = LIST_FIRST(&session->ikev1_state.ph1tree); p; p = next) { // take next pointer now, since delete change the underlying ph1tree list next = LIST_NEXT(p, ph1ofsession_chain); @@ -990,6 +999,13 @@ ike_session_cleanup_other_established_ph2s (ike_session_t *session, return; } + /* + * if we are responder, then we should wait until the server sends a delete notification. + */ + if (session->is_client && new_iph2->side == RESPONDER) { + return; + } + for (p = LIST_FIRST(&session->ikev1_state.ph2tree); p; p = next) { // take next pointer now, since delete change the underlying ph2tree list next = LIST_NEXT(p, ph2ofsession_chain); @@ -1592,8 +1608,13 @@ ike_session_get_sainfo_r (struct ph2handle *iph2) 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__); + plog(LLV_DEBUG2, LOCATION, NULL, "candidate ph2 matched in %s, spid %d.\n", __FUNCTION__, p->spid); iph2->sainfo = p->sainfo; + if (!iph2->spid) { + iph2->spid = p->spid; + } else { + plog(LLV_DEBUG2, LOCATION, NULL, "%s: pre-assigned spid %d.\n", __FUNCTION__, iph2->spid); + } if (p->ext_nat_id) { if (iph2->ext_nat_id) { vfree(iph2->ext_nat_id); @@ -1632,6 +1653,11 @@ ike_session_get_proposal_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->proposal = dupsaprop(p->approval, 1); + if (!iph2->spid) { + iph2->spid = p->spid; + } else { + plog(LLV_DEBUG2, LOCATION, NULL, "%s: pre-assigned spid %d.\n", __FUNCTION__, iph2->spid); + } return 0; } } @@ -1690,6 +1716,7 @@ ike_session_ph2_retransmits (struct ph2handle *iph2) iph2->is_rekey && iph2->ph1 && iph2->ph1->sce_rekey && !iph2->ph1->sce_rekey->dead && + iph2->side == INITIATOR && iph2->parent_session && !iph2->parent_session->is_cisco_ipsec && /* not for Cisco */ iph2->parent_session->is_client) { diff --git a/ipsec-tools/racoon/isakmp.c b/ipsec-tools/racoon/isakmp.c index 050ca42..0be5221 100644 --- a/ipsec-tools/racoon/isakmp.c +++ b/ipsec-tools/racoon/isakmp.c @@ -4208,3 +4208,43 @@ setscopeid(sp_addr0, sa_addr0) return 0; } #endif + +vchar_t * +isakmp_plist_append_initial_contact (iph1, plist) +struct ph1handle *iph1; +struct payload_list *plist; +{ + if (!iph1->is_rekey && iph1->rmconf->ini_contact && !getcontacted(iph1->remote)) { + vchar_t *notp_ini = NULL; + struct isakmp_pl_n np, *nptr; + char *cptr; + + np.doi = htonl(iph1->rmconf->doitype); + np.proto_id = IPSECDOI_PROTO_ISAKMP; + np.spi_size = sizeof(isakmp_index); + np.type = htons(ISAKMP_NTYPE_INITIAL_CONTACT); + if ((notp_ini = vmalloc(sizeof(struct isakmp_pl_n) - sizeof(struct isakmp_gen) + + sizeof(isakmp_index)))) { + nptr = &np; + memcpy(notp_ini->v, &nptr->doi, sizeof(struct isakmp_pl_n) - sizeof(struct isakmp_gen)); + cptr = notp_ini->v + sizeof(struct isakmp_pl_n) - sizeof(struct isakmp_gen); + memcpy(cptr, &iph1->index, sizeof(isakmp_index)); + plist = isakmp_plist_append(plist, notp_ini, ISAKMP_NPTYPE_N); + plog(LLV_DEBUG2, LOCATION, iph1->remote, + "added initial-contact payload.\n"); + + /* insert a node into contacted list. */ + if (inscontacted(iph1->remote) == -1) { + plog(LLV_ERROR, LOCATION, iph1->remote, + "failed to add contacted list.\n"); + /* ignore */ + } + return notp_ini; + } else { + plog(LLV_ERROR, LOCATION, iph1->remote, + "failed to allocate notification payload.\n"); + return NULL; + } + } + return NULL; +} diff --git a/ipsec-tools/racoon/isakmp_ident.c b/ipsec-tools/racoon/isakmp_ident.c index ff155e6..06f41d3 100644 --- a/ipsec-tools/racoon/isakmp_ident.c +++ b/ipsec-tools/racoon/isakmp_ident.c @@ -2225,6 +2225,7 @@ ident_ir3mx(iph1) vchar_t *gsstoken = NULL; vchar_t *gsshash = NULL; #endif + vchar_t *notp_ini = NULL; switch (AUTHMETHOD(iph1)) { case OAKLEY_ATTR_AUTH_METHOD_PSKEY: @@ -2337,6 +2338,10 @@ ident_ir3mx(iph1) goto end; } + if (iph1->side == INITIATOR) { + notp_ini = isakmp_plist_append_initial_contact(iph1, plist); + } + buf = isakmp_plist_set_all (&plist, iph1); #ifdef HAVE_PRINT_ISAKMP_C @@ -2368,6 +2373,8 @@ end: vfree(buf); buf = NULL; } + if (notp_ini) + vfree(notp_ini); return buf; } diff --git a/ipsec-tools/racoon/isakmp_quick.c b/ipsec-tools/racoon/isakmp_quick.c index 4c37b4d..871072c 100644 --- a/ipsec-tools/racoon/isakmp_quick.c +++ b/ipsec-tools/racoon/isakmp_quick.c @@ -2331,6 +2331,18 @@ get_sainfo_r(iph2) plog(LLV_DEBUG2, LOCATION, NULL, "get_sainfo_r case 2.\n"); } + // still no sainfo (or anonymous): fallback to sainfo picked by dst id + if ((iph2->sainfo == NULL || iph2->sainfo->idsrc == NULL) && iph2->id_p) { + plog(LLV_DEBUG2, LOCATION, NULL, + "get_sainfo_r about to try dst id only.\n"); + iph2->sainfo = getsainfo_by_dst_id(iph2->id_p, iph2->ph1->id_p); + if (iph2->sainfo) { + plog(LLV_DEBUG2, LOCATION, NULL, + "get_sainfo_r case 3.\n"); + if (iph2->sainfo->idsrc == NULL) + anonymous = iph2->sainfo; + } + } } } if (iph2->sainfo == NULL) { @@ -2400,9 +2412,9 @@ get_proposal_r(iph2) * NOTE: This function is only for responder. */ static int -get_proposal_r_remote(iph2, use_remote_addr) +get_proposal_r_remote(iph2, ignore_id) struct ph2handle *iph2; - int use_remote_addr; + int ignore_id; { struct policyindex spidx; struct secpolicy *sp_in, *sp_out; @@ -2418,13 +2430,16 @@ get_proposal_r_remote(iph2, use_remote_addr) return ISAKMP_NTYPE_INVALID_ID_INFORMATION; } - /* make sure if id[src,dst] is null. */ - if (iph2->src_id || iph2->dst_id) { + /* make sure if id[src,dst] is null (if use_remote_addr == 0). */ + if (!ignore_id && (iph2->src_id || iph2->dst_id)) { plog(LLV_ERROR, LOCATION, NULL, "Why do ID[src,dst] exist already.\n"); return ISAKMP_INTERNAL_ERROR; } + plog(LLV_DEBUG, LOCATION, NULL, + "%s: ignore_id %x.\n", __FUNCTION__, ignore_id); + memset(&spidx, 0, sizeof(spidx)); #define _XIDT(d) ((struct ipsecdoi_id_b *)(d)->v)->type @@ -2440,7 +2455,7 @@ get_proposal_r_remote(iph2, use_remote_addr) * use the nat's address in the ID payload. */ if (iph2->id != NULL - && use_remote_addr == 0 + && ignore_id == 0 && (_XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR || _XIDT(iph2->id) == IPSECDOI_ID_IPV6_ADDR || _XIDT(iph2->id) == IPSECDOI_ID_IPV4_ADDR_SUBNET @@ -2506,7 +2521,7 @@ get_proposal_r_remote(iph2, use_remote_addr) /* make source address in spidx */ if (iph2->id_p != NULL - && use_remote_addr == 0 + && ignore_id == 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 diff --git a/ipsec-tools/racoon/isakmp_var.h b/ipsec-tools/racoon/isakmp_var.h index a3edc8b..26d5716 100644 --- a/ipsec-tools/racoon/isakmp_var.h +++ b/ipsec-tools/racoon/isakmp_var.h @@ -121,6 +121,8 @@ extern struct payload_list *isakmp_plist_append __P((struct payload_list *plist, vchar_t *payload, int payload_type)); extern vchar_t *isakmp_plist_set_all __P((struct payload_list **plist, struct ph1handle *iph1)); +extern vchar_t *isakmp_plist_append_initial_contact __P((struct ph1handle *, + struct payload_list *)); #ifdef HAVE_PRINT_ISAKMP_C extern void isakmp_printpacket __P((vchar_t *, struct sockaddr *, diff --git a/ipsec-tools/racoon/sainfo.c b/ipsec-tools/racoon/sainfo.c index 87093ab..2c3619b 100644 --- a/ipsec-tools/racoon/sainfo.c +++ b/ipsec-tools/racoon/sainfo.c @@ -174,6 +174,61 @@ link_sainfo_to_ph2 (struct sainfo *new) return(0); } +/* + * return matching entry. + * no matching entry found and if there is anonymous entry, return it. + * else return NULL. + * XXX by each data type, should be changed to compare the buffer. + */ +struct sainfo * +getsainfo_by_dst_id(dst, peer) + const vchar_t *dst, *peer; +{ + struct sainfo *s = NULL; + struct sainfo *anonymous = NULL; + + plog(LLV_DEBUG2, LOCATION, NULL, "getsainfo_by_dst_id - dst id:\n"); + if (dst != NULL) + plogdump(LLV_DEBUG2, dst->v, dst->l); + else + return NULL; + + LIST_FOREACH(s, &sitree, chain) { + if (s->to_delete || s->to_remove) { + continue; + } + if (s->idsrc != NULL) { + plog(LLV_DEBUG2, LOCATION, NULL, "getsainfo_by_dst_id - sainfo id - src & dst:\n"); + plogdump(LLV_DEBUG2, s->idsrc->v, s->idsrc->l); + plogdump(LLV_DEBUG2, s->iddst->v, s->iddst->l); + } else { + plog(LLV_DEBUG2, LOCATION, NULL, "getsainfo_by_dst_id - sainfo id = anonymous\n"); + } + if (s->id_i != NULL) { + plog(LLV_DEBUG2, LOCATION, NULL, "getsainfo_by_dst_id - sainfo id_i:\n"); + plogdump(LLV_DEBUG2, s->id_i->v, s->id_i->l); + if (peer == NULL) + continue; + if (memcmp(peer->v, s->id_i->v, s->id_i->l) != 0) + continue; + } + if (s->idsrc == NULL) { + anonymous = s; + continue; + } + + if (memcmp(dst->v, s->iddst->v, s->iddst->l) == 0) + return s; + } + + if (anonymous) { + plog(LLV_DEBUG, LOCATION, NULL, + "anonymous sainfo selected.\n"); + } + + return anonymous; +} + int unlink_sainfo_from_ph2 (struct sainfo *old) { diff --git a/ipsec-tools/racoon/sainfo.h b/ipsec-tools/racoon/sainfo.h index c9bf7f0..ad18996 100644 --- a/ipsec-tools/racoon/sainfo.h +++ b/ipsec-tools/racoon/sainfo.h @@ -74,6 +74,7 @@ struct sainfoalg { extern struct sainfo *getsainfo __P((const vchar_t *, const vchar_t *, const vchar_t *, int)); #ifdef __APPLE__ +extern struct sainfo *getsainfo_by_dst_id __P((const vchar_t *, const vchar_t *)); extern int link_sainfo_to_ph2 __P((struct sainfo *)); extern int unlink_sainfo_from_ph2 __P((struct sainfo *)); #endif -- 2.45.2