}
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;
}
}
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
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);
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);
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);
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;
}
}
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) {
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;
+}
vchar_t *gsstoken = NULL;
vchar_t *gsshash = NULL;
#endif
+ vchar_t *notp_ini = NULL;
switch (AUTHMETHOD(iph1)) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
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
vfree(buf);
buf = NULL;
}
+ if (notp_ini)
+ vfree(notp_ini);
return buf;
}
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) {
* 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;
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
* 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
/* 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
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 *,
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)
{
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