diff options
-rw-r--r-- | src/libcharon/plugins/vici/vici_config.c | 104 | ||||
-rw-r--r-- | src/swanctl/swanctl.opt | 10 |
2 files changed, 74 insertions, 40 deletions
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c index 181b14b40..6cf127b74 100644 --- a/src/libcharon/plugins/vici/vici_config.c +++ b/src/libcharon/plugins/vici/vici_config.c @@ -2,6 +2,7 @@ * Copyright (C) 2014 Martin Willi * Copyright (C) 2014 revosec AG * + * Copyright (C) 2015-2016 Tobias Brunner * Copyright (C) 2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * @@ -225,6 +226,24 @@ typedef struct { } request_data_t; /** + * Auth config data + */ +typedef struct { + request_data_t *request; + auth_cfg_t *cfg; + u_int32_t round; +} auth_data_t; + +/** + * Clean up auth config data + */ +static void free_auth_data(auth_data_t *data) +{ + DESTROY_IF(data->cfg); + free(data); +} + +/** * Data associated to a peer config */ typedef struct { @@ -318,7 +337,7 @@ static void log_auth(auth_cfg_t *auth) static void log_peer_data(peer_data_t *data) { enumerator_t *enumerator; - auth_cfg_t *auth; + auth_data_t *auth; host_t *host; DBG2(DBG_CFG, " version = %u", data->version); @@ -357,7 +376,7 @@ static void log_peer_data(peer_data_t *data) while (enumerator->enumerate(enumerator, &auth)) { DBG2(DBG_CFG, " local:"); - log_auth(auth); + log_auth(auth->cfg); } enumerator->destroy(enumerator); @@ -365,7 +384,7 @@ static void log_peer_data(peer_data_t *data) while (enumerator->enumerate(enumerator, &auth)) { DBG2(DBG_CFG, " remote:"); - log_auth(auth); + log_auth(auth->cfg); } enumerator->destroy(enumerator); } @@ -375,10 +394,8 @@ static void log_peer_data(peer_data_t *data) */ static void free_peer_data(peer_data_t *data) { - data->local->destroy_offset(data->local, - offsetof(auth_cfg_t, destroy)); - data->remote->destroy_offset(data->remote, - offsetof(auth_cfg_t, destroy)); + data->local->destroy_function(data->local, (void*)free_auth_data); + data->remote->destroy_function(data->remote, (void*)free_auth_data); data->children->destroy_offset(data->children, offsetof(child_cfg_t, destroy)); data->proposals->destroy_offset(data->proposals, @@ -468,14 +485,6 @@ static void free_child_data(child_data_t *data) } /** - * Auth config data - */ -typedef struct { - request_data_t *request; - auth_cfg_t *cfg; -} auth_data_t; - -/** * Common proposal parsing */ static bool parse_proposal(linked_list_t *list, protocol_id_t proto, chunk_t v) @@ -1344,6 +1353,7 @@ CALLBACK(auth_kv, bool, { "eap_id", parse_eap_id, auth->cfg }, { "xauth_id", parse_xauth_id, auth->cfg }, { "revocation", parse_revocation, auth->cfg }, + { "round", parse_uint32, &auth->round }, }; return parse_rules(rules, countof(rules), name, value, @@ -1547,25 +1557,28 @@ CALLBACK(peer_sn, bool, if (strcasepfx(name, "local") || strcasepfx(name, "remote")) { - auth_data_t auth = { - .request = peer->request, - .cfg = auth_cfg_create(), - }; + enumerator_t *enumerator; + linked_list_t *auths; + auth_data_t *auth, *current; auth_rule_t rule; certificate_t *cert; pubkey_cert_t *pubkey_cert; identification_t *id; - enumerator_t *enumerator; bool default_id = FALSE; - if (!message->parse(message, ctx, NULL, auth_kv, auth_li, &auth)) + INIT(auth, + .request = peer->request, + .cfg = auth_cfg_create(), + ); + + if (!message->parse(message, ctx, NULL, auth_kv, auth_li, auth)) { - auth.cfg->destroy(auth.cfg); + free_auth_data(auth); return FALSE; } - id = auth.cfg->get(auth.cfg, AUTH_RULE_IDENTITY); + id = auth->cfg->get(auth->cfg, AUTH_RULE_IDENTITY); - enumerator = auth.cfg->create_enumerator(auth.cfg); + enumerator = auth->cfg->create_enumerator(auth->cfg); while (enumerator->enumerate(enumerator, &rule, &cert)) { if (rule == AUTH_RULE_SUBJECT_CERT && !default_id) @@ -1575,7 +1588,7 @@ CALLBACK(peer_sn, bool, id = cert->get_subject(cert); DBG1(DBG_CFG, " id not specified, defaulting to" " cert subject '%Y'", id); - auth.cfg->add(auth.cfg, AUTH_RULE_IDENTITY, id->clone(id)); + auth->cfg->add(auth->cfg, AUTH_RULE_IDENTITY, id->clone(id)); default_id = TRUE; } else if (cert->get_type(cert) == CERT_TRUSTED_PUBKEY && @@ -1589,14 +1602,17 @@ CALLBACK(peer_sn, bool, } enumerator->destroy(enumerator); - if (strcasepfx(name, "local")) + auths = strcasepfx(name, "local") ? peer->local : peer->remote; + enumerator = auths->create_enumerator(auths); + while (enumerator->enumerate(enumerator, ¤t)) { - peer->local->insert_last(peer->local, auth.cfg); - } - else - { - peer->remote->insert_last(peer->remote, auth.cfg); + if (auth->round < current->round) + { + break; + } } + auths->insert_before(auths, enumerator, auth); + enumerator->destroy(enumerator); return TRUE; } peer->request->reply = create_reply("invalid section: %s", name); @@ -1932,7 +1948,7 @@ CALLBACK(config_sn, bool, peer_cfg_t *peer_cfg; ike_cfg_t *ike_cfg; child_cfg_t *child_cfg; - auth_cfg_t *auth_cfg; + auth_data_t *auth; proposal_t *proposal; host_t *host; char *str; @@ -1947,13 +1963,17 @@ CALLBACK(config_sn, bool, if (peer.local->get_count(peer.local) == 0) { - auth_cfg = auth_cfg_create(); - peer.local->insert_last(peer.local, auth_cfg); + INIT(auth, + .cfg = auth_cfg_create(), + ); + peer.local->insert_last(peer.local, auth); } if (peer.remote->get_count(peer.remote) == 0) { - auth_cfg = auth_cfg_create(); - peer.remote->insert_last(peer.remote, auth_cfg); + INIT(auth, + .cfg = auth_cfg_create(), + ); + peer.remote->insert_last(peer.remote, auth); } if (peer.proposals->get_count(peer.proposals) == 0) { @@ -2029,14 +2049,18 @@ CALLBACK(config_sn, bool, FALSE, NULL, NULL); while (peer.local->remove_first(peer.local, - (void**)&auth_cfg) == SUCCESS) + (void**)&auth) == SUCCESS) { - peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE); + peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, TRUE); + auth->cfg = NULL; + free_auth_data(auth); } while (peer.remote->remove_first(peer.remote, - (void**)&auth_cfg) == SUCCESS) + (void**)&auth) == SUCCESS) { - peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE); + peer_cfg->add_auth_cfg(peer_cfg, auth->cfg, FALSE); + auth->cfg = NULL; + free_auth_data(auth); } while (peer.children->remove_first(peer.children, (void**)&child_cfg) == SUCCESS) diff --git a/src/swanctl/swanctl.opt b/src/swanctl/swanctl.opt index b053fe32a..145fab28d 100644 --- a/src/swanctl/swanctl.opt +++ b/src/swanctl/swanctl.opt @@ -268,6 +268,11 @@ connections.<conn>.local<suffix> {} unique suffix. To define a single authentication round, the suffix may be omitted. +connections.<conn>.local<suffix>.round = 0 + Optional numeric identifier by which authentication rounds are sorted. If + not specified rounds are ordered by their position in the config file/VICI + message. + connections.<conn>.local<suffix>.certs = Comma separated list of certificate candidates to use for authentication. @@ -374,6 +379,11 @@ connections.<conn>.remote<suffix> {} optional unique suffix. To define a single authentication round, the suffix may be omitted. +connections.<conn>.remote<suffix>.round = 0 + Optional numeric identifier by which authentication rounds are sorted. If + not specified rounds are ordered by their position in the config file/VICI + message. + connections.<conn>.remote<suffix>.id = %any IKE identity to expect for authentication round. |