mirror of
https://github.com/strongswan/strongswan.git
synced 2025-11-15 00:01:42 -05:00
added XAUTH server and client support
This commit is contained in:
parent
ac048a8d2c
commit
b4f3cd5ccf
@ -3333,6 +3333,9 @@ refine_host_connection(const struct state *st, const struct id *peer_id
|
|||||||
case XAUTHInitPreShared:
|
case XAUTHInitPreShared:
|
||||||
case XAUTHRespPreShared:
|
case XAUTHRespPreShared:
|
||||||
auth_policy = POLICY_XAUTH_PSK;
|
auth_policy = POLICY_XAUTH_PSK;
|
||||||
|
psk = get_preshared_secret(c);
|
||||||
|
if (psk == NULL)
|
||||||
|
return NULL; /* cannot determine PSK! */
|
||||||
break;
|
break;
|
||||||
case OAKLEY_RSA_SIG:
|
case OAKLEY_RSA_SIG:
|
||||||
auth_policy = POLICY_RSASIG;
|
auth_policy = POLICY_RSASIG;
|
||||||
|
|||||||
@ -54,8 +54,8 @@ const char compile_time_interop_options[] = ""
|
|||||||
#ifdef VENDORID
|
#ifdef VENDORID
|
||||||
" VENDORID"
|
" VENDORID"
|
||||||
#endif
|
#endif
|
||||||
#ifdef XAUTH_VID
|
#ifdef CISCO_QUIRKS
|
||||||
" XAUTH_VID"
|
" CISCO_QUIRKS"
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_KEYRR
|
#ifdef USE_KEYRR
|
||||||
" KEYRR"
|
" KEYRR"
|
||||||
@ -183,19 +183,22 @@ static const char *const state_name[] = {
|
|||||||
"STATE_INFO",
|
"STATE_INFO",
|
||||||
"STATE_INFO_PROTECTED",
|
"STATE_INFO_PROTECTED",
|
||||||
|
|
||||||
"STATE_XAUTH_R1",
|
|
||||||
"STATE_XAUTH_R2",
|
|
||||||
"STATE_XAUTH_R3",
|
|
||||||
"STATE_XAUTH_I0",
|
"STATE_XAUTH_I0",
|
||||||
|
"STATE_XAUTH_R1",
|
||||||
"STATE_XAUTH_I1",
|
"STATE_XAUTH_I1",
|
||||||
|
"STATE_XAUTH_R2",
|
||||||
"STATE_XAUTH_I2",
|
"STATE_XAUTH_I2",
|
||||||
|
"STATE_XAUTH_R3",
|
||||||
|
|
||||||
"STATE_MODE_CFG_R0",
|
"STATE_MODE_CFG_R0",
|
||||||
"STATE_MODE_CFG_R1",
|
|
||||||
"STATE_MODE_CFG_R2",
|
|
||||||
"STATE_MODE_CFG_I1",
|
"STATE_MODE_CFG_I1",
|
||||||
|
"STATE_MODE_CFG_R1",
|
||||||
"STATE_MODE_CFG_I2",
|
"STATE_MODE_CFG_I2",
|
||||||
|
|
||||||
|
"STATE_MODE_CFG_I0",
|
||||||
|
"STATE_MODE_CFG_R3",
|
||||||
"STATE_MODE_CFG_I3",
|
"STATE_MODE_CFG_I3",
|
||||||
|
"STATE_MODE_CFG_R4",
|
||||||
|
|
||||||
"STATE_IKE_ROOF"
|
"STATE_IKE_ROOF"
|
||||||
};
|
};
|
||||||
@ -224,19 +227,22 @@ const char *const state_story[] = {
|
|||||||
"got Informational Message in clear", /* STATE_INFO */
|
"got Informational Message in clear", /* STATE_INFO */
|
||||||
"got encrypted Informational Message", /* STATE_INFO_PROTECTED */
|
"got encrypted Informational Message", /* STATE_INFO_PROTECTED */
|
||||||
|
|
||||||
"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 */
|
"expecting XAUTH request", /* STATE_XAUTH_I0 */
|
||||||
|
"sent XAUTH request, expecting reply", /* STATE_XAUTH_R1 */
|
||||||
"sent XAUTH reply, expecting status", /* STATE_XAUTH_I1 */
|
"sent XAUTH reply, expecting status", /* STATE_XAUTH_I1 */
|
||||||
|
"sent XAUTH status, expecting ack", /* STATE_XAUTH_R2 */
|
||||||
"sent XAUTH ack, established", /* STATE_XAUTH_I2 */
|
"sent XAUTH ack, established", /* STATE_XAUTH_I2 */
|
||||||
|
"received XAUTH ack, established", /* STATE_XAUTH_R3 */
|
||||||
|
|
||||||
"expecting ModeCfg request", /* STATE_MODE_CFG_R0 */
|
"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 */
|
"sent ModeCfg request, expecting reply", /* STATE_MODE_CFG_I1 */
|
||||||
"sent ModeCfg ack, established", /* STATE_MODE_CFG_I2 */
|
"sent ModeCfg reply, established", /* STATE_MODE_CFG_R1 */
|
||||||
"received ModeCfg set, sent ack", /* STATE_MODE_CFG_I3 */
|
"received ModeCfg reply, established", /* STATE_MODE_CFG_I2 */
|
||||||
|
|
||||||
|
"expecting ModeCfg set", /* STATE_MODE_CFG_I0 */
|
||||||
|
"sent ModeCfg set, expecting ack", /* STATE_MODE_CFG_R3 */
|
||||||
|
"sent ModeCfg ack, established", /* STATE_MODE_CFG_I3 */
|
||||||
|
"received ModeCfg ack, established", /* STATE_MODE_CFG_R4 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* kind of struct connection */
|
/* kind of struct connection */
|
||||||
|
|||||||
@ -508,23 +508,27 @@ enum state_kind {
|
|||||||
|
|
||||||
/* XAUTH states */
|
/* XAUTH states */
|
||||||
|
|
||||||
STATE_XAUTH_R1, /* responder states (server) */
|
STATE_XAUTH_I0, /* initiator state (client) */
|
||||||
|
STATE_XAUTH_R1, /* responder state (server) */
|
||||||
|
STATE_XAUTH_I1,
|
||||||
STATE_XAUTH_R2,
|
STATE_XAUTH_R2,
|
||||||
|
STATE_XAUTH_I2,
|
||||||
STATE_XAUTH_R3,
|
STATE_XAUTH_R3,
|
||||||
|
|
||||||
STATE_XAUTH_I0, /* initiator states (client) */
|
|
||||||
STATE_XAUTH_I1,
|
|
||||||
STATE_XAUTH_I2,
|
|
||||||
|
|
||||||
/* Mode Config states */
|
/* Mode Config pull states */
|
||||||
|
|
||||||
STATE_MODE_CFG_R0, /* responder states */
|
STATE_MODE_CFG_R0, /* responder state (server) */
|
||||||
|
STATE_MODE_CFG_I1, /* initiator state (client) */
|
||||||
STATE_MODE_CFG_R1,
|
STATE_MODE_CFG_R1,
|
||||||
STATE_MODE_CFG_R2,
|
|
||||||
|
|
||||||
STATE_MODE_CFG_I1, /* initiator states */
|
|
||||||
STATE_MODE_CFG_I2,
|
STATE_MODE_CFG_I2,
|
||||||
|
|
||||||
|
/* Mode Config push states */
|
||||||
|
|
||||||
|
STATE_MODE_CFG_I0, /* initiator state (client) */
|
||||||
|
STATE_MODE_CFG_R3, /* responder state (server) */
|
||||||
STATE_MODE_CFG_I3,
|
STATE_MODE_CFG_I3,
|
||||||
|
STATE_MODE_CFG_R4,
|
||||||
|
|
||||||
STATE_IKE_ROOF
|
STATE_IKE_ROOF
|
||||||
};
|
};
|
||||||
@ -537,26 +541,26 @@ enum state_kind {
|
|||||||
LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \
|
LELEM(STATE_MAIN_R3) | LELEM(STATE_MAIN_I4) \
|
||||||
| LELEM(STATE_XAUTH_R1) | LELEM(STATE_XAUTH_R2) | LELEM(STATE_XAUTH_R3) \
|
| LELEM(STATE_XAUTH_R1) | LELEM(STATE_XAUTH_R2) | LELEM(STATE_XAUTH_R3) \
|
||||||
| LELEM(STATE_XAUTH_I1) | LELEM(STATE_XAUTH_I2) \
|
| LELEM(STATE_XAUTH_I1) | LELEM(STATE_XAUTH_I2) \
|
||||||
| LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_R2) \
|
| LELEM(STATE_MODE_CFG_I1) | LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_I2) \
|
||||||
| LELEM(STATE_MODE_CFG_I2) | LELEM(STATE_MODE_CFG_I3))
|
| LELEM(STATE_MODE_CFG_R3) | LELEM(STATE_MODE_CFG_I3) | LELEM(STATE_MODE_CFG_R4))
|
||||||
|
|
||||||
#define IS_PHASE1(s) ((STATE_MAIN_R0 <= (s) && (s) <= STATE_MAIN_I4) \
|
#define IS_PHASE1(s) ((STATE_MAIN_R0 <= (s) && (s) <= STATE_MAIN_I4) \
|
||||||
|| (STATE_XAUTH_R1 <= (s) && (s) <= STATE_XAUTH_I2) \
|
|| (STATE_XAUTH_I0 <= (s) && (s) <= STATE_XAUTH_R3) \
|
||||||
|| (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_I3))
|
|| (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_R4))
|
||||||
|
|
||||||
#define IS_QUICK(s) (STATE_QUICK_R0 <= (s) && (s) <= STATE_QUICK_R2)
|
#define IS_QUICK(s) (STATE_QUICK_R0 <= (s) && (s) <= STATE_QUICK_R2)
|
||||||
#define IS_ISAKMP_ENCRYPTED(s) (STATE_MAIN_I2 <= (s))
|
#define IS_ISAKMP_ENCRYPTED(s) (STATE_MAIN_I2 <= (s))
|
||||||
#define IS_ISAKMP_SA_ESTABLISHED(s) ( \
|
|
||||||
(s) == STATE_MAIN_R3 \
|
#define IS_ISAKMP_SA_ESTABLISHED(s) ( \
|
||||||
|| (s) == STATE_MAIN_I4 \
|
(s) == STATE_MAIN_R3 \
|
||||||
|| (s) == STATE_XAUTH_R1 \
|
|| (s) == STATE_MAIN_I4 \
|
||||||
|| (s) == STATE_XAUTH_R2 \
|
|| (s) == STATE_XAUTH_R3 \
|
||||||
|| (s) == STATE_XAUTH_R3 \
|
|| (s) == STATE_XAUTH_I2 \
|
||||||
|| (s) == STATE_XAUTH_I1 \
|
|| (s) == STATE_MODE_CFG_R1 \
|
||||||
|| (s) == STATE_XAUTH_I2 \
|
|| (s) == STATE_MODE_CFG_I2 \
|
||||||
|| (s) == STATE_MODE_CFG_R1 \
|
|| (s) == STATE_MODE_CFG_I3 \
|
||||||
|| (s) == STATE_MODE_CFG_R2 \
|
|| (s) == STATE_MODE_CFG_R4)
|
||||||
|| (s) == STATE_MODE_CFG_I2 \
|
|
||||||
|| (s) == STATE_MODE_CFG_I3)
|
|
||||||
#define IS_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_I2 || (s) == STATE_QUICK_R2)
|
#define IS_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_I2 || (s) == STATE_QUICK_R2)
|
||||||
#define IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_R1)
|
#define IS_ONLY_INBOUND_IPSEC_SA_ESTABLISHED(s) ((s) == STATE_QUICK_R1)
|
||||||
|
|
||||||
|
|||||||
@ -436,77 +436,81 @@ static const struct state_microcode state_microcode_table[] = {
|
|||||||
, P(HASH), LEMPTY, PT(NONE)
|
, P(HASH), LEMPTY, PT(NONE)
|
||||||
, EVENT_NULL, informational },
|
, EVENT_NULL, informational },
|
||||||
|
|
||||||
/* XAUTH server */
|
/* XAUTH state transitions */
|
||||||
|
{ STATE_XAUTH_I0, STATE_XAUTH_I1
|
||||||
|
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
|
||||||
|
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
||||||
|
, EVENT_RETRANSMIT, xauth_inI0 },
|
||||||
|
|
||||||
{ STATE_XAUTH_R1, STATE_XAUTH_R2
|
{ STATE_XAUTH_R1, STATE_XAUTH_R2
|
||||||
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
|
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
|
||||||
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
||||||
, EVENT_RETRANSMIT, xauth_inR1 },
|
, 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
|
{ STATE_XAUTH_I1, STATE_XAUTH_I2
|
||||||
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
|
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
|
||||||
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
||||||
, EVENT_SA_REPLACE, xauth_inI1 },
|
, EVENT_SA_REPLACE, xauth_inI1 },
|
||||||
|
|
||||||
|
{ 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_I2, STATE_UNDEFINED
|
{ STATE_XAUTH_I2, STATE_UNDEFINED
|
||||||
, SMF_ALL_AUTH | SMF_ENCRYPTED
|
, SMF_ALL_AUTH | SMF_ENCRYPTED
|
||||||
, LEMPTY, LEMPTY, PT(NONE)
|
, LEMPTY, LEMPTY, PT(NONE)
|
||||||
, EVENT_NULL, unexpected },
|
, EVENT_NULL, unexpected },
|
||||||
|
|
||||||
/* MODE_CFG_x:
|
{ STATE_XAUTH_R3, STATE_UNDEFINED
|
||||||
* Case R0: Responder -> Initiator
|
|
||||||
* <- Req(addr=0)
|
|
||||||
* Reply(ad=x) ->
|
|
||||||
*
|
|
||||||
* Case R1: Set(addr=x) ->
|
|
||||||
* <- Ack(ok)
|
|
||||||
*/
|
|
||||||
|
|
||||||
{ STATE_MODE_CFG_R0, STATE_MODE_CFG_R1
|
|
||||||
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY
|
|
||||||
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
|
||||||
, EVENT_SA_REPLACE, modecfg_inR0 },
|
|
||||||
|
|
||||||
{ STATE_MODE_CFG_R1, STATE_MODE_CFG_R2
|
|
||||||
, SMF_ALL_AUTH | SMF_ENCRYPTED
|
|
||||||
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
|
||||||
, EVENT_SA_REPLACE, modecfg_inR1 },
|
|
||||||
|
|
||||||
{ STATE_MODE_CFG_R2, STATE_UNDEFINED
|
|
||||||
, SMF_ALL_AUTH | SMF_ENCRYPTED
|
, SMF_ALL_AUTH | SMF_ENCRYPTED
|
||||||
, LEMPTY, LEMPTY, PT(NONE)
|
, LEMPTY, LEMPTY, PT(NONE)
|
||||||
, EVENT_NULL, unexpected },
|
, EVENT_NULL, unexpected },
|
||||||
|
|
||||||
|
/* ModeCfg pull mode state transitions */
|
||||||
|
|
||||||
|
{ STATE_MODE_CFG_R0, STATE_MODE_CFG_R1
|
||||||
|
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
|
||||||
|
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
||||||
|
, EVENT_SA_REPLACE, modecfg_inR0 },
|
||||||
|
|
||||||
{ STATE_MODE_CFG_I1, STATE_MODE_CFG_I2
|
{ STATE_MODE_CFG_I1, STATE_MODE_CFG_I2
|
||||||
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
|
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
|
||||||
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
||||||
, EVENT_SA_REPLACE, modecfg_inI1 },
|
, EVENT_SA_REPLACE, modecfg_inI1 },
|
||||||
|
|
||||||
{ STATE_MODE_CFG_I2, STATE_MODE_CFG_I3
|
{ STATE_MODE_CFG_R1, STATE_UNDEFINED
|
||||||
|
, SMF_ALL_AUTH | SMF_ENCRYPTED
|
||||||
|
, LEMPTY, LEMPTY, PT(NONE)
|
||||||
|
, EVENT_NULL, unexpected },
|
||||||
|
|
||||||
|
{ STATE_MODE_CFG_I2, STATE_UNDEFINED
|
||||||
|
, SMF_ALL_AUTH | SMF_ENCRYPTED
|
||||||
|
, LEMPTY, LEMPTY, PT(NONE)
|
||||||
|
, EVENT_NULL, unexpected },
|
||||||
|
|
||||||
|
/* ModeCfg push mode state transitions */
|
||||||
|
|
||||||
|
{ STATE_MODE_CFG_I0, STATE_MODE_CFG_I3
|
||||||
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
|
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2
|
||||||
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
||||||
, EVENT_SA_REPLACE, modecfg_inI2 },
|
, EVENT_SA_REPLACE, modecfg_inI0 },
|
||||||
|
|
||||||
|
{ STATE_MODE_CFG_R3, STATE_MODE_CFG_R4
|
||||||
|
, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2
|
||||||
|
, P(ATTR) | P(HASH), P(VID), PT(HASH)
|
||||||
|
, EVENT_SA_REPLACE, modecfg_inR3 },
|
||||||
|
|
||||||
{ STATE_MODE_CFG_I3, STATE_UNDEFINED
|
{ STATE_MODE_CFG_I3, STATE_UNDEFINED
|
||||||
, SMF_ALL_AUTH | SMF_ENCRYPTED
|
, SMF_ALL_AUTH | SMF_ENCRYPTED
|
||||||
, LEMPTY, LEMPTY, PT(NONE)
|
, LEMPTY, LEMPTY, PT(NONE)
|
||||||
, EVENT_NULL, unexpected },
|
, EVENT_NULL, unexpected },
|
||||||
|
|
||||||
|
{ STATE_MODE_CFG_R4, STATE_UNDEFINED
|
||||||
|
, SMF_ALL_AUTH | SMF_ENCRYPTED
|
||||||
|
, LEMPTY, LEMPTY, PT(NONE)
|
||||||
|
, EVENT_NULL, unexpected },
|
||||||
|
|
||||||
#undef P
|
#undef P
|
||||||
#undef PT
|
#undef PT
|
||||||
};
|
};
|
||||||
@ -1464,11 +1468,6 @@ process_packet(struct msg_digest **mdp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st->st_state == STATE_MODE_CFG_R2) /* Have we just give an IP address to peer? */
|
|
||||||
{
|
|
||||||
st->st_state = STATE_MAIN_R3; /* ISAKMP is up... */
|
|
||||||
}
|
|
||||||
|
|
||||||
set_cur_state(st);
|
set_cur_state(st);
|
||||||
|
|
||||||
if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
|
if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state))
|
||||||
@ -1588,7 +1587,7 @@ process_packet(struct msg_digest **mdp)
|
|||||||
& (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
|
& (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK))
|
||||||
!= LEMPTY;
|
!= LEMPTY;
|
||||||
|
|
||||||
if (has_xauth_policy
|
if (has_xauth_policy && !st->st_xauth.started
|
||||||
&& IS_PHASE1(st->st_state))
|
&& IS_PHASE1(st->st_state))
|
||||||
{
|
{
|
||||||
from_state = STATE_XAUTH_I0;
|
from_state = STATE_XAUTH_I0;
|
||||||
@ -1601,7 +1600,7 @@ process_packet(struct msg_digest **mdp)
|
|||||||
else if (st->st_connection->spd.this.modecfg
|
else if (st->st_connection->spd.this.modecfg
|
||||||
&& IS_PHASE1(st->st_state))
|
&& IS_PHASE1(st->st_state))
|
||||||
{
|
{
|
||||||
from_state = STATE_MODE_CFG_I2;
|
from_state = STATE_MODE_CFG_I0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1616,7 +1615,6 @@ process_packet(struct msg_digest **mdp)
|
|||||||
set_cur_state(st);
|
set_cur_state(st);
|
||||||
from_state = st->st_state;
|
from_state = st->st_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef NOTYET
|
#ifdef NOTYET
|
||||||
@ -2358,7 +2356,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
|
if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
|
||||||
|| IS_IPSEC_SA_ESTABLISHED(st->st_state))
|
|| IS_IPSEC_SA_ESTABLISHED(st->st_state))
|
||||||
{
|
{
|
||||||
/* log our success */
|
/* log our success */
|
||||||
plog("%s%s", story, sadetails);
|
plog("%s%s", story, sadetails);
|
||||||
@ -2391,6 +2389,17 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
|
|||||||
break;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/* Should we start ModeConfig as a client? */
|
/* Should we start ModeConfig as a client? */
|
||||||
if (st->st_connection->spd.this.modecfg
|
if (st->st_connection->spd.this.modecfg
|
||||||
&& IS_ISAKMP_SA_ESTABLISHED(st->st_state)
|
&& IS_ISAKMP_SA_ESTABLISHED(st->st_state)
|
||||||
@ -2417,17 +2426,6 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
|
|||||||
break;
|
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 */
|
/* Wait for ModeConfig set from server */
|
||||||
if (st->st_connection->spd.this.modecfg
|
if (st->st_connection->spd.this.modecfg
|
||||||
&& IS_ISAKMP_SA_ESTABLISHED(st->st_state)
|
&& IS_ISAKMP_SA_ESTABLISHED(st->st_state)
|
||||||
@ -2453,7 +2451,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
|
if (IS_ISAKMP_SA_ESTABLISHED(st->st_state)
|
||||||
|| IS_IPSEC_SA_ESTABLISHED(st->st_state))
|
|| IS_IPSEC_SA_ESTABLISHED(st->st_state))
|
||||||
release_whack(st);
|
release_whack(st);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@ -79,15 +79,6 @@
|
|||||||
#define SEND_PLUTO_VID 0
|
#define SEND_PLUTO_VID 0
|
||||||
#endif /* !VENDORID */
|
#endif /* !VENDORID */
|
||||||
|
|
||||||
/*
|
|
||||||
* are we sending an XAUTH VID (Cisco Mode Config Interoperability)?
|
|
||||||
*/
|
|
||||||
#ifdef XAUTH_VID
|
|
||||||
#define SEND_XAUTH_VID 1
|
|
||||||
#else /* !XAUTH_VID */
|
|
||||||
#define SEND_XAUTH_VID 0
|
|
||||||
#endif /* !XAUTH_VID */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* are we sending a Cisco Unity VID?
|
* are we sending a Cisco Unity VID?
|
||||||
*/
|
*/
|
||||||
@ -900,12 +891,12 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
|
|||||||
/* determine how many Vendor ID payloads we will be sending */
|
/* determine how many Vendor ID payloads we will be sending */
|
||||||
if (SEND_PLUTO_VID)
|
if (SEND_PLUTO_VID)
|
||||||
vids_to_send++;
|
vids_to_send++;
|
||||||
if (SEND_XAUTH_VID)
|
|
||||||
vids_to_send++;
|
|
||||||
if (SEND_CISCO_UNITY_VID)
|
if (SEND_CISCO_UNITY_VID)
|
||||||
vids_to_send++;
|
vids_to_send++;
|
||||||
if (c->spd.this.cert.type == CERT_PGP)
|
if (c->spd.this.cert.type == CERT_PGP)
|
||||||
vids_to_send++;
|
vids_to_send++;
|
||||||
|
/* always send XAUTH Vendor ID */
|
||||||
|
vids_to_send++;
|
||||||
/* always send DPD Vendor ID */
|
/* always send DPD Vendor ID */
|
||||||
vids_to_send++;
|
vids_to_send++;
|
||||||
if (nat_traversal_enabled)
|
if (nat_traversal_enabled)
|
||||||
@ -974,17 +965,6 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if enabled send XAUTH Vendor ID */
|
|
||||||
if (SEND_XAUTH_VID)
|
|
||||||
{
|
|
||||||
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
|
|
||||||
, &rbody, VID_MISC_XAUTH))
|
|
||||||
{
|
|
||||||
reset_cur_state();
|
|
||||||
return STF_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if enabled send Cisco Unity Vendor ID */
|
/* if enabled send Cisco Unity Vendor ID */
|
||||||
if (SEND_CISCO_UNITY_VID)
|
if (SEND_CISCO_UNITY_VID)
|
||||||
{
|
{
|
||||||
@ -1008,6 +988,14 @@ main_outI1(int whack_sock, struct connection *c, struct state *predecessor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Announce our ability to do eXtended AUTHentication to the peer */
|
||||||
|
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
|
||||||
|
, &rbody, VID_MISC_XAUTH))
|
||||||
|
{
|
||||||
|
reset_cur_state();
|
||||||
|
return STF_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* Announce our ability to do Dead Peer Detection to the peer */
|
/* Announce our ability to do Dead Peer Detection to the peer */
|
||||||
{
|
{
|
||||||
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
|
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
|
||||||
@ -3118,12 +3106,12 @@ main_inI1_outR1(struct msg_digest *md)
|
|||||||
/* determine how many Vendor ID payloads we will be sending */
|
/* determine how many Vendor ID payloads we will be sending */
|
||||||
if (SEND_PLUTO_VID)
|
if (SEND_PLUTO_VID)
|
||||||
vids_to_send++;
|
vids_to_send++;
|
||||||
if (SEND_XAUTH_VID)
|
|
||||||
vids_to_send++;
|
|
||||||
if (SEND_CISCO_UNITY_VID)
|
if (SEND_CISCO_UNITY_VID)
|
||||||
vids_to_send++;
|
vids_to_send++;
|
||||||
if (md->openpgp)
|
if (md->openpgp)
|
||||||
vids_to_send++;
|
vids_to_send++;
|
||||||
|
/* always send XAUTH Vendor ID */
|
||||||
|
vids_to_send++;
|
||||||
/* always send DPD Vendor ID */
|
/* always send DPD Vendor ID */
|
||||||
vids_to_send++;
|
vids_to_send++;
|
||||||
if (md->nat_traversal_vid && nat_traversal_enabled)
|
if (md->nat_traversal_vid && nat_traversal_enabled)
|
||||||
@ -3167,16 +3155,6 @@ main_inI1_outR1(struct msg_digest *md)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if enabled send XAUTH Vendor ID */
|
|
||||||
if (SEND_XAUTH_VID)
|
|
||||||
{
|
|
||||||
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
|
|
||||||
, &md->rbody, VID_MISC_XAUTH))
|
|
||||||
{
|
|
||||||
return STF_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if enabled send Cisco Unity Vendor ID */
|
/* if enabled send Cisco Unity Vendor ID */
|
||||||
if (SEND_CISCO_UNITY_VID)
|
if (SEND_CISCO_UNITY_VID)
|
||||||
{
|
{
|
||||||
@ -3199,13 +3177,18 @@ main_inI1_outR1(struct msg_digest *md)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Announce our ability to do Dead Peer Detection to the peer */
|
/* Announce our ability to do eXtended AUTHentication to the peer */
|
||||||
|
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
|
||||||
|
, &md->rbody, VID_MISC_XAUTH))
|
||||||
{
|
{
|
||||||
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
|
return STF_INTERNAL_ERROR;
|
||||||
, &md->rbody, VID_MISC_DPD))
|
}
|
||||||
{
|
|
||||||
return STF_INTERNAL_ERROR;
|
/* Announce our ability to do Dead Peer Detection to the peer */
|
||||||
}
|
if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE
|
||||||
|
, &md->rbody, VID_MISC_DPD))
|
||||||
|
{
|
||||||
|
return STF_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (md->nat_traversal_vid && nat_traversal_enabled)
|
if (md->nat_traversal_vid && nat_traversal_enabled)
|
||||||
@ -3486,8 +3469,6 @@ main_inR2_outI3(struct msg_digest *md)
|
|||||||
{
|
{
|
||||||
struct state *const st = md->st;
|
struct state *const st = md->st;
|
||||||
pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
|
pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
|
||||||
int auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
|
|
||||||
? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
|
|
||||||
pb_stream id_pbs; /* ID Payload; also used for hash calculation */
|
pb_stream id_pbs; /* ID Payload; also used for hash calculation */
|
||||||
|
|
||||||
certpolicy_t cert_policy = st->st_connection->spd.this.sendcert;
|
certpolicy_t cert_policy = st->st_connection->spd.this.sendcert;
|
||||||
@ -3498,6 +3479,8 @@ main_inR2_outI3(struct msg_digest *md)
|
|||||||
|| st->st_oakley.auth == XAUTHInitRSA
|
|| st->st_oakley.auth == XAUTHInitRSA
|
||||||
|| st->st_oakley.auth == XAUTHRespRSA;
|
|| st->st_oakley.auth == XAUTHRespRSA;
|
||||||
|
|
||||||
|
int auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
|
||||||
|
|
||||||
/* KE in */
|
/* KE in */
|
||||||
RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs));
|
RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr", st->st_oakley.group, keyex_pbs));
|
||||||
|
|
||||||
@ -3960,8 +3943,7 @@ main_inI3_outR3_tail(struct msg_digest *md
|
|||||||
*/
|
*/
|
||||||
echo_hdr(md, TRUE, ISAKMP_NEXT_ID);
|
echo_hdr(md, TRUE, ISAKMP_NEXT_ID);
|
||||||
|
|
||||||
auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY
|
auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH;
|
||||||
? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG;
|
|
||||||
|
|
||||||
/* IDir out */
|
/* IDir out */
|
||||||
{
|
{
|
||||||
|
|||||||
@ -54,6 +54,7 @@
|
|||||||
#include "whack.h" /* for RC_LOG_SERIOUS */
|
#include "whack.h" /* for RC_LOG_SERIOUS */
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "fetch.h"
|
#include "fetch.h"
|
||||||
|
#include "xauth.h"
|
||||||
|
|
||||||
const char *shared_secrets_file = SHARED_SECRETS_FILE;
|
const char *shared_secrets_file = SHARED_SECRETS_FILE;
|
||||||
|
|
||||||
@ -97,11 +98,11 @@ allocate_RSA_public_key(const cert_t cert)
|
|||||||
default:
|
default:
|
||||||
plog("RSA public key allocation error");
|
plog("RSA public key allocation error");
|
||||||
}
|
}
|
||||||
init_RSA_public_key(&pk->u.rsa, e, n);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
init_RSA_public_key(&pk->u.rsa, e, n);
|
||||||
DBG(DBG_PRIVATE, RSA_show_public_key(&pk->u.rsa));
|
DBG(DBG_RAW,
|
||||||
#endif
|
RSA_show_public_key(&pk->u.rsa)
|
||||||
|
)
|
||||||
|
|
||||||
pk->alg = PUBKEY_ALG_RSA;
|
pk->alg = PUBKEY_ALG_RSA;
|
||||||
pk->id = empty_id;
|
pk->id = empty_id;
|
||||||
@ -182,7 +183,7 @@ get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym)
|
|||||||
his_id = &rw_id;
|
his_id = &rw_id;
|
||||||
}
|
}
|
||||||
else if (kind == PPK_PSK
|
else if (kind == PPK_PSK
|
||||||
&& (c->policy & POLICY_PSK)
|
&& (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK))
|
||||||
&& ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_NONE) ||
|
&& ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_NONE) ||
|
||||||
(c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id))))
|
(c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id))))
|
||||||
{
|
{
|
||||||
@ -414,7 +415,7 @@ process_psk_secret(chunk_t *psk)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char buf[RSA_MAX_ENCODING_BYTES]; /* limit on size of binary representation of key */
|
char buf[BUF_LEN]; /* limit on size of binary representation of key */
|
||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz
|
ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz
|
||||||
@ -589,7 +590,6 @@ static err_t
|
|||||||
process_xauth(secret_t *s)
|
process_xauth(secret_t *s)
|
||||||
{
|
{
|
||||||
chunk_t user_name;
|
chunk_t user_name;
|
||||||
chunk_t user_password;
|
|
||||||
|
|
||||||
s->kind = PPK_XAUTH;
|
s->kind = PPK_XAUTH;
|
||||||
|
|
||||||
@ -605,31 +605,21 @@ process_xauth(secret_t *s)
|
|||||||
user_name.ptr = tok;
|
user_name.ptr = tok;
|
||||||
user_name.len = flp->cur - tok;
|
user_name.len = flp->cur - tok;
|
||||||
}
|
}
|
||||||
|
plog(" loaded xauth credentials of user '%.*s'"
|
||||||
|
, user_name.len
|
||||||
|
, user_name.ptr);
|
||||||
|
clonetochunk(s->u.xauth_secret.user_name
|
||||||
|
, user_name.ptr, user_name.len, "xauth user name");
|
||||||
|
|
||||||
if (!shift())
|
if (!shift())
|
||||||
return "missing xauth user password";
|
return "missing xauth user password";
|
||||||
if (*tok == '"' || *tok == '\'') /* quoted user password */
|
return process_psk_secret(&s->u.xauth_secret.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
|
/* get XAUTH secret from chained secrets lists
|
||||||
* only one entry is currently supported
|
* only one entry is currently supported
|
||||||
*/
|
*/
|
||||||
bool
|
static bool
|
||||||
xauth_get_secret(xauth_t *xauth_secret)
|
xauth_get_secret(xauth_t *xauth_secret)
|
||||||
{
|
{
|
||||||
secret_t *s;
|
secret_t *s;
|
||||||
@ -656,9 +646,10 @@ xauth_get_secret(xauth_t *xauth_secret)
|
|||||||
/*
|
/*
|
||||||
* find a matching secret
|
* find a matching secret
|
||||||
*/
|
*/
|
||||||
bool
|
static bool
|
||||||
xauth_verify_secret(const xauth_t *xauth_secret)
|
xauth_verify_secret(const xauth_t *xauth_secret)
|
||||||
{
|
{
|
||||||
|
bool found = FALSE;
|
||||||
secret_t *s;
|
secret_t *s;
|
||||||
|
|
||||||
for (s = secrets; s != NULL; s = s->next)
|
for (s = secrets; s != NULL; s = s->next)
|
||||||
@ -667,13 +658,44 @@ xauth_verify_secret(const xauth_t *xauth_secret)
|
|||||||
{
|
{
|
||||||
if (!same_chunk(xauth_secret->user_name, s->u.xauth_secret.user_name))
|
if (!same_chunk(xauth_secret->user_name, s->u.xauth_secret.user_name))
|
||||||
continue;
|
continue;
|
||||||
|
found = TRUE;
|
||||||
if (same_chunk(xauth_secret->user_password, s->u.xauth_secret.user_password))
|
if (same_chunk(xauth_secret->user_password, s->u.xauth_secret.user_password))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
plog("xauth user '%.*s' %s"
|
||||||
|
, xauth_secret->user_name.len, xauth_secret->user_name.ptr
|
||||||
|
, found? "sent wrong password":"not found");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the global xauth_module struct is defined here
|
||||||
|
*/
|
||||||
|
xauth_module_t xauth_module;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* assign the default xauth functions to any null function pointers
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xauth_defaults(void)
|
||||||
|
{
|
||||||
|
if (xauth_module.get_secret == NULL)
|
||||||
|
{
|
||||||
|
DBG(DBG_CONTROL,
|
||||||
|
DBG_log("xauth_module: using default get_secret() function")
|
||||||
|
)
|
||||||
|
xauth_module.get_secret = xauth_get_secret;
|
||||||
|
}
|
||||||
|
if (xauth_module.verify_secret == NULL)
|
||||||
|
{
|
||||||
|
DBG(DBG_CONTROL,
|
||||||
|
DBG_log("xauth_module: using default verify_secret() function")
|
||||||
|
)
|
||||||
|
xauth_module.verify_secret = xauth_verify_secret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* process pin read from ipsec.secrets or prompted for it using whack
|
* process pin read from ipsec.secrets or prompted for it using whack
|
||||||
*/
|
*/
|
||||||
@ -1202,14 +1224,11 @@ unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey)
|
|||||||
return RSA_MAX_OCTETS_UGH;
|
return RSA_MAX_OCTETS_UGH;
|
||||||
|
|
||||||
init_RSA_public_key(rsa, exp, mod);
|
init_RSA_public_key(rsa, exp, mod);
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
DBG(DBG_PRIVATE, RSA_show_public_key(rsa));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
rsa->k = mpz_sizeinbase(&rsa->n, 2); /* size in bits, for a start */
|
rsa->k = mpz_sizeinbase(&rsa->n, 2); /* size in bits, for a start */
|
||||||
rsa->k = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE; /* now octets */
|
rsa->k = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE; /* now octets */
|
||||||
|
DBG(DBG_RAW,
|
||||||
|
RSA_show_public_key(rsa)
|
||||||
|
)
|
||||||
|
|
||||||
if (rsa->k != mod.len)
|
if (rsa->k != mod.len)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -41,6 +41,11 @@ enum PrivateKeyKind {
|
|||||||
PPK_PIN
|
PPK_PIN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern void xauth_defaults(void);
|
||||||
|
|
||||||
|
/* forward declaration */
|
||||||
|
struct connection;
|
||||||
|
|
||||||
extern const chunk_t *get_preshared_secret(const struct connection *c);
|
extern const chunk_t *get_preshared_secret(const struct connection *c);
|
||||||
extern err_t unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey);
|
extern err_t unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey);
|
||||||
extern const RSA_private_key_t *get_RSA_private_key(const struct connection *c);
|
extern const RSA_private_key_t *get_RSA_private_key(const struct connection *c);
|
||||||
@ -86,7 +91,6 @@ extern void delete_public_keys(const struct id *id, enum pubkey_alg alg
|
|||||||
extern pubkey_t *reference_key(pubkey_t *pk);
|
extern pubkey_t *reference_key(pubkey_t *pk);
|
||||||
extern void unreference_key(pubkey_t **pkp);
|
extern void unreference_key(pubkey_t **pkp);
|
||||||
|
|
||||||
|
|
||||||
extern err_t add_public_key(const struct id *id
|
extern err_t add_public_key(const struct id *id
|
||||||
, enum dns_auth_level dns_auth_level
|
, enum dns_auth_level dns_auth_level
|
||||||
, enum pubkey_alg alg
|
, enum pubkey_alg alg
|
||||||
@ -101,16 +105,6 @@ extern void add_pgp_public_key(pgpcert_t *cert, time_t until
|
|||||||
extern void remove_x509_public_key(const x509cert_t *cert);
|
extern void remove_x509_public_key(const x509cert_t *cert);
|
||||||
extern void list_public_keys(bool utc);
|
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) */
|
struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
|
||||||
extern void transfer_to_public_keys(struct gw_info *gateways_from_dns
|
extern void transfer_to_public_keys(struct gw_info *gateways_from_dns
|
||||||
#ifdef USE_KEYRR
|
#ifdef USE_KEYRR
|
||||||
|
|||||||
@ -39,7 +39,9 @@
|
|||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "modecfg.h"
|
#include "modecfg.h"
|
||||||
#include "whack.h"
|
#include "whack.h"
|
||||||
#include "keys.h"
|
#include "xauth.h"
|
||||||
|
|
||||||
|
#define MAX_XAUTH_TRIES 3
|
||||||
|
|
||||||
#define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
|
#define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
|
||||||
| LELEM(INTERNAL_IP4_NETMASK) \
|
| LELEM(INTERNAL_IP4_NETMASK) \
|
||||||
@ -410,6 +412,7 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
|
|||||||
, 0 /* XXX isama_id */
|
, 0 /* XXX isama_id */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
freeanychunk(st->st_tpacket);
|
||||||
clonetochunk(st->st_tpacket, msg.start, pbs_offset(&msg), "ModeCfg msg");
|
clonetochunk(st->st_tpacket, msg.start, pbs_offset(&msg), "ModeCfg msg");
|
||||||
|
|
||||||
/* Transmit */
|
/* Transmit */
|
||||||
@ -423,67 +426,6 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia)
|
|||||||
return STF_OK;
|
return STF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Send ModeCfg request message from client to server in pull mode
|
|
||||||
*/
|
|
||||||
stf_status
|
|
||||||
modecfg_send_request(struct state *st)
|
|
||||||
{
|
|
||||||
stf_status stat;
|
|
||||||
internal_addr_t ia;
|
|
||||||
|
|
||||||
init_internal_addr(&ia);
|
|
||||||
ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
|
|
||||||
| LELEM(INTERNAL_IP4_NETMASK);
|
|
||||||
|
|
||||||
plog("sending ModeCfg request");
|
|
||||||
st->st_state = STATE_MODE_CFG_I1;
|
|
||||||
stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
|
|
||||||
if (stat == STF_OK)
|
|
||||||
st->st_modecfg.started = TRUE;
|
|
||||||
return stat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send ModeCfg set message from server to client in push mode
|
|
||||||
*/
|
|
||||||
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;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse a ModeCfg attribute payload
|
* Parse a ModeCfg attribute payload
|
||||||
*/
|
*/
|
||||||
@ -595,6 +537,27 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id
|
|||||||
return STF_IGNORE;
|
return STF_IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send ModeCfg request message from client to server in pull mode
|
||||||
|
*/
|
||||||
|
stf_status
|
||||||
|
modecfg_send_request(struct state *st)
|
||||||
|
{
|
||||||
|
stf_status stat;
|
||||||
|
internal_addr_t ia;
|
||||||
|
|
||||||
|
init_internal_addr(&ia);
|
||||||
|
ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
|
||||||
|
| LELEM(INTERNAL_IP4_NETMASK);
|
||||||
|
|
||||||
|
plog("sending ModeCfg request");
|
||||||
|
st->st_state = STATE_MODE_CFG_I1;
|
||||||
|
stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia);
|
||||||
|
if (stat == STF_OK)
|
||||||
|
st->st_modecfg.started = TRUE;
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
/* STATE_MODE_CFG_R0:
|
/* STATE_MODE_CFG_R0:
|
||||||
* HDR*, HASH, ATTR(REQ=IP) --> HDR*, HASH, ATTR(REPLY=IP)
|
* HDR*, HASH, ATTR(REQ=IP) --> HDR*, HASH, ATTR(REPLY=IP)
|
||||||
*
|
*
|
||||||
@ -606,49 +569,22 @@ modecfg_inR0(struct msg_digest *md)
|
|||||||
struct state *const st = md->st;
|
struct state *const st = md->st;
|
||||||
u_int16_t isama_id;
|
u_int16_t isama_id;
|
||||||
internal_addr_t ia;
|
internal_addr_t ia;
|
||||||
stf_status stat;
|
stf_status stat, stat_build;
|
||||||
|
|
||||||
stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
|
stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
|
||||||
if (stat != STF_OK)
|
if (stat != STF_OK)
|
||||||
return stat;
|
return stat;
|
||||||
|
|
||||||
get_internal_addr(st->st_connection, &ia);
|
get_internal_addr(st->st_connection, &ia);
|
||||||
|
|
||||||
plog("sending ModeCfg reply");
|
plog("sending ModeCfg reply");
|
||||||
|
|
||||||
stat = modecfg_build_msg(st, &md->rbody
|
stat_build = modecfg_build_msg(st, &md->rbody
|
||||||
, ISAKMP_CFG_REPLY
|
, ISAKMP_CFG_REPLY
|
||||||
, &ia
|
, &ia
|
||||||
, isama_id);
|
, isama_id);
|
||||||
if (stat != STF_OK)
|
if (stat_build != STF_OK)
|
||||||
{
|
return stat_build;
|
||||||
/* notification payload - not exactly the right choice, but okay */
|
|
||||||
md->note = ATTRIBUTES_NOT_SUPPORTED;
|
|
||||||
return stat;
|
|
||||||
}
|
|
||||||
|
|
||||||
st->st_msgid = 0;
|
|
||||||
return STF_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* STATE_MODE_CFG_R1:
|
|
||||||
* HDR*, HASH, ATTR(ACK,OK)
|
|
||||||
*
|
|
||||||
* used in ModeCfg push mode, on the server (responder)
|
|
||||||
*/
|
|
||||||
stf_status
|
|
||||||
modecfg_inR1(struct msg_digest *md)
|
|
||||||
{
|
|
||||||
struct state *const st = md->st;
|
|
||||||
u_int16_t isama_id;
|
|
||||||
internal_addr_t ia;
|
|
||||||
stf_status stat;
|
|
||||||
|
|
||||||
plog("parsing ModeCfg ack");
|
|
||||||
|
|
||||||
stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia);
|
|
||||||
if (stat != STF_OK)
|
|
||||||
return stat;
|
|
||||||
|
|
||||||
st->st_msgid = 0;
|
st->st_msgid = 0;
|
||||||
return STF_OK;
|
return STF_OK;
|
||||||
@ -678,19 +614,39 @@ modecfg_inI1(struct msg_digest *md)
|
|||||||
return STF_OK;
|
return STF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* STATE_MODE_CFG_I2:
|
|
||||||
|
/*
|
||||||
|
* Send ModeCfg set message from server to client in push mode
|
||||||
|
*/
|
||||||
|
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_R3;
|
||||||
|
stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia);
|
||||||
|
if (stat == STF_OK)
|
||||||
|
st->st_modecfg.started = TRUE;
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STATE_MODE_CFG_I0:
|
||||||
* HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK)
|
* HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK)
|
||||||
*
|
*
|
||||||
* used in ModeCfg push mode, on the client (initiator).
|
* used in ModeCfg push mode, on the client (initiator).
|
||||||
*/
|
*/
|
||||||
stf_status
|
stf_status
|
||||||
modecfg_inI2(struct msg_digest *md)
|
modecfg_inI0(struct msg_digest *md)
|
||||||
{
|
{
|
||||||
struct state *const st = md->st;
|
struct state *const st = md->st;
|
||||||
u_int16_t isama_id;
|
u_int16_t isama_id;
|
||||||
internal_addr_t ia;
|
internal_addr_t ia;
|
||||||
lset_t attr_set;
|
lset_t attr_set;
|
||||||
stf_status stat;
|
stf_status stat, stat_build;
|
||||||
|
|
||||||
plog("parsing ModeCfg set");
|
plog("parsing ModeCfg set");
|
||||||
|
|
||||||
@ -707,21 +663,157 @@ modecfg_inI2(struct msg_digest *md)
|
|||||||
|
|
||||||
plog("sending ModeCfg ack");
|
plog("sending ModeCfg ack");
|
||||||
|
|
||||||
stat = modecfg_build_msg(st, &md->rbody
|
stat_build = modecfg_build_msg(st, &md->rbody
|
||||||
, ISAKMP_CFG_ACK
|
, ISAKMP_CFG_ACK
|
||||||
, &ia
|
, &ia
|
||||||
, isama_id);
|
, isama_id);
|
||||||
if (stat != STF_OK)
|
if (stat_build != STF_OK)
|
||||||
{
|
return stat_build;
|
||||||
/* notification payload - not exactly the right choice, but okay */
|
|
||||||
md->note = ATTRIBUTES_NOT_SUPPORTED;
|
|
||||||
return stat;
|
|
||||||
}
|
|
||||||
|
|
||||||
st->st_msgid = 0;
|
st->st_msgid = 0;
|
||||||
return STF_OK;
|
return STF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* STATE_MODE_CFG_R3:
|
||||||
|
* HDR*, HASH, ATTR(ACK,OK)
|
||||||
|
*
|
||||||
|
* used in ModeCfg push mode, on the server (responder)
|
||||||
|
*/
|
||||||
|
stf_status
|
||||||
|
modecfg_inR3(struct msg_digest *md)
|
||||||
|
{
|
||||||
|
struct state *const st = md->st;
|
||||||
|
u_int16_t isama_id;
|
||||||
|
internal_addr_t ia;
|
||||||
|
stf_status stat;
|
||||||
|
|
||||||
|
plog("parsing ModeCfg 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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, stat_build;
|
||||||
|
|
||||||
|
plog("parsing XAUTH request");
|
||||||
|
|
||||||
|
stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia);
|
||||||
|
if (stat != STF_OK)
|
||||||
|
return stat;
|
||||||
|
|
||||||
|
/* check XAUTH attributes */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else 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;
|
||||||
|
}
|
||||||
|
else 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 using a plugin function */
|
||||||
|
if (!xauth_module.get_secret(&ia.xauth_secret))
|
||||||
|
{
|
||||||
|
plog("xauth user credentials not found");
|
||||||
|
stat = STF_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stat == STF_OK)
|
||||||
|
{
|
||||||
|
DBG(DBG_CONTROL,
|
||||||
|
DBG_log("my xauth user name is '%.*s'"
|
||||||
|
, ia.xauth_secret.user_name.len
|
||||||
|
, ia.xauth_secret.user_name.ptr)
|
||||||
|
)
|
||||||
|
DBG(DBG_PRIVATE,
|
||||||
|
DBG_log("my xauth user password is '%.*s'"
|
||||||
|
, ia.xauth_secret.user_password.len
|
||||||
|
, ia.xauth_secret.user_password.ptr)
|
||||||
|
)
|
||||||
|
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_build = modecfg_build_msg(st, &md->rbody
|
||||||
|
, ISAKMP_CFG_REPLY
|
||||||
|
, &ia
|
||||||
|
, isama_id);
|
||||||
|
if (stat_build != STF_OK)
|
||||||
|
return stat_build;
|
||||||
|
|
||||||
|
if (stat == STF_OK)
|
||||||
|
{
|
||||||
|
st->st_xauth.started = TRUE;
|
||||||
|
return STF_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* send XAUTH reply msg and then delete ISAKMP SA */
|
||||||
|
freeanychunk(st->st_tpacket);
|
||||||
|
clonetochunk(st->st_tpacket, md->reply.start
|
||||||
|
, pbs_offset(&md->reply), "XAUTH reply msg");
|
||||||
|
send_packet(st, "XAUTH reply msg");
|
||||||
|
delete_state(st);
|
||||||
|
return STF_IGNORE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* STATE_XAUTH_R1:
|
/* STATE_XAUTH_R1:
|
||||||
* HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD) --> HDR*, HASH, ATTR(STATUS)
|
* HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD) --> HDR*, HASH, ATTR(STATUS)
|
||||||
*
|
*
|
||||||
@ -733,48 +825,119 @@ xauth_inR1(struct msg_digest *md)
|
|||||||
struct state *const st = md->st;
|
struct state *const st = md->st;
|
||||||
u_int16_t isama_id;
|
u_int16_t isama_id;
|
||||||
internal_addr_t ia;
|
internal_addr_t ia;
|
||||||
stf_status stat;
|
stf_status stat, stat_build;
|
||||||
bool status;
|
|
||||||
|
|
||||||
plog("parsing XAUTH reply");
|
plog("parsing XAUTH reply");
|
||||||
|
|
||||||
stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
|
stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia);
|
||||||
if (stat != STF_OK)
|
if (stat != STF_OK)
|
||||||
return stat;
|
return stat;
|
||||||
|
|
||||||
/* check XAUTH reply */
|
/* did the client return an XAUTH FAIL status? */
|
||||||
if ((ia.attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF)) != LEMPTY)
|
if ((ia.attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF)) != LEMPTY)
|
||||||
{
|
{
|
||||||
plog("received FAIL status in XAUTH reply");
|
plog("received FAIL status in XAUTH reply");
|
||||||
return STF_INTERNAL_ERROR;
|
|
||||||
|
/* client is not able to do XAUTH, delete ISAKMP SA */
|
||||||
|
delete_state(st);
|
||||||
|
return STF_IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check XAUTH reply */
|
||||||
if ((ia.attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
|
if ((ia.attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
|
||||||
{
|
{
|
||||||
plog("user name attribute is missing in XAUTH reply");
|
plog("user name attribute is missing in XAUTH reply");
|
||||||
return STF_SUSPEND;
|
st->st_xauth.status = FALSE;
|
||||||
}
|
}
|
||||||
if ((ia.attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
|
else if ((ia.attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY)
|
||||||
{
|
{
|
||||||
plog("user password attribute is missing in XAUTH reply");
|
plog("user password attribute is missing in XAUTH reply");
|
||||||
return STF_SUSPEND;
|
st->st_xauth.status = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG(DBG_CONTROL,
|
||||||
|
DBG_log("peer xauth user name is '%.*s'"
|
||||||
|
, ia.xauth_secret.user_name.len
|
||||||
|
, ia.xauth_secret.user_name.ptr)
|
||||||
|
)
|
||||||
|
DBG(DBG_PRIVATE,
|
||||||
|
DBG_log("peer xauth user password is '%.*s'"
|
||||||
|
, ia.xauth_secret.user_password.len
|
||||||
|
, ia.xauth_secret.user_password.ptr)
|
||||||
|
)
|
||||||
|
/* verify the user credentials using a plugn function */
|
||||||
|
st->st_xauth.status = xauth_module.verify_secret(&ia.xauth_secret);
|
||||||
|
plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
status = xauth_verify_secret(&ia.xauth_secret);
|
|
||||||
|
|
||||||
/* prepare XAUTH set which sends the authentication status */
|
/* prepare XAUTH set which sends the authentication status */
|
||||||
init_internal_addr(&ia);
|
init_internal_addr(&ia);
|
||||||
ia.attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF);
|
ia.attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF);
|
||||||
ia.xauth_status = status;
|
ia.xauth_status = st->st_xauth.status;
|
||||||
|
|
||||||
plog("sending XAUTH status: %s", status? "OK":"FAIL");
|
plog("sending XAUTH status:");
|
||||||
|
|
||||||
stat = modecfg_build_msg(st, &md->rbody
|
stat_build = modecfg_build_msg(st, &md->rbody
|
||||||
, ISAKMP_CFG_SET
|
, ISAKMP_CFG_SET
|
||||||
, &ia
|
, &ia
|
||||||
, isama_id);
|
, isama_id);
|
||||||
|
if (stat_build != STF_OK)
|
||||||
|
return stat_build;
|
||||||
return STF_OK;
|
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, stat_build;
|
||||||
|
|
||||||
|
plog("parsing XAUTH status");
|
||||||
|
stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia);
|
||||||
|
if (stat != STF_OK)
|
||||||
|
{
|
||||||
|
/* notification payload - not exactly the right choice, but okay */
|
||||||
|
md->note = ATTRIBUTES_NOT_SUPPORTED;
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
st->st_xauth.status = ia.xauth_status;
|
||||||
|
plog("extended authentication %s", st->st_xauth.status? "was successful":"failed");
|
||||||
|
|
||||||
|
plog("sending XAUTH ack");
|
||||||
|
init_internal_addr(&ia);
|
||||||
|
stat_build = modecfg_build_msg(st, &md->rbody
|
||||||
|
, ISAKMP_CFG_ACK
|
||||||
|
, &ia
|
||||||
|
, isama_id);
|
||||||
|
if (stat_build != STF_OK)
|
||||||
|
return stat_build;
|
||||||
|
|
||||||
|
if (st->st_xauth.status)
|
||||||
|
{
|
||||||
|
st->st_msgid = 0;
|
||||||
|
return STF_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* send XAUTH ack msg and then delete ISAKMP SA */
|
||||||
|
freeanychunk(st->st_tpacket);
|
||||||
|
clonetochunk(st->st_tpacket, md->reply.start
|
||||||
|
, pbs_offset(&md->reply), "XAUTH ack msg");
|
||||||
|
send_packet(st, "XAUTH ack msg");
|
||||||
|
delete_state(st);
|
||||||
|
return STF_IGNORE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* STATE_XAUTH_R2:
|
/* STATE_XAUTH_R2:
|
||||||
* HDR*, ATTR(STATUS), HASH --> Done
|
* HDR*, ATTR(STATUS), HASH --> Done
|
||||||
*
|
*
|
||||||
@ -795,113 +958,13 @@ xauth_inR2(struct msg_digest *md)
|
|||||||
return stat;
|
return stat;
|
||||||
|
|
||||||
st->st_msgid = 0;
|
st->st_msgid = 0;
|
||||||
return STF_OK;
|
if (st->st_xauth.status)
|
||||||
}
|
|
||||||
|
|
||||||
/* 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));
|
return STF_OK;
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
ia.attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF);
|
delete_state(st);
|
||||||
ia.xauth_status = FALSE;
|
return STF_IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,23 +21,27 @@
|
|||||||
struct state;
|
struct state;
|
||||||
struct msg_digest;
|
struct msg_digest;
|
||||||
|
|
||||||
/* ModeConfig starting functions */
|
/* ModeConfig pull mode start function */
|
||||||
extern stf_status modecfg_send_request(struct state *st);
|
extern stf_status modecfg_send_request(struct state *st);
|
||||||
|
|
||||||
|
/* ModeConfig pull mode state transition functions */
|
||||||
|
extern stf_status modecfg_inR0(struct msg_digest *md);
|
||||||
|
extern stf_status modecfg_inI1(struct msg_digest *md);
|
||||||
|
|
||||||
|
/* ModeConfig push mode start function */
|
||||||
extern stf_status modecfg_send_set(struct state *st);
|
extern stf_status modecfg_send_set(struct state *st);
|
||||||
|
|
||||||
/* ModeConfig state transition functions */
|
/* ModeConfig push mode state transition functions */
|
||||||
extern stf_status modecfg_inR0(struct msg_digest *md);
|
extern stf_status modecfg_inI0(struct msg_digest *md);
|
||||||
extern stf_status modecfg_inR1(struct msg_digest *md);
|
extern stf_status modecfg_inR3(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 */
|
/* XAUTH start function */
|
||||||
extern stf_status xauth_send_request(struct state *st);
|
extern stf_status xauth_send_request(struct state *st);
|
||||||
|
|
||||||
/* XAUTH state transition funcgtions */
|
/* 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_inI0(struct msg_digest *md);
|
||||||
|
extern stf_status xauth_inR1(struct msg_digest *md);
|
||||||
extern stf_status xauth_inI1(struct msg_digest *md);
|
extern stf_status xauth_inI1(struct msg_digest *md);
|
||||||
|
extern stf_status xauth_inR2(struct msg_digest *md);
|
||||||
|
|
||||||
#endif /* _MODECFG_H */
|
#endif /* _MODECFG_H */
|
||||||
|
|||||||
@ -216,6 +216,7 @@ struct state
|
|||||||
struct {
|
struct {
|
||||||
int attempt;
|
int attempt;
|
||||||
bool started;
|
bool started;
|
||||||
|
bool status;
|
||||||
} st_xauth;
|
} st_xauth;
|
||||||
|
|
||||||
u_int32_t nat_traversal;
|
u_int32_t nat_traversal;
|
||||||
|
|||||||
@ -394,6 +394,9 @@ handle_known_vendorid (struct msg_digest *md
|
|||||||
md->dpd = TRUE;
|
md->dpd = TRUE;
|
||||||
vid_useful = TRUE;
|
vid_useful = TRUE;
|
||||||
break;
|
break;
|
||||||
|
case VID_MISC_XAUTH:
|
||||||
|
vid_useful = TRUE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
36
src/pluto/xauth.c
Normal file
36
src/pluto/xauth.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* Initialization and finalization of the dynamic XAUTH module
|
||||||
|
* Copyright (C) 2006 Andreas Steffen
|
||||||
|
* Hochschule fuer Technik Rapperswil, Switzerland
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* RCSID $Id: xauth.c,v 1.1 2005/01/06 22:10:15 as Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <freeswan.h>
|
||||||
|
|
||||||
|
#include "constants.h"
|
||||||
|
#include "defs.h"
|
||||||
|
#include "xauth.h"
|
||||||
|
#include "keys.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
xauth_init(void)
|
||||||
|
{
|
||||||
|
/* TODO: locate and load dynamic XAUTH module */
|
||||||
|
xauth_defaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xauth_finalize(void)
|
||||||
|
{
|
||||||
|
/* TODO: unload dynamic XAUTH module */
|
||||||
|
}
|
||||||
40
src/pluto/xauth.h
Normal file
40
src/pluto/xauth.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* Interface definition of the XAUTH server and|or client module
|
||||||
|
* Copyright (C) 2006 Andreas Steffen
|
||||||
|
* Hochschule fuer Technik Rapperswil, Switzerland
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* RCSID $Id: xauth.h,v 1.1 2005/01/06 22:10:15 as Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _XAUTH_H
|
||||||
|
#define _XAUTH_H
|
||||||
|
|
||||||
|
/* XAUTH credentials */
|
||||||
|
|
||||||
|
struct chunk_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
chunk_t user_name;
|
||||||
|
chunk_t user_password;
|
||||||
|
} xauth_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool (*get_secret) (const xauth_t *xauth_secret);
|
||||||
|
bool (*verify_secret) (const xauth_t *xauth_secret);
|
||||||
|
} xauth_module_t;
|
||||||
|
|
||||||
|
extern xauth_module_t xauth_module;
|
||||||
|
|
||||||
|
extern void xauth_init(void);
|
||||||
|
extern void xauth_finalize(void);
|
||||||
|
|
||||||
|
#endif /* _XAUTH_H */
|
||||||
Loading…
x
Reference in New Issue
Block a user