diff options
Diffstat (limited to 'src/pluto/modecfg.c')
-rw-r--r-- | src/pluto/modecfg.c | 433 |
1 files changed, 248 insertions, 185 deletions
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; + } } |