diff options
Diffstat (limited to 'src/pluto/modecfg.c')
-rw-r--r-- | src/pluto/modecfg.c | 1773 |
1 files changed, 980 insertions, 793 deletions
diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c index 93624588a..228827f2a 100644 --- a/src/pluto/modecfg.c +++ b/src/pluto/modecfg.c @@ -2,7 +2,7 @@ * Copyright (C) 2001-2002 Colubris Networks * Copyright (C) 2003 Sean Mathews - Nu Tech Software Solutions, inc. * Copyright (C) 2003-2004 Xelerance Corporation - * Copyright (C) 2006-2007 Andreas Steffen - Hochschule fuer Technik Rapperswil + * Copyright (C) 2006-2009 Andreas Steffen - Hochschule fuer Technik Rapperswil * * 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 @@ -14,8 +14,6 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: modecfg.c 3738 2008-04-02 19:04:45Z andreas $ - * * This code originally written by Colubris Networks, Inc. * Extraction of patch and porting to 1.99 codebases by Xelerance Corporation * Porting to 2.x by Sean Mathews @@ -27,6 +25,9 @@ #include <freeswan.h> +#include <library.h> +#include <crypto/prfs/prf.h> + #include "constants.h" #include "defs.h" #include "state.h" @@ -34,21 +35,23 @@ #include "timer.h" #include "ipsec_doi.h" #include "log.h" -#include "md5.h" -#include "sha1.h" #include "crypto.h" #include "modecfg.h" #include "whack.h" #include "xauth.h" -#define MAX_XAUTH_TRIES 3 +#define MAX_XAUTH_TRIES 3 +#define DNS_SERVER_MAX 2 +#define NBNS_SERVER_MAX 2 #define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \ - | LELEM(INTERNAL_IP4_NETMASK) \ - | LELEM(INTERNAL_IP4_DNS) \ - | LELEM(INTERNAL_IP4_NBNS) \ - | LELEM(APPLICATION_VERSION) \ - ) + | LELEM(INTERNAL_IP4_NETMASK) \ + | LELEM(INTERNAL_IP4_DNS) \ + | LELEM(INTERNAL_IP4_NBNS) \ + | LELEM(APPLICATION_VERSION) \ + | LELEM(INTERNAL_IP6_DNS) \ + | LELEM(INTERNAL_IP6_NBNS) \ + ) #define SUPPORTED_UNITY_ATTR_SET ( LELEM(UNITY_BANNER - UNITY_BASE) ) @@ -61,21 +64,21 @@ typedef struct internal_addr internal_addr_t; struct internal_addr { - lset_t attr_set; - lset_t xauth_attr_set; - lset_t unity_attr_set; + lset_t attr_set; + lset_t xauth_attr_set; + lset_t unity_attr_set; - /* ModeCfg variables */ - ip_address ipaddr; - ip_address dns[2]; - ip_address wins[2]; + /* ModeCfg variables */ + ip_address ipaddr; + ip_address dns[DNS_SERVER_MAX]; + ip_address nbns[NBNS_SERVER_MAX]; - char *unity_banner; + char *unity_banner; - /* XAUTH variables */ - u_int16_t xauth_type; - xauth_t xauth_secret; - bool xauth_status; + /* XAUTH variables */ + u_int16_t xauth_type; + xauth_t xauth_secret; + bool xauth_status; }; /* @@ -84,20 +87,30 @@ struct internal_addr static void init_internal_addr(internal_addr_t *ia) { - ia->attr_set = LEMPTY; - ia->xauth_attr_set = LEMPTY; - ia->xauth_secret.user_name = empty_chunk; - ia->xauth_secret.user_password = empty_chunk; - ia->xauth_type = XAUTH_TYPE_GENERIC; - ia->xauth_status = XAUTH_STATUS_FAIL; - ia->unity_attr_set = LEMPTY; - ia->unity_banner = NULL; - - anyaddr(AF_INET, &ia->ipaddr); - anyaddr(AF_INET, &ia->dns[0]); - anyaddr(AF_INET, &ia->dns[1]); - anyaddr(AF_INET, &ia->wins[0]); - anyaddr(AF_INET, &ia->wins[1]); + int i; + + ia->attr_set = LEMPTY; + ia->xauth_attr_set = LEMPTY; + ia->xauth_secret.user_name = chunk_empty; + ia->xauth_secret.user_password = chunk_empty; + ia->xauth_type = XAUTH_TYPE_GENERIC; + ia->xauth_status = XAUTH_STATUS_FAIL; + ia->unity_attr_set = LEMPTY; + ia->unity_banner = NULL; + + anyaddr(AF_INET, &ia->ipaddr); + + /* initialize DNS server information */ + for (i = 0; i < DNS_SERVER_MAX; i++) + { + anyaddr(AF_INET, &ia->dns[i]); + } + + /* initialize WINS server information */ + for (i = 0; i < NBNS_SERVER_MAX; i++) + { + anyaddr(AF_INET, &ia->nbns[i]); + } } /* @@ -106,97 +119,152 @@ init_internal_addr(internal_addr_t *ia) static void get_internal_addr(struct connection *c, internal_addr_t *ia) { - if (isanyaddr(&c->spd.that.host_srcip)) - { - /* not defined in connection - fetch it from LDAP */ - } - else - { - char srcip[ADDRTOT_BUF]; - - ia->ipaddr = c->spd.that.host_srcip; - - addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip)); - plog("assigning virtual IP source address %s", srcip); - } - - if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */ - { - c->spd.that.client.addr = ia->ipaddr; - c->spd.that.client.maskbits = 32; - c->spd.that.has_client = TRUE; - - ia->attr_set = LELEM(INTERNAL_IP4_ADDRESS) - | LELEM(INTERNAL_IP4_NETMASK); - } - - if (!isanyaddr(&ia->dns[0])) /* We got DNS addresses, send them */ - ia->attr_set |= LELEM(INTERNAL_IP4_DNS); - - if (!isanyaddr(&ia->wins[0])) /* We got WINS addresses, send them */ - ia->attr_set |= LELEM(INTERNAL_IP4_NBNS); + int i, dns_idx = 0, nbns_idx = 0; + + if (isanyaddr(&c->spd.that.host_srcip)) + { + /* not defined in connection - fetch it from LDAP */ + } + else + { + char srcip[ADDRTOT_BUF]; + + ia->ipaddr = c->spd.that.host_srcip; + + addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip)); + plog("assigning virtual IP source address %s", srcip); + } + + if (!isanyaddr(&ia->ipaddr)) /* We got an IP address, send it */ + { + c->spd.that.client.addr = ia->ipaddr; + c->spd.that.client.maskbits = 32; + c->spd.that.has_client = TRUE; + + ia->attr_set = LELEM(INTERNAL_IP4_ADDRESS) + | LELEM(INTERNAL_IP4_NETMASK); + } + + /* assign DNS servers */ + for (i = 1; i <= DNS_SERVER_MAX; i++) + { + char dns_key[16], *dns_str; + + snprintf(dns_key, sizeof(dns_key), "pluto.dns%d", i); + dns_str = lib->settings->get_str(lib->settings, dns_key, NULL); + if (dns_str) + { + err_t ugh; + sa_family_t family = strchr(dns_str, ':') ? AF_INET6 : AF_INET; + + ugh = ttoaddr(dns_str, 0, family, &ia->dns[dns_idx]); + if (ugh != NULL) + { + plog("error in DNS server address: %s", ugh); + continue; + } + plog("assigning DNS server %s to peer", dns_str); + + /* differentiate between IP4 and IP6 in modecfg_build_msg() */ + ia->attr_set |= LELEM(INTERNAL_IP4_DNS); + dns_idx++; + } + } + + /* assign WINS servers */ + for (i = 1; i <= NBNS_SERVER_MAX; i++) + { + char nbns_key[16], *nbns_str; + + snprintf(nbns_key, sizeof(nbns_key), "pluto.nbns%d", i); + nbns_str = lib->settings->get_str(lib->settings, nbns_key, NULL); + if (nbns_str) + { + err_t ugh; + sa_family_t family = strchr(nbns_str, ':') ? AF_INET6 : AF_INET; + + ugh = ttoaddr(nbns_str, 0, family, &ia->nbns[nbns_idx]); + if (ugh != NULL) + { + plog("error in WINS server address: %s", ugh); + continue; + } + plog("assigning NBNS server %s to peer", nbns_str); + + /* differentiate between IP4 and IP6 in modecfg_build_msg() */ + ia->attr_set |= LELEM(INTERNAL_IP4_NBNS); + nbns_idx++; + } + } } + /* * Set srcip and client subnet to internal IP address */ static bool set_internal_addr(struct connection *c, internal_addr_t *ia) { - if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS) - && !isanyaddr(&ia->ipaddr)) - { - if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0 - || isanyaddr(&c->spd.this.host_srcip) - || sameaddr(&c->spd.this.host_srcip, &ia->ipaddr)) + if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS) + && !isanyaddr(&ia->ipaddr)) { - char srcip[ADDRTOT_BUF]; + if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0 + || isanyaddr(&c->spd.this.host_srcip) + || sameaddr(&c->spd.this.host_srcip, &ia->ipaddr)) + { + char srcip[ADDRTOT_BUF]; - addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip)); - plog("setting virtual IP source address to %s", srcip); - } - else - { - char old_srcip[ADDRTOT_BUF]; - char new_srcip[ADDRTOT_BUF]; + addrtot(&ia->ipaddr, 0, srcip, sizeof(srcip)); + plog("setting virtual IP source address to %s", srcip); + } + else + { + char old_srcip[ADDRTOT_BUF]; + char new_srcip[ADDRTOT_BUF]; - addrtot(&c->spd.this.host_srcip, 0, old_srcip, sizeof(old_srcip)); - addrtot(&ia->ipaddr, 0, new_srcip, sizeof(new_srcip)); - plog("replacing virtual IP source address %s by %s" - , old_srcip, new_srcip); + addrtot(&c->spd.this.host_srcip, 0, old_srcip, sizeof(old_srcip)); + addrtot(&ia->ipaddr, 0, new_srcip, sizeof(new_srcip)); + plog("replacing virtual IP source address %s by %s" + , old_srcip, new_srcip); + } + + /* setting srcip */ + c->spd.this.host_srcip = ia->ipaddr; + + /* setting client subnet to srcip/32 */ + addrtosubnet(&ia->ipaddr, &c->spd.this.client); + setportof(0, &c->spd.this.client.addr); + c->spd.this.has_client = TRUE; + return TRUE; } - - /* setting srcip */ - c->spd.this.host_srcip = ia->ipaddr; - - /* setting client subnet to srcip/32 */ - addrtosubnet(&ia->ipaddr, &c->spd.this.client); - setportof(0, &c->spd.this.client.addr); - c->spd.this.has_client = TRUE; - return TRUE; - } - return FALSE; + return FALSE; } /* * Compute HASH of Mode Config. */ -static size_t -modecfg_hash(u_char *dest, const u_char *start, const u_char *roof - , const struct state *st) +static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof, + const struct state *st) { - struct hmac_ctx ctx; - - hmac_init_chunk(&ctx, st->st_oakley.hasher, st->st_skeyid_a); - hmac_update(&ctx, (const u_char *) &st->st_msgid, sizeof(st->st_msgid)); - hmac_update(&ctx, start, roof-start); - hmac_final(dest, &ctx); - - DBG(DBG_CRYPT, - DBG_log("ModeCfg HASH computed:"); - DBG_dump("", dest, ctx.hmac_digest_size) - ) - return ctx.hmac_digest_size; + chunk_t msgid_chunk = chunk_from_thing(st->st_msgid); + chunk_t msg_chunk = { start, roof - start }; + size_t prf_block_size; + pseudo_random_function_t prf_alg; + prf_t *prf; + + prf_alg = oakley_to_prf(st->st_oakley.hash); + prf = lib->crypto->create_prf(lib->crypto, prf_alg); + prf->set_key(prf, st->st_skeyid_a); + prf->get_bytes(prf, msgid_chunk, NULL); + prf->get_bytes(prf, msg_chunk, dest); + prf_block_size = prf->get_block_size(prf); + prf->destroy(prf); + + DBG(DBG_CRYPT, + DBG_log("ModeCfg HASH computed:"); + DBG_dump("", dest, prf_block_size) + ) + return prf_block_size; } @@ -205,202 +273,222 @@ modecfg_hash(u_char *dest, const u_char *start, const u_char *roof */ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody - , u_int16_t msg_type - , internal_addr_t *ia - , u_int16_t ap_id) + , u_int16_t msg_type + , internal_addr_t *ia + , u_int16_t ap_id) { - u_char *r_hash_start, *r_hashval; + u_char *r_hash_start, *r_hashval; - START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR); + START_HASH_PAYLOAD(*rbody, ISAKMP_NEXT_ATTR); - /* ATTR out */ - { - struct isakmp_mode_attr attrh; - struct isakmp_attribute attr; - pb_stream strattr,attrval; - int attr_type; - int dns_idx, wins_idx; - bool dont_advance; - bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY; - bool is_unity_attr_set = ia->unity_attr_set != LEMPTY; - lset_t attr_set = ia->attr_set; - - attrh.isama_np = ISAKMP_NEXT_NONE; - attrh.isama_type = msg_type; - attrh.isama_identifier = ap_id; - - if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr)) - return STF_INTERNAL_ERROR; - - attr_type = 0; - dns_idx = 0; - wins_idx = 0; - - while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set) + /* ATTR out */ { - if (attr_set == LEMPTY) - { - if (is_xauth_attr_set) - { - attr_set = ia->xauth_attr_set; - attr_type = XAUTH_BASE; - is_xauth_attr_set = FALSE; - } - else + struct isakmp_mode_attr attrh; + struct isakmp_attribute attr; + pb_stream strattr,attrval; + int attr_type, dns_attr_type, nbns_attr_type; + int dns_idx, nbns_idx; + bool dont_advance; + bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY; + bool is_unity_attr_set = ia->unity_attr_set != LEMPTY; + lset_t attr_set = ia->attr_set; + + attrh.isama_np = ISAKMP_NEXT_NONE; + attrh.isama_type = msg_type; + attrh.isama_identifier = ap_id; + + if (!out_struct(&attrh, &isakmp_attr_desc, rbody, &strattr)) { - attr_set = ia->unity_attr_set; - attr_type = UNITY_BASE; - is_unity_attr_set = FALSE; + return STF_INTERNAL_ERROR; } - } - - dont_advance = FALSE; + attr_type = 0; + dns_idx = 0; + nbns_idx = 0; - if (attr_set & 1) - { - const u_char *byte_ptr; - u_int len; - - /* ISAKMP attr out */ - if (attr_type == XAUTH_TYPE) - { - attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV; - attr.isaat_lv = ia->xauth_type; - } - else if (attr_type == XAUTH_STATUS) + while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set) { - attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV; - attr.isaat_lv = ia->xauth_status; - } - else - { - attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV; - } - out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval); - - switch (attr_type) - { - case INTERNAL_IP4_ADDRESS: - if (!isanyaddr(&ia->ipaddr)) - { - len = addrbytesptr(&ia->ipaddr, &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP4_addr"); - } - break; - case INTERNAL_IP4_NETMASK: - { - u_int mask; -#if 0 - char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; - int t,m=st->st_connection->that.host_addr.maskbit; - for (t=0; t<4; t++) + if (attr_set == LEMPTY) { - if (m < 8) - mask[t] = bits[m]; - else - mask[t] = 0xff; - m -= 8; + if (is_xauth_attr_set) + { + attr_set = ia->xauth_attr_set; + attr_type = XAUTH_BASE; + is_xauth_attr_set = FALSE; + } + else + { + attr_set = ia->unity_attr_set; + attr_type = UNITY_BASE; + is_unity_attr_set = FALSE; + } } -#endif - if (st->st_connection->spd.this.client.maskbits == 0) - mask = 0; - else - mask = 0xffffffff * 1; - out_raw(&mask, 4, &attrval, "IP4_mask"); - } - break; - case INTERNAL_IP4_SUBNET: - { - char mask[4]; - char bits[8] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; - int t; - int m = st->st_connection->spd.this.client.maskbits; + + dont_advance = FALSE; - for (t = 0; t < 4; t++) + if (attr_set & 1) { - if (m < 8) - mask[t] = bits[m]; - else - mask[t] = 0xff; - m -= 8; - if (m < 0) - m = 0; + const u_char *byte_ptr; + u_int len; + + /* ISAKMP attr out */ + if (attr_type == XAUTH_TYPE) + { + attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV; + attr.isaat_lv = ia->xauth_type; + } + else if (attr_type == XAUTH_STATUS) + { + attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TV; + attr.isaat_lv = ia->xauth_status; + } + else if (attr_type == INTERNAL_IP4_DNS && !isanyaddr(&ia->dns[dns_idx])) + { + dns_attr_type = (addrtypeof(&ia->dns[dns_idx]) == AF_INET) ? + INTERNAL_IP4_DNS : INTERNAL_IP6_DNS; + attr.isaat_af_type = dns_attr_type | ISAKMP_ATTR_AF_TLV; + + } + else if (attr_type == INTERNAL_IP4_NBNS && !isanyaddr(&ia->nbns[nbns_idx])) + { + nbns_attr_type = (addrtypeof(&ia->nbns[nbns_idx]) == AF_INET) ? + INTERNAL_IP4_NBNS : INTERNAL_IP6_NBNS; + attr.isaat_af_type = nbns_attr_type | ISAKMP_ATTR_AF_TLV; + + } + else + { + attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV; + } + out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval); + + switch (attr_type) + { + case INTERNAL_IP4_ADDRESS: + if (!isanyaddr(&ia->ipaddr)) + { + len = addrbytesptr(&ia->ipaddr, &byte_ptr); + out_raw(byte_ptr, len, &attrval, "IP4_addr"); + } + break; + case INTERNAL_IP4_NETMASK: + { + u_int mask; +#if 0 + char mask[4],bits[8]={0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; + int t,m=st->st_connection->that.host_addr.maskbit; + for (t=0; t<4; t++) + { + if (m < 8) + mask[t] = bits[m]; + else + mask[t] = 0xff; + m -= 8; + } +#endif + if (st->st_connection->spd.this.client.maskbits == 0) + { + mask = 0; + } + else + { + mask = 0xffffffff * 1; + out_raw(&mask, 4, &attrval, "IP4_mask"); + } + } + break; + case INTERNAL_IP4_SUBNET: + { + char mask[4]; + char bits[8] = {0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe}; + int t; + int m = st->st_connection->spd.this.client.maskbits; + + for (t = 0; t < 4; t++) + { + mask[t] = (m < 8) ? bits[m] : 0xff; + m -= 8; + if (m < 0) + { + m = 0; + } + } + len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr); + out_raw(byte_ptr, len, &attrval, "IP4_subnet"); + out_raw(mask, sizeof(mask), &attrval, "IP4_submsk"); + } + break; + case INTERNAL_IP4_DNS: + case INTERNAL_IP6_DNS: + if (!isanyaddr(&ia->dns[dns_idx])) + { + len = addrbytesptr(&ia->dns[dns_idx++], &byte_ptr); + out_raw(byte_ptr, len, &attrval, "IP_dns"); + } + if (dns_idx < DNS_SERVER_MAX && !isanyaddr(&ia->dns[dns_idx])) + { + dont_advance = TRUE; + } + break; + case INTERNAL_IP4_NBNS: + case INTERNAL_IP6_NBNS: + if (!isanyaddr(&ia->nbns[nbns_idx])) + { + len = addrbytesptr(&ia->nbns[nbns_idx++], &byte_ptr); + out_raw(byte_ptr, len, &attrval, "IP_nbns"); + } + if (nbns_idx < NBNS_SERVER_MAX && !isanyaddr(&ia->nbns[nbns_idx])) + { + dont_advance = TRUE; + } + break; + case XAUTH_TYPE: + break; + case XAUTH_USER_NAME: + if (ia->xauth_secret.user_name.ptr != NULL) + { + out_raw(ia->xauth_secret.user_name.ptr + , ia->xauth_secret.user_name.len + , &attrval, "xauth_user_name"); + } + break; + case XAUTH_USER_PASSWORD: + if (ia->xauth_secret.user_password.ptr != NULL) + { + out_raw(ia->xauth_secret.user_password.ptr + , ia->xauth_secret.user_password.len + , &attrval, "xauth_user_password"); + } + break; + case XAUTH_STATUS: + break; + case UNITY_BANNER: + if (ia->unity_banner != NULL) + { + out_raw(ia->unity_banner + , strlen(ia->unity_banner) + , &attrval, "UNITY_BANNER"); + } + break; + default: + plog("attempt to send unsupported mode cfg attribute %s." + , enum_show(&modecfg_attr_names, attr_type)); + break; + } + close_output_pbs(&attrval); + } + if (!dont_advance) + { + attr_type++; + attr_set >>= 1; } - len = addrbytesptr(&st->st_connection->spd.this.client.addr, &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP4_subnet"); - out_raw(mask, sizeof(mask), &attrval, "IP4_submsk"); - } - break; - case INTERNAL_IP4_DNS: - if (!isanyaddr(&ia->dns[dns_idx])) - { - len = addrbytesptr(&ia->dns[dns_idx++], &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP4_dns"); - } - if (dns_idx < 2 && !isanyaddr(&ia->dns[dns_idx])) - { - dont_advance = TRUE; - } - break; - case INTERNAL_IP4_NBNS: - if (!isanyaddr(&ia->wins[wins_idx])) - { - len = addrbytesptr(&ia->wins[wins_idx++], &byte_ptr); - out_raw(byte_ptr, len, &attrval, "IP4_wins"); - } - if (wins_idx < 2 && !isanyaddr(&ia->wins[wins_idx])) - { - dont_advance = TRUE; - } - break; - case XAUTH_TYPE: - break; - case XAUTH_USER_NAME: - if (ia->xauth_secret.user_name.ptr != NULL) - { - out_raw(ia->xauth_secret.user_name.ptr - , ia->xauth_secret.user_name.len - , &attrval, "xauth_user_name"); - } - break; - case XAUTH_USER_PASSWORD: - if (ia->xauth_secret.user_password.ptr != NULL) - { - out_raw(ia->xauth_secret.user_password.ptr - , ia->xauth_secret.user_password.len - , &attrval, "xauth_user_password"); - } - break; - case XAUTH_STATUS: - break; - case UNITY_BANNER: - if (ia->unity_banner != NULL) - { - out_raw(ia->unity_banner - , strlen(ia->unity_banner) - , &attrval, "UNITY_BANNER"); - } - break; - default: - plog("attempt to send unsupported mode cfg attribute %s." - , enum_show(&modecfg_attr_names, attr_type)); - break; } - close_output_pbs(&attrval); - } - if (!dont_advance) - { - attr_type++; - attr_set >>= 1; - } + close_message(&strattr); } - close_message(&strattr); - } - modecfg_hash(r_hashval, r_hash_start, rbody->cur, st); - close_message(rbody); - encrypt_message(rbody, st); - return STF_OK; + modecfg_hash(r_hashval, r_hash_start, rbody->cur, st); + close_message(rbody); + encrypt_message(rbody, st); + return STF_OK; } /* @@ -409,55 +497,56 @@ modecfg_build_msg(struct state *st, pb_stream *rbody static stf_status modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia) { - pb_stream msg; - pb_stream rbody; - char buf[BUF_LEN]; - - /* set up attr */ - init_pbs(&msg, buf, sizeof(buf), "ModeCfg msg buffer"); - - /* this is the beginning of a new exchange */ - st->st_msgid = generate_msgid(st); - init_phase2_iv(st, &st->st_msgid); - - /* HDR out */ - { - struct isakmp_hdr hdr; - - zero(&hdr); /* default to 0 */ - hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; - hdr.isa_np = ISAKMP_NEXT_HASH; - hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG; - hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; - memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); - memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); - hdr.isa_msgid = st->st_msgid; - - if (!out_struct(&hdr, &isakmp_hdr_desc, &msg, &rbody)) + pb_stream msg; + pb_stream rbody; + char buf[BUF_LEN]; + + /* set up attr */ + init_pbs(&msg, buf, sizeof(buf), "ModeCfg msg buffer"); + + /* this is the beginning of a new exchange */ + st->st_msgid = generate_msgid(st); + init_phase2_iv(st, &st->st_msgid); + + /* HDR out */ { - return STF_INTERNAL_ERROR; + struct isakmp_hdr hdr; + + zero(&hdr); /* default to 0 */ + hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; + hdr.isa_np = ISAKMP_NEXT_HASH; + hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG; + hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; + memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); + memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); + hdr.isa_msgid = st->st_msgid; + + if (!out_struct(&hdr, &isakmp_hdr_desc, &msg, &rbody)) + { + return STF_INTERNAL_ERROR; + } } - } - - /* ATTR out */ - modecfg_build_msg(st, &rbody - , isama_type - , ia - , 0 /* XXX isama_id */ - ); - - freeanychunk(st->st_tpacket); - clonetochunk(st->st_tpacket, msg.start, pbs_offset(&msg), "ModeCfg msg"); - - /* Transmit */ - send_packet(st, "ModeCfg msg"); - - if (st->st_event->ev_type != EVENT_RETRANSMIT) - { - delete_event(st); - event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st); - } - return STF_OK; + + /* ATTR out */ + modecfg_build_msg(st, &rbody + , isama_type + , ia + , 0 /* XXX isama_id */ + ); + + free(st->st_tpacket.ptr); + st->st_tpacket = chunk_create(msg.start, pbs_offset(&msg)); + st->st_tpacket = chunk_clone(st->st_tpacket); + + /* Transmit */ + send_packet(st, "ModeCfg msg"); + + if (st->st_event->ev_type != EVENT_RETRANSMIT) + { + delete_event(st); + event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st); + } + return STF_OK; } /* @@ -466,111 +555,184 @@ modecfg_send_msg(struct state *st, int isama_type, internal_addr_t *ia) static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia) { - struct isakmp_attribute attr; - pb_stream strattr; - - while (pbs_left(attrs) >= sizeof(struct isakmp_attribute)) - { - u_int16_t attr_type; - u_int16_t attr_len; + struct isakmp_attribute attr; + pb_stream strattr; + err_t ugh; + char buf[BUF_LEN]; + int dns_idx = 0; + int nbns_idx = 0; - if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr)) + while (pbs_left(attrs) >= sizeof(struct isakmp_attribute)) { - return STF_FAIL; - } - attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK; - attr_len = attr.isaat_lv; + u_int16_t attr_type; + u_int16_t attr_len; - switch (attr_type) - { - case INTERNAL_IP4_ADDRESS: - if (attr_len == 4) - { - initaddr((char *)(strattr.cur), 4, AF_INET, &ia->ipaddr); - } - /* fall through to set attribute flag */ - case INTERNAL_IP4_NETMASK: - case INTERNAL_IP4_DNS: - case INTERNAL_IP4_SUBNET: - case INTERNAL_IP4_NBNS: - case INTERNAL_ADDRESS_EXPIRY: - case INTERNAL_IP4_DHCP: - case INTERNAL_IP6_ADDRESS: - case INTERNAL_IP6_NETMASK: - case INTERNAL_IP6_DNS: - case INTERNAL_IP6_NBNS: - case INTERNAL_IP6_DHCP: - case SUPPORTED_ATTRIBUTES: - case INTERNAL_IP6_SUBNET: - ia->attr_set |= LELEM(attr_type); - break; - case APPLICATION_VERSION: - if (attr_len > 0) - { - DBG(DBG_PARSING, - DBG_log(" '%.*s'", attr_len, strattr.cur) - ) - } - ia->attr_set |= LELEM(attr_type); - break; - case XAUTH_TYPE: - ia->xauth_type = attr.isaat_lv; - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_USER_NAME: - setchunk(ia->xauth_secret.user_name, strattr.cur, attr_len); - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_USER_PASSWORD: - setchunk(ia->xauth_secret.user_password, strattr.cur, attr_len); - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_STATUS: - ia->xauth_status = attr.isaat_lv; - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case XAUTH_MESSAGE: - if (attr_len > 0) - { - DBG(DBG_PARSING, - DBG_log(" '%.*s'", attr_len, strattr.cur) - ) - } - /* fall through to set attribute flag */ - case XAUTH_PASSCODE: - case XAUTH_CHALLENGE: - case XAUTH_DOMAIN: - case XAUTH_NEXT_PIN: - case XAUTH_ANSWER: - ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); - break; - case UNITY_DDNS_HOSTNAME: - if (attr_len > 0) - { - DBG(DBG_PARSING, - DBG_log(" '%.*s'", attr_len, strattr.cur) - ) - } - /* fall through to set attribute flag */ - case UNITY_BANNER: - case UNITY_SAVE_PASSWD: - case UNITY_DEF_DOMAIN: - case UNITY_SPLITDNS_NAME: - case UNITY_SPLIT_INCLUDE: - case UNITY_NATT_PORT: - case UNITY_LOCAL_LAN: - case UNITY_PFS: - case UNITY_FW_TYPE: - case UNITY_BACKUP_SERVERS: - ia->unity_attr_set |= LELEM(attr_type - UNITY_BASE); - break; - default: - plog("unsupported ModeCfg attribute %s received." - , enum_show(&modecfg_attr_names, attr_type)); - break; + if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr)) + { + return STF_FAIL; + } + attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK; + attr_len = attr.isaat_lv; + + switch (attr_type) + { + case INTERNAL_IP4_ADDRESS: + if (attr_len == 4) + { + ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->ipaddr); + if (ugh != NULL) + { + plog("received invalid virtual IPv4 address: %s", ugh); + } + } + ia->attr_set |= LELEM(attr_type); + break; + case INTERNAL_IP4_DNS: + if (attr_len == 4 && dns_idx < DNS_SERVER_MAX) + { + ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->dns[dns_idx]); + if (ugh != NULL) + { + plog("received invalid IPv4 DNS server address: %s", ugh); + } + else + { + addrtot(&ia->dns[dns_idx], 0, buf, BUF_LEN); + plog("received IPv4 DNS server address %s", buf); + dns_idx++; + } + } + ia->attr_set |= LELEM(attr_type); + break; + case INTERNAL_IP4_NBNS: + if (attr_len == 4 && nbns_idx < NBNS_SERVER_MAX) + { + ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->nbns[nbns_idx]); + if (ugh != NULL) + { + plog("received invalid IPv4 WINS server address: %s", ugh); + } + else + { + addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN); + plog("received IPv4 WINS server address %s", buf); + nbns_idx++; + } + } + ia->attr_set |= LELEM(attr_type); + break; + case INTERNAL_IP6_DNS: + if (attr_len == 16 && dns_idx < DNS_SERVER_MAX) + { + ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->dns[dns_idx]); + if (ugh != NULL) + { + plog("received invalid IPv6 DNS server address: %s", ugh); + } + else + { + addrtot(&ia->dns[dns_idx], 0, buf, BUF_LEN); + plog("received IPv6 DNS server address %s", buf); + dns_idx++; + } + } + ia->attr_set |= LELEM(attr_type); + break; + case INTERNAL_IP6_NBNS: + if (attr_len == 16 && nbns_idx < NBNS_SERVER_MAX) + { + ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->nbns[nbns_idx]); + if (ugh != NULL) + { + plog("received invalid IPv6 WINS server address: %s", ugh); + } + else + { + addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN); + plog("received IPv6 WINS server address %s", buf); + nbns_idx++; + } + } + ia->attr_set |= LELEM(attr_type); + break; + case INTERNAL_IP4_NETMASK: + case INTERNAL_IP4_SUBNET: + case INTERNAL_ADDRESS_EXPIRY: + case INTERNAL_IP4_DHCP: + case INTERNAL_IP6_ADDRESS: + case INTERNAL_IP6_NETMASK: + case INTERNAL_IP6_DHCP: + case SUPPORTED_ATTRIBUTES: + case INTERNAL_IP6_SUBNET: + ia->attr_set |= LELEM(attr_type); + break; + case APPLICATION_VERSION: + if (attr_len > 0) + { + DBG(DBG_PARSING, + DBG_log(" '%.*s'", attr_len, strattr.cur) + ) + } + ia->attr_set |= LELEM(attr_type); + break; + case XAUTH_TYPE: + ia->xauth_type = attr.isaat_lv; + ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); + break; + case XAUTH_USER_NAME: + ia->xauth_secret.user_name = chunk_create(strattr.cur, attr_len); + ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); + break; + case XAUTH_USER_PASSWORD: + ia->xauth_secret.user_password = chunk_create(strattr.cur, attr_len); + ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); + break; + case XAUTH_STATUS: + ia->xauth_status = attr.isaat_lv; + ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); + break; + case XAUTH_MESSAGE: + if (attr_len > 0) + { + DBG(DBG_PARSING, + DBG_log(" '%.*s'", attr_len, strattr.cur) + ) + } + /* fall through to set attribute flag */ + case XAUTH_PASSCODE: + case XAUTH_CHALLENGE: + case XAUTH_DOMAIN: + case XAUTH_NEXT_PIN: + case XAUTH_ANSWER: + ia->xauth_attr_set |= LELEM(attr_type - XAUTH_BASE); + break; + case UNITY_DDNS_HOSTNAME: + if (attr_len > 0) + { + DBG(DBG_PARSING, + DBG_log(" '%.*s'", attr_len, strattr.cur) + ) + } + /* fall through to set attribute flag */ + case UNITY_BANNER: + case UNITY_SAVE_PASSWD: + case UNITY_DEF_DOMAIN: + case UNITY_SPLITDNS_NAME: + case UNITY_SPLIT_INCLUDE: + case UNITY_NATT_PORT: + case UNITY_LOCAL_LAN: + case UNITY_PFS: + case UNITY_FW_TYPE: + case UNITY_BACKUP_SERVERS: + ia->unity_attr_set |= LELEM(attr_type - UNITY_BASE); + break; + default: + plog("unsupported ModeCfg attribute %s received." + , enum_show(&modecfg_attr_names, attr_type)); + break; + } } - } - return STF_OK; + return STF_OK; } /* @@ -578,50 +740,52 @@ modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia) */ static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id - , internal_addr_t *ia) + , internal_addr_t *ia) { - struct state *const st = md->st; - struct payload_digest *p; - stf_status stat; + struct state *const st = md->st; + struct payload_digest *p; + stf_status stat; - st->st_msgid = md->hdr.isa_msgid; + st->st_msgid = md->hdr.isa_msgid; - CHECK_QUICK_HASH(md, modecfg_hash(hash_val - , hash_pbs->roof - , md->message_pbs.roof, st) - , "MODECFG-HASH", "ISAKMP_CFG_MSG"); + CHECK_QUICK_HASH(md, modecfg_hash(hash_val + , hash_pbs->roof + , md->message_pbs.roof, st) + , "MODECFG-HASH", "ISAKMP_CFG_MSG"); - /* process the ModeCfg payloads received */ - for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next) - { - internal_addr_t ia_candidate; + /* process the ModeCfg payloads received */ + for (p = md->chain[ISAKMP_NEXT_ATTR]; p != NULL; p = p->next) + { + internal_addr_t ia_candidate; - init_internal_addr(&ia_candidate); + init_internal_addr(&ia_candidate); - if (p->payload.attribute.isama_type == isama_type) - { - *isama_id = p->payload.attribute.isama_identifier; + if (p->payload.attribute.isama_type == isama_type) + { + *isama_id = p->payload.attribute.isama_identifier; - stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); - if (stat == STF_OK) - { - /* return with a valid set of attributes */ - *ia = ia_candidate; - return STF_OK; - } - } - else - { - plog("expected %s, got %s instead (ignored)" - , enum_name(&attr_msg_type_names, isama_type) - , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type)); + stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); + if (stat == STF_OK) + { + /* return with a valid set of attributes */ + *ia = ia_candidate; + return STF_OK; + } + } + else + { + plog("expected %s, got %s instead (ignored)" + , enum_name(&attr_msg_type_names, isama_type) + , enum_name(&attr_msg_type_names, p->payload.attribute.isama_type)); - stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); + stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); + } + if (stat != STF_OK) + { + return stat; + } } - if (stat != STF_OK) - return stat; - } - return STF_IGNORE; + return STF_IGNORE; } /* @@ -630,20 +794,22 @@ modecfg_parse_msg(struct msg_digest *md, int isama_type, u_int16_t *isama_id stf_status modecfg_send_request(struct state *st) { - stf_status stat; - internal_addr_t ia; + stf_status stat; + internal_addr_t ia; - init_internal_addr(&ia); + init_internal_addr(&ia); - ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS) - | LELEM(INTERNAL_IP4_NETMASK); + 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; + 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: @@ -654,38 +820,40 @@ modecfg_send_request(struct state *st) stf_status modecfg_inR0(struct msg_digest *md) { - struct state *const st = md->st; - u_int16_t isama_id; - internal_addr_t ia; - bool want_unity_banner; - stf_status stat, stat_build; - - stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); - if (stat != STF_OK) - return stat; - - want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + bool want_unity_banner; + stf_status stat, stat_build; - init_internal_addr(&ia); - get_internal_addr(st->st_connection, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); + if (stat != STF_OK) + { + return stat; + } - if (want_unity_banner) - { - ia.unity_banner = UNITY_BANNER_STR; - ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE); - } + want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY; + init_internal_addr(&ia); + get_internal_addr(st->st_connection, &ia); - plog("sending ModeCfg reply"); + if (want_unity_banner) + { + ia.unity_banner = UNITY_BANNER_STR; + ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE); + } - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_REPLY - , &ia - , isama_id); - if (stat_build != STF_OK) - return stat_build; + plog("sending ModeCfg reply"); - st->st_msgid = 0; - return STF_OK; + 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_I1: @@ -696,20 +864,21 @@ modecfg_inR0(struct msg_digest *md) stf_status 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 reply"); + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + stf_status stat; - stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); - if (stat != STF_OK) - return stat; + plog("parsing ModeCfg reply"); - st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); - st->st_msgid = 0; - return STF_OK; + 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; } @@ -719,23 +888,25 @@ modecfg_inI1(struct msg_digest *md) stf_status modecfg_send_set(struct state *st) { - stf_status stat; - internal_addr_t ia; + stf_status stat; + internal_addr_t ia; - init_internal_addr(&ia); - get_internal_addr(st->st_connection, &ia); + init_internal_addr(&ia); + get_internal_addr(st->st_connection, &ia); #ifdef CISCO_QUIRKS - ia.unity_banner = UNITY_BANNER_STR; - ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE); + ia.unity_banner = UNITY_BANNER_STR; + ia.unity_attr_set |= LELEM(UNITY_BANNER - UNITY_BASE); #endif 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; + 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: @@ -746,38 +917,40 @@ modecfg_send_set(struct state *st) stf_status 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, unity_attr_set; - stf_status stat, stat_build; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + lset_t attr_set, unity_attr_set; + stf_status stat, stat_build; - plog("parsing ModeCfg set"); + plog("parsing ModeCfg set"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia); - if (stat != STF_OK) - return stat; - - st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); - - /* prepare ModeCfg ack which sends zero length attributes */ - attr_set = ia.attr_set; - unity_attr_set = ia.unity_attr_set; - init_internal_addr(&ia); - ia.attr_set = attr_set & SUPPORTED_ATTR_SET; - ia.unity_attr_set = unity_attr_set & SUPPORTED_UNITY_ATTR_SET; - - plog("sending ModeCfg ack"); - - 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; + stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia); + if (stat != STF_OK) + { + return stat; + } + st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); + + /* prepare ModeCfg ack which sends zero length attributes */ + attr_set = ia.attr_set; + unity_attr_set = ia.unity_attr_set; + init_internal_addr(&ia); + ia.attr_set = attr_set & SUPPORTED_ATTR_SET; + ia.unity_attr_set = unity_attr_set & SUPPORTED_UNITY_ATTR_SET; + + plog("sending ModeCfg ack"); + + 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_MODE_CFG_R3: @@ -788,19 +961,20 @@ modecfg_inI0(struct msg_digest *md) 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; + 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; + plog("parsing ModeCfg ack"); - st->st_msgid = 0; - return STF_OK; + stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); + if (stat != STF_OK) + { + return stat; + } + st->st_msgid = 0; + return STF_OK; } /* @@ -809,19 +983,21 @@ modecfg_inR3(struct msg_digest *md) stf_status xauth_send_request(struct state *st) { - stf_status stat; - internal_addr_t ia; - - init_internal_addr(&ia); - ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) - | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE); - - 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; + stf_status stat; + internal_addr_t ia; + + init_internal_addr(&ia); + ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) + | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE); + + 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: @@ -832,97 +1008,102 @@ xauth_send_request(struct state *st) 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; - bool xauth_type_present; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + stf_status stat, stat_build; + bool xauth_type_present; - plog("parsing XAUTH request"); + plog("parsing XAUTH request"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); - if (stat != STF_OK) - return stat; - - /* check XAUTH attributes */ - xauth_type_present = (ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY; - - if (xauth_type_present && 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.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY) - { - plog("user name attribute is missing in XAUTH request"); - stat = STF_FAIL; - } - else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == 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)) + stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); + if (stat != STF_OK) { - plog("xauth user credentials not found"); - stat = STF_FAIL; + return stat; } - } - 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.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) - | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE); - if (xauth_type_present) - ia.xauth_attr_set |= LELEM(XAUTH_TYPE - XAUTH_BASE); - } - else - { - ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); - ia.xauth_status = XAUTH_STATUS_FAIL; - } - plog("sending XAUTH reply"); + /* check XAUTH attributes */ + xauth_type_present = (ia.xauth_attr_set & LELEM(XAUTH_TYPE - XAUTH_BASE)) != LEMPTY; - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_REPLY - , &ia - , isama_id); - if (stat_build != STF_OK) - return stat_build; + if (xauth_type_present && 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.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY) + { + plog("user name attribute is missing in XAUTH request"); + stat = STF_FAIL; + } + else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY) + { + plog("user password attribute is missing in XAUTH request"); + stat = STF_FAIL; + } - if (stat == STF_OK) - { - st->st_xauth.started = TRUE; - st->st_msgid = 0; - 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; - } + /* 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.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) + | LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE); + if (xauth_type_present) + { + ia.xauth_attr_set |= LELEM(XAUTH_TYPE - XAUTH_BASE); + } + } + else + { + ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); + ia.xauth_status = XAUTH_STATUS_FAIL; + } + + 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; + st->st_msgid = 0; + return STF_OK; + } + else + { + /* send XAUTH reply msg and then delete ISAKMP SA */ + free(st->st_tpacket.ptr); + st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply)); + st->st_tpacket = chunk_clone(st->st_tpacket); + send_packet(st, "XAUTH reply msg"); + delete_state(st); + return STF_IGNORE; + } } /* STATE_XAUTH_R1: @@ -933,72 +1114,76 @@ xauth_inI0(struct msg_digest *md) 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; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + stf_status stat, stat_build; - plog("parsing XAUTH reply"); + 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.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != 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.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY) - { - plog("user name attribute is missing in XAUTH reply"); - st->st_xauth.status = FALSE; - } - else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY) - { - plog("user password attribute is missing in XAUTH reply"); - st->st_xauth.status = FALSE; - } - else - { - xauth_peer_t peer; - - peer.conn_name = st->st_connection->name; - addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address)); - idtoa(&md->st->st_connection->spd.that.id, peer.id, sizeof(peer.id)); - - 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 plugin function */ - st->st_xauth.status = xauth_module.verify_secret(&peer, &ia.xauth_secret); - plog("extended authentication %s", st->st_xauth.status? "was successful":"failed"); - } + 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.xauth_attr_set & LELEM(XAUTH_STATUS - XAUTH_BASE)) != 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.xauth_attr_set & LELEM(XAUTH_USER_NAME - XAUTH_BASE)) == LEMPTY) + { + plog("user name attribute is missing in XAUTH reply"); + st->st_xauth.status = FALSE; + } + else if ((ia.xauth_attr_set & LELEM(XAUTH_USER_PASSWORD - XAUTH_BASE)) == LEMPTY) + { + plog("user password attribute is missing in XAUTH reply"); + st->st_xauth.status = FALSE; + } + else + { + xauth_peer_t peer; + + peer.conn_name = st->st_connection->name; + addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address)); + idtoa(&md->st->st_connection->spd.that.id, peer.id, sizeof(peer.id)); + + 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 plugin function */ + st->st_xauth.status = xauth_module.verify_secret(&peer, &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.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); - ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL; + /* prepare XAUTH set which sends the authentication status */ + init_internal_addr(&ia); + ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); + ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL; - plog("sending XAUTH status:"); + plog("sending XAUTH status:"); - stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia); - if (stat_build != STF_OK) - return stat_build; - return STF_OK; + stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia); + if (stat_build != STF_OK) + { + return stat_build; + } + return STF_OK; } /* STATE_XAUTH_I1: @@ -1009,47 +1194,48 @@ xauth_inR1(struct msg_digest *md) 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; - } + 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 */ + free(st->st_tpacket.ptr); + st->st_tpacket = chunk_create(md->reply.start, pbs_offset(&md->reply)); + st->st_tpacket = chunk_clone(st->st_tpacket); + send_packet(st, "XAUTH ack msg"); + delete_state(st); + return STF_IGNORE; + } } /* STATE_XAUTH_R2: @@ -1060,25 +1246,26 @@ xauth_inI1(struct msg_digest *md) 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; + struct state *const st = md->st; + u_int16_t isama_id; + internal_addr_t ia; + stf_status stat; - plog("parsing XAUTH ack"); + plog("parsing XAUTH ack"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); - if (stat != STF_OK) - return stat; - - st->st_msgid = 0; - if (st->st_xauth.status) - { - return STF_OK; - } - else - { - delete_state(st); - return STF_IGNORE; - } + stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); + if (stat != STF_OK) + { + return stat; + } + st->st_msgid = 0; + if (st->st_xauth.status) + { + return STF_OK; + } + else + { + delete_state(st); + return STF_IGNORE; + } } |