c->sa_keying_tries = wm->sa_keying_tries;
/* RFC 3706 DPD */
- c->dpd_delay = wm->dpd_delay;
- c->dpd_timeout = wm->dpd_timeout;
- c->dpd_action = wm->dpd_action;
-
+ c->dpd_delay = wm->dpd_delay;
+ c->dpd_timeout = wm->dpd_timeout;
+ c->dpd_action = wm->dpd_action;
+
c->addr_family = wm->addr_family;
c->tunnel_addr_family = wm->tunnel_addr_family;
if (policy != LEMPTY)
{
+ lset_t auth_requested = policy & POLICY_ID_AUTH_MASK;
+
/* if we have requirements for the policy,
* choose the first matching connection.
*/
while (c != NULL)
{
- if ((c->policy & policy) == policy)
- break;
+ if (c->policy & auth_requested)
+ {
+ break;
+ }
c = c->hp_next;
}
}
if (psk == NULL)
return NULL; /* cannot determine PSK! */
break;
-
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ auth_policy = POLICY_XAUTH_PSK;
+ break;
case OAKLEY_RSA_SIG:
auth_policy = POLICY_RSASIG;
break;
-
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ auth_policy = POLICY_XAUTH_RSASIG;
+ break;
default:
bad_case(auth);
}
bool matching_id = match_id(peer_id
, &d->spd.that.id, &wildcards);
+ bool matching_auth = (d->policy & auth_policy) != LEMPTY;
+
bool matching_trust = trusted_ca(peer_ca
, d->spd.that.ca, &peer_pathlen);
bool matching_request = match_requested_ca(c->requested_ca
, d->spd.this.ca, &our_pathlen);
- bool match = matching_id && matching_trust && matching_request;
-
+ bool match = matching_id && matching_auth &&
+ matching_trust && matching_request;
+
DBG(DBG_CONTROLMORE,
- DBG_log("%s: %s match (id: %s, trust: %s, request: %s)"
+ DBG_log("%s: %s match (id: %s, auth: %s, trust: %s, request: %s)"
, d->name
, match ? "full":" no"
, match_name[matching_id]
+ , match_name[matching_auth]
, match_name[matching_trust]
, match_name[matching_request])
)
continue;
}
- /* authentication used must fit policy of this connection */
- if ((d->policy & auth_policy) == LEMPTY)
- continue; /* our auth isn't OK for this connection */
-
switch (auth)
{
case OAKLEY_PRESHARED_KEY:
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
/* secret must match the one we already used */
{
const chunk_t *dpsk = get_preshared_secret(d);
break;
case OAKLEY_RSA_SIG:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
/*
* We must at least be able to find our private key
.*/
"STATE_INFO",
"STATE_INFO_PROTECTED",
- "STATE_XAUTH_R0",
"STATE_XAUTH_R1",
+ "STATE_XAUTH_R2",
+ "STATE_XAUTH_R3",
+ "STATE_XAUTH_I0",
"STATE_XAUTH_I1",
"STATE_XAUTH_I2",
"got Informational Message in clear", /* STATE_INFO */
"got encrypted Informational Message", /* STATE_INFO_PROTECTED */
- "sent XAUTH request, expecting reply", /* STATE_XAUTH_R0 */
- "sent XAUTH status, expecting ack", /* STATE_XAUTH_R1 */
- "received XAUTH request, sent reply", /* STATE_XAUTH_I1 */
- "received XAUTH status, sent ack", /* STATE_XAUTH_I2 */
+ "sent XAUTH request, expecting reply", /* STATE_XAUTH_R1 */
+ "sent XAUTH status, expecting ack", /* STATE_XAUTH_R2 */
+ "received XAUTH ack, established", /* STATE_XAUTH_R3 */
+ "expecting XAUTH request", /* STATE_XAUTH_I0 */
+ "sent XAUTH reply, expecting status", /* STATE_XAUTH_I1 */
+ "sent XAUTH ack, established", /* STATE_XAUTH_I2 */
- "sent ModeCfg reply", /* STATE_MODE_CFG_R0 */
- "sent ModeCfg reply", /* STATE_MODE_CFG_R1 */
- "received ModeCfg ack", /* STATE_MODE_CFG_R2 */
+ "expecting ModeCfg request", /* STATE_MODE_CFG_R0 */
+ "sent ModeCfg reply, expecting ack", /* STATE_MODE_CFG_R1 */
+ "received ModeCfg ack, established" /* STATE_MODE_CFG_R2 */
"sent ModeCfg request, expecting reply", /* STATE_MODE_CFG_I1 */
- "received ModeCfg reply", /* STATE_MODE_CFG_I2 */
+ "sent ModeCfg ack, established", /* STATE_MODE_CFG_I2 */
"received ModeCfg set, sent ack", /* STATE_MODE_CFG_I3 */
};
/* XAUTH states */
- STATE_XAUTH_R0, /* responder states (server) */
- STATE_XAUTH_R1,
+ STATE_XAUTH_R1, /* responder states (server) */
+ STATE_XAUTH_R2,
+ STATE_XAUTH_R3,
- STATE_XAUTH_I1, /* initiator states (client) */
+ STATE_XAUTH_I0, /* initiator states (client) */
+ STATE_XAUTH_I1,
STATE_XAUTH_I2,
/* Mode Config states */
#define PHASE1_INITIATOR_STATES (LELEM(STATE_MAIN_I1) | LELEM(STATE_MAIN_I2) \
| LELEM(STATE_MAIN_I3) | LELEM(STATE_MAIN_I4))
-#define ISAKMP_SA_ESTABLISHED_STATES (LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \
+#define ISAKMP_SA_ESTABLISHED_STATES ( \
+ LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \
+ | LELEM(STATE_XAUTH_R1) | LELEM(STATE_XAUTH_R2) | LELEM(STATE_XAUTH_R3) \
+ | LELEM(STATE_XAUTH_I1) | LELEM(STATE_XAUTH_I2) \
| LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_R2) \
| LELEM(STATE_MODE_CFG_I2) | LELEM(STATE_MODE_CFG_I3))
#define IS_PHASE1(s) ((STATE_MAIN_R0 <= (s) && (s) <= STATE_MAIN_I4) \
+ || (STATE_XAUTH_R1 <= (s) && (s) <= STATE_XAUTH_I2) \
|| (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_I3))
#define IS_QUICK(s) (STATE_QUICK_R0 <= (s) && (s) <= STATE_QUICK_R2)
#define IS_ISAKMP_ENCRYPTED(s) (STATE_MAIN_I2 <= (s))
#define IS_ISAKMP_SA_ESTABLISHED(s) ( \
- (s) == STATE_MAIN_R3 \
+ (s) == STATE_MAIN_R3 \
|| (s) == STATE_MAIN_I4 \
- || (s) == STATE_MODE_CFG_R0 \
+ || (s) == STATE_XAUTH_R1 \
+ || (s) == STATE_XAUTH_R2 \
+ || (s) == STATE_XAUTH_R3 \
+ || (s) == STATE_XAUTH_I1 \
+ || (s) == STATE_XAUTH_I2 \
|| (s) == STATE_MODE_CFG_R1 \
|| (s) == STATE_MODE_CFG_R2 \
|| (s) == STATE_MODE_CFG_I2 \
, P(HASH), LEMPTY, PT(NONE)
, EVENT_NULL, informational },
+ /* XAUTH server */
+ { STATE_XAUTH_R1, STATE_XAUTH_R2
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_RETRANSMIT, xauth_inR1 },
+
+ { STATE_XAUTH_R2, STATE_XAUTH_R3
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(NONE)
+ , EVENT_SA_REPLACE, xauth_inR2 },
+
+ { STATE_XAUTH_R3, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
+
+ /* XAUTH client */
+ { STATE_XAUTH_I0, STATE_XAUTH_I1
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_SA_REPLACE, xauth_inI0 },
+
+ { STATE_XAUTH_I1, STATE_XAUTH_I2
+ , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
+ , P(ATTR) | P(HASH), P(VID), PT(HASH)
+ , EVENT_SA_REPLACE, xauth_inI1 },
+
+ { STATE_XAUTH_I2, STATE_UNDEFINED
+ , SMF_ALL_AUTH | SMF_ENCRYPTED
+ , LEMPTY, LEMPTY, PT(NONE)
+ , EVENT_NULL, unexpected },
+
/* MODE_CFG_x:
* Case R0: Responder -> Initiator
* <- Req(addr=0)
{
plog("size (%u) differs from size specified in ISAKMP HDR (%u)"
, (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length);
+#ifdef CISCO_QUIRKS
+ if (pbs_room(&md->packet_pbs) - md->hdr.isa_length == 16)
+ plog("Cisco VPN client appends 16 surplus NULL bytes");
+ else
+#endif
return;
}
case ISAKMP_XCHG_MODE_CFG:
if (is_zero_cookie(md->hdr.isa_icookie))
{
- plog("Mode Config message is invalid because"
+ plog("ModeCfg message is invalid because"
" it has an Initiator Cookie of 0");
/* XXX Could send notification back */
return;
if (is_zero_cookie(md->hdr.isa_rcookie))
{
- plog("Mode Config message is invalid because"
+ plog("ModeCfg message is invalid because"
" it has a Responder Cookie of 0");
/* XXX Could send notification back */
return;
if (md->hdr.isa_msgid == 0)
{
- plog("Mode Config message is invalid because"
+ plog("ModeCfg message is invalid because"
" it has a Message ID of 0");
/* XXX Could send notification back */
return;
if (st == NULL)
{
- /* No appropriate Mode Config state.
+ bool has_xauth_policy;
+
+ /* No appropriate ModeCfg state.
* See if we have a Main Mode state.
* ??? what if this is a duplicate of another message?
*/
if (st == NULL)
{
- plog("Mode Config message is for a non-existent (expired?)"
+ plog("ModeCfg message is for a non-existent (expired?)"
" ISAKMP SA");
/* XXX Could send notification back */
return;
if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
{
- loglog(RC_LOG_SERIOUS, "Mode Config message is unacceptable because"
+ loglog(RC_LOG_SERIOUS, "ModeCfg message is unacceptable because"
" it is for an incomplete ISAKMP SA (state=%s)"
, enum_name(&state_names, st->st_state));
/* XXX Could send notification back */
*
*/
- if (st->st_connection->spd.that.modecfg
+ has_xauth_policy = (st->st_connection->policy
+ & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
+ != LEMPTY;
+
+ if (has_xauth_policy
+ && IS_PHASE1(st->st_state))
+ {
+ from_state = STATE_XAUTH_I0;
+ }
+ else if (st->st_connection->spd.that.modecfg
&& IS_PHASE1(st->st_state))
{
from_state = STATE_MODE_CFG_R0;
else
{
/* XXX check if we are being a mode config server here */
- plog("received MODECFG message when in state %s, and we aren't mode config client"
+ plog("received ModeCfg message when in state %s, and we aren't mode config client"
, enum_name(&state_names, st->st_state));
return;
}
if (st != NULL)
{
- while (!LHAS(smc->flags, st->st_oakley.auth))
+ u_int16_t auth;
+
+ switch (st->st_oakley.auth)
+ {
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
+ auth = OAKLEY_PRESHARED_KEY;
+ break;
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
+ auth = OAKLEY_RSA_SIG;
+ break;
+ default:
+ auth = st->st_oakley.auth;
+ }
+
+ while (!LHAS(smc->flags, auth))
{
smc++;
passert(smc->state == from_state);
void
complete_state_transition(struct msg_digest **mdp, stf_status result)
{
+ bool has_xauth_policy;
+ bool is_xauth_server;
struct msg_digest *md = *mdp;
const struct state_microcode *smc = md->smc;
enum state_kind from_state = md->from_state;
}
/* advance b to end of string */
b = b + strlen(b);
-
+
if (st->st_ah.present)
{
snprintf(b, sizeof(sadetails)-(b-sadetails)-1
}
/* advance b to end of string */
b = b + strlen(b);
-
+
if (st->st_ipcomp.present)
{
snprintf(b, sizeof(sadetails)-(b-sadetails)-1
, story, sadetails);
}
+ has_xauth_policy = (st->st_connection->policy
+ & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
+ != LEMPTY;
+ is_xauth_server = (st->st_connection->policy
+ & POLICY_XAUTH_SERVER)
+ != LEMPTY;
+
+ /* Should we start XAUTH as a server */
+ if (has_xauth_policy && is_xauth_server
+ && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ && !st->st_xauth.started)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("starting XAUTH server")
+ )
+ xauth_send_request(st);
+ break;
+ }
+
/* Should we start ModeConfig as a client? */
if (st->st_connection->spd.this.modecfg
&& IS_ISAKMP_SA_ESTABLISHED(st->st_state)
break;
}
+ /* Wait for XAUTH request from server */
+ if (has_xauth_policy && !is_xauth_server
+ && IS_ISAKMP_SA_ESTABLISHED(st->st_state)
+ && !st->st_xauth.started)
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("waiting for XAUTH request from server")
+ )
+ break;
+ }
+
/* Wait for ModeConfig set from server */
if (st->st_connection->spd.this.modecfg
&& IS_ISAKMP_SA_ESTABLISHED(st->st_state)
struct ike_info *ike_info;
u_int ealg, halg, modp, eklen = 0;
struct encrypt_desc *enc_desc;
+ bool is_xauth_server;
int i;
if (!ai)
db_trans_add(db_ctx, KEY_IKE);
db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
- if (ike_info->ike_eklen)
- db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, ike_info->ike_eklen);
+ if (eklen)
+ db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD, OAKLEY_PRESHARED_KEY);
db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
}
+
+ is_xauth_server = (policy & POLICY_XAUTH_SERVER) != LEMPTY;
+
+ if (policy & POLICY_XAUTH_RSASIG)
+ {
+ db_trans_add(db_ctx, KEY_IKE);
+ db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
+ db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
+ if (eklen)
+ db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
+ db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
+ , is_xauth_server ? XAUTHRespRSA : XAUTHInitRSA);
+ db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
+ }
+
+ if (policy & POLICY_XAUTH_PSK)
+ {
+ db_trans_add(db_ctx, KEY_IKE);
+ db_attr_add_values(db_ctx, OAKLEY_ENCRYPTION_ALGORITHM, ealg);
+ db_attr_add_values(db_ctx, OAKLEY_HASH_ALGORITHM, halg);
+ if (eklen)
+ db_attr_add_values(db_ctx, OAKLEY_KEY_LENGTH, eklen);
+ db_attr_add_values(db_ctx, OAKLEY_AUTHENTICATION_METHOD
+ , is_xauth_server ? XAUTHRespPreShared : XAUTHInitPreShared);
+ db_attr_add_values(db_ctx, OAKLEY_GROUP_DESCRIPTION, modp);
+ }
}
fail:
return db_ctx;
u_char *sa_start = rbody.cur;
lset_t auth_policy = policy & POLICY_ID_AUTH_MASK;
- if (!out_sa(&rbody, &oakley_sadb[auth_policy >> POLICY_ISAKMP_SHIFT]
- , st, TRUE, vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE))
+ if (!out_sa(&rbody, &oakley_sadb, st, TRUE
+ , vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE))
{
reset_cur_state();
return STF_INTERNAL_ERROR;
switch (st->st_oakley.auth)
{
case OAKLEY_PRESHARED_KEY:
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
if (!skeyid_preshared(st))
return FALSE;
break;
case OAKLEY_RSA_SIG:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
if (!skeyid_digisig(st))
return FALSE;
break;
/* SA body in and out */
RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit, &proposal_pbs
- ,&proposal, &r_sa_pbs, st));
+ ,&proposal, &r_sa_pbs, st, FALSE));
/* if enabled send Pluto Vendor ID */
if (SEND_PLUTO_VID)
RETURN_STF_FAILURE(BAD_PROPOSAL_SYNTAX);
}
RETURN_STF_FAILURE(parse_isakmp_sa_body(ipsecdoisit
- , &proposal_pbs, &proposal, NULL, st));
+ , &proposal_pbs, &proposal, NULL, st, TRUE));
}
if (nat_traversal_enabled && md->nat_traversal_vid)
pb_stream *keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
/* send CR if auth is RSA and no preloaded RSA public key exists*/
- bool send_cr = !no_cr_send && (st->st_oakley.auth == OAKLEY_RSA_SIG) &&
- !has_preloaded_public_key(st);
-
+ bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
+ || st->st_oakley.auth == XAUTHInitRSA
+ || st->st_oakley.auth == XAUTHRespRSA;
+ bool send_cr = !no_cr_send && RSA_auth && !has_preloaded_public_key(st);
+
u_int8_t np = ISAKMP_NEXT_NONE;
/* KE in */
cert_t mycert = st->st_connection->spd.this.cert;
bool requested, send_cert, send_cr;
+ bool RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
+ || st->st_oakley.auth == XAUTHInitRSA
+ || st->st_oakley.auth == XAUTHRespRSA;
+
/* KE in */
RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs));
*/
requested = cert_policy == CERT_SEND_IF_ASKED
&& st->st_connection->got_certrequest;
- send_cert = st->st_oakley.auth == OAKLEY_RSA_SIG
- && mycert.type != CERT_NONE
+ send_cert = RSA_auth && mycert.type != CERT_NONE
&& (cert_policy == CERT_ALWAYS_SEND || requested);
/* send certificate request if we don't have a preloaded RSA public key */
}
/* CERT out */
- if ( st->st_oakley.auth == OAKLEY_RSA_SIG)
+ if (RSA_auth)
{
DBG(DBG_CONTROL,
DBG_log("our certificate policy is %s"
switch (st->st_oakley.auth)
{
case OAKLEY_PRESHARED_KEY:
+ case XAUTHInitPreShared:
+ case XAUTHRespPreShared:
{
pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs;
break;
case OAKLEY_RSA_SIG:
+ case XAUTHInitRSA:
+ case XAUTHRespRSA:
r = RSA_check_signature(&peer, st, hash_val, hash_len
, &md->chain[ISAKMP_NEXT_SIG]->pbs
#ifdef USE_KEYRR
pb_stream r_id_pbs; /* ID Payload; also used for hash calculation */
certpolicy_t cert_policy;
cert_t mycert;
+ bool RSA_auth;
bool send_cert;
bool requested;
mycert = st->st_connection->spd.this.cert;
requested = cert_policy == CERT_SEND_IF_ASKED
&& st->st_connection->got_certrequest;
- send_cert = st->st_oakley.auth == OAKLEY_RSA_SIG
+ RSA_auth = st->st_oakley.auth == OAKLEY_RSA_SIG
+ || st->st_oakley.auth == XAUTHInitRSA
+ || st->st_oakley.auth == XAUTHRespRSA;
+ send_cert = RSA_auth
&& mycert.type != CERT_NONE
&& (cert_policy == CERT_ALWAYS_SEND || requested);
}
/* CERT out */
- if (st->st_oakley.auth == OAKLEY_RSA_SIG)
+ if (RSA_auth)
{
DBG(DBG_CONTROL,
DBG_log("our certificate policy is %s"
union {
chunk_t preshared_secret;
RSA_private_key_t RSA_private_key;
+ xauth_t xauth_secret;
smartcard_t *smartcard;
} u;
secret_t *next;
{
const secret_t *s = get_secret(c, PPK_PSK, FALSE);
-#ifdef DEBUG
DBG(DBG_PRIVATE,
if (s == NULL)
DBG_log("no Preshared Key Found");
else
DBG_dump_chunk("Preshared Key", s->u.preshared_secret);
- );
-#endif
+ )
return s == NULL? NULL : &s->u.preshared_secret;
}
}
/*
+ * process xauth secret read from ipsec.secrets
+ */
+static err_t
+process_xauth(secret_t *s)
+{
+ chunk_t user_name;
+ chunk_t user_password;
+
+ s->kind = PPK_XAUTH;
+
+ if (!shift())
+ return "missing xauth user name";
+ if (*tok == '"' || *tok == '\'') /* quoted user name */
+ {
+ user_name.ptr = tok + 1;
+ user_name.len = flp->cur - tok - 2;
+ }
+ else
+ {
+ user_name.ptr = tok;
+ user_name.len = flp->cur - tok;
+ }
+ if (!shift())
+ return "missing xauth user password";
+ if (*tok == '"' || *tok == '\'') /* quoted user password */
+ {
+ user_password.ptr = tok + 1;
+ user_password.len = flp->cur - tok - 2;
+ }
+ else
+ {
+ user_password.ptr = tok;
+ user_password.len = flp->cur - tok;
+ }
+ if (shift())
+ return "unexpected token after xauth user passpword";
+ clonetochunk(s->u.xauth_secret.user_name
+ , user_name.ptr, user_name.len, "user_name");
+ clonetochunk(s->u.xauth_secret.user_password
+ , user_password.ptr, user_password.len, "user_password");
+ return NULL;
+}
+
+/* get XAUTH secret from chained secrets lists
+ * only one entry is currently supported
+ */
+bool
+xauth_get_secret(xauth_t *xauth_secret)
+{
+ secret_t *s;
+ bool found = FALSE;
+
+ for (s = secrets; s != NULL; s = s->next)
+ {
+ if (s->kind == PPK_XAUTH)
+ {
+ if (found)
+ {
+ plog("found multiple xauth secrets - first selected");
+ }
+ else
+ {
+ found = TRUE;
+ *xauth_secret = s->u.xauth_secret;
+ }
+ }
+ }
+ return found;
+}
+
+/*
+ * find a matching secret
+ */
+bool
+xauth_verify_secret(const xauth_t *xauth_secret)
+{
+ secret_t *s;
+
+ for (s = secrets; s != NULL; s = s->next)
+ {
+ if (s->kind == PPK_XAUTH)
+ {
+ if (!same_chunk(xauth_secret->user_name, s->u.xauth_secret.user_name))
+ continue;
+ if (same_chunk(xauth_secret->user_password, s->u.xauth_secret.user_password))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
* process pin read from ipsec.secrets or prompted for it using whack
*/
static err_t
ugh = process_rsa_keyfile(&s->u.RSA_private_key, whackfd);
}
}
+ else if (tokeqword("xauth"))
+ {
+ ugh = process_xauth(s);
+ }
else if (tokeqword("pin"))
{
ugh = process_pin(s, whackfd);
free_preshared_secrets(void)
{
lock_certs_and_keys("free_preshared_secrets");
-
+
if (secrets != NULL)
{
secret_t *s, *ns;
case PPK_RSA:
free_RSA_private_content(&s->u.RSA_private_key);
break;
+ case PPK_XAUTH:
+ pfree(s->u.xauth_secret.user_name.ptr);
+ pfree(s->u.xauth_secret.user_password.ptr);
+ break;
case PPK_PIN:
scx_release(s->u.smartcard);
break;
}
secrets = NULL;
}
-
+
unlock_certs_and_keys("free_preshard_secrets");
}
PPK_PSK,
/* PPK_DSS, */ /* not implemented */
PPK_RSA,
+ PPK_XAUTH,
PPK_PIN
};
extern void remove_x509_public_key(const x509cert_t *cert);
extern void list_public_keys(bool utc);
+/* XAUTH credentials */
+
+typedef struct {
+ chunk_t user_name;
+ chunk_t user_password;
+} xauth_t;
+
+extern bool xauth_get_secrect(const xauth_t *xauth_secret);
+extern bool xauth_verify_secret(const xauth_t *xauth_secret);
+
struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
extern void transfer_to_public_keys(struct gw_info *gateways_from_dns
#ifdef USE_KEYRR
, pubkey_list_t **keys
#endif /* USE_KEYRR */
);
-
+
#endif /* _KEYS_H */
#include "crypto.h"
#include "modecfg.h"
#include "whack.h"
+#include "keys.h"
#define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
| LELEM(INTERNAL_IP4_NETMASK) \
struct internal_addr
{
- lset_t attr_set;
- ip_address ipaddr;
- ip_address dns[2];
- ip_address wins[2];
+ lset_t attr_set;
+
+ /* ModeCfg variables */
+ ip_address ipaddr;
+ ip_address dns[2];
+ ip_address wins[2];
+
+ /* XAUTH variables */
+ u_int16_t xauth_type;
+ xauth_t xauth_secret;
+ bool xauth_status;
};
/*
init_internal_addr(internal_addr_t *ia)
{
ia->attr_set = LEMPTY;
+ ia->xauth_secret.user_name = empty_chunk;
+ ia->xauth_secret.user_password = empty_chunk;
+ ia->xauth_status = FALSE;
+
anyaddr(AF_INET, &ia->ipaddr);
anyaddr(AF_INET, &ia->dns[0]);
anyaddr(AF_INET, &ia->dns[1]);
u_int len;
/* ISAKMP attr out */
- attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
+ if (attr_type == XAUTH_TYPE)
+ {
+ attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
+ attr.isaat_lv = ia->xauth_type;
+ }
+ else if (attr_type == XAUTH_STATUS)
+ {
+ attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV;
+ attr.isaat_lv = ia->xauth_status;
+ }
+ else
+ {
+ attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV;
+ }
out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval);
switch (attr_type)
case INTERNAL_IP4_NBNS:
if (!isanyaddr(&ia->wins[wins_idx]))
{
- len = addrbytesptr(&ia->wins[wins_idx++], &byte_ptr);
- out_raw(byte_ptr, len, &attrval, "IP4_wins");
+ len = addrbytesptr(&ia->wins[wins_idx++], &byte_ptr);
+ out_raw(byte_ptr, len, &attrval, "IP4_wins");
}
if (wins_idx < 2 && !isanyaddr(&ia->wins[wins_idx]))
{
dont_advance = TRUE;
}
- break;
+ break;
+ case XAUTH_TYPE:
+ break;
+ case XAUTH_USER_NAME:
+ if (ia->xauth_secret.user_name.ptr != NULL)
+ {
+ out_raw(ia->xauth_secret.user_name.ptr
+ , ia->xauth_secret.user_name.len
+ , &attrval, "xauth_user_name");
+ }
+ break;
+ case XAUTH_USER_PASSWORD:
+ if (ia->xauth_secret.user_password.ptr != NULL)
+ {
+ out_raw(ia->xauth_secret.user_password.ptr
+ , ia->xauth_secret.user_password.len
+ , &attrval, "xauth_user_password");
+ }
+ break;
+ case XAUTH_STATUS:
+ break;
default:
plog("attempt to send unsupported mode cfg attribute %s."
, enum_show(&modecfg_attr_names, attr_type));
if (!dont_advance)
{
attr_type++;
+ if (attr_type == MODECFG_ROOF)
+ {
+ attr_type = XAUTH_BASE;
+ }
attr_set >>= 1;
}
}
close_message(&strattr);
}
- modecfg_hash(r_hashval, r_hash_start, rbody->cur,st);
+ modecfg_hash(r_hashval, r_hash_start, rbody->cur, st);
close_message(rbody);
encrypt_message(rbody, st);
return STF_OK;
delete_event(st);
event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
}
- st->st_modecfg.started = TRUE;
return STF_OK;
}
stf_status
modecfg_send_request(struct state *st)
{
+ stf_status stat;
internal_addr_t ia;
init_internal_addr(&ia);
plog("sending ModeCfg request");
st->st_state = STATE_MODE_CFG_I1;
- return modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
+ stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
+ if (stat == STF_OK)
+ st->st_modecfg.started = TRUE;
+ return stat;
}
/*
stf_status
modecfg_send_set(struct state *st)
{
+ stf_status stat;
internal_addr_t ia;
get_internal_addr(st->st_connection, &ia);
plog("sending ModeCfg set");
st->st_state = STATE_MODE_CFG_R1;
- return modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
+ stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
+ if (stat == STF_OK)
+ st->st_modecfg.started = TRUE;
+ return stat;
+}
+
+/*
+ * Send XAUTH credentials request (username + password)
+ */
+stf_status
+xauth_send_request(struct state *st)
+{
+ stf_status stat;
+ internal_addr_t ia;
+
+ init_internal_addr(&ia);
+ ia.attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)
+ | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF);
+
+ plog("sending XAUTH request");
+ st->st_state = STATE_XAUTH_R1;
+ stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
+ if (stat == STF_OK)
+ st->st_xauth.started = TRUE;
+ return stat;
}
/*
case INTERNAL_IP4_NBNS:
ia->attr_set |= LELEM(attr_type);
break;
+ case XAUTH_TYPE:
+ ia->xauth_type = attr.isaat_lv;
+ ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
+ break;
+ case XAUTH_USER_NAME:
+ setchunk(ia->xauth_secret.user_name, strattr.cur, attr_len);
+ ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
+ break;
+ case XAUTH_USER_PASSWORD:
+ setchunk(ia->xauth_secret.user_password, strattr.cur, attr_len);
+ ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
+ break;
+ case XAUTH_STATUS:
+ ia->xauth_status = attr.isaat_lv;
+ ia->attr_set |= LELEM(attr_type - XAUTH_BASE + MODECFG_ROOF);
+ break;
default:
plog("unsupported ModeCfg attribute %s received."
, enum_show(&modecfg_attr_names, attr_type));
stat = modecfg_parse_attributes(&p->pbs, &ia_candidate);
if (stat == STF_OK)
{
- /* retrun with a valid set of attributes */
+ /* return with a valid set of attributes */
*ia = ia_candidate;
return STF_OK;
}
get_internal_addr(st->st_connection, &ia);
- /* build ISAKMP_CFG_REPLY */
+ plog("sending ModeCfg reply");
+
stat = modecfg_build_msg(st, &md->rbody
, ISAKMP_CFG_REPLY
, &ia
init_internal_addr(&ia);
ia.attr_set = attr_set & SUPPORTED_ATTR_SET;
+ plog("sending ModeCfg ack");
+
stat = modecfg_build_msg(st, &md->rbody
, ISAKMP_CFG_ACK
, &ia
st->st_msgid = 0;
return STF_OK;
}
+
+/* STATE_XAUTH_R1:
+ * HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD) --> HDR*, HASH, ATTR(STATUS)
+ *
+ * used on the XAUTH server (responder)
+ */
+stf_status
+xauth_inR1(struct msg_digest *md)
+{
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat;
+ bool status;
+
+ plog("parsing XAUTH reply");
+
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
+ if (stat != STF_OK)
+ return stat;
+
+ /* check XAUTH reply */
+ if ((ia.attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF)) != LEMPTY)
+ {
+ plog("received FAIL status in XAUTH reply");
+ return STF_INTERNAL_ERROR;
+ }
+ if ((ia.attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
+ {
+ plog("user name attribute is missing in XAUTH reply");
+ return STF_SUSPEND;
+ }
+ if ((ia.attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
+ {
+ plog("user password attribute is missing in XAUTH reply");
+ return STF_SUSPEND;
+ }
+
+ status = xauth_verify_secret(&ia.xauth_secret);
+
+ /* prepare XAUTH set which sends the authentication status */
+ init_internal_addr(&ia);
+ ia.attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF);
+ ia.xauth_status = status;
+
+ plog("sending XAUTH status: %s", status? "OK":"FAIL");
+
+ stat = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_SET
+ , &ia
+ , isama_id);
+ return STF_OK;
+}
+
+/* STATE_XAUTH_R2:
+ * HDR*, ATTR(STATUS), HASH --> Done
+ *
+ * used on the XAUTH server (responder)
+ */
+stf_status
+xauth_inR2(struct msg_digest *md)
+{
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat;
+
+ plog("parsing XAUTH ack");
+
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
+ if (stat != STF_OK)
+ return stat;
+
+ st->st_msgid = 0;
+ return STF_OK;
+}
+
+/* STATE_XAUTH_I0:
+ * HDR*, HASH, ATTR(REQ) --> HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD)
+ *
+ * used on the XAUTH client (initiator)
+ */
+stf_status
+xauth_inI0(struct msg_digest *md)
+{
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat;
+
+ plog("parsing XAUTH request");
+
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
+ if (stat != STF_OK)
+ return stat;
+
+ /* check XAUTH request */
+ if ((ia.attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE + MODECFG_ROOF)) != LEMPTY
+ && ia.xauth_type != XAUTH_TYPE_GENERIC)
+ {
+ plog("xauth type %s is not supported", enum_name(&xauth_type_names, ia.xauth_type));
+ stat = STF_FAIL;
+ }
+ if ((ia.attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
+ {
+ plog("user name attribute is missing in XAUTH request");
+ stat = STF_FAIL;
+ }
+ if ((ia.attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
+ {
+ plog("user password attribute is missing in XAUTH request");
+ stat = STF_FAIL;
+ }
+
+ /* prepare XAUTH reply */
+ init_internal_addr(&ia);
+
+ if (stat == STF_OK)
+ {
+ /* get user credentials */
+ if (!xauth_get_secret(&ia.xauth_secret))
+ {
+ plog("xauth user credentials not found");
+ stat = STF_FAIL;
+ }
+ }
+ if (stat == STF_OK)
+ {
+ ia.attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)
+ | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF);
+ }
+ else
+ {
+ ia.attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF);
+ ia.xauth_status = FALSE;
+ }
+
+ plog("sending XAUTH reply");
+
+ stat = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_REPLY
+ , &ia
+ , isama_id);
+ if (stat != STF_OK)
+ {
+ /* notification payload - not exactly the right choice, but okay */
+ md->note = ATTRIBUTES_NOT_SUPPORTED;
+ return stat;
+ }
+ st->st_xauth.started = TRUE;
+ return STF_OK;
+}
+
+/* STATE_XAUTH_I1:
+ * HDR*, HASH, ATTR(STATUS) --> HDR*, HASH, ATTR(ACK)
+ *
+ * used on the XAUTH client (initiator)
+ */
+stf_status
+xauth_inI1(struct msg_digest *md)
+{
+ struct state *const st = md->st;
+ u_int16_t isama_id;
+ internal_addr_t ia;
+ stf_status stat;
+
+ plog("parsing XAUTH status");
+
+ stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
+ if (stat != STF_OK)
+ return stat;
+
+ /* prepare XAUTH set which sends the authentication status */
+ init_internal_addr(&ia);
+
+ plog("sending XAUTH ack");
+
+ stat = modecfg_build_msg(st, &md->rbody
+ , ISAKMP_CFG_ACK
+ , &ia
+ , isama_id);
+ st->st_msgid = 0;
+ return stat;
+}
* RCSID $Id: modecfg.h,v 1.1 2005/01/06 22:10:15 as Exp $
*/
+#ifndef _MODECFG_H
+#define _MODECFG_H
+
struct state;
+struct msg_digest;
/* ModeConfig starting functions */
extern stf_status modecfg_send_request(struct state *st);
extern stf_status modecfg_inR1(struct msg_digest *md);
extern stf_status modecfg_inI1(struct msg_digest *md);
extern stf_status modecfg_inI2(struct msg_digest *md);
+
+/* XAUTH start function */
+extern stf_status xauth_send_request(struct state *st);
+
+/* XAUTH state transition funcgtions */
+extern stf_status xauth_inR1(struct msg_digest *md);
+extern stf_status xauth_inR2(struct msg_digest *md);
+extern stf_status xauth_inI0(struct msg_digest *md);
+extern stf_status xauth_inI1(struct msg_digest *md);
+
+#endif /* _MODECFG_H */
/**************** 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 },
};
/* arrays of transforms, each in in preference order */
static struct db_trans espa_trans[] = {
- { ESP_3DES, AD(espmd5_attr) },
{ ESP_3DES, AD(espsha1_attr) },
};
#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) },
};
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
*/
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);
* 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;
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;
}
}
}
}
+ 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).
, 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;
/* 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:
}
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:
}
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));
{
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:
*/
};
-/* The oakley sadb is subscripted by a bitset with members
- * from POLICY_PSK and POLICY_RSASIG.
- */
-extern struct db_sa oakley_sadb[1 << 2];
+/* The oakley sadb */
+extern struct db_sa oakley_sadb;
/* The ipsec sadb is subscripted by a bitset with members
* from POLICY_ENCRYPT, POLICY_AUTHENTICATE, POLICY_COMPRESS
extern notification_t parse_isakmp_policy(
pb_stream *proposal_pbs, /* body of proposal Payload */
u_int notrans, /* number of transforms */
- lset_t *policy); /* RSA or PSK policy */
+ lset_t *policy); /* RSA, PSK or XAUTH policy */
extern notification_t parse_isakmp_sa_body(
u_int32_t ipsecdoisit, /* IPsec DOI SIT bitset */
pb_stream *proposal_pbs, /* body of proposal Payload */
struct isakmp_proposal *proposal,
pb_stream *r_sa_pbs, /* if non-NULL, where to emit winning SA */
- struct state *st); /* current state object */
+ struct state *st, /* current state object */
+ bool initiator); /* is caller initiator? */
extern notification_t parse_ipsec_sa_body(
pb_stream *sa_pbs, /* body of input SA Payload */