diff options
-rw-r--r-- | src/pluto/connections.c | 3 | ||||
-rw-r--r-- | src/pluto/constants.c | 34 | ||||
-rw-r--r-- | src/pluto/constants.h | 54 | ||||
-rw-r--r-- | src/pluto/demux.c | 106 | ||||
-rw-r--r-- | src/pluto/ipsec_doi.c | 68 | ||||
-rw-r--r-- | src/pluto/keys.c | 83 | ||||
-rw-r--r-- | src/pluto/keys.h | 16 | ||||
-rw-r--r-- | src/pluto/modecfg.c | 433 | ||||
-rw-r--r-- | src/pluto/modecfg.h | 18 | ||||
-rw-r--r-- | src/pluto/state.h | 1 | ||||
-rw-r--r-- | src/pluto/vendor.c | 3 | ||||
-rw-r--r-- | src/pluto/xauth.c | 36 | ||||
-rw-r--r-- | src/pluto/xauth.h | 40 |
13 files changed, 524 insertions, 371 deletions
diff --git a/src/pluto/connections.c b/src/pluto/connections.c index eb1570163..0d02b979c 100644 --- a/src/pluto/connections.c +++ b/src/pluto/connections.c @@ -3333,6 +3333,9 @@ refine_host_connection(const struct state *st, const struct id *peer_id case XAUTHInitPreShared: case XAUTHRespPreShared: auth_policy = POLICY_XAUTH_PSK; + psk = get_preshared_secret(c); + if (psk == NULL) + return NULL; /* cannot determine PSK! */ break; case OAKLEY_RSA_SIG: auth_policy = POLICY_RSASIG; diff --git a/src/pluto/constants.c b/src/pluto/constants.c index 883f82ece..ed8073b0b 100644 --- a/src/pluto/constants.c +++ b/src/pluto/constants.c @@ -54,8 +54,8 @@ const char compile_time_interop_options[] = "" #ifdef VENDORID " VENDORID" #endif -#ifdef XAUTH_VID - " XAUTH_VID" +#ifdef CISCO_QUIRKS + " CISCO_QUIRKS" #endif #ifdef USE_KEYRR " KEYRR" @@ -183,19 +183,22 @@ static const char *const state_name[] = { "STATE_INFO", "STATE_INFO_PROTECTED", - "STATE_XAUTH_R1", - "STATE_XAUTH_R2", - "STATE_XAUTH_R3", "STATE_XAUTH_I0", + "STATE_XAUTH_R1", "STATE_XAUTH_I1", + "STATE_XAUTH_R2", "STATE_XAUTH_I2", + "STATE_XAUTH_R3", "STATE_MODE_CFG_R0", - "STATE_MODE_CFG_R1", - "STATE_MODE_CFG_R2", "STATE_MODE_CFG_I1", + "STATE_MODE_CFG_R1", "STATE_MODE_CFG_I2", + + "STATE_MODE_CFG_I0", + "STATE_MODE_CFG_R3", "STATE_MODE_CFG_I3", + "STATE_MODE_CFG_R4", "STATE_IKE_ROOF" }; @@ -224,19 +227,22 @@ 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_R1 */ - "sent XAUTH status, expecting ack", /* STATE_XAUTH_R2 */ - "received XAUTH ack, established", /* STATE_XAUTH_R3 */ "expecting XAUTH request", /* STATE_XAUTH_I0 */ + "sent XAUTH request, expecting reply", /* STATE_XAUTH_R1 */ "sent XAUTH reply, expecting status", /* STATE_XAUTH_I1 */ + "sent XAUTH status, expecting ack", /* STATE_XAUTH_R2 */ "sent XAUTH ack, established", /* STATE_XAUTH_I2 */ + "received XAUTH ack, established", /* STATE_XAUTH_R3 */ "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 ack, established", /* STATE_MODE_CFG_I2 */ - "received ModeCfg set, sent ack", /* STATE_MODE_CFG_I3 */ + "sent ModeCfg reply, established", /* STATE_MODE_CFG_R1 */ + "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 */ diff --git a/src/pluto/constants.h b/src/pluto/constants.h index 57e9cf93a..7d99ce217 100644 --- a/src/pluto/constants.h +++ b/src/pluto/constants.h @@ -508,23 +508,27 @@ enum state_kind { /* 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_I2, 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_R2, - - STATE_MODE_CFG_I1, /* initiator states */ 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_R4, STATE_IKE_ROOF }; @@ -537,26 +541,26 @@ enum state_kind { 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)) + | LELEM(STATE_MODE_CFG_I1) | LELEM(STATE_MODE_CFG_R1) | LELEM(STATE_MODE_CFG_I2) \ + | 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) \ - || (STATE_XAUTH_R1 <= (s) && (s) <= STATE_XAUTH_I2) \ - || (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_I3)) + || (STATE_XAUTH_I0 <= (s) && (s) <= STATE_XAUTH_R3) \ + || (STATE_MODE_CFG_R0 <= (s) && (s) <= STATE_MODE_CFG_R4)) + #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_I4 \ - || (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 \ - || (s) == STATE_MODE_CFG_I3) + +#define IS_ISAKMP_SA_ESTABLISHED(s) ( \ + (s) == STATE_MAIN_R3 \ + || (s) == STATE_MAIN_I4 \ + || (s) == STATE_XAUTH_R3 \ + || (s) == STATE_XAUTH_I2 \ + || (s) == STATE_MODE_CFG_R1 \ + || (s) == STATE_MODE_CFG_I2 \ + || (s) == STATE_MODE_CFG_I3 \ + || (s) == STATE_MODE_CFG_R4) + #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) diff --git a/src/pluto/demux.c b/src/pluto/demux.c index 564988cb2..1f47daf8f 100644 --- a/src/pluto/demux.c +++ b/src/pluto/demux.c @@ -436,77 +436,81 @@ static const struct state_microcode state_microcode_table[] = { , P(HASH), LEMPTY, PT(NONE) , 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 , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY , P(ATTR) | P(HASH), P(VID), PT(HASH) , EVENT_RETRANSMIT, xauth_inR1 }, + { 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_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 + { STATE_XAUTH_I2, 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 + { STATE_XAUTH_R3, STATE_UNDEFINED , SMF_ALL_AUTH | SMF_ENCRYPTED , LEMPTY, LEMPTY, PT(NONE) , EVENT_NULL, unexpected }, - /* MODE_CFG_x: - * Case R0: Responder -> Initiator - * <- Req(addr=0) - * Reply(ad=x) -> - * - * Case R1: Set(addr=x) -> - * <- Ack(ok) - */ + /* ModeCfg pull mode state transitions */ { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1 - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY + , 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_R1, STATE_MODE_CFG_R2 - , SMF_ALL_AUTH | SMF_ENCRYPTED + { STATE_MODE_CFG_I1, STATE_MODE_CFG_I2 + , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 , P(ATTR) | P(HASH), P(VID), PT(HASH) - , EVENT_SA_REPLACE, modecfg_inR1 }, + , EVENT_SA_REPLACE, modecfg_inI1 }, - { STATE_MODE_CFG_R2, STATE_UNDEFINED + { STATE_MODE_CFG_R1, STATE_UNDEFINED , SMF_ALL_AUTH | SMF_ENCRYPTED , LEMPTY, LEMPTY, PT(NONE) , EVENT_NULL, unexpected }, - { STATE_MODE_CFG_I1, STATE_MODE_CFG_I2 - , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RELEASE_PENDING_P2 - , P(ATTR) | P(HASH), P(VID), PT(HASH) - , EVENT_SA_REPLACE, modecfg_inI1 }, + { 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_I2, STATE_MODE_CFG_I3 + { STATE_MODE_CFG_I0, STATE_MODE_CFG_I3 , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY | SMF_RELEASE_PENDING_P2 , 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 , SMF_ALL_AUTH | SMF_ENCRYPTED , LEMPTY, LEMPTY, PT(NONE) , EVENT_NULL, unexpected }, + { STATE_MODE_CFG_R4, STATE_UNDEFINED + , SMF_ALL_AUTH | SMF_ENCRYPTED + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, unexpected }, + #undef P #undef PT }; @@ -1464,11 +1468,6 @@ process_packet(struct msg_digest **mdp) 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); if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) @@ -1588,7 +1587,7 @@ process_packet(struct msg_digest **mdp) & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK)) != LEMPTY; - if (has_xauth_policy + if (has_xauth_policy && !st->st_xauth.started && IS_PHASE1(st->st_state)) { from_state = STATE_XAUTH_I0; @@ -1601,7 +1600,7 @@ process_packet(struct msg_digest **mdp) else if (st->st_connection->spd.this.modecfg && IS_PHASE1(st->st_state)) { - from_state = STATE_MODE_CFG_I2; + from_state = STATE_MODE_CFG_I0; } else { @@ -1616,7 +1615,6 @@ process_packet(struct msg_digest **mdp) set_cur_state(st); from_state = st->st_state; } - break; #ifdef NOTYET @@ -2358,7 +2356,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result) } 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 */ plog("%s%s", story, sadetails); @@ -2391,6 +2389,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; + } + /* Should we start ModeConfig as a client? */ if (st->st_connection->spd.this.modecfg && IS_ISAKMP_SA_ESTABLISHED(st->st_state) @@ -2417,17 +2426,6 @@ 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) @@ -2453,7 +2451,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result) } 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); break; diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c index 9d53a1a99..f35b5f9f3 100644 --- a/src/pluto/ipsec_doi.c +++ b/src/pluto/ipsec_doi.c @@ -80,15 +80,6 @@ #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? */ #ifdef CISCO_QUIRKS @@ -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 */ if (SEND_PLUTO_VID) vids_to_send++; - if (SEND_XAUTH_VID) - vids_to_send++; if (SEND_CISCO_UNITY_VID) vids_to_send++; if (c->spd.this.cert.type == CERT_PGP) vids_to_send++; + /* always send XAUTH Vendor ID */ + vids_to_send++; /* always send DPD Vendor ID */ vids_to_send++; 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 (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 */ { 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 */ if (SEND_PLUTO_VID) vids_to_send++; - if (SEND_XAUTH_VID) - vids_to_send++; if (SEND_CISCO_UNITY_VID) vids_to_send++; if (md->openpgp) vids_to_send++; + /* always send XAUTH Vendor ID */ + vids_to_send++; /* always send DPD Vendor ID */ vids_to_send++; 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 (SEND_CISCO_UNITY_VID) { @@ -3199,13 +3177,18 @@ main_inI1_outR1(struct msg_digest *md) } } + /* 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)) + { + 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)) { - if (!out_vendorid(vids_to_send-- ? ISAKMP_NEXT_VID : ISAKMP_NEXT_NONE - , &md->rbody, VID_MISC_DPD)) - { - return STF_INTERNAL_ERROR; - } + return STF_INTERNAL_ERROR; } 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; 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 */ 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 == XAUTHRespRSA; + int auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH; + /* KE in */ 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); - auth_payload = st->st_oakley.auth == OAKLEY_PRESHARED_KEY - ? ISAKMP_NEXT_HASH : ISAKMP_NEXT_SIG; + auth_payload = RSA_auth ? ISAKMP_NEXT_SIG : ISAKMP_NEXT_HASH; /* IDir out */ { diff --git a/src/pluto/keys.c b/src/pluto/keys.c index 37cb6fbe6..7aea81fbf 100644 --- a/src/pluto/keys.c +++ b/src/pluto/keys.c @@ -54,6 +54,7 @@ #include "whack.h" /* for RC_LOG_SERIOUS */ #include "timer.h" #include "fetch.h" +#include "xauth.h" const char *shared_secrets_file = SHARED_SECRETS_FILE; @@ -97,11 +98,11 @@ allocate_RSA_public_key(const cert_t cert) default: plog("RSA public key allocation error"); } - init_RSA_public_key(&pk->u.rsa, e, n); -#ifdef DEBUG - DBG(DBG_PRIVATE, RSA_show_public_key(&pk->u.rsa)); -#endif + init_RSA_public_key(&pk->u.rsa, e, n); + DBG(DBG_RAW, + RSA_show_public_key(&pk->u.rsa) + ) pk->alg = PUBKEY_ALG_RSA; pk->id = empty_id; @@ -182,7 +183,7 @@ get_secret(const struct connection *c, enum PrivateKeyKind kind, bool asym) his_id = &rw_id; } 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_INSTANCE && id_is_ipaddr(&c->spd.that.id)))) { @@ -414,7 +415,7 @@ process_psk_secret(chunk_t *psk) } 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; ugh = ttodatav(tok, flp->cur - tok, 0, buf, sizeof(buf), &sz @@ -589,7 +590,6 @@ static err_t process_xauth(secret_t *s) { chunk_t user_name; - chunk_t user_password; s->kind = PPK_XAUTH; @@ -605,31 +605,21 @@ process_xauth(secret_t *s) user_name.ptr = 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()) 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; + return process_psk_secret(&s->u.xauth_secret.user_password); } /* get XAUTH secret from chained secrets lists * only one entry is currently supported */ -bool +static bool xauth_get_secret(xauth_t *xauth_secret) { secret_t *s; @@ -656,9 +646,10 @@ xauth_get_secret(xauth_t *xauth_secret) /* * find a matching secret */ -bool +static bool xauth_verify_secret(const xauth_t *xauth_secret) { + bool found = FALSE; secret_t *s; for (s = secrets; s != NULL; s = s->next) @@ -667,14 +658,45 @@ xauth_verify_secret(const xauth_t *xauth_secret) { if (!same_chunk(xauth_secret->user_name, s->u.xauth_secret.user_name)) continue; + found = TRUE; if (same_chunk(xauth_secret->user_password, s->u.xauth_secret.user_password)) 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; } /* + * 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 */ static err_t @@ -1202,14 +1224,11 @@ unpack_RSA_public_key(RSA_public_key_t *rsa, const chunk_t *pubkey) return RSA_MAX_OCTETS_UGH; 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 = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE; /* now octets */ + DBG(DBG_RAW, + RSA_show_public_key(rsa) + ) if (rsa->k != mod.len) { diff --git a/src/pluto/keys.h b/src/pluto/keys.h index 3e583e495..d1442ce56 100644 --- a/src/pluto/keys.h +++ b/src/pluto/keys.h @@ -41,6 +41,11 @@ enum PrivateKeyKind { PPK_PIN }; +extern void xauth_defaults(void); + +/* forward declaration */ +struct connection; + 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 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 void unreference_key(pubkey_t **pkp); - extern err_t add_public_key(const struct id *id , enum dns_auth_level dns_auth_level , 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 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 diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c index af2ee30c1..2fcc27deb 100644 --- a/src/pluto/modecfg.c +++ b/src/pluto/modecfg.c @@ -39,7 +39,9 @@ #include "crypto.h" #include "modecfg.h" #include "whack.h" -#include "keys.h" +#include "xauth.h" + +#define MAX_XAUTH_TRIES 3 #define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \ | 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 */ ); + freeanychunk(st->st_tpacket); clonetochunk(st->st_tpacket, msg.start, pbs_offset(&msg), "ModeCfg msg"); /* Transmit */ @@ -424,67 +427,6 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia) } /* - * 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 */ static stf_status @@ -595,6 +537,27 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id 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: * HDR*, HASH, ATTR(REQ=IP) --> HDR*, HASH, ATTR(REPLY=IP) * @@ -606,91 +569,84 @@ modecfg_inR0(struct msg_digest *md) struct state *const st = md->st; u_int16_t isama_id; internal_addr_t ia; - stf_status stat; + stf_status stat, stat_build; stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); if (stat != STF_OK) return stat; - + get_internal_addr(st->st_connection, &ia); plog("sending ModeCfg 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; - } + stat_build = modecfg_build_msg(st, &md->rbody + , ISAKMP_CFG_REPLY + , &ia + , isama_id); + if (stat_build != STF_OK) + return stat_build; st->st_msgid = 0; return STF_OK; } -/* STATE_MODE_CFG_R1: - * HDR*, HASH, ATTR(ACK,OK) +/* STATE_MODE_CFG_I1: + * HDR*, HASH, ATTR(REPLY=IP) * - * used in ModeCfg push mode, on the server (responder) + * used in ModeCfg pull mode, on the client (initiator) */ stf_status -modecfg_inR1(struct msg_digest *md) +modecfg_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 ModeCfg ack"); + plog("parsing ModeCfg reply"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); if (stat != STF_OK) return stat; + st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); st->st_msgid = 0; return STF_OK; } -/* STATE_MODE_CFG_I1: - * HDR*, HASH, ATTR(REPLY=IP) - * - * used in ModeCfg pull mode, on the client (initiator) + +/* + * Send ModeCfg set message from server to client in push mode */ stf_status -modecfg_inI1(struct msg_digest *md) +modecfg_send_set(struct state *st) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; stf_status stat; + internal_addr_t ia; - plog("parsing ModeCfg reply"); - - stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); - if (stat != STF_OK) - return stat; + get_internal_addr(st->st_connection, &ia); - st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); - st->st_msgid = 0; - return STF_OK; + 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_I2: +/* STATE_MODE_CFG_I0: * HDR*, HASH, ATTR(SET=IP) --> HDR*, HASH, ATTR(ACK,OK) * * used in ModeCfg push mode, on the client (initiator). */ stf_status -modecfg_inI2(struct msg_digest *md) +modecfg_inI0(struct msg_digest *md) { struct state *const st = md->st; u_int16_t isama_id; internal_addr_t ia; lset_t attr_set; - stf_status stat; + stf_status stat, stat_build; plog("parsing ModeCfg set"); @@ -707,95 +663,59 @@ modecfg_inI2(struct msg_digest *md) plog("sending ModeCfg ack"); - stat = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_ACK - , &ia - , isama_id); - if (stat != STF_OK) - { - /* notification payload - not exactly the right choice, but okay */ - md->note = ATTRIBUTES_NOT_SUPPORTED; - return stat; - } + stat_build = modecfg_build_msg(st, &md->rbody + , ISAKMP_CFG_ACK + , &ia + , isama_id); + if (stat_build != STF_OK) + return stat_build; st->st_msgid = 0; return STF_OK; } -/* STATE_XAUTH_R1: - * HDR*, HASH, ATTR(REPLY=USERNAME/PASSWORD) --> HDR*, HASH, ATTR(STATUS) +/* STATE_MODE_CFG_R3: + * HDR*, HASH, ATTR(ACK,OK) * - * used on the XAUTH server (responder) + * used in ModeCfg push mode, on the server (responder) */ stf_status -xauth_inR1(struct msg_digest *md) +modecfg_inR3(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"); + plog("parsing ModeCfg ack"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &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); + st->st_msgid = 0; return STF_OK; } -/* STATE_XAUTH_R2: - * HDR*, ATTR(STATUS), HASH --> Done - * - * used on the XAUTH server (responder) +/* + * Send XAUTH credentials request (username + password) */ stf_status -xauth_inR2(struct msg_digest *md) +xauth_send_request(struct state *st) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; stf_status stat; + internal_addr_t ia; - plog("parsing XAUTH ack"); - - stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); - if (stat != STF_OK) - return stat; + init_internal_addr(&ia); + ia.attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF) + | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF); - st->st_msgid = 0; - return STF_OK; + 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: @@ -809,7 +729,7 @@ xauth_inI0(struct msg_digest *md) struct state *const st = md->st; u_int16_t isama_id; internal_addr_t ia; - stf_status stat; + stf_status stat, stat_build; plog("parsing XAUTH request"); @@ -817,19 +737,19 @@ xauth_inI0(struct msg_digest *md) if (stat != STF_OK) return stat; - /* check XAUTH request */ + /* 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; } - if ((ia.attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY) + 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; } - 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 request"); stat = STF_FAIL; @@ -840,8 +760,8 @@ xauth_inI0(struct msg_digest *md) if (stat == STF_OK) { - /* get user credentials */ - if (!xauth_get_secret(&ia.xauth_secret)) + /* get user credentials using a plugin function */ + if (!xauth_module.get_secret(&ia.xauth_secret)) { plog("xauth user credentials not found"); stat = STF_FAIL; @@ -849,6 +769,16 @@ xauth_inI0(struct msg_digest *md) } 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); } @@ -860,17 +790,100 @@ xauth_inI0(struct msg_digest *md) plog("sending XAUTH reply"); - stat = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_REPLY - , &ia - , isama_id); - if (stat != STF_OK) + 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) { - /* notification payload - not exactly the right choice, but okay */ - md->note = ATTRIBUTES_NOT_SUPPORTED; + 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: + * 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, stat_build; + + plog("parsing XAUTH reply"); + + stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); + if (stat != STF_OK) return stat; + + /* did the client return an XAUTH FAIL status? */ + if ((ia.attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE + MODECFG_ROOF)) != LEMPTY) + { + plog("received FAIL status in XAUTH reply"); + + /* 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) + { + plog("user name attribute is missing in XAUTH reply"); + st->st_xauth.status = FALSE; } - st->st_xauth.started = TRUE; + else if ((ia.attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE + MODECFG_ROOF)) == LEMPTY) + { + plog("user password attribute is missing in XAUTH reply"); + 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"); + } + + /* 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 = st->st_xauth.status; + + plog("sending XAUTH status:"); + + stat_build = modecfg_build_msg(st, &md->rbody + , ISAKMP_CFG_SET + , &ia + , isama_id); + if (stat_build != STF_OK) + return stat_build; return STF_OK; } @@ -882,26 +895,76 @@ xauth_inI0(struct msg_digest *md) stf_status xauth_inI1(struct msg_digest *md) { - struct state *const st = md->st; + struct state *const st = md->st; u_int16_t isama_id; internal_addr_t ia; - stf_status stat; + 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; + } - /* prepare XAUTH set which sends the authentication status */ - init_internal_addr(&ia); + 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: + * 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; - stat = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_ACK - , &ia - , isama_id); st->st_msgid = 0; - return stat; + if (st->st_xauth.status) + { + return STF_OK; + } + else + { + delete_state(st); + return STF_IGNORE; + } } diff --git a/src/pluto/modecfg.h b/src/pluto/modecfg.h index fe00067b7..68b7ef446 100644 --- a/src/pluto/modecfg.h +++ b/src/pluto/modecfg.h @@ -21,23 +21,27 @@ struct state; 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_set(struct state *st); -/* ModeConfig state transition functions */ +/* ModeConfig pull mode state transition functions */ 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); + +/* ModeConfig push mode start function */ +extern stf_status modecfg_send_set(struct state *st); + +/* ModeConfig push mode state transition functions */ +extern stf_status modecfg_inI0(struct msg_digest *md); +extern stf_status modecfg_inR3(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_inR1(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 */ diff --git a/src/pluto/state.h b/src/pluto/state.h index 2c34fc94b..d3a980564 100644 --- a/src/pluto/state.h +++ b/src/pluto/state.h @@ -216,6 +216,7 @@ struct state struct { int attempt; bool started; + bool status; } st_xauth; u_int32_t nat_traversal; diff --git a/src/pluto/vendor.c b/src/pluto/vendor.c index 4983a45a0..54333c49b 100644 --- a/src/pluto/vendor.c +++ b/src/pluto/vendor.c @@ -394,6 +394,9 @@ handle_known_vendorid (struct msg_digest *md md->dpd = TRUE; vid_useful = TRUE; break; + case VID_MISC_XAUTH: + vid_useful = TRUE; + break; default: break; } diff --git a/src/pluto/xauth.c b/src/pluto/xauth.c new file mode 100644 index 000000000..e44ac4ec9 --- /dev/null +++ b/src/pluto/xauth.c @@ -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 */ +} diff --git a/src/pluto/xauth.h b/src/pluto/xauth.h new file mode 100644 index 000000000..f60d1d025 --- /dev/null +++ b/src/pluto/xauth.h @@ -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 */ |