diff -ru openswan-1.0.0/pluto/connections.c openswan-1.0.0-psk-rsa-2/pluto/connections.c --- openswan-1.0.0/pluto/connections.c Fri Nov 28 18:44:22 2003 +++ openswan-1.0.0-psk-rsa-2/pluto/connections.c Fri Mar 12 17:16:32 2004 @@ -792,6 +792,7 @@ { if (c->policy & POLICY_AGGRESSIVE) continue; +#if 0 if ((c->policy ^ wm->policy) & (POLICY_PSK | POLICY_RSASIG)) { loglog(RC_CLASH @@ -799,6 +800,7 @@ , c->name); return FALSE; } +#endif } } } @@ -1960,9 +1962,20 @@ */ struct connection * find_host_connection(const ip_address *me, u_int16_t my_port -, const ip_address *him, u_int16_t his_port) +, const ip_address *him, u_int16_t his_port, lset_t policy) { - return find_host_pair_connections(me, my_port, him, his_port); + struct connection *c; + c = find_host_pair_connections(me, my_port, him, his_port); + if (policy != LEMPTY) { + /* if we have requirements for the policy, choose the first matching + * connection. + */ + for (; c != NULL; c = c->hp_next) { + if ((c->policy & policy) == policy) + break; + } + } + return c; } /* given an up-until-now satisfactory connection, find the best connection diff -ru openswan-1.0.0/pluto/connections.h openswan-1.0.0-psk-rsa-2/pluto/connections.h --- openswan-1.0.0/pluto/connections.h Fri Nov 28 18:44:22 2003 +++ openswan-1.0.0-psk-rsa-2/pluto/connections.h Fri Mar 12 17:16:32 2004 @@ -213,7 +213,7 @@ extern struct connection *con_by_name(const char *nm, bool strict), *find_host_connection(const ip_address *me, u_int16_t my_port - , const ip_address *him, u_int16_t his_port), + , const ip_address *him, u_int16_t his_port, lset_t policy), *refine_host_connection(const struct state *st, const struct id *id , bool initiator, bool aggrmode), *find_client_connection(struct connection *c diff -ru openswan-1.0.0/pluto/ipsec_doi.c openswan-1.0.0-psk-rsa-2/pluto/ipsec_doi.c --- openswan-1.0.0/pluto/ipsec_doi.c Fri Nov 28 18:44:22 2003 +++ openswan-1.0.0-psk-rsa-2/pluto/ipsec_doi.c Fri Mar 12 17:16:32 2004 @@ -298,7 +298,7 @@ collect_rw_ca_candidates(struct msg_digest *md, generalName_t **top) { struct connection *d = find_host_connection(&md->iface->addr - , pluto_port, (ip_address*)NULL, md->sender_port); + , pluto_port, (ip_address*)NULL, md->sender_port, LEMPTY); for (; d != NULL; d = d->hp_next) { @@ -3018,15 +3018,18 @@ struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA]; struct state *st; struct connection *c = find_host_connection(&md->iface->addr, pluto_port - , &md->sender, md->sender_port); + , &md->sender, md->sender_port, LEMPTY); pb_stream r_sa_pbs; if (c == NULL) { + pb_stream pre_sa_pbs = sa_pd->pbs; + lset_t policy = preparse_isakmp_sa_body(&pre_sa_pbs); + /* see if a wildcarded connection can be found */ c = find_host_connection(&md->iface->addr, pluto_port - , (ip_address*)NULL, md->sender_port); + , (ip_address*)NULL, md->sender_port, policy); if (c != NULL) { /* Create a temporary connection that is a copy of this one. @@ -3044,8 +3047,10 @@ else { loglog(RC_LOG_SERIOUS, "initial Main Mode message received on %s:%u" - " but no connection has been authorized" - , ip_str(&md->iface->addr), ntohs(portof(&md->iface->addr))); + " but no connection has been authorized%s%s" + , ip_str(&md->iface->addr), ntohs(portof(&md->iface->addr)) + , (policy != LEMPTY) ? " with policy=" : "" + , (policy != LEMPTY) ? bitnamesof(sa_policy_bit_names, policy) : ""); /* XXX notification is in order! */ return STF_IGNORE; } @@ -3919,16 +3924,19 @@ struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA]; pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs; struct connection *c = find_host_connection(&md->iface->addr, pluto_port - , &md->sender, md->sender_port); + , &md->sender, md->sender_port, LEMPTY); pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */ pb_stream r_sa_pbs; int auth_payload,next_payload; if (c == NULL) { + pb_stream pre_sa_pbs = sa_pd->pbs; + lset_t policy = preparse_isakmp_sa_body(&pre_sa_pbs); + /* see if a wildcarded connection can be found */ c = find_host_connection(&md->iface->addr, pluto_port - , (ip_address*)NULL, md->sender_port); + , (ip_address*)NULL, md->sender_port, policy); if (c != NULL && c->policy & POLICY_AGGRESSIVE) { /* Create a temporary connection that is a copy of this one. @@ -3946,8 +3954,10 @@ else { loglog(RC_LOG_SERIOUS, "initial Aggressive Mode message from %s" - " but no (wildcard) connection has been configured" - , ip_str(&md->sender)); + " but no (wildcard) connection has been configured%s%s" + , ip_str(&md->sender) + , (policy != LEMPTY) ? " with policy=" : "" + , (policy != LEMPTY) ? bitnamesof(sa_policy_bit_names, policy) : ""); /* XXX notification is in order! */ return STF_IGNORE; } diff -ru openswan-1.0.0/pluto/spdb.c openswan-1.0.0-psk-rsa-2/pluto/spdb.c --- openswan-1.0.0/pluto/spdb.c Tue Nov 25 01:37:27 2003 +++ openswan-1.0.0-psk-rsa-2/pluto/spdb.c Wed Mar 17 17:44:16 2004 @@ -806,6 +806,79 @@ return val; } +/* Preparse the body of an ISAKMP SA Payload and find which policy is required + * to match the packet. Errors are just ignored and will be detected and + * handled later in parse_isakmp_sa_body(). + * + * All we want for the moment is to know whether peer is using RSA or PSK. + */ +lset_t preparse_isakmp_sa_body(pb_stream *sa_pbs) +{ + pb_stream proposal_pbs; + struct isakmp_proposal proposal; + pb_stream trans_pbs; + struct isakmp_transform trans; + u_char *attr_start; + size_t attr_len; + struct isakmp_attribute a; + pb_stream attr_pbs; + u_int32_t ipsecdoisit; + unsigned trans_left; + lset_t policy = 0; + + if (!in_struct(&ipsecdoisit, &ipsec_sit_desc, sa_pbs, NULL)) + return LEMPTY; + + if (!in_struct(&proposal, &isakmp_proposal_desc, sa_pbs, &proposal_pbs)) + return LEMPTY; + + if (proposal.isap_spisize > MAX_ISAKMP_SPI_SIZE) + return LEMPTY; + + if (proposal.isap_spisize > 0) + { + u_char junk_spi[MAX_ISAKMP_SPI_SIZE]; + + if (!in_raw(junk_spi, proposal.isap_spisize, &proposal_pbs, "Oakley SPI")) + return LEMPTY; + } + + trans_left = proposal.isap_notrans; + while (trans_left--) { + if (!in_struct(&trans, &isakmp_isakmp_transform_desc, &proposal_pbs, + &trans_pbs)) + return LEMPTY; + + attr_start = trans_pbs.cur; + attr_len = pbs_left(&trans_pbs); + + while (pbs_left(&trans_pbs) != 0) { + if (!in_struct(&a, &isakmp_oakley_attribute_desc, &trans_pbs, + &attr_pbs)) + return LEMPTY; + switch (a.isaat_af_type) { + case OAKLEY_AUTHENTICATION_METHOD | ISAKMP_ATTR_AF_TV: + switch (a.isaat_lv) { + case XAUTHInitPreShared: + case OAKLEY_PRESHARED_KEY: + policy |= POLICY_PSK; + break; + case XAUTHInitRSA: + case OAKLEY_RSA_SIG: + policy |= POLICY_RSASIG; + break; + } + break; + } + } + } + + if ((policy & POLICY_PSK) && (policy & POLICY_RSASIG)) + policy &= ~(POLICY_PSK|POLICY_RSASIG); + + return policy; +} + /* Parse the body of an ISAKMP SA Payload (i.e. Phase 1 / Main Mode). * Various shortcuts are taken. In particular, the policy, such as * it is, is hardwired. diff -ru openswan-1.0.0/pluto/spdb.h openswan-1.0.0-psk-rsa-2/pluto/spdb.h --- openswan-1.0.0/pluto/spdb.h Mon Mar 3 23:29:54 2003 +++ openswan-1.0.0-psk-rsa-2/pluto/spdb.h Fri Mar 12 17:16:32 2004 @@ -84,6 +84,8 @@ bool credcheck); /* whether we can check credentials now */ #endif +extern lset_t preparse_isakmp_sa_body(pb_stream *sa_pbs); + extern notification_t parse_isakmp_sa_body( pb_stream *sa_pbs, /* body of input SA Payload */ const struct isakmp_sa *sa, /* header of input SA Payload */