added XAUTH server and client support
This commit is contained in:
+29
-15
@@ -1043,10 +1043,10 @@ add_connection(const whack_message_t *wm)
|
||||
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;
|
||||
|
||||
@@ -3213,13 +3213,17 @@ find_host_connection(const ip_address *me, u_int16_t my_port
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -3326,11 +3330,17 @@ refine_host_connection(const struct state *st, const struct id *peer_id
|
||||
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);
|
||||
}
|
||||
@@ -3353,17 +3363,21 @@ refine_host_connection(const struct state *st, const struct id *peer_id
|
||||
|
||||
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])
|
||||
)
|
||||
@@ -3382,13 +3396,11 @@ refine_host_connection(const struct state *st, const struct id *peer_id
|
||||
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);
|
||||
@@ -3404,6 +3416,8 @@ refine_host_connection(const struct state *st, const struct id *peer_id
|
||||
break;
|
||||
|
||||
case OAKLEY_RSA_SIG:
|
||||
case XAUTHInitRSA:
|
||||
case XAUTHRespRSA:
|
||||
/*
|
||||
* We must at least be able to find our private key
|
||||
.*/
|
||||
|
||||
+13
-9
@@ -183,8 +183,10 @@ static const char *const state_name[] = {
|
||||
"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",
|
||||
|
||||
@@ -222,16 +224,18 @@ const char *const state_story[] = {
|
||||
"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 */
|
||||
};
|
||||
|
||||
|
||||
+16
-6
@@ -508,10 +508,12 @@ enum state_kind {
|
||||
|
||||
/* 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 */
|
||||
@@ -531,18 +533,26 @@ enum state_kind {
|
||||
|
||||
#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 \
|
||||
|
||||
+107
-11
@@ -436,6 +436,38 @@ static const struct state_microcode state_microcode_table[] = {
|
||||
, 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)
|
||||
@@ -1238,6 +1270,11 @@ process_packet(struct msg_digest **mdp)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1470,7 +1507,7 @@ process_packet(struct msg_digest **mdp)
|
||||
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;
|
||||
@@ -1478,7 +1515,7 @@ process_packet(struct msg_digest **mdp)
|
||||
|
||||
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;
|
||||
@@ -1486,7 +1523,7 @@ process_packet(struct msg_digest **mdp)
|
||||
|
||||
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;
|
||||
@@ -1497,7 +1534,9 @@ process_packet(struct msg_digest **mdp)
|
||||
|
||||
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?
|
||||
*/
|
||||
@@ -1506,7 +1545,7 @@ process_packet(struct msg_digest **mdp)
|
||||
|
||||
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;
|
||||
@@ -1516,7 +1555,7 @@ process_packet(struct msg_digest **mdp)
|
||||
|
||||
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 */
|
||||
@@ -1545,7 +1584,16 @@ process_packet(struct msg_digest **mdp)
|
||||
*
|
||||
*/
|
||||
|
||||
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;
|
||||
@@ -1558,7 +1606,7 @@ process_packet(struct msg_digest **mdp)
|
||||
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;
|
||||
}
|
||||
@@ -1610,7 +1658,23 @@ process_packet(struct msg_digest **mdp)
|
||||
|
||||
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);
|
||||
@@ -2023,6 +2087,8 @@ process_packet(struct msg_digest **mdp)
|
||||
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;
|
||||
@@ -2238,7 +2304,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
|
||||
}
|
||||
/* advance b to end of string */
|
||||
b = b + strlen(b);
|
||||
|
||||
|
||||
if (st->st_ah.present)
|
||||
{
|
||||
snprintf(b, sizeof(sadetails)-(b-sadetails)-1
|
||||
@@ -2251,7 +2317,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
|
||||
}
|
||||
/* advance b to end of string */
|
||||
b = b + strlen(b);
|
||||
|
||||
|
||||
if (st->st_ipcomp.present)
|
||||
{
|
||||
snprintf(b, sizeof(sadetails)-(b-sadetails)-1
|
||||
@@ -2306,6 +2372,25 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
|
||||
, 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)
|
||||
@@ -2332,6 +2417,17 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
|
||||
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)
|
||||
|
||||
+29
-2
@@ -233,6 +233,7 @@ ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
|
||||
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)
|
||||
@@ -298,11 +299,37 @@ ike_alg_db_new(struct alg_info_ike *ai , lset_t policy)
|
||||
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;
|
||||
|
||||
+29
-12
@@ -950,8 +950,8 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
|
||||
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;
|
||||
@@ -1211,11 +1211,15 @@ generate_skeyids_iv(struct state *st)
|
||||
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;
|
||||
@@ -3151,7 +3155,7 @@ main_inI1_outR1(struct msg_digest *md)
|
||||
|
||||
/* 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)
|
||||
@@ -3258,7 +3262,7 @@ main_inR1_outI2(struct msg_digest *md)
|
||||
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)
|
||||
@@ -3343,9 +3347,11 @@ main_inI2_outR2(struct msg_digest *md)
|
||||
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 */
|
||||
@@ -3488,6 +3494,10 @@ main_inR2_outI3(struct msg_digest *md)
|
||||
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));
|
||||
|
||||
@@ -3509,8 +3519,7 @@ main_inR2_outI3(struct msg_digest *md)
|
||||
*/
|
||||
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 */
|
||||
@@ -3554,7 +3563,7 @@ main_inR2_outI3(struct msg_digest *md)
|
||||
}
|
||||
|
||||
/* CERT out */
|
||||
if ( st->st_oakley.auth == OAKLEY_RSA_SIG)
|
||||
if (RSA_auth)
|
||||
{
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("our certificate policy is %s"
|
||||
@@ -3710,6 +3719,8 @@ main_id_and_auth(struct msg_digest *md
|
||||
switch (st->st_oakley.auth)
|
||||
{
|
||||
case OAKLEY_PRESHARED_KEY:
|
||||
case XAUTHInitPreShared:
|
||||
case XAUTHRespPreShared:
|
||||
{
|
||||
pb_stream *const hash_pbs = &md->chain[ISAKMP_NEXT_HASH]->pbs;
|
||||
|
||||
@@ -3726,6 +3737,8 @@ main_id_and_auth(struct msg_digest *md
|
||||
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
|
||||
@@ -3903,6 +3916,7 @@ main_inI3_outR3_tail(struct msg_digest *md
|
||||
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;
|
||||
|
||||
@@ -3925,7 +3939,10 @@ main_inI3_outR3_tail(struct msg_digest *md
|
||||
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);
|
||||
|
||||
@@ -3963,7 +3980,7 @@ main_inI3_outR3_tail(struct msg_digest *md
|
||||
}
|
||||
|
||||
/* CERT out */
|
||||
if (st->st_oakley.auth == OAKLEY_RSA_SIG)
|
||||
if (RSA_auth)
|
||||
{
|
||||
DBG(DBG_CONTROL,
|
||||
DBG_log("our certificate policy is %s"
|
||||
|
||||
+104
-5
@@ -72,6 +72,7 @@ struct secret {
|
||||
union {
|
||||
chunk_t preshared_secret;
|
||||
RSA_private_key_t RSA_private_key;
|
||||
xauth_t xauth_secret;
|
||||
smartcard_t *smartcard;
|
||||
} u;
|
||||
secret_t *next;
|
||||
@@ -293,14 +294,12 @@ get_preshared_secret(const struct connection *c)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -583,6 +582,98 @@ process_rsa_keyfile(RSA_private_key_t *rsak, int whackfd)
|
||||
return load_rsa_private_key(filename, &pass, rsak);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
@@ -694,6 +785,10 @@ process_secret(secret_t *s, int whackfd)
|
||||
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);
|
||||
@@ -923,7 +1018,7 @@ void
|
||||
free_preshared_secrets(void)
|
||||
{
|
||||
lock_certs_and_keys("free_preshared_secrets");
|
||||
|
||||
|
||||
if (secrets != NULL)
|
||||
{
|
||||
secret_t *s, *ns;
|
||||
@@ -949,6 +1044,10 @@ free_preshared_secrets(void)
|
||||
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;
|
||||
@@ -959,7 +1058,7 @@ free_preshared_secrets(void)
|
||||
}
|
||||
secrets = NULL;
|
||||
}
|
||||
|
||||
|
||||
unlock_certs_and_keys("free_preshard_secrets");
|
||||
}
|
||||
|
||||
|
||||
+12
-1
@@ -37,6 +37,7 @@ enum PrivateKeyKind {
|
||||
PPK_PSK,
|
||||
/* PPK_DSS, */ /* not implemented */
|
||||
PPK_RSA,
|
||||
PPK_XAUTH,
|
||||
PPK_PIN
|
||||
};
|
||||
|
||||
@@ -100,11 +101,21 @@ extern void add_pgp_public_key(pgpcert_t *cert, time_t until
|
||||
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 */
|
||||
|
||||
+294
-14
@@ -39,6 +39,7 @@
|
||||
#include "crypto.h"
|
||||
#include "modecfg.h"
|
||||
#include "whack.h"
|
||||
#include "keys.h"
|
||||
|
||||
#define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
|
||||
| LELEM(INTERNAL_IP4_NETMASK) \
|
||||
@@ -53,10 +54,17 @@ typedef struct internal_addr internal_addr_t;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -66,6 +74,10 @@ static void
|
||||
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]);
|
||||
@@ -218,7 +230,20 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
|
||||
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)
|
||||
@@ -288,14 +313,34 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
|
||||
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));
|
||||
@@ -306,13 +351,17 @@ modecfg_build_msg(struct state *st, pb_stream *rbody
|
||||
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;
|
||||
@@ -371,7 +420,6 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
|
||||
delete_event(st);
|
||||
event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st);
|
||||
}
|
||||
st->st_modecfg.started = TRUE;
|
||||
return STF_OK;
|
||||
}
|
||||
|
||||
@@ -381,6 +429,7 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
|
||||
stf_status
|
||||
modecfg_send_request(struct state *st)
|
||||
{
|
||||
stf_status stat;
|
||||
internal_addr_t ia;
|
||||
|
||||
init_internal_addr(&ia);
|
||||
@@ -389,7 +438,10 @@ modecfg_send_request(struct state *st)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -398,13 +450,38 @@ modecfg_send_request(struct state *st)
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -442,6 +519,22 @@ modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia)
|
||||
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));
|
||||
@@ -483,7 +576,7 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
|
||||
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;
|
||||
}
|
||||
@@ -521,7 +614,8 @@ modecfg_inR0(struct msg_digest *md)
|
||||
|
||||
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
|
||||
@@ -611,6 +705,8 @@ modecfg_inI2(struct msg_digest *md)
|
||||
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
|
||||
@@ -625,3 +721,187 @@ modecfg_inI2(struct msg_digest *md)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,11 @@
|
||||
* 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);
|
||||
@@ -26,3 +30,14 @@ extern stf_status modecfg_inR0(struct msg_digest *md);
|
||||
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 */
|
||||
|
||||
+114
-187
@@ -50,158 +50,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 },
|
||||
};
|
||||
@@ -209,7 +77,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) },
|
||||
};
|
||||
|
||||
@@ -219,13 +86,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) },
|
||||
};
|
||||
|
||||
@@ -448,7 +313,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
|
||||
*/
|
||||
@@ -499,7 +364,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);
|
||||
@@ -877,7 +742,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;
|
||||
|
||||
@@ -934,6 +801,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;
|
||||
}
|
||||
@@ -943,25 +822,37 @@ parse_isakmp_policy(pb_stream *proposal_pbs, u_int notrans, lset_t *policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
DBG(DBG_CONTROL|DBG_PARSING,
|
||||
DBG_log("preparse_isakmp_policy: peer requests %s authentication"
|
||||
, (*policy & POLICY_PSK) ? "PSK":"RSASIG")
|
||||
)
|
||||
}
|
||||
DBG(DBG_CONTROL|DBG_PARSING,
|
||||
DBG_log("preparse_isakmp_policy: peer requests %s authentication"
|
||||
, prettypolicy(*policy))
|
||||
)
|
||||
return NOTHING_WRONG;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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 ugh;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
@@ -976,7 +867,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;
|
||||
@@ -1082,6 +974,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:
|
||||
@@ -1091,23 +987,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:
|
||||
@@ -1118,18 +1021,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));
|
||||
@@ -1183,10 +1097,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:
|
||||
|
||||
+5
-6
@@ -60,10 +60,8 @@ struct db_sa {
|
||||
*/
|
||||
};
|
||||
|
||||
/* 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
|
||||
@@ -90,14 +88,15 @@ extern notification_t preparse_isakmp_sa_body(
|
||||
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 */
|
||||
|
||||
Reference in New Issue
Block a user