implemented support of resolve plugin

This commit is contained in:
Andreas Steffen
2010-05-08 16:09:02 +02:00
parent c2651ff13d
commit fb7de3a8bf
4 changed files with 268 additions and 240 deletions
+24 -2
View File
@@ -63,6 +63,7 @@
#include "nat_traversal.h" #include "nat_traversal.h"
#include "virtual.h" #include "virtual.h"
#include "whack_attribute.h" #include "whack_attribute.h"
#include "modecfg.h"
static void flush_pending_by_connection(connection_t *c); /* forward */ 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) void delete_connection(connection_t *c, bool relations)
{ {
connection_t *old_cur_connection modecfg_attribute_t *ca;
= cur_connection == c? NULL : cur_connection; connection_t *old_cur_connection;
old_cur_connection = cur_connection == c? NULL : cur_connection;
#ifdef DEBUG #ifdef DEBUG
lset_t old_cur_debugging = cur_debugging; lset_t old_cur_debugging = cur_debugging;
#endif #endif
@@ -376,6 +379,25 @@ void delete_connection(connection_t *c, bool relations)
vip->destroy(vip); 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) if (c->kind != CK_GOING_AWAY)
{ {
whack_attr->del_pool(whack_attr, c->name); whack_attr->del_pool(whack_attr, c->name);
+2
View File
@@ -226,6 +226,8 @@ struct connection {
connection_t *hp_next; /* host pair list link */ connection_t *hp_next; /* host pair list link */
connection_t *ac_next; /* all connections list link */ connection_t *ac_next; /* all connections list link */
linked_list_t *requested_ca; /* collected certificate requests */ 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; bool got_certrequest;
}; };
+211 -235
View File
@@ -27,7 +27,7 @@
#include <library.h> #include <library.h>
#include <hydra.h> #include <hydra.h>
#include <attributes/attributes.h> #include <utils/linked_list.h>
#include <crypto/prfs/prf.h> #include <crypto/prfs/prf.h>
#include "constants.h" #include "constants.h"
@@ -43,8 +43,6 @@
#include "xauth.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) \ #define SUPPORTED_ATTR_SET ( LELEM(INTERNAL_IP4_ADDRESS) \
| LELEM(INTERNAL_IP4_NETMASK) \ | LELEM(INTERNAL_IP4_NETMASK) \
@@ -59,6 +57,32 @@
#define UNITY_BANNER_STR "Welcome to strongSwan - the Linux VPN Solution!\n" #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 * Addresses assigned (usually via ModeCfg) to the Initiator
*/ */
@@ -72,8 +96,6 @@ struct internal_addr
/* ModeCfg variables */ /* ModeCfg variables */
ip_address ipaddr; ip_address ipaddr;
ip_address dns[DNS_SERVER_MAX];
ip_address nbns[NBNS_SERVER_MAX];
char *unity_banner; char *unity_banner;
@@ -88,8 +110,6 @@ struct internal_addr
*/ */
static void init_internal_addr(internal_addr_t *ia) static void init_internal_addr(internal_addr_t *ia)
{ {
int i;
ia->attr_set = LEMPTY; ia->attr_set = LEMPTY;
ia->xauth_attr_set = LEMPTY; ia->xauth_attr_set = LEMPTY;
ia->xauth_secret.user_name = chunk_empty; ia->xauth_secret.user_name = chunk_empty;
@@ -100,30 +120,18 @@ static void init_internal_addr(internal_addr_t *ia)
ia->unity_banner = NULL; ia->unity_banner = NULL;
anyaddr(AF_INET, &ia->ipaddr); 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 * Get internal IP address for a connection
*/ */
static void get_internal_addr(connection_t *c, host_t *requested_vip, 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; enumerator_t *enumerator;
configuration_attribute_type_t type; configuration_attribute_type_t type;
chunk_t value; chunk_t value;
modecfg_attribute_t *ca;
host_t *vip = NULL; host_t *vip = NULL;
if (isanyaddr(&c->spd.that.host_srcip)) 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); c->spd.that.id, vip);
while (enumerator->enumerate(enumerator, &type, &value)) while (enumerator->enumerate(enumerator, &type, &value))
{ {
err_t ugh; DBG(DBG_CONTROLMORE,
host_t *server; DBG_log("building %N attribute",
sa_family_t family = AF_INET; configuration_attribute_type_names, type)
)
switch (type) ca = modecfg_attribute_create(type, value);
{ ca_list->insert_last(ca_list, ca);
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;
}
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
DESTROY_IF(vip); 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 * 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) if (ia->attr_set & LELEM(INTERNAL_IP4_ADDRESS)
&& !isanyaddr(&ia->ipaddr)) && !isanyaddr(&ia->ipaddr))
{ {
host_t *vip;
modecfg_attribute_t *ca;
enumerator_t *enumerator;
if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0 if (addrbytesptr(&c->spd.this.host_srcip, NULL) == 0
|| isanyaddr(&c->spd.this.host_srcip) || isanyaddr(&c->spd.this.host_srcip)
|| sameaddr(&c->spd.this.host_srcip, &ia->ipaddr)) || 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 */ /* setting srcip */
c->spd.this.host_srcip = ia->ipaddr; c->spd.this.host_srcip = ia->ipaddr;
vip = host_create_from_sockaddr((sockaddr_t*)&ia->ipaddr);
/* setting client subnet to srcip/32 */ /* setting client subnet to srcip/32 */
addrtosubnet(&ia->ipaddr, &c->spd.this.client); addrtosubnet(&ia->ipaddr, &c->spd.this.client);
setportof(0, &c->spd.this.client.addr); setportof(0, &c->spd.this.client.addr);
c->spd.this.has_client = TRUE; 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 TRUE;
} }
return FALSE; 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, static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody,
u_int16_t msg_type, u_int16_t msg_type,
internal_addr_t *ia, internal_addr_t *ia,
linked_list_t *ca_list,
u_int16_t ap_id) u_int16_t ap_id)
{ {
u_char *r_hash_start, *r_hashval; 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_mode_attr attrh;
struct isakmp_attribute attr; struct isakmp_attribute attr;
pb_stream strattr,attrval; pb_stream strattr,attrval;
int attr_type, dns_attr_type, nbns_attr_type; int attr_type;
int dns_idx, nbns_idx;
bool dont_advance;
bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY; bool is_xauth_attr_set = ia->xauth_attr_set != LEMPTY;
bool is_unity_attr_set = ia->unity_attr_set != LEMPTY; bool is_unity_attr_set = ia->unity_attr_set != LEMPTY;
lset_t attr_set = ia->attr_set; lset_t attr_set = ia->attr_set;
enumerator_t *enumerator;
modecfg_attribute_t *ca;
attrh.isama_np = ISAKMP_NEXT_NONE; attrh.isama_np = ISAKMP_NEXT_NONE;
attrh.isama_type = msg_type; 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; return STF_INTERNAL_ERROR;
} }
attr_type = 0; 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) 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) if (attr_set & 1)
{ {
const u_char *byte_ptr; 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_af_type = attr_type | ISAKMP_ATTR_AF_TV;
attr.isaat_lv = ia->xauth_status; 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 else
{ {
attr.isaat_af_type = attr_type | ISAKMP_ATTR_AF_TLV; 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"); out_raw(mask, sizeof(mask), &attrval, "IP4_submsk");
} }
break; 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: case XAUTH_TYPE:
break; break;
case XAUTH_USER_NAME: case XAUTH_USER_NAME:
@@ -510,11 +485,8 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody,
} }
close_output_pbs(&attrval); close_output_pbs(&attrval);
} }
if (!dont_advance) attr_type++;
{ attr_set >>= 1;
attr_type++;
attr_set >>= 1;
}
} }
close_message(&strattr); close_message(&strattr);
} }
@@ -529,7 +501,7 @@ static stf_status modecfg_build_msg(struct state *st, pb_stream *rbody,
* Send ModeCfg message * Send ModeCfg message
*/ */
static stf_status modecfg_send_msg(struct state *st, int isama_type, 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 msg;
pb_stream rbody; pb_stream rbody;
@@ -561,12 +533,8 @@ static stf_status modecfg_send_msg(struct state *st, int isama_type,
} }
} }
/* ATTR out */ /* ATTR out with isama_id of 0 */
modecfg_build_msg(st, &rbody modecfg_build_msg(st, &rbody, isama_type, ia, ca_list, 0);
, isama_type
, ia
, 0 /* XXX isama_id */
);
free(st->st_tpacket.ptr); free(st->st_tpacket.ptr);
st->st_tpacket = chunk_create(msg.start, pbs_offset(&msg)); 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 * 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; struct isakmp_attribute attr;
pb_stream strattr; pb_stream strattr;
err_t ugh; err_t ugh;
char buf[BUF_LEN];
int dns_idx = 0;
int nbns_idx = 0;
while (pbs_left(attrs) >= sizeof(struct isakmp_attribute)) while (pbs_left(attrs) >= sizeof(struct isakmp_attribute))
{ {
u_int16_t attr_type; u_int16_t attr_type;
u_int16_t attr_len; u_int16_t attr_len;
chunk_t attr_chunk;
modecfg_attribute_t *ca;
if (!in_struct(&attr, &isakmp_modecfg_attribute_desc, attrs, &strattr)) 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_type = attr.isaat_af_type & ISAKMP_ATTR_RTYPE_MASK;
attr_len = attr.isaat_lv; attr_len = attr.isaat_lv;
DBG(DBG_CONTROLMORE,
DBG_log("processing %N attribute",
configuration_attribute_type_names, attr_type)
)
switch (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); ia->attr_set |= LELEM(attr_type);
break; break;
case INTERNAL_IP4_DNS: 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: 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]); attr_chunk = chunk_create(strattr.cur, attr_len);
if (ugh != NULL) ca = modecfg_attribute_create(attr_type, attr_chunk);
{ ca_list->insert_last(ca_list, ca);
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++;
}
} }
ia->attr_set |= LELEM(attr_type);
break; break;
case INTERNAL_IP6_DNS: 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: 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]); attr_chunk = chunk_create(strattr.cur, attr_len);
if (ugh != NULL) ca = modecfg_attribute_create(attr_type, attr_chunk);
{ ca_list->insert_last(ca_list, ca);
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++;
}
} }
ia->attr_set |= LELEM(attr_type);
break; break;
case INTERNAL_IP4_NETMASK: case INTERNAL_IP4_NETMASK:
case INTERNAL_IP4_SUBNET: 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 * Parse a ModeCfg message
*/ */
static stf_status modecfg_parse_msg(struct msg_digest *md, int isama_type, 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 state *const st = md->st;
struct payload_digest *p; 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; *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) if (stat == STF_OK)
{ {
/* return with a valid set of attributes */ /* 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, isama_type)
, enum_name(&attr_msg_type_names, p->payload.attribute.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) if (stat != STF_OK)
{ {
@@ -828,16 +751,45 @@ stf_status modecfg_send_request(struct state *st)
connection_t *c = st->st_connection; connection_t *c = st->st_connection;
stf_status stat; stf_status stat;
internal_addr_t ia; 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); init_internal_addr(&ia);
ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS) ia.attr_set = LELEM(INTERNAL_IP4_ADDRESS)
| LELEM(INTERNAL_IP4_NETMASK); | LELEM(INTERNAL_IP4_NETMASK);
ia.ipaddr = c->spd.this.host_srcip; 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"); plog("sending ModeCfg request");
st->st_state = STATE_MODE_CFG_I1; 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) if (stat == STF_OK)
{ {
st->st_modecfg.started = TRUE; st->st_modecfg.started = TRUE;
@@ -858,8 +810,9 @@ stf_status modecfg_inR0(struct msg_digest *md)
bool want_unity_banner; bool want_unity_banner;
stf_status stat, stat_build; stf_status stat, stat_build;
host_t *requested_vip; 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) if (stat != STF_OK)
{ {
return stat; return stat;
@@ -876,8 +829,12 @@ stf_status modecfg_inR0(struct msg_digest *md)
plog("peer requested virtual IP %H", requested_vip); plog("peer requested virtual IP %H", requested_vip);
want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY; want_unity_banner = (ia.unity_attr_set & LELEM(UNITY_BANNER - UNITY_BASE)) != LEMPTY;
ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
/* build the CFG_REPLY */
ca_list = linked_list_create();
init_internal_addr(&ia); init_internal_addr(&ia);
get_internal_addr(st->st_connection, requested_vip, &ia); get_internal_addr(st->st_connection, requested_vip, &ia, ca_list);
requested_vip->destroy(requested_vip); requested_vip->destroy(requested_vip);
if (want_unity_banner) if (want_unity_banner)
@@ -888,10 +845,10 @@ stf_status modecfg_inR0(struct msg_digest *md)
plog("sending ModeCfg reply"); plog("sending ModeCfg reply");
stat_build = modecfg_build_msg(st, &md->rbody stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY,
, ISAKMP_CFG_REPLY &ia, ca_list, isama_id);
, &ia ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
, isama_id);
if (stat_build != STF_OK) if (stat_build != STF_OK)
{ {
return stat_build; return stat_build;
@@ -911,16 +868,18 @@ stf_status modecfg_inI1(struct msg_digest *md)
u_int16_t isama_id; u_int16_t isama_id;
internal_addr_t ia; internal_addr_t ia;
stf_status stat; stf_status stat;
linked_list_t *ca_list = linked_list_create();
plog("parsing ModeCfg reply"); 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) if (stat != STF_OK)
{ {
return stat; 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; st->st_msgid = 0;
ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
return STF_OK; return STF_OK;
} }
@@ -933,10 +892,11 @@ stf_status modecfg_send_set(struct state *st)
stf_status stat; stf_status stat;
internal_addr_t ia; internal_addr_t ia;
host_t *vip; host_t *vip;
linked_list_t *ca_list = linked_list_create();
init_internal_addr(&ia); init_internal_addr(&ia);
vip = host_create_any(AF_INET); 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); vip->destroy(vip);
#ifdef CISCO_QUIRKS #ifdef CISCO_QUIRKS
@@ -946,7 +906,8 @@ stf_status modecfg_send_set(struct state *st)
plog("sending ModeCfg set"); plog("sending ModeCfg set");
st->st_state = STATE_MODE_CFG_R3; 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) if (stat == STF_OK)
{ {
st->st_modecfg.started = TRUE; st->st_modecfg.started = TRUE;
@@ -966,15 +927,18 @@ stf_status modecfg_inI0(struct msg_digest *md)
internal_addr_t ia; internal_addr_t ia;
lset_t attr_set, unity_attr_set; lset_t attr_set, unity_attr_set;
stf_status stat, stat_build; stf_status stat, stat_build;
linked_list_t *ca_list = linked_list_create();
plog("parsing ModeCfg set"); 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) if (stat != STF_OK)
{ {
return stat; 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 */ /* prepare ModeCfg ack which sends zero length attributes */
attr_set = ia.attr_set; attr_set = ia.attr_set;
@@ -985,10 +949,9 @@ stf_status modecfg_inI0(struct msg_digest *md)
plog("sending ModeCfg ack"); plog("sending ModeCfg ack");
stat_build = modecfg_build_msg(st, &md->rbody stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK,
, ISAKMP_CFG_ACK &ia, ca_list, isama_id);
, &ia ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
, isama_id);
if (stat_build != STF_OK) if (stat_build != STF_OK)
{ {
return stat_build; return stat_build;
@@ -1008,10 +971,12 @@ stf_status modecfg_inR3(struct msg_digest *md)
u_int16_t isama_id; u_int16_t isama_id;
internal_addr_t ia; internal_addr_t ia;
stf_status stat; stf_status stat;
linked_list_t *ca_list = linked_list_create();
plog("parsing ModeCfg ack"); 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) if (stat != STF_OK)
{ {
return stat; return stat;
@@ -1027,6 +992,7 @@ stf_status xauth_send_request(struct state *st)
{ {
stf_status stat; stf_status stat;
internal_addr_t ia; internal_addr_t ia;
linked_list_t *ca_list = linked_list_create();
init_internal_addr(&ia); init_internal_addr(&ia);
ia.xauth_attr_set = LELEM(XAUTH_USER_NAME - XAUTH_BASE) 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"); plog("sending XAUTH request");
st->st_state = STATE_XAUTH_R1; 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) if (stat == STF_OK)
{ {
st->st_xauth.started = TRUE; st->st_xauth.started = TRUE;
@@ -1054,10 +1021,12 @@ stf_status xauth_inI0(struct msg_digest *md)
internal_addr_t ia; internal_addr_t ia;
stf_status stat, stat_build; stf_status stat, stat_build;
bool xauth_type_present; bool xauth_type_present;
linked_list_t *ca_list = linked_list_create();
plog("parsing XAUTH request"); 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) if (stat != STF_OK)
{ {
return stat; return stat;
@@ -1121,10 +1090,9 @@ stf_status xauth_inI0(struct msg_digest *md)
plog("sending XAUTH reply"); plog("sending XAUTH reply");
stat_build = modecfg_build_msg(st, &md->rbody stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_REPLY,
, ISAKMP_CFG_REPLY &ia, ca_list, isama_id);
, &ia ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
, isama_id);
if (stat_build != STF_OK) if (stat_build != STF_OK)
{ {
return stat_build; return stat_build;
@@ -1158,10 +1126,12 @@ stf_status xauth_inR1(struct msg_digest *md)
u_int16_t isama_id; u_int16_t isama_id;
internal_addr_t ia; internal_addr_t ia;
stf_status stat, stat_build; stf_status stat, stat_build;
linked_list_t *ca_list = linked_list_create();
plog("parsing XAUTH reply"); 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) if (stat != STF_OK)
{ {
return stat; return stat;
@@ -1216,10 +1186,12 @@ stf_status xauth_inR1(struct msg_digest *md)
init_internal_addr(&ia); init_internal_addr(&ia);
ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE); ia.xauth_attr_set = LELEM(XAUTH_STATUS - XAUTH_BASE);
ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL; ia.xauth_status = (st->st_xauth.status)? XAUTH_STATUS_OK : XAUTH_STATUS_FAIL;
ca_list = linked_list_create();
plog("sending XAUTH status:"); 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) if (stat_build != STF_OK)
{ {
return stat_build; return stat_build;
@@ -1238,9 +1210,11 @@ stf_status xauth_inI1(struct msg_digest *md)
u_int16_t isama_id; u_int16_t isama_id;
internal_addr_t ia; internal_addr_t ia;
stf_status stat, stat_build; stf_status stat, stat_build;
linked_list_t *ca_list = linked_list_create();
plog("parsing XAUTH status"); 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) if (stat != STF_OK)
{ {
/* notification payload - not exactly the right choice, but okay */ /* 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"); plog("sending XAUTH ack");
init_internal_addr(&ia); init_internal_addr(&ia);
stat_build = modecfg_build_msg(st, &md->rbody stat_build = modecfg_build_msg(st, &md->rbody, ISAKMP_CFG_ACK,
, ISAKMP_CFG_ACK &ia, ca_list, isama_id);
, &ia ca_list->destroy_function(ca_list, (void *)modecfg_attribute_destroy);
, isama_id);
if (stat_build != STF_OK) if (stat_build != STF_OK)
{ {
return stat_build; return stat_build;
@@ -1289,10 +1262,12 @@ stf_status xauth_inR2(struct msg_digest *md)
u_int16_t isama_id; u_int16_t isama_id;
internal_addr_t ia; internal_addr_t ia;
stf_status stat; stf_status stat;
linked_list_t *ca_list = linked_list_create();
plog("parsing XAUTH ack"); 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) if (stat != STF_OK)
{ {
return stat; return stat;
@@ -1307,4 +1282,5 @@ stf_status xauth_inR2(struct msg_digest *md)
delete_state(st); delete_state(st);
return STF_IGNORE; return STF_IGNORE;
} }
} }
+30 -2
View File
@@ -16,8 +16,36 @@
#ifndef _MODECFG_H #ifndef _MODECFG_H
#define _MODECFG_H #define _MODECFG_H
struct state; #include <chunk.h>
struct msg_digest; #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 */ /* ModeConfig pull mode start function */
extern stf_status modecfg_send_request(struct state *st); extern stf_status modecfg_send_request(struct state *st);