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;
|
eap_radius_provider_t *provider;
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
|
ike_sa_t *ike_sa;
|
||||||
host_t *host;
|
host_t *host;
|
||||||
chunk_t data;
|
chunk_t data;
|
||||||
int type;
|
int type, vendor;
|
||||||
|
|
||||||
|
ike_sa = charon->bus->get_sa(charon->bus);
|
||||||
provider = eap_radius_provider_get();
|
provider = eap_radius_provider_get();
|
||||||
if (provider)
|
if (provider && ike_sa)
|
||||||
{
|
{
|
||||||
enumerator = msg->create_enumerator(msg);
|
enumerator = msg->create_enumerator(msg);
|
||||||
while (enumerator->enumerate(enumerator, &type, &data))
|
while (enumerator->enumerate(enumerator, &type, &data))
|
||||||
@@ -356,6 +358,28 @@ static void process_cfg_attributes(private_eap_radius_t *this,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
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;
|
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 {
|
typedef struct {
|
||||||
/** identity we assigned the IP lease */
|
/** identity we assigned the IP lease */
|
||||||
identification_t *id;
|
identification_t *id;
|
||||||
/** list of IP leases received from AAA, as host_t */
|
/** list of IP leases received from AAA, as host_t */
|
||||||
linked_list_t *addrs;
|
linked_list_t *addrs;
|
||||||
|
/** list of configuration attributes, as attr_t */
|
||||||
|
linked_list_t *attrs;
|
||||||
} entry_t;
|
} entry_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,6 +107,7 @@ static void destroy_entry(entry_t *this)
|
|||||||
{
|
{
|
||||||
this->id->destroy(this->id);
|
this->id->destroy(this->id);
|
||||||
this->addrs->destroy_offset(this->addrs, offsetof(host_t, destroy));
|
this->addrs->destroy_offset(this->addrs, offsetof(host_t, destroy));
|
||||||
|
this->attrs->destroy_function(this->attrs, (void*)destroy_attr);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +124,7 @@ static entry_t* get_or_create_entry(hashtable_t *hashtable, identification_t *id
|
|||||||
INIT(entry,
|
INIT(entry,
|
||||||
.id = id->clone(id),
|
.id = id->clone(id),
|
||||||
.addrs = linked_list_create(),
|
.addrs = linked_list_create(),
|
||||||
|
.attrs = linked_list_create(),
|
||||||
);
|
);
|
||||||
hashtable->put(hashtable, entry->id, entry);
|
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)
|
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);
|
hashtable->put(hashtable, entry->id, entry);
|
||||||
}
|
}
|
||||||
@@ -169,6 +193,36 @@ static host_t* remove_addr(private_eap_radius_provider_t *this,
|
|||||||
return addr;
|
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
|
* Clean up unclaimed leases assigned for an IKE_SA
|
||||||
*/
|
*/
|
||||||
@@ -276,11 +330,77 @@ METHOD(attribute_provider_t, release_address, bool,
|
|||||||
return FALSE;
|
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*,
|
METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
|
||||||
private_eap_radius_provider_t *this, linked_list_t *pools,
|
private_eap_radius_provider_t *this, linked_list_t *pools,
|
||||||
identification_t *id, linked_list_t *vips)
|
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,
|
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);
|
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,
|
METHOD(eap_radius_provider_t, destroy, void,
|
||||||
private_eap_radius_provider_t *this)
|
private_eap_radius_provider_t *this)
|
||||||
{
|
{
|
||||||
@@ -319,6 +454,7 @@ eap_radius_provider_t *eap_radius_provider_create()
|
|||||||
.create_attribute_enumerator = _create_attribute_enumerator,
|
.create_attribute_enumerator = _create_attribute_enumerator,
|
||||||
},
|
},
|
||||||
.add_framed_ip = _add_framed_ip,
|
.add_framed_ip = _add_framed_ip,
|
||||||
|
.add_attribute = _add_attribute,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.listener = {
|
.listener = {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#ifndef EAP_RADIUS_PROVIDER_H_
|
#ifndef EAP_RADIUS_PROVIDER_H_
|
||||||
#define EAP_RADIUS_PROVIDER_H_
|
#define EAP_RADIUS_PROVIDER_H_
|
||||||
|
|
||||||
|
#include <attributes/attributes.h>
|
||||||
#include <attributes/attribute_provider.h>
|
#include <attributes/attribute_provider.h>
|
||||||
|
|
||||||
typedef struct eap_radius_provider_t eap_radius_provider_t;
|
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,
|
void (*add_framed_ip)(eap_radius_provider_t *this, identification_t *id,
|
||||||
host_t *ip);
|
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.
|
* Destroy a eap_radius_provider_t.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user