summaryrefslogtreecommitdiff
path: root/programs/pluto/spdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'programs/pluto/spdb.c')
-rw-r--r--programs/pluto/spdb.c299
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: