diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2010-05-08 16:09:02 +0200 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2010-05-08 16:09:02 +0200 |
commit | fb7de3a8bf1a7882d512bcee1c3bab6df47873c2 (patch) | |
tree | 07fefe6ecab45db721260199f55c6ac89c5aad84 | |
parent | c2651ff13d9cba7004f2965bdf850284efbf736f (diff) | |
download | strongswan-fb7de3a8bf1a7882d512bcee1c3bab6df47873c2.tar.bz2 strongswan-fb7de3a8bf1a7882d512bcee1c3bab6df47873c2.tar.xz |
implemented support of resolve plugin
-rw-r--r-- | src/pluto/connections.c | 26 | ||||
-rw-r--r-- | src/pluto/connections.h | 2 | ||||
-rw-r--r-- | src/pluto/modecfg.c | 448 | ||||
-rw-r--r-- | src/pluto/modecfg.h | 32 |
4 files changed, 268 insertions, 240 deletions
diff --git a/src/pluto/connections.c b/src/pluto/connections.c index dd193042a..d6c38514d 100644 --- a/src/pluto/connections.c +++ b/src/pluto/connections.c @@ -63,6 +63,7 @@ #include "nat_traversal.h" #include "virtual.h" #include "whack_attribute.h" +#include "modecfg.h" static void flush_pending_by_connection(connection_t *c); /* forward */ @@ -294,8 +295,10 @@ void release_connection(connection_t *c, bool relations) void delete_connection(connection_t *c, bool relations) { - connection_t *old_cur_connection - = cur_connection == c? NULL : cur_connection; + modecfg_attribute_t *ca; + connection_t *old_cur_connection; + + old_cur_connection = cur_connection == c? NULL : cur_connection; #ifdef DEBUG lset_t old_cur_debugging = cur_debugging; #endif @@ -376,6 +379,25 @@ void delete_connection(connection_t *c, bool relations) vip->destroy(vip); } + /* release requested attributes if any */ + if (c->requested) + { + c->requested->destroy_function(c->requested, + (void*)modecfg_attribute_destroy); + } + + /* release other attributes if any */ + if (c->attributes) + { + while (c->attributes->remove_last(c->attributes, (void **)&ca) == SUCCESS) + { + hydra->attributes->release(hydra->attributes, ca->handler, + c->spd.that.id, ca->type, ca->value); + modecfg_attribute_destroy(ca); + } + c->attributes->destroy(c->attributes); + } + if (c->kind != CK_GOING_AWAY) { whack_attr->del_pool(whack_attr, c->name); diff --git a/src/pluto/connections.h b/src/pluto/connections.h index 66aea1541..ae6356db1 100644 --- a/src/pluto/connections.h +++ b/src/pluto/connections.h @@ -226,6 +226,8 @@ struct connection { connection_t *hp_next; /* host pair list link */ connection_t *ac_next; /* all connections list link */ linked_list_t *requested_ca; /* collected certificate requests */ + linked_list_t *requested; /* requested attributes with handlers */ + linked_list_t *attributes; /* configuration attributes with handlers */ bool got_certrequest; }; diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c index 0c4f2bd6b..1f2711f33 100644 --- a/src/pluto/modecfg.c +++ b/src/pluto/modecfg.c @@ -27,7 +27,7 @@ #include <library.h> #include <hydra.h> -#include <attributes/attributes.h> +#include <utils/linked_list.h> #include <crypto/prfs/prf.h> #include "constants.h" @@ -43,8 +43,6 @@ #include "xauth.h" #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) \ @@ -59,6 +57,32 @@ #define UNITY_BANNER_STR "Welcome to strongSwan - the Linux VPN Solution!\n" + +/** + * Creates a modecfg_attribute_t object + */ +static modecfg_attribute_t *modecfg_attribute_create(configuration_attribute_type_t type, + chunk_t value) +{ + modecfg_attribute_t *this; + + this = malloc_thing(modecfg_attribute_t); + this->type = ((u_int16_t)type) & 0x7FFF; + this->value = chunk_clone(value); + this->handler = NULL; + + return this; +} + +/** + * Destroys a modecfg_attribute_t object + */ +void modecfg_attribute_destroy(modecfg_attribute_t *this) +{ + free(this->value.ptr); + free(this); +} + /* * Addresses assigned (usually via ModeCfg) to the Initiator */ @@ -72,8 +96,6 @@ struct internal_addr /* ModeCfg variables */ ip_address ipaddr; - ip_address dns[DNS_SERVER_MAX]; - ip_address nbns[NBNS_SERVER_MAX]; char *unity_banner; @@ -88,8 +110,6 @@ struct internal_addr */ static void init_internal_addr(internal_addr_t *ia) { - int i; - ia->attr_set = LEMPTY; ia->xauth_attr_set = LEMPTY; ia->xauth_secret.user_name = chunk_empty; @@ -100,30 +120,18 @@ static void init_internal_addr(internal_addr_t *ia) 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 NBNS server information */ - for (i = 0; i < NBNS_SERVER_MAX; i++) - { - anyaddr(AF_INET, &ia->nbns[i]); - } } /** * Get internal IP address for a connection */ static void get_internal_addr(connection_t *c, host_t *requested_vip, - internal_addr_t *ia) + internal_addr_t *ia, linked_list_t *ca_list) { - int dns_idx = 0, nbns_idx = 0; enumerator_t *enumerator; configuration_attribute_type_t type; chunk_t value; + modecfg_attribute_t *ca; host_t *vip = NULL; if (isanyaddr(&c->spd.that.host_srcip)) @@ -170,65 +178,12 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip, c->spd.that.id, vip); while (enumerator->enumerate(enumerator, &type, &value)) { - err_t ugh; - host_t *server; - sa_family_t family = AF_INET; - - switch (type) - { - case INTERNAL_IP6_DNS: - family = AF_INET6; - /* fallthrough */ - case INTERNAL_IP4_DNS: - if (dns_idx >= DNS_SERVER_MAX) - { - plog("exceeded the maximum number of %d DNS servers", - DNS_SERVER_MAX); - break; - } - ugh = initaddr(value.ptr, value.len, family, &ia->dns[dns_idx]); - if (ugh) - { - plog("error in DNS server address: %s", ugh); - break; - } - server = host_create_from_chunk(family, value, 0); - plog("assigning DNS server %H to peer", server); - server->destroy(server); - - /* differentiate between IP4 and IP6 in modecfg_build_msg() */ - ia->attr_set |= LELEM(INTERNAL_IP4_DNS); - dns_idx++; - break; - - case INTERNAL_IP6_NBNS: - family = AF_INET6; - /* fallthrough */ - case INTERNAL_IP4_NBNS: - if (nbns_idx >= NBNS_SERVER_MAX) - { - plog("exceeded the maximum number of %d NBNS servers", - NBNS_SERVER_MAX); - break; - } - ugh = initaddr(value.ptr, value.len, family, &ia->nbns[nbns_idx]); - if (ugh) - { - plog("error in NBNS server address: %s", ugh); - break; - } - server = host_create_from_chunk(family, value, 0); - plog("assigning NBNS server %H to peer", server); - server->destroy(server); - - /* differentiate between IP4 and IP6 in modecfg_build_msg() */ - ia->attr_set |= LELEM(INTERNAL_IP4_NBNS); - nbns_idx++; - break; - - default: - break; - } + DBG(DBG_CONTROLMORE, + DBG_log("building %N attribute", + configuration_attribute_type_names, type) + ) + ca = modecfg_attribute_create(type, value); + ca_list->insert_last(ca_list, ca); } enumerator->destroy(enumerator); DESTROY_IF(vip); @@ -238,11 +193,16 @@ static void get_internal_addr(connection_t *c, host_t *requested_vip, /** * Set srcip and client subnet to internal IP address */ -static bool set_internal_addr(connection_t *c, internal_addr_t *ia) +static bool set_internal_addr(connection_t *c, internal_addr_t *ia, + linked_list_t *ca_list) { if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS) && !isanyaddr(&ia->ipaddr)) { + host_t *vip; + modecfg_attribute_t *ca; + enumerator_t *enumerator; + if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0 || isanyaddr(&c->spd.this.host_srcip) || sameaddr(&c->spd.this.host_srcip, &ia->ipaddr)) @@ -265,11 +225,53 @@ static bool set_internal_addr(connection_t *c, internal_addr_t *ia) /* setting srcip */ c->spd.this.host_srcip = ia->ipaddr; + vip = host_create_from_sockaddr((sockaddr_t*)&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; + + /* setting other attributes (e.g. DNS and NBNS servers) */ + enumerator = ca_list->create_enumerator(ca_list); + while (enumerator->enumerate(enumerator, &ca)) + { + modecfg_attribute_t *ca_handler; + attribute_handler_t *handler = NULL; + enumerator_t *e; + + /* find the first handler which requested this attribute */ + e = c->requested->create_enumerator(c->requested); + while (e->enumerate(e, &ca_handler)) + { + if (ca_handler->type == ca->type) + { + handler = ca_handler->handler; + break; + } + } + e->destroy(e); + + /* and pass it to the handle function */ + handler = hydra->attributes->handle(hydra->attributes, + c->spd.that.id, handler, ca->type, ca->value); + if (handler) + { + ca_handler = modecfg_attribute_create(ca->type, ca->value); + ca_handler->handler = handler; + + if (c->attributes == NULL) + { + c->attributes = linked_list_create(); + } + c->attributes->insert_last(c->attributes, ca_handler); + } + } + enumerator->destroy(enumerator); + vip->destroy(vip); + c->requested->destroy_function(c->requested, + (void*)modecfg_attribute_destroy); + c->requested = NULL; return TRUE; } return FALSE; @@ -309,6 +311,7 @@ static size_t modecfg_hash(u_char *dest, u_char *start, u_char *roof, static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody, u_int16_t msg_type, internal_addr_t *ia, + linked_list_t *ca_list, u_int16_t ap_id) { u_char *r_hash_start, *r_hashval; @@ -320,12 +323,12 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody, 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; + int attr_type; 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; + enumerator_t *enumerator; + modecfg_attribute_t *ca; attrh.isama_np = ISAKMP_NEXT_NONE; attrh.isama_type = msg_type; @@ -336,8 +339,20 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody, return STF_INTERNAL_ERROR; } attr_type = 0; - dns_idx = 0; - nbns_idx = 0; + + enumerator = ca_list->create_enumerator(ca_list); + while (enumerator->enumerate(enumerator, &ca)) + { + char ca_type_name[BUF_LEN]; + + snprintf(ca_type_name, BUF_LEN, "%N", + configuration_attribute_type_names, ca->type); + attr.isaat_af_type = ca->type | ISAKMP_ATTR_AF_TLV; + out_struct(&attr, &isakmp_modecfg_attribute_desc, &strattr, &attrval); + out_raw(ca->value.ptr, ca->value.len, &attrval, ca_type_name); + close_output_pbs(&attrval); + } + enumerator->destroy(enumerator); while (attr_set != LEMPTY || is_xauth_attr_set || is_unity_attr_set) { @@ -357,8 +372,6 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody, } } - dont_advance = FALSE; - if (attr_set & 1) { const u_char *byte_ptr; @@ -375,20 +388,6 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody, 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; @@ -451,30 +450,6 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody, 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: @@ -510,11 +485,8 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody, } close_output_pbs(&attrval); } - if (!dont_advance) - { - attr_type++; - attr_set >>= 1; - } + attr_type++; + attr_set >>= 1; } close_message(&strattr); } @@ -529,7 +501,7 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody, * Send ModeCfg message */ static stf_status modecfg_send_msg(struct state *st, int isama_type, - internal_addr_t *ia) + internal_addr_t *ia, linked_list_t *ca_list) { pb_stream msg; pb_stream rbody; @@ -561,12 +533,8 @@ static stf_status modecfg_send_msg(struct state *st, int isama_type, } } - /* ATTR out */ - modecfg_build_msg(st, &rbody - , isama_type - , ia - , 0 /* XXX isama_id */ - ); + /* ATTR out with isama_id of 0 */ + modecfg_build_msg(st, &rbody, isama_type, ia, ca_list, 0); free(st->st_tpacket.ptr); st->st_tpacket = chunk_create(msg.start, pbs_offset(&msg)); @@ -586,19 +554,19 @@ static stf_status modecfg_send_msg(struct state *st, int isama_type, /** * Parse a ModeCfg attribute payload */ -static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia) +static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia, + linked_list_t *ca_list) { struct isakmp_attribute attr; pb_stream strattr; err_t ugh; - char buf[BUF_LEN]; - int dns_idx = 0; - int nbns_idx = 0; while (pbs_left(attrs) >= sizeof(struct isakmp_attribute)) { u_int16_t attr_type; u_int16_t attr_len; + chunk_t attr_chunk; + modecfg_attribute_t *ca; if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr)) { @@ -606,6 +574,10 @@ static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia } attr_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK; attr_len = attr.isaat_lv; + DBG(DBG_CONTROLMORE, + DBG_log("processing %N attribute", + configuration_attribute_type_names, attr_type) + ) switch (attr_type) { @@ -621,72 +593,22 @@ static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia 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) + if (attr_len == 4) { - ugh = initaddr((char *)(strattr.cur), 4, AF_INET, &ia->nbns[nbns_idx]); - if (ugh != NULL) - { - plog("received invalid IPv4 NBNS server address: %s", ugh); - } - else - { - addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN); - plog("received IPv4 NBNS server address %s", buf); - nbns_idx++; - } + attr_chunk = chunk_create(strattr.cur, attr_len); + ca = modecfg_attribute_create(attr_type, attr_chunk); + ca_list->insert_last(ca_list, ca); } - 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) + if (attr_len == 16) { - ugh = initaddr((char *)(strattr.cur), 16, AF_INET6, &ia->nbns[nbns_idx]); - if (ugh != NULL) - { - plog("received invalid IPv6 NBNS server address: %s", ugh); - } - else - { - addrtot(&ia->nbns[nbns_idx], 0, buf, BUF_LEN); - plog("received IPv6 NBNS server address %s", buf); - nbns_idx++; - } + attr_chunk = chunk_create(strattr.cur, attr_len); + ca = modecfg_attribute_create(attr_type, attr_chunk); + ca_list->insert_last(ca_list, ca); } - ia->attr_set |= LELEM(attr_type); break; case INTERNAL_IP4_NETMASK: case INTERNAL_IP4_SUBNET: @@ -772,7 +694,8 @@ static stf_status modecfg_parse_attributes(pb_stream *attrs, internal_addr_t *ia * Parse a ModeCfg message */ static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type, - u_int16_t *isama_id, internal_addr_t *ia) + u_int16_t *isama_id, internal_addr_t *ia, + linked_list_t *ca_list) { struct state *const st = md->st; struct payload_digest *p; @@ -796,7 +719,7 @@ static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type, { *isama_id = p->payload.attribute.isama_identifier; - stat = modecfg_parse_attributes(&p->pbs, &ia_candidate); + stat = modecfg_parse_attributes(&p->pbs, &ia_candidate, ca_list); if (stat == STF_OK) { /* return with a valid set of attributes */ @@ -810,7 +733,7 @@ static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type, , 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, ca_list); } if (stat != STF_OK) { @@ -828,16 +751,45 @@ stf_status modecfg_send_request(struct state *st) connection_t *c = st->st_connection; stf_status stat; internal_addr_t ia; + attribute_handler_t *handler; + configuration_attribute_type_t type; + chunk_t data; + host_t *vip; + enumerator_t *enumerator; init_internal_addr(&ia); ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS) | LELEM(INTERNAL_IP4_NETMASK); ia.ipaddr = c->spd.this.host_srcip; + vip = host_create_from_sockaddr((sockaddr_t*)&ia.ipaddr); + + /* add configuration attributes requested by handlers */ + enumerator = hydra->attributes->create_initiator_enumerator( + hydra->attributes,c->spd.that.id, vip); + while (enumerator->enumerate(enumerator, &handler, &type, &data)) + { + modecfg_attribute_t *ca; + + /* create configuration attribute request and link to handler */ + DBG(DBG_CONTROLMORE, + DBG_log("building %N attribute", configuration_attribute_type_names, type) + ) + ca = modecfg_attribute_create(type, data); + ca->handler = handler; + + if (c->requested == NULL) + { + c->requested = linked_list_create(); + } + c->requested->insert_last(c->requested, ca); + } + enumerator->destroy(enumerator); + vip->destroy(vip); plog("sending ModeCfg request"); st->st_state = STATE_MODE_CFG_I1; - stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia); + stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia, c->requested); if (stat == STF_OK) { st->st_modecfg.started = TRUE; @@ -858,8 +810,9 @@ stf_status modecfg_inR0(struct msg_digest *md) bool want_unity_banner; stf_status stat, stat_build; host_t *requested_vip; + linked_list_t *ca_list = linked_list_create(); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia, ca_list); if (stat != STF_OK) { return stat; @@ -876,8 +829,12 @@ stf_status modecfg_inR0(struct msg_digest *md) plog("peer requested virtual IP %H", requested_vip); want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY; - init_internal_addr(&ia); - get_internal_addr(st->st_connection, requested_vip, &ia); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); + + /* build the CFG_REPLY */ + ca_list = linked_list_create(); + init_internal_addr(&ia); + get_internal_addr(st->st_connection, requested_vip, &ia, ca_list); requested_vip->destroy(requested_vip); if (want_unity_banner) @@ -888,10 +845,10 @@ stf_status modecfg_inR0(struct msg_digest *md) plog("sending ModeCfg reply"); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_REPLY - , &ia - , isama_id); + stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY, + &ia, ca_list, isama_id); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); + if (stat_build != STF_OK) { return stat_build; @@ -911,16 +868,18 @@ stf_status modecfg_inI1(struct msg_digest *md) u_int16_t isama_id; internal_addr_t ia; stf_status stat; + linked_list_t *ca_list = linked_list_create(); plog("parsing ModeCfg reply"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia, ca_list); if (stat != STF_OK) { return stat; } - st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); + st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia, ca_list); st->st_msgid = 0; + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); return STF_OK; } @@ -933,10 +892,11 @@ stf_status modecfg_send_set(struct state *st) stf_status stat; internal_addr_t ia; host_t *vip; + linked_list_t *ca_list = linked_list_create(); init_internal_addr(&ia); vip = host_create_any(AF_INET); - get_internal_addr(st->st_connection, vip, &ia); + get_internal_addr(st->st_connection, vip, &ia, ca_list); vip->destroy(vip); #ifdef CISCO_QUIRKS @@ -946,7 +906,8 @@ stf_status modecfg_send_set(struct state *st) plog("sending ModeCfg set"); st->st_state = STATE_MODE_CFG_R3; - stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia); + stat = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat == STF_OK) { st->st_modecfg.started = TRUE; @@ -966,15 +927,18 @@ stf_status modecfg_inI0(struct msg_digest *md) internal_addr_t ia; lset_t attr_set, unity_attr_set; stf_status stat, stat_build; + linked_list_t *ca_list = linked_list_create(); plog("parsing ModeCfg set"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); + if (stat != STF_OK) { return stat; } - st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia); + st->st_modecfg.vars_set = set_internal_addr(st->st_connection, &ia, ca_list); /* prepare ModeCfg ack which sends zero length attributes */ attr_set = ia.attr_set; @@ -985,10 +949,9 @@ stf_status modecfg_inI0(struct msg_digest *md) plog("sending ModeCfg ack"); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_ACK - , &ia - , isama_id); + stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK, + &ia, ca_list, isama_id); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat_build != STF_OK) { return stat_build; @@ -1008,10 +971,12 @@ stf_status modecfg_inR3(struct msg_digest *md) u_int16_t isama_id; internal_addr_t ia; stf_status stat; + linked_list_t *ca_list = linked_list_create(); plog("parsing ModeCfg ack"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat != STF_OK) { return stat; @@ -1027,6 +992,7 @@ stf_status xauth_send_request(struct state *st) { stf_status stat; internal_addr_t ia; + linked_list_t *ca_list = linked_list_create(); init_internal_addr(&ia); ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) @@ -1034,7 +1000,8 @@ stf_status xauth_send_request(struct state *st) plog("sending XAUTH request"); st->st_state = STATE_XAUTH_R1; - stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia); + stat = modecfg_send_msg(st, ISAKMP_CFG_REQUEST, &ia, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat == STF_OK) { st->st_xauth.started = TRUE; @@ -1054,10 +1021,12 @@ stf_status xauth_inI0(struct msg_digest *md) internal_addr_t ia; stf_status stat, stat_build; bool xauth_type_present; + linked_list_t *ca_list = linked_list_create(); plog("parsing XAUTH request"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_REQUEST, &isama_id, &ia, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat != STF_OK) { return stat; @@ -1121,10 +1090,9 @@ stf_status xauth_inI0(struct msg_digest *md) plog("sending XAUTH reply"); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_REPLY - , &ia - , isama_id); + stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY, + &ia, ca_list, isama_id); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat_build != STF_OK) { return stat_build; @@ -1158,10 +1126,12 @@ stf_status xauth_inR1(struct msg_digest *md) u_int16_t isama_id; internal_addr_t ia; stf_status stat, stat_build; + linked_list_t *ca_list = linked_list_create(); plog("parsing XAUTH reply"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_REPLY, &isama_id, &ia, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat != STF_OK) { return stat; @@ -1216,10 +1186,12 @@ stf_status xauth_inR1(struct msg_digest *md) 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; + ca_list = linked_list_create(); plog("sending XAUTH status:"); - stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia); + stat_build = modecfg_send_msg(st, ISAKMP_CFG_SET, &ia, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat_build != STF_OK) { return stat_build; @@ -1238,9 +1210,11 @@ stf_status xauth_inI1(struct msg_digest *md) u_int16_t isama_id; internal_addr_t ia; stf_status stat, stat_build; + linked_list_t *ca_list = linked_list_create(); plog("parsing XAUTH status"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_SET, &isama_id, &ia, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat != STF_OK) { /* notification payload - not exactly the right choice, but okay */ @@ -1253,10 +1227,9 @@ stf_status xauth_inI1(struct msg_digest *md) plog("sending XAUTH ack"); init_internal_addr(&ia); - stat_build = modecfg_build_msg(st, &md->rbody - , ISAKMP_CFG_ACK - , &ia - , isama_id); + stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK, + &ia, ca_list, isama_id); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat_build != STF_OK) { return stat_build; @@ -1289,10 +1262,12 @@ stf_status xauth_inR2(struct msg_digest *md) u_int16_t isama_id; internal_addr_t ia; stf_status stat; + linked_list_t *ca_list = linked_list_create(); plog("parsing XAUTH ack"); - stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia); + stat = modecfg_parse_msg(md, ISAKMP_CFG_ACK, &isama_id, &ia, ca_list); + ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy); if (stat != STF_OK) { return stat; @@ -1307,4 +1282,5 @@ stf_status xauth_inR2(struct msg_digest *md) delete_state(st); return STF_IGNORE; } + } diff --git a/src/pluto/modecfg.h b/src/pluto/modecfg.h index bc1443012..8ed5de9a5 100644 --- a/src/pluto/modecfg.h +++ b/src/pluto/modecfg.h @@ -16,8 +16,36 @@ #ifndef _MODECFG_H #define _MODECFG_H -struct state; -struct msg_digest; +#include <chunk.h> +#include <attributes/attribute_handler.h> + +#include "state.h" +#include "demux.h" + +typedef struct modecfg_attribute_t modecfg_attribute_t; + +/** + * Defines a modecfg_attribute_t object. + */ +struct modecfg_attribute_t { + /** + * Type of the attribute. + */ + u_int16_t type; + + /** + * Attribute value as chunk. + */ + chunk_t value; + + /** + * Attribute handler. + */ + attribute_handler_t *handler; +}; + +/* Destroys a modecfg_attribute_t object */ +extern void modecfg_attribute_destroy(modecfg_attribute_t *this); /* ModeConfig pull mode start function */ extern stf_status modecfg_send_request(struct state *st); |