Forward Cisco Banner received from RADIUS to Unity capable clients
This commit is contained in:
@@ -336,12 +336,14 @@ static void process_cfg_attributes(private_eap_radius_t *this,
|
||||
{
|
||||
eap_radius_provider_t *provider;
|
||||
enumerator_t *enumerator;
|
||||
ike_sa_t *ike_sa;
|
||||
host_t *host;
|
||||
chunk_t data;
|
||||
int type;
|
||||
int type, vendor;
|
||||
|
||||
ike_sa = charon->bus->get_sa(charon->bus);
|
||||
provider = eap_radius_provider_get();
|
||||
if (provider)
|
||||
if (provider && ike_sa)
|
||||
{
|
||||
enumerator = msg->create_enumerator(msg);
|
||||
while (enumerator->enumerate(enumerator, &type, &data))
|
||||
@@ -356,6 +358,28 @@ static void process_cfg_attributes(private_eap_radius_t *this,
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
enumerator = msg->create_vendor_enumerator(msg);
|
||||
while (enumerator->enumerate(enumerator, &vendor, &type, &data))
|
||||
{
|
||||
if (vendor == PEN_ALTIGA /* aka Cisco VPN3000 */)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 15: /* CVPN3000-IPSec-Banner1 */
|
||||
case 36: /* CVPN3000-IPSec-Banner2 */
|
||||
if (ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
|
||||
{
|
||||
provider->add_attribute(provider, this->peer,
|
||||
UNITY_BANNER, data);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,13 +70,34 @@ struct private_eap_radius_provider_t {
|
||||
static eap_radius_provider_t *singleton = NULL;
|
||||
|
||||
/**
|
||||
* Hashtable entry with leases
|
||||
* Configuration attribute in an entry
|
||||
*/
|
||||
typedef struct {
|
||||
/** type of attribute */
|
||||
configuration_attribute_type_t type;
|
||||
/** attribute data */
|
||||
chunk_t data;
|
||||
} attr_t;
|
||||
|
||||
/**
|
||||
* Destroy an attr_t
|
||||
*/
|
||||
static void destroy_attr(attr_t *this)
|
||||
{
|
||||
free(this->data.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashtable entry with leases and attributes
|
||||
*/
|
||||
typedef struct {
|
||||
/** identity we assigned the IP lease */
|
||||
identification_t *id;
|
||||
/** list of IP leases received from AAA, as host_t */
|
||||
linked_list_t *addrs;
|
||||
/** list of configuration attributes, as attr_t */
|
||||
linked_list_t *attrs;
|
||||
} entry_t;
|
||||
|
||||
/**
|
||||
@@ -86,6 +107,7 @@ static void destroy_entry(entry_t *this)
|
||||
{
|
||||
this->id->destroy(this->id);
|
||||
this->addrs->destroy_offset(this->addrs, offsetof(host_t, destroy));
|
||||
this->attrs->destroy_function(this->attrs, (void*)destroy_attr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
@@ -102,6 +124,7 @@ static entry_t* get_or_create_entry(hashtable_t *hashtable, identification_t *id
|
||||
INIT(entry,
|
||||
.id = id->clone(id),
|
||||
.addrs = linked_list_create(),
|
||||
.attrs = linked_list_create(),
|
||||
);
|
||||
hashtable->put(hashtable, entry->id, entry);
|
||||
}
|
||||
@@ -113,7 +136,8 @@ static entry_t* get_or_create_entry(hashtable_t *hashtable, identification_t *id
|
||||
*/
|
||||
static void put_or_destroy_entry(hashtable_t *hashtable, entry_t *entry)
|
||||
{
|
||||
if (entry->addrs->get_count(entry->addrs) > 0)
|
||||
if (entry->addrs->get_count(entry->addrs) > 0 ||
|
||||
entry->attrs->get_count(entry->attrs) > 0)
|
||||
{
|
||||
hashtable->put(hashtable, entry->id, entry);
|
||||
}
|
||||
@@ -169,6 +193,36 @@ static host_t* remove_addr(private_eap_radius_provider_t *this,
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an attribute entry to a locked claimed/unclaimed hashtable
|
||||
*/
|
||||
static void add_attr(private_eap_radius_provider_t *this,
|
||||
hashtable_t *hashtable, identification_t *id, attr_t *attr)
|
||||
{
|
||||
entry_t *entry;
|
||||
|
||||
entry = get_or_create_entry(hashtable, id);
|
||||
entry->attrs->insert_last(entry->attrs, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the next attribute from the locked hashtable stored for given id
|
||||
*/
|
||||
static attr_t* remove_attr(private_eap_radius_provider_t *this,
|
||||
hashtable_t *hashtable, identification_t *id)
|
||||
{
|
||||
entry_t *entry;
|
||||
attr_t *attr = NULL;
|
||||
|
||||
entry = hashtable->remove(hashtable, id);
|
||||
if (entry)
|
||||
{
|
||||
entry->attrs->remove_first(entry->attrs, (void**)&attr);
|
||||
put_or_destroy_entry(hashtable, entry);
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up unclaimed leases assigned for an IKE_SA
|
||||
*/
|
||||
@@ -276,11 +330,77 @@ METHOD(attribute_provider_t, release_address, bool,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerator implementation over attributes
|
||||
*/
|
||||
typedef struct {
|
||||
/** implements enumerator_t */
|
||||
enumerator_t public;
|
||||
/** list of attributes to enumerate */
|
||||
linked_list_t *list;
|
||||
/** currently enumerating attribute */
|
||||
attr_t *current;
|
||||
} attribute_enumerator_t;
|
||||
|
||||
|
||||
METHOD(enumerator_t, attribute_enumerate, bool,
|
||||
attribute_enumerator_t *this, configuration_attribute_type_t *type,
|
||||
chunk_t *data)
|
||||
{
|
||||
if (this->current)
|
||||
{
|
||||
destroy_attr(this->current);
|
||||
this->current = NULL;
|
||||
}
|
||||
if (this->list->remove_first(this->list, (void**)&this->current) == SUCCESS)
|
||||
{
|
||||
*type = this->current->type;
|
||||
*data = this->current->data;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(enumerator_t, attribute_destroy, void,
|
||||
attribute_enumerator_t *this)
|
||||
{
|
||||
if (this->current)
|
||||
{
|
||||
destroy_attr(this->current);
|
||||
}
|
||||
this->list->destroy_function(this->list, (void*)destroy_attr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
|
||||
private_eap_radius_provider_t *this, linked_list_t *pools,
|
||||
identification_t *id, linked_list_t *vips)
|
||||
{
|
||||
return enumerator_create_empty();
|
||||
attribute_enumerator_t *enumerator;
|
||||
attr_t *attr;
|
||||
|
||||
INIT(enumerator,
|
||||
.public = {
|
||||
.enumerate = (void*)_attribute_enumerate,
|
||||
.destroy = _attribute_destroy,
|
||||
},
|
||||
.list = linked_list_create(),
|
||||
);
|
||||
|
||||
/* we forward attributes regardless of pool configurations */
|
||||
this->listener.mutex->lock(this->listener.mutex);
|
||||
while (TRUE)
|
||||
{
|
||||
attr = remove_attr(this, this->listener.unclaimed, id);
|
||||
if (!attr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
enumerator->list->insert_last(enumerator->list, attr);
|
||||
}
|
||||
this->listener.mutex->unlock(this->listener.mutex);
|
||||
|
||||
return &enumerator->public;
|
||||
}
|
||||
|
||||
METHOD(eap_radius_provider_t, add_framed_ip, void,
|
||||
@@ -291,6 +411,21 @@ METHOD(eap_radius_provider_t, add_framed_ip, void,
|
||||
this->listener.mutex->unlock(this->listener.mutex);
|
||||
}
|
||||
|
||||
METHOD(eap_radius_provider_t, add_attribute, void,
|
||||
private_eap_radius_provider_t *this, identification_t *id,
|
||||
configuration_attribute_type_t type, chunk_t data)
|
||||
{
|
||||
attr_t *attr;
|
||||
|
||||
INIT(attr,
|
||||
.type = type,
|
||||
.data = chunk_clone(data),
|
||||
);
|
||||
this->listener.mutex->lock(this->listener.mutex);
|
||||
add_attr(this, this->listener.unclaimed, id, attr);
|
||||
this->listener.mutex->unlock(this->listener.mutex);
|
||||
}
|
||||
|
||||
METHOD(eap_radius_provider_t, destroy, void,
|
||||
private_eap_radius_provider_t *this)
|
||||
{
|
||||
@@ -319,6 +454,7 @@ eap_radius_provider_t *eap_radius_provider_create()
|
||||
.create_attribute_enumerator = _create_attribute_enumerator,
|
||||
},
|
||||
.add_framed_ip = _add_framed_ip,
|
||||
.add_attribute = _add_attribute,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.listener = {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#ifndef EAP_RADIUS_PROVIDER_H_
|
||||
#define EAP_RADIUS_PROVIDER_H_
|
||||
|
||||
#include <attributes/attributes.h>
|
||||
#include <attributes/attribute_provider.h>
|
||||
|
||||
typedef struct eap_radius_provider_t eap_radius_provider_t;
|
||||
@@ -44,6 +45,16 @@ struct eap_radius_provider_t {
|
||||
void (*add_framed_ip)(eap_radius_provider_t *this, identification_t *id,
|
||||
host_t *ip);
|
||||
|
||||
/**
|
||||
* Add a configuration attribute received from RADIUS to forward.
|
||||
*
|
||||
* @param id client identity
|
||||
* @param type attribute type
|
||||
* @param data attribute data
|
||||
*/
|
||||
void (*add_attribute)(eap_radius_provider_t *this, identification_t *id,
|
||||
configuration_attribute_type_t type, chunk_t data);
|
||||
|
||||
/**
|
||||
* Destroy a eap_radius_provider_t.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user