diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2007-01-28 21:00:49 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2007-01-28 21:00:49 +0000 |
commit | cd4e20d58fb0d782ba9f7bd4bead4f333d670370 (patch) | |
tree | 40dedbc421cf4811b9f70b8a62977fd962b9facd /programs/pluto/demux.c | |
parent | 5c3858b7d7ae271065816bea3a4944b75bc890d1 (diff) | |
download | vyos-strongswan-cd4e20d58fb0d782ba9f7bd4bead4f333d670370.tar.gz vyos-strongswan-cd4e20d58fb0d782ba9f7bd4bead4f333d670370.zip |
- New upstream release, now _with_ XAUTH support.
Diffstat (limited to 'programs/pluto/demux.c')
-rw-r--r-- | programs/pluto/demux.c | 168 |
1 files changed, 131 insertions, 37 deletions
diff --git a/programs/pluto/demux.c b/programs/pluto/demux.c index 3146b3d40..304d790e3 100644 --- a/programs/pluto/demux.c +++ b/programs/pluto/demux.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: demux.c,v 1.16 2006/10/19 21:07:40 as Exp $ + * RCSID $Id: demux.c,v 1.17 2007/01/10 00:36:19 as Exp $ */ /* Ordering Constraints on Payloads @@ -454,45 +454,81 @@ static const struct state_microcode state_microcode_table[] = { , P(HASH), LEMPTY, PT(NONE) , EVENT_NULL, informational }, - /* MODE_CFG_x: - * Case R0: Responder -> Initiator - * <- Req(addr=0) - * Reply(ad=x) -> - * - * Case R1: Set(addr=x) -> - * <- Ack(ok) - */ + /* 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_MODE_CFG_R0, STATE_MODE_CFG_R1 + { STATE_XAUTH_R1, STATE_XAUTH_R2 , SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY , P(ATTR) | P(HASH), P(VID), PT(HASH) - , EVENT_SA_REPLACE, modecfg_inR0 }, + , EVENT_RETRANSMIT, xauth_inR1 }, - { STATE_MODE_CFG_R1, STATE_MODE_CFG_R2 - , SMF_ALL_AUTH | SMF_ENCRYPTED + { 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, modecfg_inR1 }, + , 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 + , SMF_ALL_AUTH | SMF_ENCRYPTED + , LEMPTY, LEMPTY, PT(NONE) + , EVENT_NULL, unexpected }, - { STATE_MODE_CFG_R2, STATE_UNDEFINED + { STATE_XAUTH_R3, STATE_UNDEFINED , SMF_ALL_AUTH | SMF_ENCRYPTED , LEMPTY, LEMPTY, PT(NONE) , 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 , 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_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 , 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 }; @@ -1258,6 +1294,11 @@ process_packet(struct msg_digest **mdp) { plog("size (%u) differs from size specified in ISAKMP HDR (%u)" , (unsigned) pbs_room(&md->packet_pbs), md->hdr.isa_length); +#ifdef CISCO_QUIRKS + if (pbs_room(&md->packet_pbs) - md->hdr.isa_length == 16) + plog("Cisco VPN client appends 16 surplus NULL bytes"); + else +#endif return; } @@ -1447,11 +1488,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)) @@ -1490,7 +1526,7 @@ process_packet(struct msg_digest **mdp) case ISAKMP_XCHG_MODE_CFG: if (is_zero_cookie(md->hdr.isa_icookie)) { - plog("Mode Config message is invalid because" + plog("ModeCfg message is invalid because" " it has an Initiator Cookie of 0"); /* XXX Could send notification back */ return; @@ -1498,7 +1534,7 @@ process_packet(struct msg_digest **mdp) if (is_zero_cookie(md->hdr.isa_rcookie)) { - plog("Mode Config message is invalid because" + plog("ModeCfg message is invalid because" " it has a Responder Cookie of 0"); /* XXX Could send notification back */ return; @@ -1506,7 +1542,7 @@ process_packet(struct msg_digest **mdp) if (md->hdr.isa_msgid == 0) { - plog("Mode Config message is invalid because" + plog("ModeCfg message is invalid because" " it has a Message ID of 0"); /* XXX Could send notification back */ return; @@ -1517,7 +1553,9 @@ process_packet(struct msg_digest **mdp) if (st == NULL) { - /* No appropriate Mode Config state. + bool has_xauth_policy; + + /* No appropriate ModeCfg state. * See if we have a Main Mode state. * ??? what if this is a duplicate of another message? */ @@ -1526,7 +1564,7 @@ process_packet(struct msg_digest **mdp) if (st == NULL) { - plog("Mode Config message is for a non-existent (expired?)" + plog("ModeCfg message is for a non-existent (expired?)" " ISAKMP SA"); /* XXX Could send notification back */ return; @@ -1536,7 +1574,7 @@ process_packet(struct msg_digest **mdp) if (!IS_ISAKMP_SA_ESTABLISHED(st->st_state)) { - loglog(RC_LOG_SERIOUS, "Mode Config message is unacceptable because" + loglog(RC_LOG_SERIOUS, "ModeCfg message is unacceptable because" " it is for an incomplete ISAKMP SA (state=%s)" , enum_name(&state_names, st->st_state)); /* XXX Could send notification back */ @@ -1565,7 +1603,16 @@ process_packet(struct msg_digest **mdp) * */ - if (st->st_connection->spd.that.modecfg + has_xauth_policy = (st->st_connection->policy + & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK)) + != LEMPTY; + + if (has_xauth_policy && !st->st_xauth.started + && IS_PHASE1(st->st_state)) + { + from_state = STATE_XAUTH_I0; + } + else if (st->st_connection->spd.that.modecfg && IS_PHASE1(st->st_state)) { from_state = STATE_MODE_CFG_R0; @@ -1573,12 +1620,12 @@ 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 { /* XXX check if we are being a mode config server here */ - plog("received MODECFG message when in state %s, and we aren't mode config client" + plog("received ModeCfg message when in state %s, and we aren't mode config client" , enum_name(&state_names, st->st_state)); return; } @@ -1588,7 +1635,6 @@ process_packet(struct msg_digest **mdp) set_cur_state(st); from_state = st->st_state; } - break; #ifdef NOTYET @@ -1630,7 +1676,23 @@ process_packet(struct msg_digest **mdp) if (st != NULL) { - while (!LHAS(smc->flags, st->st_oakley.auth)) + u_int16_t auth; + + switch (st->st_oakley.auth) + { + case XAUTHInitPreShared: + case XAUTHRespPreShared: + auth = OAKLEY_PRESHARED_KEY; + break; + case XAUTHInitRSA: + case XAUTHRespRSA: + auth = OAKLEY_RSA_SIG; + break; + default: + auth = st->st_oakley.auth; + } + + while (!LHAS(smc->flags, auth)) { smc++; passert(smc->state == from_state); @@ -2046,6 +2108,8 @@ process_packet(struct msg_digest **mdp) void complete_state_transition(struct msg_digest **mdp, stf_status result) { + bool has_xauth_policy; + bool is_xauth_server; struct msg_digest *md = *mdp; const struct state_microcode *smc = md->smc; enum state_kind from_state = md->from_state; @@ -2263,7 +2327,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result) } /* advance b to end of string */ b = b + strlen(b); - + if (st->st_ah.present) { snprintf(b, sizeof(sadetails)-(b-sadetails)-1 @@ -2276,7 +2340,7 @@ complete_state_transition(struct msg_digest **mdp, stf_status result) } /* advance b to end of string */ b = b + strlen(b); - + if (st->st_ipcomp.present) { snprintf(b, sizeof(sadetails)-(b-sadetails)-1 @@ -2319,7 +2383,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); @@ -2333,6 +2397,36 @@ complete_state_transition(struct msg_digest **mdp, stf_status result) , story, sadetails); } + has_xauth_policy = (st->st_connection->policy + & (POLICY_XAUTH_RSASIG | POLICY_XAUTH_PSK)) + != LEMPTY; + is_xauth_server = (st->st_connection->policy + & POLICY_XAUTH_SERVER) + != LEMPTY; + + /* Should we start XAUTH as a server */ + if (has_xauth_policy && is_xauth_server + && IS_ISAKMP_SA_ESTABLISHED(st->st_state) + && !st->st_xauth.started) + { + DBG(DBG_CONTROL, + DBG_log("starting XAUTH server") + ) + xauth_send_request(st); + break; + } + + /* 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) @@ -2384,7 +2478,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; |