diff options
Diffstat (limited to 'programs/pluto/spdb.c')
-rw-r--r-- | programs/pluto/spdb.c | 299 |
1 files changed, 113 insertions, 186 deletions
diff --git a/programs/pluto/spdb.c b/programs/pluto/spdb.c index 0544a1da2..ab976511e 100644 --- a/programs/pluto/spdb.c +++ b/programs/pluto/spdb.c @@ -11,7 +11,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: spdb.c,v 1.9 2006/04/22 21:59:20 as Exp $ + * RCSID $Id: spdb.c,v 1.10 2007/01/10 00:36:19 as Exp $ */ #include <stdio.h> @@ -54,158 +54,26 @@ /**************** Oakely (main mode) SA database ****************/ -/* arrays of attributes for transforms, preshared key */ - -static struct db_attr otpsk1024des3md5[] = { - { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC }, - { OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 }, - { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY }, - { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 }, - }; - -static struct db_attr otpsk1536des3md5[] = { - { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC }, - { OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 }, - { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY }, - { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 }, - }; - -static struct db_attr otpsk1024des3sha[] = { - { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC }, - { OAKLEY_HASH_ALGORITHM, OAKLEY_SHA }, - { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY }, - { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 }, - }; - -static struct db_attr otpsk1536des3sha[] = { - { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC }, - { OAKLEY_HASH_ALGORITHM, OAKLEY_SHA }, - { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY }, - { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 }, - }; - -/* arrays of attributes for transforms, RSA signatures */ - -static struct db_attr otrsasig1024des3md5[] = { - { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC }, - { OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 }, - { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG }, - { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 }, - }; - -static struct db_attr otrsasig1536des3md5[] = { - { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC }, - { OAKLEY_HASH_ALGORITHM, OAKLEY_MD5 }, - { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG }, - { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 }, - }; - -static struct db_attr otrsasig1024des3sha[] = { - { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC }, - { OAKLEY_HASH_ALGORITHM, OAKLEY_SHA }, - { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG }, - { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 }, - }; - -static struct db_attr otrsasig1536des3sha[] = { - { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC }, - { OAKLEY_HASH_ALGORITHM, OAKLEY_SHA }, - { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_RSA_SIG }, - { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1536 }, - }; - -/* We won't accept this, but by proposing it, we get to test - * our rejection. We better not propose it to an IKE daemon - * that will accept it! - */ -#ifdef TEST_INDECENT_PROPOSAL -static struct db_attr otpsk1024des3tiger[] = { - { OAKLEY_ENCRYPTION_ALGORITHM, OAKLEY_3DES_CBC }, - { OAKLEY_HASH_ALGORITHM, OAKLEY_TIGER }, - { OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY }, - { OAKLEY_GROUP_DESCRIPTION, OAKLEY_GROUP_MODP1024 }, - }; -#endif /* TEST_INDECENT_PROPOSAL */ - -/* tables of transforms, in preference order (select based on AUTH) */ - -static struct db_trans oakley_trans_psk[] = { -#ifdef TEST_INDECENT_PROPOSAL - { KEY_IKE, AD(otpsk1024des3tiger) }, -#endif - { KEY_IKE, AD(otpsk1536des3md5) }, - { KEY_IKE, AD(otpsk1536des3sha) }, - { KEY_IKE, AD(otpsk1024des3sha) }, - { KEY_IKE, AD(otpsk1024des3md5) }, - }; - -static struct db_trans oakley_trans_rsasig[] = { - { KEY_IKE, AD(otrsasig1536des3md5) }, - { KEY_IKE, AD(otrsasig1536des3sha) }, - { KEY_IKE, AD(otrsasig1024des3sha) }, - { KEY_IKE, AD(otrsasig1024des3md5) }, - }; - -/* In this table, either PSK or RSA sig is accepted. - * The order matters, but I don't know what would be best. - */ -static struct db_trans oakley_trans_pskrsasig[] = { -#ifdef TEST_INDECENT_PROPOSAL - { KEY_IKE, AD(otpsk1024des3tiger) }, -#endif - { KEY_IKE, AD(otrsasig1536des3md5) }, - { KEY_IKE, AD(otpsk1536des3md5) }, - { KEY_IKE, AD(otrsasig1536des3sha) }, - { KEY_IKE, AD(otpsk1536des3sha) }, - { KEY_IKE, AD(otrsasig1024des3sha) }, - { KEY_IKE, AD(otpsk1024des3sha) }, - { KEY_IKE, AD(otrsasig1024des3md5) }, - { KEY_IKE, AD(otpsk1024des3md5) }, - }; - /* array of proposals to be conjoined (can only be one for Oakley) */ -static struct db_prop oakley_pc_psk[] = - { { PROTO_ISAKMP, AD(oakley_trans_psk) } }; - -static struct db_prop oakley_pc_rsasig[] = - { { PROTO_ISAKMP, AD(oakley_trans_rsasig) } }; - -static struct db_prop oakley_pc_pskrsasig[] = - { { PROTO_ISAKMP, AD(oakley_trans_pskrsasig) } }; +static struct db_prop oakley_pc[] = + { { PROTO_ISAKMP, AD_NULL } }; /* array of proposal conjuncts (can only be one) */ -static struct db_prop_conj oakley_props_psk[] = { { AD(oakley_pc_psk) } }; +static struct db_prop_conj oakley_props[] = { { AD(oakley_pc) } }; -static struct db_prop_conj oakley_props_rsasig[] = { { AD(oakley_pc_rsasig) } }; - -static struct db_prop_conj oakley_props_pskrsasig[] = { { AD(oakley_pc_pskrsasig) } }; - -/* the sadb entry, subscripted by POLICY_PSK and POLICY_RSASIG bits */ -struct db_sa oakley_sadb[] = { - { AD_NULL }, /* none */ - { AD(oakley_props_psk) }, /* POLICY_PSK */ - { AD(oakley_props_rsasig) }, /* POLICY_RSASIG */ - { AD(oakley_props_pskrsasig) }, /* POLICY_PSK + POLICY_RSASIG */ - }; +/* the sadb entry */ +struct db_sa oakley_sadb = { AD(oakley_props) }; /**************** IPsec (quick mode) SA database ****************/ /* arrays of attributes for transforms */ -static struct db_attr espmd5_attr[] = { - { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_MD5 }, - }; - static struct db_attr espsha1_attr[] = { { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1 }, }; -static struct db_attr ah_HMAC_MD5_attr[] = { - { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_MD5 }, - }; - static struct db_attr ah_HMAC_SHA1_attr[] = { { AUTH_ALGORITHM, AUTH_ALGORITHM_HMAC_SHA1 }, }; @@ -213,7 +81,6 @@ static struct db_attr ah_HMAC_SHA1_attr[] = { /* arrays of transforms, each in in preference order */ static struct db_trans espa_trans[] = { - { ESP_3DES, AD(espmd5_attr) }, { ESP_3DES, AD(espsha1_attr) }, }; @@ -223,13 +90,11 @@ static struct db_trans esp_trans[] = { #ifdef SUPPORT_ESP_NULL static struct db_trans espnull_trans[] = { - { ESP_NULL, AD(espmd5_attr) }, { ESP_NULL, AD(espsha1_attr) }, }; #endif /* SUPPORT_ESP_NULL */ static struct db_trans ah_trans[] = { - { AH_MD5, AD(ah_HMAC_MD5_attr) }, { AH_SHA, AD(ah_HMAC_SHA1_attr) }, }; @@ -452,7 +317,7 @@ out_sa(pb_stream *outs proposal.isap_spisize = oakley_mode ? 0 : p->protoid == PROTO_IPCOMP ? IPCOMP_CPI_SIZE : IPSEC_DOI_SPI_SIZE; - + /* In quick mode ONLY, create proposal for runtime kernel algos. * Replace ESP proposals with runtime created one */ @@ -503,7 +368,7 @@ out_sa(pb_stream *outs return_on(ret, FALSE); } } - + proposal.isap_notrans = p->trans_cnt; if (!out_struct(&proposal, &isakmp_proposal_desc, &sa_pbs, &proposal_pbs)) return_on(ret, FALSE); @@ -888,7 +753,9 @@ restore_pbs(pb_stream *pbs) * Parse an ISAKMP Proposal Payload for RSA and PSK authentication policies */ notification_t -parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans, lset_t *policy) +parse_isakmp_policy(pb_stream *proposal_pbs + , u_int notrans + , lset_t *policy) { int last_transnum = -1; @@ -945,6 +812,18 @@ parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans, lset_t *policy) case OAKLEY_RSA_SIG: *policy |= POLICY_RSASIG; break; + case XAUTHInitPreShared: + *policy |= POLICY_XAUTH_SERVER; + /* fall through */ + case XAUTHRespPreShared: + *policy |= POLICY_XAUTH_PSK; + break; + case XAUTHInitRSA: + *policy |= POLICY_XAUTH_SERVER; + /* fall through */ + case XAUTHRespRSA: + *policy |= POLICY_XAUTH_RSASIG; + break; default: break; } @@ -954,23 +833,35 @@ parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans, lset_t *policy) } } } + DBG(DBG_CONTROL|DBG_PARSING, + DBG_log("preparse_isakmp_policy: peer requests %s authentication" + , prettypolicy(*policy)) + ) + return NOTHING_WRONG; +} - if ((*policy & POLICY_PSK) && (*policy & POLICY_RSASIG)) - { - DBG(DBG_CONTROL|DBG_PARSING, - DBG_log("preparse_isakmp_policy: " - "peer supports both PSK and RSASIG authentication") - ) - *policy = LEMPTY; - } - else +/* + * check that we can find a preshared secret + */ +static err_t +find_preshared_key(struct state* st) +{ + err_t ugh = NULL; + struct connection *c = st->st_connection; + + if (get_preshared_secret(c) == NULL) { - DBG(DBG_CONTROL|DBG_PARSING, - DBG_log("preparse_isakmp_policy: peer requests %s authentication" - , (*policy & POLICY_PSK) ? "PSK":"RSASIG") - ) + char my_id[BUF_LEN], his_id[BUF_LEN]; + + idtoa(&c->spd.this.id, my_id, sizeof(my_id)); + if (his_id_was_instantiated(c)) + strcpy(his_id, "%any"); + else + idtoa(&c->spd.that.id, his_id, sizeof(his_id)); + ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'" + , my_id, his_id); } - return NOTHING_WRONG; + return ugh; } /* Parse the body of an ISAKMP SA Payload (i.e. Phase 1 / Main Mode). @@ -987,7 +878,8 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit , pb_stream *proposal_pbs , struct isakmp_proposal *proposal , pb_stream *r_sa_pbs - , struct state *st) + , struct state *st + , bool initiator) { struct connection *c = st->st_connection; unsigned no_trans_left; @@ -1093,6 +985,10 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit /* check that authentication method is acceptable */ lset_t iap = st->st_policy & POLICY_ID_AUTH_MASK; + /* is the initiator the XAUTH client? */ + bool xauth_init = initiator && (st->st_policy & POLICY_XAUTH_SERVER) == LEMPTY + || !initiator && (st->st_policy & POLICY_XAUTH_SERVER) != LEMPTY; + switch (val) { case OAKLEY_PRESHARED_KEY: @@ -1102,23 +998,30 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit } else { - /* check that we can find a preshared secret */ - struct connection *c = st->st_connection; - - if (get_preshared_secret(c) == NULL) - { - char mid[BUF_LEN] - , hid[BUF_LEN]; - - idtoa(&c->spd.this.id, mid, sizeof(mid)); - if (his_id_was_instantiated(c)) - strcpy(hid, "%any"); - else - idtoa(&c->spd.that.id, hid, sizeof(hid)); - ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'" - , mid, hid); - } - ta.auth = val; + ugh = find_preshared_key(st); + ta.auth = OAKLEY_PRESHARED_KEY; + } + break; + case XAUTHInitPreShared: + if ((iap & POLICY_XAUTH_PSK) == LEMPTY || !xauth_init) + { + ugh = "policy does not allow XAUTHInitPreShared authentication"; + } + else + { + ugh = find_preshared_key(st); + ta.auth = XAUTHInitPreShared; + } + break; + case XAUTHRespPreShared: + if ((iap & POLICY_XAUTH_PSK) == LEMPTY || xauth_init) + { + ugh = "policy does not allow XAUTHRespPreShared authentication"; + } + else + { + ugh = find_preshared_key(st); + ta.auth = XAUTHRespPreShared; } break; case OAKLEY_RSA_SIG: @@ -1129,18 +1032,29 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit } else { - /* We'd like to check that we can find a public - * key for him and a private key for us that is - * suitable, but we don't yet have his - * Id Payload, so it seems futile to try. - * We can assume that if he proposes it, he - * thinks we've got it. If we proposed it, - * perhaps we know what we're doing. - */ - ta.auth = val; + ta.auth = OAKLEY_RSA_SIG; + } + break; + case XAUTHInitRSA: + if ((iap & POLICY_XAUTH_RSASIG) == LEMPTY || !xauth_init) + { + ugh = "policy does not allow XAUTHInitRSA authentication"; + } + else + { + ta.auth = XAUTHInitRSA; + } + break; + case XAUTHRespRSA: + if ((iap & POLICY_XAUTH_RSASIG) == LEMPTY || xauth_init) + { + ugh = "policy does not allow XAUTHRespRSA authentication"; + } + else + { + ta.auth = XAUTHRespRSA; } break; - default: ugh = builddiag("Pluto does not support %s authentication" , enum_show(&oakley_auth_names, val)); @@ -1194,10 +1108,23 @@ parse_isakmp_sa_body(u_int32_t ipsecdoisit { case OAKLEY_LIFE_SECONDS: if (val > OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM) + { +#ifdef CISCO_QUIRKS + plog("peer requested %lu seconds" + " which exceeds our limit %d seconds" + , (long) val + , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM); + plog("lifetime reduced to %d seconds " + "(todo: IPSEC_RESPONDER_LIFETIME notification)" + , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM); + val = OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM; +#else ugh = builddiag("peer requested %lu seconds" " which exceeds our limit %d seconds" , (long) val , OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM); +#endif + } ta.life_seconds = val; break; case OAKLEY_LIFE_KILOBYTES: |