Added support for named attribute groups

Add the possibility to group attributes by a name and assign these
groups to connections. This allows a more granular configuration of
which client will receive what atrributes.
This commit is contained in:
Heiko Hund
2010-07-09 13:09:31 +02:00
committed by Martin Willi
parent db4ad736be
commit ec7adea007
12 changed files with 377 additions and 95 deletions
+1 -1
View File
@@ -342,7 +342,7 @@ static status_t build_r(private_ike_config_t *this, message_t *message)
/* query registered providers for additional attributes to include */ /* query registered providers for additional attributes to include */
enumerator = hydra->attributes->create_responder_enumerator( enumerator = hydra->attributes->create_responder_enumerator(
hydra->attributes, id, vip); hydra->attributes, config->get_pool(config), id, vip);
while (enumerator->enumerate(enumerator, &type, &value)) while (enumerator->enumerate(enumerator, &type, &value))
{ {
if (!cp) if (!cp)
+8 -3
View File
@@ -51,6 +51,8 @@ struct private_attribute_manager_t {
* Data to pass to enumerator filters * Data to pass to enumerator filters
*/ */
typedef struct { typedef struct {
/** attribute group pool */
char *pool;
/** server/peer identity */ /** server/peer identity */
identification_t *id; identification_t *id;
/** requesting/assigned virtual IP */ /** requesting/assigned virtual IP */
@@ -123,17 +125,20 @@ static void release_address(private_attribute_manager_t *this,
static enumerator_t *responder_enum_create(attribute_provider_t *provider, static enumerator_t *responder_enum_create(attribute_provider_t *provider,
enum_data_t *data) enum_data_t *data)
{ {
return provider->create_attribute_enumerator(provider, data->id, data->vip); return provider->create_attribute_enumerator(provider, data->pool,
data->id, data->vip);
} }
/** /**
* Implementation of attribute_manager_t.create_responder_enumerator * Implementation of attribute_manager_t.create_responder_enumerator
*/ */
static enumerator_t* create_responder_enumerator( static enumerator_t* create_responder_enumerator(
private_attribute_manager_t *this, identification_t *id, host_t *vip) private_attribute_manager_t *this, char *pool,
identification_t *id, host_t *vip)
{ {
enum_data_t *data = malloc_thing(enum_data_t); enum_data_t *data = malloc_thing(enum_data_t);
data->pool = pool;
data->id = id; data->id = id;
data->vip = vip; data->vip = vip;
this->lock->read_lock(this->lock); this->lock->read_lock(this->lock);
@@ -355,7 +360,7 @@ attribute_manager_t *attribute_manager_create()
this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,host_t*))acquire_address; this->public.acquire_address = (host_t*(*)(attribute_manager_t*, char*, identification_t*,host_t*))acquire_address;
this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*, identification_t*))release_address; this->public.release_address = (void(*)(attribute_manager_t*, char *, host_t*, identification_t*))release_address;
this->public.create_responder_enumerator = (enumerator_t*(*)(attribute_manager_t*, identification_t*, host_t*))create_responder_enumerator; this->public.create_responder_enumerator = (enumerator_t*(*)(attribute_manager_t*, char *name, identification_t*, host_t*))create_responder_enumerator;
this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider; this->public.add_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))add_provider;
this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider; this->public.remove_provider = (void(*)(attribute_manager_t*, attribute_provider_t *provider))remove_provider;
this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*,identification_t*, attribute_handler_t*, configuration_attribute_type_t, chunk_t))handle; this->public.handle = (attribute_handler_t*(*)(attribute_manager_t*,identification_t*, attribute_handler_t*, configuration_attribute_type_t, chunk_t))handle;
+2 -1
View File
@@ -61,12 +61,13 @@ struct attribute_manager_t {
/** /**
* Create an enumerator over attributes to hand out to a peer. * Create an enumerator over attributes to hand out to a peer.
* *
* @param pool pool name to get attributes from
* @param id peer identity to hand out attributes to * @param id peer identity to hand out attributes to
* @param vip virtual IP to assign to peer, if any * @param vip virtual IP to assign to peer, if any
* @return enumerator (configuration_attribute_type_t, chunk_t) * @return enumerator (configuration_attribute_type_t, chunk_t)
*/ */
enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this, enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this,
identification_t *id, host_t *vip); char *pool, identification_t *id, host_t *vip);
/** /**
* Register an attribute provider to the manager. * Register an attribute provider to the manager.
+2 -1
View File
@@ -56,12 +56,13 @@ struct attribute_provider_t {
/** /**
* Create an enumerator over attributes to hand out to a peer. * Create an enumerator over attributes to hand out to a peer.
* *
* @param pool pool name to get attributes from
* @param id peer ID * @param id peer ID
* @param vip virtual IP to assign to peer, if any * @param vip virtual IP to assign to peer, if any
* @return enumerator (configuration_attribute_type_t, chunk_t) * @return enumerator (configuration_attribute_type_t, chunk_t)
*/ */
enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this, enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this,
identification_t *id, host_t *vip); char *pool, identification_t *id, host_t *vip);
}; };
#endif /** ATTRIBUTE_PROVIDER_H_ @}*/ #endif /** ATTRIBUTE_PROVIDER_H_ @}*/
+2 -2
View File
@@ -65,7 +65,7 @@ static bool attr_enum_filter(void *null, attribute_entry_t **in,
* Implementation of attribute_provider_t.create_attribute_enumerator * Implementation of attribute_provider_t.create_attribute_enumerator
*/ */
static enumerator_t* create_attribute_enumerator(private_attr_provider_t *this, static enumerator_t* create_attribute_enumerator(private_attr_provider_t *this,
identification_t *id, host_t *vip) char *pool, identification_t *id, host_t *vip)
{ {
if (vip) if (vip)
{ {
@@ -250,7 +250,7 @@ attr_provider_t *attr_provider_create(database_t *db)
this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))return_null; this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))return_null;
this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))return_false; this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))return_false;
this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *vip))create_attribute_enumerator; this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, char *names, identification_t *id, host_t *vip))create_attribute_enumerator;
this->public.destroy = (void(*)(attr_provider_t*))destroy; this->public.destroy = (void(*)(attr_provider_t*))destroy;
this->attributes = linked_list_create(); this->attributes = linked_list_create();
+30 -25
View File
@@ -390,29 +390,14 @@ static bool add_address(u_int pool_id, char *address_str, int *family)
char *pos_eq = strchr(address_str, '='); char *pos_eq = strchr(address_str, '=');
if (pos_eq != NULL) if (pos_eq != NULL)
{ {
enumerator_t *e;
identification_t *id = identification_create_from_string(pos_eq + 1); identification_t *id = identification_create_from_string(pos_eq + 1);
user_id = get_identity(id);
/* look for peer identity in the identities table */
e = db->query(db,
"SELECT id FROM identities WHERE type = ? AND data = ?",
DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id),
DB_UINT);
if (!e || !e->enumerate(e, &user_id))
{
/* not found, insert new one */
if (db->execute(db, &user_id,
"INSERT INTO identities (type, data) VALUES (?, ?)",
DB_INT, id->get_type(id),
DB_BLOB, id->get_encoding(id)) != 1)
{
fprintf(stderr, "creating id '%s' failed.\n", pos_eq + 1);
return FALSE;
}
}
DESTROY_IF(e);
id->destroy(id); id->destroy(id);
if (user_id == 0)
{
return FALSE;
}
*pos_eq = '\0'; *pos_eq = '\0';
} }
@@ -943,7 +928,8 @@ static void cleanup(void)
static void do_args(int argc, char *argv[]) static void do_args(int argc, char *argv[])
{ {
char *name = "", *value = "", *filter = "", *addresses = NULL; char *name = "", *value = "", *filter = "";
char *pool = NULL, *identity = NULL, *addresses = NULL;
value_type_t value_type = VALUE_NONE; value_type_t value_type = VALUE_NONE;
int timeout = 0; int timeout = 0;
bool utc = FALSE, hexout = FALSE; bool utc = FALSE, hexout = FALSE;
@@ -1000,6 +986,8 @@ static void do_args(int argc, char *argv[])
{ "string", required_argument, NULL, 'g' }, { "string", required_argument, NULL, 'g' },
{ "hex", required_argument, NULL, 'x' }, { "hex", required_argument, NULL, 'x' },
{ "hexout", no_argument, NULL, '5' }, { "hexout", no_argument, NULL, '5' },
{ "pool", required_argument, NULL, '6' },
{ "identity", required_argument, NULL, '7' },
{ 0,0,0,0 } { 0,0,0,0 }
}; };
@@ -1122,6 +1110,12 @@ static void do_args(int argc, char *argv[])
case '5': case '5':
hexout = TRUE; hexout = TRUE;
continue; continue;
case '6':
pool = optarg;
continue;
case '7':
identity = optarg;
continue;
default: default:
usage(); usage();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@@ -1164,14 +1158,25 @@ static void do_args(int argc, char *argv[])
usage(); usage();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
add_attr(name, value, value_type); if (identity && !pool)
{
fprintf(stderr, "--identity option can't be used without --pool.\n");
usage();
exit(EXIT_FAILURE);
}
add_attr(name, pool, identity, value, value_type);
break; break;
case OP_DEL: case OP_DEL:
del(name); del(name);
break; break;
case OP_DEL_ATTR: case OP_DEL_ATTR:
if (identity && !pool)
del_attr(name, value, value_type); {
fprintf(stderr, "--identity option can't be used without --pool.\n");
usage();
exit(EXIT_FAILURE);
}
del_attr(name, pool, identity, value, value_type);
break; break;
case OP_SHOW_ATTR: case OP_SHOW_ATTR:
show_attr(); show_attr();
+184 -45
View File
@@ -264,54 +264,165 @@ static bool parse_attributes(char *name, char *value, value_type_t *value_type,
} }
/** /**
* ipsec pool --addattr <type> --string|server|subnet - add attribute entry * Lookup/insert an attribute pool by name
*/ */
void add_attr(char *name, char *value, value_type_t value_type) static u_int get_attr_pool(char *name)
{
enumerator_t *e;
u_int row = 0;
/* look for an existing attribute pool in the table */
e = db->query(db, "SELECT id FROM attribute_pools WHERE name = ?",
DB_TEXT, name, DB_UINT);
if (e && e->enumerate(e, &row))
{
e->destroy(e);
return row;
}
DESTROY_IF(e);
/* not found, insert new one */
if (db->execute(db, &row, "INSERT INTO attribute_pools (name) VALUES (?)",
DB_TEXT, name) != 1)
{
fprintf(stderr, "creating attribute pool '%s' failed.\n", name);
return 0;
}
return row;
}
/**
* Lookup/insert an identity
*/
u_int get_identity(identification_t *id)
{
enumerator_t *e;
u_int row;
/* look for peer identity in the identities table */
e = db->query(db, "SELECT id FROM identities WHERE type = ? AND data = ?",
DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id), DB_UINT);
if (e && e->enumerate(e, &row))
{
e->destroy(e);
return row;
}
DESTROY_IF(e);
/* not found, insert new one */
if (db->execute(db, &row, "INSERT INTO identities (type,data) VALUES (?,?)",
DB_INT, id->get_type(id), DB_BLOB, id->get_encoding(id)) != 1)
{
fprintf(stderr, "creating id '%Y' failed.\n", id);
return 0;
}
return row;
}
/**
* ipsec pool --addattr <type> - add attribute entry
*/
void add_attr(char *name, char *pool, char *identity,
char *value, value_type_t value_type)
{ {
configuration_attribute_type_t type, type_ip6; configuration_attribute_type_t type, type_ip6;
u_int pool_id = 0, identity_id = 0;
char id_pool_str[128] = "";
chunk_t blob; chunk_t blob;
bool success; bool success;
if (pool)
{
pool_id = get_attr_pool(pool);
if (pool_id == 0)
{
exit(EXIT_FAILURE);
}
if (identity)
{
identification_t *id = identification_create_from_string(identity);
identity_id = get_identity(id);
id->destroy(id);
if (identity_id == 0)
{
exit(EXIT_FAILURE);
}
snprintf(id_pool_str, sizeof(id_pool_str),
" for '%Y' in pool '%s'", identity, pool);
}
else
{
snprintf(id_pool_str, sizeof(id_pool_str), " in pool '%s'", pool);
}
}
if (value_type == VALUE_NONE) if (value_type == VALUE_NONE)
{ {
fprintf(stderr, "the value of the %s attribute is missing.\n", name); fprintf(stderr, "the value of the %s attribute is missing.\n", name);
usage(); usage();
exit(EXIT_FAILURE); }
}
if (!parse_attributes(name, value, &value_type, &type, &type_ip6, &blob)) if (!parse_attributes(name, value, &value_type, &type, &type_ip6, &blob))
{ {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
success = db->execute(db, NULL, success = db->execute(db, NULL,
"INSERT INTO attributes (type, value) VALUES (?, ?)", "INSERT INTO attributes (identity, pool, type, value) "
"VALUES (?, ?, ?, ?)", DB_UINT, identity_id, DB_UINT, pool_id,
DB_INT, type, DB_BLOB, blob) == 1; DB_INT, type, DB_BLOB, blob) == 1;
free(blob.ptr); free(blob.ptr);
if (success) if (success)
{ {
printf("added %s attribute (%N).\n", name, printf("added %s attribute (%N)%s.\n", name,
configuration_attribute_type_names, type); configuration_attribute_type_names, type, id_pool_str);
} }
else else
{ {
fprintf(stderr, "adding %s attribute (%N) failed.\n", name, fprintf(stderr, "adding %s attribute (%N)%s failed.\n", name,
configuration_attribute_type_names, type); configuration_attribute_type_names, type, id_pool_str);
exit(EXIT_FAILURE);
} }
} }
/** /**
* ipsec pool --delattr <type> --string|server|subnet - delete attribute entry * ipsec pool --delattr <type> - delete attribute entry
*/ */
void del_attr(char *name, char *value, value_type_t value_type) void del_attr(char *name, char *pool, char *identity,
char *value, value_type_t value_type)
{ {
configuration_attribute_type_t type, type_ip6, type_db; configuration_attribute_type_t type, type_ip6, type_db;
u_int pool_id = 0, identity_id = 0;
char id_pool_str[128] = "";
chunk_t blob, blob_db; chunk_t blob, blob_db;
u_int id; u_int id;
enumerator_t *query; enumerator_t *query;
bool found = FALSE; bool found = FALSE;
if (pool)
{
pool_id = get_attr_pool(pool);
if (pool_id == 0)
{
exit(EXIT_FAILURE);
}
if (identity)
{
identification_t *id = identification_create_from_string(identity);
identity_id = get_identity(id);
id->destroy(id);
if (identity_id == 0)
{
exit(EXIT_FAILURE);
}
snprintf(id_pool_str, sizeof(id_pool_str),
" for '%Y' in pool '%s'", identity, pool);
}
else
{
snprintf(id_pool_str, sizeof(id_pool_str), " in pool '%s'", pool);
}
}
if (!parse_attributes(name, value, &value_type, &type, &type_ip6, &blob)) if (!parse_attributes(name, value, &value_type, &type, &type_ip6, &blob))
{ {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@@ -321,31 +432,31 @@ void del_attr(char *name, char *value, value_type_t value_type)
{ {
query = db->query(db, query = db->query(db,
"SELECT id, type, value FROM attributes " "SELECT id, type, value FROM attributes "
"WHERE type = ? AND value = ?", "WHERE identity = ? AND pool = ? AND type = ? AND value = ?",
DB_INT, type, DB_BLOB, blob, DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type,
DB_UINT, DB_INT, DB_BLOB); DB_BLOB, blob, DB_UINT, DB_INT, DB_BLOB);
} }
else if (type_ip6 == 0) else if (type_ip6 == 0)
{ {
query = db->query(db, query = db->query(db,
"SELECT id, type, value FROM attributes " "SELECT id, type, value FROM attributes "
"WHERE type = ?", "WHERE identity = ? AND pool = ? AND type = ?",
DB_INT, type, DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type,
DB_UINT, DB_INT, DB_BLOB); DB_UINT, DB_INT, DB_BLOB);
} }
else else
{ {
query = db->query(db, query = db->query(db,
"SELECT id, type, value FROM attributes " "SELECT id, type, value FROM attributes "
"WHERE type = ? OR type = ?", "WHERE identity = ? AND pool = ? AND (type = ? OR type = ?)",
DB_INT, type, DB_INT, type_ip6, DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type,
DB_UINT, DB_INT, DB_BLOB); DB_INT, type_ip6, DB_UINT, DB_INT, DB_BLOB);
} }
if (!query) if (!query)
{ {
fprintf(stderr, "deleting '%s' attribute (%N) failed.\n", fprintf(stderr, "deleting '%s' attribute (%N)%s failed.\n",
name, configuration_attribute_type_names, type); name, configuration_attribute_type_names, type, id_pool_str);
free(blob.ptr); free(blob.ptr);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -369,21 +480,22 @@ void del_attr(char *name, char *value, value_type_t value_type)
{ {
if (server) if (server)
{ {
fprintf(stderr, "deleting %s server %H failed\n", name, server); fprintf(stderr, "deleting %s server %H%s failed\n",
name, server, id_pool_str);
server->destroy(server); server->destroy(server);
} }
else if (value_type == VALUE_STRING) else if (value_type == VALUE_STRING)
{ {
fprintf(stderr, "deleting %s attribute (%N) with value '%.*s' failed.\n", fprintf(stderr, "deleting %s attribute (%N) with value '%.*s'%s failed.\n",
name, configuration_attribute_type_names, type, name, configuration_attribute_type_names, type,
blob_db.len, blob_db.ptr); blob_db.len, blob_db.ptr, id_pool_str);
} }
else else
{ {
fprintf(stderr, "deleting %s attribute (%N) with value %#B failed.\n", fprintf(stderr, "deleting %s attribute (%N) with value %#B%s failed.\n",
name, configuration_attribute_type_names, type, name, configuration_attribute_type_names, type,
&blob_db); &blob_db, id_pool_str);
} }
query->destroy(query); query->destroy(query);
free(blob.ptr); free(blob.ptr);
@@ -391,20 +503,20 @@ void del_attr(char *name, char *value, value_type_t value_type)
} }
if (server) if (server)
{ {
printf("deleted %s server %H\n", name, server); printf("deleted %s server %H%s\n", name, server, id_pool_str);
server->destroy(server); server->destroy(server);
} }
else if (value_type == VALUE_STRING) else if (value_type == VALUE_STRING)
{ {
printf("deleted %s attribute (%N) with value '%.*s'.\n", printf("deleted %s attribute (%N) with value '%.*s'%s.\n",
name, configuration_attribute_type_names, type, name, configuration_attribute_type_names, type,
blob_db.len, blob_db.ptr); blob_db.len, blob_db.ptr, id_pool_str);
} }
else else
{ {
printf("deleted %s attribute (%N) with value %#B.\n", printf("deleted %s attribute (%N) with value %#B%s.\n",
name, configuration_attribute_type_names, type, name, configuration_attribute_type_names, type,
&blob_db); &blob_db, id_pool_str);
} }
} }
query->destroy(query); query->destroy(query);
@@ -415,12 +527,13 @@ void del_attr(char *name, char *value, value_type_t value_type)
{ {
if (type_ip6 == 0) if (type_ip6 == 0)
{ {
fprintf(stderr, "no %s attribute (%N) was found.\n", name, fprintf(stderr, "no %s attribute (%N) was found%s.\n", name,
configuration_attribute_type_names, type); configuration_attribute_type_names, type, id_pool_str);
} }
else else
{ {
fprintf(stderr, "no %s attribute was found.\n", name); fprintf(stderr, "no %s attribute%s was found.\n",
name, id_pool_str);
} }
} }
else else
@@ -429,16 +542,16 @@ void del_attr(char *name, char *value, value_type_t value_type)
{ {
host_t *server = host_create_from_chunk(AF_UNSPEC, blob, 0); host_t *server = host_create_from_chunk(AF_UNSPEC, blob, 0);
fprintf(stderr, "the %s server %H was not found.\n", name, fprintf(stderr, "the %s server %H%s was not found.\n", name,
server); server, id_pool_str);
server->destroy(server); server->destroy(server);
} }
else else
{ {
fprintf(stderr, "the %s attribute (%N) with value '%.*s' " fprintf(stderr, "the %s attribute (%N) with value '%.*s'%s "
"was not found.\n", name, "was not found.\n", name,
configuration_attribute_type_names, type, configuration_attribute_type_names, type,
blob.len, blob.ptr); blob.len, blob.ptr, id_pool_str);
} }
} }
} }
@@ -452,23 +565,36 @@ void status_attr(bool hexout)
{ {
configuration_attribute_type_t type; configuration_attribute_type_t type;
value_type_t value_type; value_type_t value_type;
chunk_t value, addr_chunk, mask_chunk; chunk_t value, addr_chunk, mask_chunk, identity_chunk;
identification_t *identity;
enumerator_t *enumerator; enumerator_t *enumerator;
host_t *addr, *mask; host_t *addr, *mask;
char type_name[30]; char type_name[30];
bool first = TRUE; bool first = TRUE;
int i; int i, identity_type;
char *pool_name;
/* enumerate over all attributes */ /* enumerate over all attributes */
enumerator = db->query(db, "SELECT type, value FROM attributes ORDER BY type", enumerator = db->query(db,
DB_INT, DB_BLOB); "SELECT identities.type, identities.data, "
"attribute_pools.name, attributes.type, attributes.value "
"FROM attributes "
"LEFT OUTER JOIN identities "
"ON attributes.identity = identities.id "
"LEFT OUTER JOIN attribute_pools "
"ON attributes.pool = attribute_pools.id "
"ORDER BY identities.type, identities.data, "
"attribute_pools.name, attributes.type",
DB_INT, DB_BLOB, DB_TEXT, DB_INT, DB_BLOB);
if (enumerator) if (enumerator)
{ {
while (enumerator->enumerate(enumerator, &type, &value)) while (enumerator->enumerate(enumerator, &identity_type,
&identity_chunk, &pool_name, &type, &value))
{ {
if (first) if (first)
{ {
printf(" type description value\n"); printf(" type description pool "
" identity value\n");
first = FALSE; first = FALSE;
} }
snprintf(type_name, sizeof(type_name), "%N", snprintf(type_name, sizeof(type_name), "%N",
@@ -479,6 +605,19 @@ void status_attr(bool hexout)
} }
printf("%5d %-20s ",type, type_name); printf("%5d %-20s ",type, type_name);
printf(" %-15.15s ", (pool_name ? pool_name : ""));
if (identity_type)
{
identity = identification_create_from_encoding(identity_type, identity_chunk);
printf(" %-15.15Y ", identity);
identity->destroy(identity);
}
else
{
printf(" ");
}
value_type = VALUE_HEX; value_type = VALUE_HEX;
if (!hexout) if (!hexout)
{ {
@@ -33,15 +33,22 @@ enum value_type_t {
*/ */
extern enum_name_t *value_type_names; extern enum_name_t *value_type_names;
/**
* lookup/insert an identity
*/
u_int get_identity(identification_t *id);
/** /**
* ipsec pool --addattr <type> - add attribute entry * ipsec pool --addattr <type> - add attribute entry
*/ */
void add_attr(char *name, char *value, value_type_t value_type); void add_attr(char *name, char *pool, char *identity,
char *value, value_type_t value_type);
/** /**
* ipsec pool --delattr <type> - delete attribute entry * ipsec pool --delattr <type> - delete attribute entry
*/ */
void del_attr(char *name, char *value, value_type_t value_type); void del_attr(char *name, char *pool, char *identity,
char *value, value_type_t value_type);
/** /**
* ipsec pool --statusattr - show all attribute entries * ipsec pool --statusattr - show all attribute entries
+11 -3
View File
@@ -59,9 +59,14 @@ Usage:\n\
resized.\n\ resized.\n\
timeout: Lease time in hours, 0 for static leases\n\ timeout: Lease time in hours, 0 for static leases\n\
\n\ \n\
ipsec pool --addattr <type> --addr|--mask|--server|--subnet|--string|--hex <value>\n\ ipsec pool --addattr <type> [--pool <name> [--identity <id>]]\n\
Add a new attribute to the database.\n\ --addr|--mask|--server|--subnet|--string|--hex <value>\n\
Add a new attribute to the database. Attributes can be bundled by using\n\
the --pool and --identity options. If a bundle matches a peer the contained\n\
attributes are sent to that peer instead of the global ones.\n\
type: a keyword from --showattr or a number from the range 1..32767\n\ type: a keyword from --showattr or a number from the range 1..32767\n\
name: the name of the pool this attribute is added to\n\
id: identity of the peer this attribute is bound to\n\
addr: IPv4 or IPv6 address\n\ addr: IPv4 or IPv6 address\n\
mask: IPv4 or IPv6 netmask (synonym for --addr)\n\ mask: IPv4 or IPv6 netmask (synonym for --addr)\n\
server: IPv4 or IPv6 address of a server (synonym for --addr)\n\ server: IPv4 or IPv6 address of a server (synonym for --addr)\n\
@@ -73,9 +78,12 @@ Usage:\n\
Delete a pool from the database.\n\ Delete a pool from the database.\n\
name: Name of the pool to delete\n\ name: Name of the pool to delete\n\
\n\ \n\
ipsec pool --delattr <type> [--addr|--mask|--server|--subnet|--string|--hex <value>]\n\ ipsec pool --delattr <type> [--pool <name> [--identity <id>]]\n\
[--addr|--mask|--server|--subnet|--string|--hex <value>]\n\
Delete a specific or all attributes of a given type from the database.\n\ Delete a specific or all attributes of a given type from the database.\n\
type: a keyword from --showattr or a number from the range 1..32767\n\ type: a keyword from --showattr or a number from the range 1..32767\n\
name: the name of the pool this attribute is added to\n\
id: identity of the peer this attribute is bound to\n\
addr: IPv4 or IPv6 address\n\ addr: IPv4 or IPv6 address\n\
mask: IPv4 or IPv6 netmask (synonym for --addr)\n\ mask: IPv4 or IPv6 netmask (synonym for --addr)\n\
server: IPv4 or IPv6 address of a server (synonym for --addr)\n\ server: IPv4 or IPv6 address of a server (synonym for --addr)\n\
+109 -8
View File
@@ -73,6 +73,26 @@ static u_int get_identity(private_sql_attribute_t *this, identification_t *id)
return 0; return 0;
} }
/**
* Lookup an attribute pool by name
*/
static u_int get_attr_pool(private_sql_attribute_t *this, char *name)
{
enumerator_t *e;
u_int row = 0;
e = this->db->query(this->db,
"SELECT id FROM attribute_pools WHERE name = ?",
DB_TEXT, name, DB_UINT);
if (e)
{
e->enumerate(e, &row);
}
DESTROY_IF(e);
return row;
}
/** /**
* Lookup pool by name * Lookup pool by name
*/ */
@@ -327,20 +347,101 @@ static bool release_address(private_sql_attribute_t *this,
* Implementation of sql_attribute_t.create_attribute_enumerator * Implementation of sql_attribute_t.create_attribute_enumerator
*/ */
static enumerator_t* create_attribute_enumerator(private_sql_attribute_t *this, static enumerator_t* create_attribute_enumerator(private_sql_attribute_t *this,
identification_t *id, host_t *vip) char *names, identification_t *id, host_t *vip)
{ {
enumerator_t *attr_enumerator = NULL;
if (vip) if (vip)
{ {
enumerator_t *enumerator; enumerator_t *names_enumerator;
u_int count;
char *name;
enumerator = this->db->query(this->db, this->db->execute(this->db, NULL, "BEGIN EXCLUSIVE TRANSACTION");
"SELECT type, value FROM attributes", DB_INT, DB_BLOB);
if (enumerator) /* in a first step check for attributes that match name and id */
if (id)
{ {
return enumerator; u_int identity = get_identity(this, id);
names_enumerator = enumerator_create_token(names, ",", " ");
while (names_enumerator->enumerate(names_enumerator, &name))
{
u_int attr_pool = get_attr_pool(this, name);
if (!attr_pool)
{
continue;
}
attr_enumerator = this->db->query(this->db,
"SELECT count(*) FROM attributes "
"WHERE pool = ? AND identity = ?",
DB_UINT, attr_pool, DB_UINT, identity, DB_UINT);
if (attr_enumerator &&
attr_enumerator->enumerate(attr_enumerator, &count) &&
count != 0)
{
attr_enumerator->destroy(attr_enumerator);
attr_enumerator = this->db->query(this->db,
"SELECT type, value FROM attributes "
"WHERE pool = ? AND identity = ?", DB_UINT,
attr_pool, DB_UINT, identity, DB_INT, DB_BLOB);
break;
}
DESTROY_IF(attr_enumerator);
attr_enumerator = NULL;
}
names_enumerator->destroy(names_enumerator);
}
/* in a second step check for attributes that match name */
if (!attr_enumerator)
{
names_enumerator = enumerator_create_token(names, ",", " ");
while (names_enumerator->enumerate(names_enumerator, &name))
{
u_int attr_pool = get_attr_pool(this, name);
if (!attr_pool)
{
continue;
}
attr_enumerator = this->db->query(this->db,
"SELECT count(*) FROM attributes "
"WHERE pool = ? AND identity = 0",
DB_UINT, attr_pool, DB_UINT);
if (attr_enumerator &&
attr_enumerator->enumerate(attr_enumerator, &count) &&
count != 0)
{
attr_enumerator->destroy(attr_enumerator);
attr_enumerator = this->db->query(this->db,
"SELECT type, value FROM attributes "
"WHERE pool = ? AND identity = 0",
DB_UINT, attr_pool, DB_INT, DB_BLOB);
break;
}
DESTROY_IF(attr_enumerator);
attr_enumerator = NULL;
}
names_enumerator->destroy(names_enumerator);
}
this->db->execute(this->db, NULL, "END TRANSACTION");
/* lastly try to find global attributes */
if (!attr_enumerator)
{
attr_enumerator = this->db->query(this->db,
"SELECT type, value FROM attributes "
"WHERE pool = 0 AND identity = 0",
DB_INT, DB_BLOB);
} }
} }
return enumerator_create_empty();
return (attr_enumerator ? attr_enumerator : enumerator_create_empty());
} }
/** /**
@@ -361,7 +462,7 @@ sql_attribute_t *sql_attribute_create(database_t *db)
this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))acquire_address; this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *, host_t *))acquire_address;
this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address; this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *, identification_t*))release_address;
this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, identification_t *id, host_t *host))create_attribute_enumerator; this->public.provider.create_attribute_enumerator = (enumerator_t*(*)(attribute_provider_t*, char *names, identification_t *id, host_t *host))create_attribute_enumerator;
this->public.destroy = (void(*)(sql_attribute_t*))destroy; this->public.destroy = (void(*)(sql_attribute_t*))destroy;
this->db = db; this->db = db;
+4 -4
View File
@@ -93,6 +93,7 @@ void modecfg_attribute_destroy(modecfg_attribute_t *this)
static void get_attributes(connection_t *c, linked_list_t *ca_list) static void get_attributes(connection_t *c, linked_list_t *ca_list)
{ {
configuration_attribute_type_t type; configuration_attribute_type_t type;
identification_t *client_id;
modecfg_attribute_t *ca; modecfg_attribute_t *ca;
enumerator_t *enumerator; enumerator_t *enumerator;
chunk_t value; chunk_t value;
@@ -141,14 +142,13 @@ static void get_attributes(connection_t *c, linked_list_t *ca_list)
requested_vip = host_create_any(AF_INET); requested_vip = host_create_any(AF_INET);
} }
client_id = (c->xauth_identity) ? c->xauth_identity : c->spd.that.id;
/* if no virtual IP has been assigned yet - acquire one */ /* if no virtual IP has been assigned yet - acquire one */
if (c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip)) if (c->spd.that.host_srcip->is_anyaddr(c->spd.that.host_srcip))
{ {
if (c->spd.that.pool) if (c->spd.that.pool)
{ {
identification_t *client_id;
client_id = (c->xauth_identity) ? c->xauth_identity : c->spd.that.id;
vip = hydra->attributes->acquire_address(hydra->attributes, vip = hydra->attributes->acquire_address(hydra->attributes,
c->spd.that.pool, client_id, requested_vip); c->spd.that.pool, client_id, requested_vip);
if (vip) if (vip)
@@ -185,7 +185,7 @@ static void get_attributes(connection_t *c, linked_list_t *ca_list)
/* assign attributes from registered providers */ /* assign attributes from registered providers */
enumerator = hydra->attributes->create_responder_enumerator(hydra->attributes, enumerator = hydra->attributes->create_responder_enumerator(hydra->attributes,
c->spd.that.id, vip); c->spd.that.pool, client_id, vip);
while (enumerator->enumerate(enumerator, &type, &value)) while (enumerator->enumerate(enumerator, &type, &value))
{ {
ca = modecfg_attribute_create(type, value); ca = modecfg_attribute_create(type, value);
@@ -183,12 +183,27 @@ CREATE TABLE leases (
released INTEGER NOT NULL released INTEGER NOT NULL
); );
DROP TABLE IF EXISTS attribute_pools;
CREATE TABLE attribute_pools (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
);
DROP TABLE IF EXISTS attributes; DROP TABLE IF EXISTS attributes;
CREATE TABLE attributes ( CREATE TABLE attributes (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
identity INTEGER NOT NULL DEFAULT 0,
pool INTEGER NOT NULL DEFAULT 0,
type INTEGER NOT NULL, type INTEGER NOT NULL,
value BLOB NOT NULL value BLOB NOT NULL
); );
DROP INDEX IF EXISTS attributes_identity;
CREATE INDEX attributes_identity ON attributes (
identity
);
DROP INDEX IF EXISTS attributes_pool;
CREATE INDEX attributes_pool ON attributes (
pool
);
DROP TABLE IF EXISTS ike_sas; DROP TABLE IF EXISTS ike_sas;
CREATE TABLE ike_sas ( CREATE TABLE ike_sas (