diff options
author | Heiko Hund <hhund@astaro.com> | 2010-07-07 16:45:36 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2010-07-09 13:09:31 +0200 |
commit | ec7adea0073a603f1ba40c45a931ec7eadab25d9 (patch) | |
tree | 5c0c319ada5f8f35408f42f4b0ada5fb5aee3a15 /src/libhydra | |
parent | db4ad736becd342c9b9b926801324f5ea5ab20df (diff) | |
download | strongswan-ec7adea0073a603f1ba40c45a931ec7eadab25d9.tar.bz2 strongswan-ec7adea0073a603f1ba40c45a931ec7eadab25d9.tar.xz |
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.
Diffstat (limited to 'src/libhydra')
-rw-r--r-- | src/libhydra/attributes/attribute_manager.c | 11 | ||||
-rw-r--r-- | src/libhydra/attributes/attribute_manager.h | 3 | ||||
-rw-r--r-- | src/libhydra/attributes/attribute_provider.h | 3 | ||||
-rw-r--r-- | src/libhydra/plugins/attr/attr_provider.c | 4 | ||||
-rw-r--r-- | src/libhydra/plugins/attr_sql/pool.c | 51 | ||||
-rw-r--r-- | src/libhydra/plugins/attr_sql/pool_attributes.c | 229 | ||||
-rw-r--r-- | src/libhydra/plugins/attr_sql/pool_attributes.h | 11 | ||||
-rw-r--r-- | src/libhydra/plugins/attr_sql/pool_usage.c | 14 | ||||
-rw-r--r-- | src/libhydra/plugins/attr_sql/sql_attribute.c | 117 |
9 files changed, 355 insertions, 88 deletions
diff --git a/src/libhydra/attributes/attribute_manager.c b/src/libhydra/attributes/attribute_manager.c index 3080b56eb..0d4cbda82 100644 --- a/src/libhydra/attributes/attribute_manager.c +++ b/src/libhydra/attributes/attribute_manager.c @@ -51,6 +51,8 @@ struct private_attribute_manager_t { * Data to pass to enumerator filters */ typedef struct { + /** attribute group pool */ + char *pool; /** server/peer identity */ identification_t *id; /** 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, 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 */ 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); + data->pool = pool; data->id = id; data->vip = vip; 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.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.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; diff --git a/src/libhydra/attributes/attribute_manager.h b/src/libhydra/attributes/attribute_manager.h index 642662366..56afef7c6 100644 --- a/src/libhydra/attributes/attribute_manager.h +++ b/src/libhydra/attributes/attribute_manager.h @@ -61,12 +61,13 @@ struct attribute_manager_t { /** * 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 vip virtual IP to assign to peer, if any * @return enumerator (configuration_attribute_type_t, chunk_t) */ 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. diff --git a/src/libhydra/attributes/attribute_provider.h b/src/libhydra/attributes/attribute_provider.h index f8485cc6c..e4b4e13f3 100644 --- a/src/libhydra/attributes/attribute_provider.h +++ b/src/libhydra/attributes/attribute_provider.h @@ -56,12 +56,13 @@ struct attribute_provider_t { /** * Create an enumerator over attributes to hand out to a peer. * + * @param pool pool name to get attributes from * @param id peer ID * @param vip virtual IP to assign to peer, if any * @return enumerator (configuration_attribute_type_t, chunk_t) */ 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_ @}*/ diff --git a/src/libhydra/plugins/attr/attr_provider.c b/src/libhydra/plugins/attr/attr_provider.c index cd504e03f..b3c0cc076 100644 --- a/src/libhydra/plugins/attr/attr_provider.c +++ b/src/libhydra/plugins/attr/attr_provider.c @@ -65,7 +65,7 @@ static bool attr_enum_filter(void *null, attribute_entry_t **in, * Implementation of attribute_provider_t.create_attribute_enumerator */ 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) { @@ -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.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->attributes = linked_list_create(); diff --git a/src/libhydra/plugins/attr_sql/pool.c b/src/libhydra/plugins/attr_sql/pool.c index e54d7642e..b4bdfc629 100644 --- a/src/libhydra/plugins/attr_sql/pool.c +++ b/src/libhydra/plugins/attr_sql/pool.c @@ -390,29 +390,14 @@ static bool add_address(u_int pool_id, char *address_str, int *family) char *pos_eq = strchr(address_str, '='); if (pos_eq != NULL) { - enumerator_t *e; identification_t *id = identification_create_from_string(pos_eq + 1); + user_id = get_identity(id); + id->destroy(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)) + if (user_id == 0) { - /* 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; - } + return FALSE; } - DESTROY_IF(e); - id->destroy(id); *pos_eq = '\0'; } @@ -943,7 +928,8 @@ static void cleanup(void) 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; int timeout = 0; bool utc = FALSE, hexout = FALSE; @@ -1000,6 +986,8 @@ static void do_args(int argc, char *argv[]) { "string", required_argument, NULL, 'g' }, { "hex", required_argument, NULL, 'x' }, { "hexout", no_argument, NULL, '5' }, + { "pool", required_argument, NULL, '6' }, + { "identity", required_argument, NULL, '7' }, { 0,0,0,0 } }; @@ -1122,6 +1110,12 @@ static void do_args(int argc, char *argv[]) case '5': hexout = TRUE; continue; + case '6': + pool = optarg; + continue; + case '7': + identity = optarg; + continue; default: usage(); exit(EXIT_FAILURE); @@ -1164,14 +1158,25 @@ static void do_args(int argc, char *argv[]) usage(); 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; case OP_DEL: del(name); break; case OP_DEL_ATTR: - - del_attr(name, value, value_type); + if (identity && !pool) + { + fprintf(stderr, "--identity option can't be used without --pool.\n"); + usage(); + exit(EXIT_FAILURE); + } + del_attr(name, pool, identity, value, value_type); break; case OP_SHOW_ATTR: show_attr(); diff --git a/src/libhydra/plugins/attr_sql/pool_attributes.c b/src/libhydra/plugins/attr_sql/pool_attributes.c index 0ef1b4a26..52efc6310 100644 --- a/src/libhydra/plugins/attr_sql/pool_attributes.c +++ b/src/libhydra/plugins/attr_sql/pool_attributes.c @@ -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; + u_int pool_id = 0, identity_id = 0; + char id_pool_str[128] = ""; chunk_t blob; 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) { fprintf(stderr, "the value of the %s attribute is missing.\n", name); usage(); - exit(EXIT_FAILURE); - } + } if (!parse_attributes(name, value, &value_type, &type, &type_ip6, &blob)) { exit(EXIT_FAILURE); } 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; free(blob.ptr); if (success) { - printf("added %s attribute (%N).\n", name, - configuration_attribute_type_names, type); + printf("added %s attribute (%N)%s.\n", name, + configuration_attribute_type_names, type, id_pool_str); } else { - fprintf(stderr, "adding %s attribute (%N) failed.\n", name, - configuration_attribute_type_names, type); - exit(EXIT_FAILURE); + fprintf(stderr, "adding %s attribute (%N)%s failed.\n", name, + configuration_attribute_type_names, type, id_pool_str); } } /** - * 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; + u_int pool_id = 0, identity_id = 0; + char id_pool_str[128] = ""; chunk_t blob, blob_db; u_int id; enumerator_t *query; 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)) { exit(EXIT_FAILURE); @@ -321,31 +432,31 @@ void del_attr(char *name, char *value, value_type_t value_type) { query = db->query(db, "SELECT id, type, value FROM attributes " - "WHERE type = ? AND value = ?", - DB_INT, type, DB_BLOB, blob, - DB_UINT, DB_INT, DB_BLOB); + "WHERE identity = ? AND pool = ? AND type = ? AND value = ?", + DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type, + DB_BLOB, blob, DB_UINT, DB_INT, DB_BLOB); } else if (type_ip6 == 0) { query = db->query(db, "SELECT id, type, value FROM attributes " - "WHERE type = ?", - DB_INT, type, + "WHERE identity = ? AND pool = ? AND type = ?", + DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type, DB_UINT, DB_INT, DB_BLOB); } else { query = db->query(db, "SELECT id, type, value FROM attributes " - "WHERE type = ? OR type = ?", - DB_INT, type, DB_INT, type_ip6, - DB_UINT, DB_INT, DB_BLOB); + "WHERE identity = ? AND pool = ? AND (type = ? OR type = ?)", + DB_UINT, identity_id, DB_UINT, pool_id, DB_INT, type, + DB_INT, type_ip6, DB_UINT, DB_INT, DB_BLOB); } if (!query) { - fprintf(stderr, "deleting '%s' attribute (%N) failed.\n", - name, configuration_attribute_type_names, type); + fprintf(stderr, "deleting '%s' attribute (%N)%s failed.\n", + name, configuration_attribute_type_names, type, id_pool_str); free(blob.ptr); exit(EXIT_FAILURE); } @@ -369,21 +480,22 @@ void del_attr(char *name, char *value, value_type_t value_type) { 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); } 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, - blob_db.len, blob_db.ptr); + blob_db.len, blob_db.ptr, id_pool_str); } 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, - &blob_db); + &blob_db, id_pool_str); } query->destroy(query); free(blob.ptr); @@ -391,20 +503,20 @@ void del_attr(char *name, char *value, value_type_t value_type) } 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); } 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, - blob_db.len, blob_db.ptr); + blob_db.len, blob_db.ptr, id_pool_str); } 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, - &blob_db); + &blob_db, id_pool_str); } } query->destroy(query); @@ -415,12 +527,13 @@ void del_attr(char *name, char *value, value_type_t value_type) { if (type_ip6 == 0) { - fprintf(stderr, "no %s attribute (%N) was found.\n", name, - configuration_attribute_type_names, type); + fprintf(stderr, "no %s attribute (%N) was found%s.\n", name, + configuration_attribute_type_names, type, id_pool_str); } else { - fprintf(stderr, "no %s attribute was found.\n", name); + fprintf(stderr, "no %s attribute%s was found.\n", + name, id_pool_str); } } 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); - fprintf(stderr, "the %s server %H was not found.\n", name, - server); + fprintf(stderr, "the %s server %H%s was not found.\n", name, + server, id_pool_str); server->destroy(server); } 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, 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; 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; host_t *addr, *mask; char type_name[30]; bool first = TRUE; - int i; + int i, identity_type; + char *pool_name; /* enumerate over all attributes */ - enumerator = db->query(db, "SELECT type, value FROM attributes ORDER BY type", - DB_INT, DB_BLOB); + enumerator = db->query(db, + "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) { - while (enumerator->enumerate(enumerator, &type, &value)) + while (enumerator->enumerate(enumerator, &identity_type, + &identity_chunk, &pool_name, &type, &value)) { if (first) { - printf(" type description value\n"); + printf(" type description pool " + " identity value\n"); first = FALSE; } snprintf(type_name, sizeof(type_name), "%N", @@ -479,6 +605,19 @@ void status_attr(bool hexout) } 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; if (!hexout) { diff --git a/src/libhydra/plugins/attr_sql/pool_attributes.h b/src/libhydra/plugins/attr_sql/pool_attributes.h index 04cfbf948..a42291f57 100644 --- a/src/libhydra/plugins/attr_sql/pool_attributes.h +++ b/src/libhydra/plugins/attr_sql/pool_attributes.h @@ -34,14 +34,21 @@ enum value_type_t { 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 */ -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 */ -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 diff --git a/src/libhydra/plugins/attr_sql/pool_usage.c b/src/libhydra/plugins/attr_sql/pool_usage.c index b28c8ae15..985bc3ae8 100644 --- a/src/libhydra/plugins/attr_sql/pool_usage.c +++ b/src/libhydra/plugins/attr_sql/pool_usage.c @@ -59,9 +59,14 @@ Usage:\n\ resized.\n\ timeout: Lease time in hours, 0 for static leases\n\ \n\ - ipsec pool --addattr <type> --addr|--mask|--server|--subnet|--string|--hex <value>\n\ - Add a new attribute to the database.\n\ + ipsec pool --addattr <type> [--pool <name> [--identity <id>]]\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\ + 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\ mask: IPv4 or IPv6 netmask (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\ name: Name of the pool to delete\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\ 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\ mask: IPv4 or IPv6 netmask (synonym for --addr)\n\ server: IPv4 or IPv6 address of a server (synonym for --addr)\n\ diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.c b/src/libhydra/plugins/attr_sql/sql_attribute.c index a7cfde649..7f7bb190c 100644 --- a/src/libhydra/plugins/attr_sql/sql_attribute.c +++ b/src/libhydra/plugins/attr_sql/sql_attribute.c @@ -74,6 +74,26 @@ static u_int get_identity(private_sql_attribute_t *this, identification_t *id) } /** + * 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 */ static u_int get_pool(private_sql_attribute_t *this, char *name, u_int *timeout) @@ -327,20 +347,101 @@ static bool release_address(private_sql_attribute_t *this, * Implementation of sql_attribute_t.create_attribute_enumerator */ 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) { - enumerator_t *enumerator; + enumerator_t *names_enumerator; + u_int count; + char *name; - enumerator = this->db->query(this->db, - "SELECT type, value FROM attributes", DB_INT, DB_BLOB); - if (enumerator) + this->db->execute(this->db, NULL, "BEGIN EXCLUSIVE TRANSACTION"); + + /* 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.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->db = db; |