diff options
Diffstat (limited to 'src/libcharon/config')
-rw-r--r-- | src/libcharon/config/backend.h | 2 | ||||
-rw-r--r-- | src/libcharon/config/backend_manager.c | 69 | ||||
-rw-r--r-- | src/libcharon/config/backend_manager.h | 5 | ||||
-rw-r--r-- | src/libcharon/config/child_cfg.c | 4 | ||||
-rw-r--r-- | src/libcharon/config/ike_cfg.c | 39 | ||||
-rw-r--r-- | src/libcharon/config/ike_cfg.h | 59 | ||||
-rw-r--r-- | src/libcharon/config/peer_cfg.c | 21 | ||||
-rw-r--r-- | src/libcharon/config/peer_cfg.h | 23 | ||||
-rw-r--r-- | src/libcharon/config/proposal.c | 91 | ||||
-rw-r--r-- | src/libcharon/config/proposal.h | 8 |
10 files changed, 194 insertions, 127 deletions
diff --git a/src/libcharon/config/backend.h b/src/libcharon/config/backend.h index 458abc37f..aca3352ba 100644 --- a/src/libcharon/config/backend.h +++ b/src/libcharon/config/backend.h @@ -26,7 +26,7 @@ typedef struct backend_t backend_t; #include <library.h> #include <config/ike_cfg.h> #include <config/peer_cfg.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> /** * The interface for a configuration backend. diff --git a/src/libcharon/config/backend_manager.c b/src/libcharon/config/backend_manager.c index 09e123e67..f47d5715a 100644 --- a/src/libcharon/config/backend_manager.c +++ b/src/libcharon/config/backend_manager.c @@ -18,7 +18,7 @@ #include <sys/types.h> #include <daemon.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <threading/rwlock.h> @@ -49,10 +49,16 @@ struct private_backend_manager_t { * match of an ike_cfg */ typedef enum ike_cfg_match_t { - MATCH_NONE = 0x00, - MATCH_ANY = 0x01, - MATCH_ME = 0x04, - MATCH_OTHER = 0x08, + /* doesn't match at all */ + MATCH_NONE = 0x00, + /* match for a %any host. For both hosts, hence skip 0x02 */ + MATCH_ANY = 0x01, + /* IKE version matches exactly (config is not for any version) */ + MATCH_VERSION = 0x04, + /* local identity matches */ + MATCH_ME = 0x08, + /* remote identity matches */ + MATCH_OTHER = 0x10, } ike_cfg_match_t; /** @@ -75,13 +81,20 @@ static enumerator_t *ike_enum_create(backend_t *backend, ike_data_t *data) /** * get a match of a candidate ike_cfg for two hosts */ -static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) +static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other, + ike_version_t version) { host_t *me_cand, *other_cand; char *my_addr, *other_addr; bool my_allow_any, other_allow_any; ike_cfg_match_t match = MATCH_NONE; + if (cand->get_version(cand) != IKE_ANY && + version != cand->get_version(cand)) + { + return MATCH_NONE; + } + if (me) { my_addr = cand->get_my_addr(cand, &my_allow_any); @@ -137,11 +150,18 @@ static ike_cfg_match_t get_ike_match(ike_cfg_t *cand, host_t *me, host_t *other) { match += MATCH_ANY; } + + if (match != MATCH_NONE && + cand->get_version(cand) != IKE_ANY) + { /* if we have a match, improve it if candidate version specified */ + match += MATCH_VERSION; + } return match; } METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*, - private_backend_manager_t *this, host_t *me, host_t *other) + private_backend_manager_t *this, host_t *me, host_t *other, + ike_version_t version) { ike_cfg_t *current, *found = NULL; char *my_addr, *other_addr; @@ -164,8 +184,9 @@ METHOD(backend_manager_t, get_ike_cfg, ike_cfg_t*, (void*)ike_enum_create, data, (void*)free); while (enumerator->enumerate(enumerator, (void**)¤t)) { - match = get_ike_match(current, me, other); - DBG3(DBG_CFG, "ike config match: %d (%H %H)", match, me, other); + match = get_ike_match(current, me, other, version); + DBG3(DBG_CFG, "ike config match: %d (%H %H %N)", + match, me, other, ike_version_names, version); if (match) { my_addr = current->get_my_addr(current, &my_allow_any); @@ -243,22 +264,6 @@ static id_match_t get_peer_match(identification_t *id, } /** - * Get match quality of IKE version - */ -static int get_version_match(ike_version_t cfg, ike_version_t req) -{ - if (req == IKE_ANY || cfg == IKE_ANY) - { - return 1; - } - if (req == cfg) - { - return 2; - } - return 0; -} - -/** * data to pass nested peer enumerator */ typedef struct { @@ -382,20 +387,18 @@ METHOD(backend_manager_t, create_peer_cfg_enumerator, enumerator_t*, { id_match_t match_peer_me, match_peer_other; ike_cfg_match_t match_ike; - int match_version; match_entry_t *entry; match_peer_me = get_peer_match(my_id, cfg, TRUE); match_peer_other = get_peer_match(other_id, cfg, FALSE); - match_ike = get_ike_match(cfg->get_ike_cfg(cfg), me, other); - match_version = get_version_match(cfg->get_ike_version(cfg), version); - DBG3(DBG_CFG, "ike config match: %d (%H %H)", match_ike, me, other); + match_ike = get_ike_match(cfg->get_ike_cfg(cfg), me, other, version); + DBG3(DBG_CFG, "ike config match: %d (%H %H %N)", + match_ike, me, other, ike_version_names, version); - if (match_peer_me && match_peer_other && match_ike && match_version) + if (match_peer_me && match_peer_other && match_ike) { - DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d/%d " - "(me/other/ike/version)", cfg->get_name(cfg), - match_peer_me, match_peer_other, match_ike, match_version); + DBG2(DBG_CFG, " candidate \"%s\", match: %d/%d/%d (me/other/ike)", + cfg->get_name(cfg), match_peer_me, match_peer_other, match_ike); INIT(entry, .match_peer = match_peer_me + match_peer_other, diff --git a/src/libcharon/config/backend_manager.h b/src/libcharon/config/backend_manager.h index de263365b..cc8ef8785 100644 --- a/src/libcharon/config/backend_manager.h +++ b/src/libcharon/config/backend_manager.h @@ -24,7 +24,7 @@ typedef struct backend_manager_t backend_manager_t; #include <library.h> -#include <utils/host.h> +#include <networking/host.h> #include <utils/identification.h> #include <config/ike_cfg.h> #include <config/peer_cfg.h> @@ -60,7 +60,8 @@ struct backend_manager_t { * @return matching ike_config, or NULL if none found */ ike_cfg_t* (*get_ike_cfg)(backend_manager_t *this, - host_t *my_host, host_t *other_host); + host_t *my_host, host_t *other_host, + ike_version_t version); /** * Get a peer_config identified by it's name. diff --git a/src/libcharon/config/child_cfg.c b/src/libcharon/config/child_cfg.c index b675c908f..33d47a41e 100644 --- a/src/libcharon/config/child_cfg.c +++ b/src/libcharon/config/child_cfg.c @@ -165,7 +165,7 @@ METHOD(child_cfg_t, get_proposals, linked_list_t*, current = current->clone(current); if (strip_dh) { - current->strip_dh(current); + current->strip_dh(current, MODP_NONE); } proposals->insert_last(proposals, current); } @@ -194,7 +194,7 @@ METHOD(child_cfg_t, select_proposal, proposal_t*, { if (strip_dh) { - stored->strip_dh(stored); + stored->strip_dh(stored, MODP_NONE); } selected = stored->select(stored, supplied, private); if (selected) diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c index acf4b6141..5e5fbba42 100644 --- a/src/libcharon/config/ike_cfg.c +++ b/src/libcharon/config/ike_cfg.c @@ -21,6 +21,12 @@ #include <daemon.h> +ENUM(ike_version_names, IKE_ANY, IKEV2, + "IKEv1/2", + "IKEv1", + "IKEv2", +); + typedef struct private_ike_cfg_t private_ike_cfg_t; /** @@ -39,6 +45,11 @@ struct private_ike_cfg_t { refcount_t refcount; /** + * IKE version to use + */ + ike_version_t version; + + /** * Address of local host */ char *me; @@ -79,11 +90,22 @@ struct private_ike_cfg_t { bool force_encap; /** + * use IKEv1 fragmentation + */ + fragmentation_t fragmentation; + + /** * List of proposals to use */ linked_list_t *proposals; }; +METHOD(ike_cfg_t, get_version, ike_version_t, + private_ike_cfg_t *this) +{ + return this->version; +} + METHOD(ike_cfg_t, send_certreq, bool, private_ike_cfg_t *this) { @@ -96,6 +118,12 @@ METHOD(ike_cfg_t, force_encap_, bool, return this->force_encap; } +METHOD(ike_cfg_t, fragmentation, fragmentation_t, + private_ike_cfg_t *this) +{ + return this->fragmentation; +} + METHOD(ike_cfg_t, get_my_addr, char*, private_ike_cfg_t *this, bool *allow_any) { @@ -248,8 +276,10 @@ METHOD(ike_cfg_t, equals, bool, e2->destroy(e2); return (eq && + this->version == other->version && this->certreq == other->certreq && this->force_encap == other->force_encap && + this->fragmentation == other->fragmentation && streq(this->me, other->me) && streq(this->other, other->other) && this->my_port == other->my_port && @@ -279,16 +309,19 @@ METHOD(ike_cfg_t, destroy, void, /** * Described in header. */ -ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, +ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap, char *me, bool my_allow_any, u_int16_t my_port, - char *other, bool other_allow_any, u_int16_t other_port) + char *other, bool other_allow_any, u_int16_t other_port, + fragmentation_t fragmentation) { private_ike_cfg_t *this; INIT(this, .public = { + .get_version = _get_version, .send_certreq = _send_certreq, .force_encap = _force_encap_, + .fragmentation = _fragmentation, .get_my_addr = _get_my_addr, .get_other_addr = _get_other_addr, .get_my_port = _get_my_port, @@ -302,8 +335,10 @@ ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, .destroy = _destroy, }, .refcount = 1, + .version = version, .certreq = certreq, .force_encap = force_encap, + .fragmentation = fragmentation, .me = strdup(me), .other = strdup(other), .my_allow_any = my_allow_any, diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h index 691d223a3..5a7fae1e9 100644 --- a/src/libcharon/config/ike_cfg.h +++ b/src/libcharon/config/ike_cfg.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2012 Tobias Brunner * Copyright (C) 2005-2007 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -22,16 +23,47 @@ #ifndef IKE_CFG_H_ #define IKE_CFG_H_ +typedef enum ike_version_t ike_version_t; +typedef enum fragmentation_t fragmentation_t; typedef struct ike_cfg_t ike_cfg_t; #include <library.h> -#include <utils/host.h> -#include <utils/linked_list.h> +#include <networking/host.h> +#include <collections/linked_list.h> #include <utils/identification.h> #include <config/proposal.h> #include <crypto/diffie_hellman.h> /** + * IKE version. + */ +enum ike_version_t { + /** any version */ + IKE_ANY = 0, + /** IKE version 1 */ + IKEV1 = 1, + /** IKE version 2 */ + IKEV2 = 2, +}; + +/** + * Proprietary IKEv1 fragmentation + */ +enum fragmentation_t { + /** disable fragmentation */ + FRAGMENTATION_NO, + /** enable fragmentation if supported by peer */ + FRAGMENTATION_YES, + /** force use of fragmentation (even for the first message) */ + FRAGMENTATION_FORCE, +}; + +/** + * enum strings fro ike_version_t + */ +extern enum_name_t *ike_version_names; + +/** * An ike_cfg_t defines the rules to set up an IKE_SA. * * @see peer_cfg_t to get an overview over the configurations. @@ -39,6 +71,13 @@ typedef struct ike_cfg_t ike_cfg_t; struct ike_cfg_t { /** + * Get the IKE version to use with this configuration. + * + * @return IKE major version + */ + ike_version_t (*get_version)(ike_cfg_t *this); + + /** * Get own address. * * @param allow_any allow any address to match @@ -109,11 +148,18 @@ struct ike_cfg_t { /** * Enforce UDP encapsulation by faking NATD notifies? * - * @return TRUE to enfoce UDP encapsulation + * @return TRUE to enforce UDP encapsulation */ bool (*force_encap) (ike_cfg_t *this); /** + * Use proprietary IKEv1 fragmentation + * + * @return TRUE to use fragmentation + */ + fragmentation_t (*fragmentation) (ike_cfg_t *this); + + /** * Get the DH group to use for IKE_SA setup. * * @return dh group to use for initialization @@ -149,6 +195,7 @@ struct ike_cfg_t { * * Supplied hosts become owned by ike_cfg, the name gets cloned. * + * @param version IKE major version to use for this config * @param certreq TRUE to send a certificate request * @param force_encap enforce UDP encapsulation by faking NATD notify * @param me address/DNS name of local peer @@ -157,10 +204,12 @@ struct ike_cfg_t { * @param other address/DNS name of remote peer * @param other_allow_any allow override of remote address by any address * @param other_port IKE port to use as dest, 500 uses IKEv2 port floating + * @param fragmentation use IKEv1 fragmentation * @return ike_cfg_t object. */ -ike_cfg_t *ike_cfg_create(bool certreq, bool force_encap, +ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap, char *me, bool my_allow_any, u_int16_t my_port, - char *other, bool other_allow_any, u_int16_t other_port); + char *other, bool other_allow_any, u_int16_t other_port, + fragmentation_t fragmentation); #endif /** IKE_CFG_H_ @}*/ diff --git a/src/libcharon/config/peer_cfg.c b/src/libcharon/config/peer_cfg.c index 01ca026e1..8de7d1289 100644 --- a/src/libcharon/config/peer_cfg.c +++ b/src/libcharon/config/peer_cfg.c @@ -22,15 +22,9 @@ #include <daemon.h> #include <threading/mutex.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <utils/identification.h> -ENUM(ike_version_names, IKE_ANY, IKEV2, - "IKEv1/2", - "IKEv1", - "IKEv2", -); - ENUM(cert_policy_names, CERT_ALWAYS_SEND, CERT_NEVER_SEND, "CERT_ALWAYS_SEND", "CERT_SEND_IF_ASKED", @@ -66,11 +60,6 @@ struct private_peer_cfg_t { char *name; /** - * IKE version to use for initiation - */ - ike_version_t ike_version; - - /** * IKE config associated to this peer config */ ike_cfg_t *ike_cfg; @@ -188,7 +177,7 @@ METHOD(peer_cfg_t, get_name, char*, METHOD(peer_cfg_t, get_ike_version, ike_version_t, private_peer_cfg_t *this) { - return this->ike_version; + return this->ike_cfg->get_version(this->ike_cfg); } METHOD(peer_cfg_t, get_ike_cfg, ike_cfg_t*, @@ -584,7 +573,7 @@ METHOD(peer_cfg_t, equals, bool, e2->destroy(e2); return ( - this->ike_version == other->ike_version && + get_ike_version(this) == get_ike_version(other) && this->cert_policy == other->cert_policy && this->unique == other->unique && this->keyingtries == other->keyingtries && @@ -594,6 +583,7 @@ METHOD(peer_cfg_t, equals, bool, this->jitter_time == other->jitter_time && this->over_time == other->over_time && this->dpd == other->dpd && + this->aggressive == other->aggressive && auth_cfg_equal(this, other) #ifdef ME && this->mediation == other->mediation && @@ -639,7 +629,7 @@ METHOD(peer_cfg_t, destroy, void, /* * Described in header-file */ -peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version, +peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg, cert_policy_t cert_policy, unique_policy_t unique, u_int32_t keyingtries, u_int32_t rekey_time, u_int32_t reauth_time, @@ -695,7 +685,6 @@ peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version, #endif /* ME */ }, .name = strdup(name), - .ike_version = ike_version, .ike_cfg = ike_cfg, .child_cfgs = linked_list_create(), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), diff --git a/src/libcharon/config/peer_cfg.h b/src/libcharon/config/peer_cfg.h index 97089e1b0..80913beba 100644 --- a/src/libcharon/config/peer_cfg.h +++ b/src/libcharon/config/peer_cfg.h @@ -23,14 +23,13 @@ #ifndef PEER_CFG_H_ #define PEER_CFG_H_ -typedef enum ike_version_t ike_version_t; typedef enum cert_policy_t cert_policy_t; typedef enum unique_policy_t unique_policy_t; typedef struct peer_cfg_t peer_cfg_t; #include <library.h> #include <utils/identification.h> -#include <utils/enumerator.h> +#include <collections/enumerator.h> #include <selectors/traffic_selector.h> #include <config/proposal.h> #include <config/ike_cfg.h> @@ -38,23 +37,6 @@ typedef struct peer_cfg_t peer_cfg_t; #include <credentials/auth_cfg.h> /** - * IKE version. - */ -enum ike_version_t { - /** any version */ - IKE_ANY = 0, - /** IKE version 1 */ - IKEV1 = 1, - /** IKE version 2 */ - IKEV2 = 2, -}; - -/** - * enum strings fro ike_version_t - */ -extern enum_name_t *ike_version_names; - -/** * Certificate sending policy. This is also used for certificate * requests when using this definition for the other peer. If * it is CERT_NEVER_SEND, a certreq is omitted, otherwise its @@ -374,7 +356,6 @@ struct peer_cfg_t { * (rekeylifetime - random(0, jitter)). * * @param name name of the peer_cfg - * @param ike_version which IKE version we should use for this peer * @param ike_cfg IKE config to use when acting as initiator * @param cert_policy should we send a certificate payload? * @param unique uniqueness of an IKE_SA @@ -392,7 +373,7 @@ struct peer_cfg_t { * @param peer_id ID that identifies our peer at the mediation server * @return peer_cfg_t object */ -peer_cfg_t *peer_cfg_create(char *name, ike_version_t ike_version, +peer_cfg_t *peer_cfg_create(char *name, ike_cfg_t *ike_cfg, cert_policy_t cert_policy, unique_policy_t unique, u_int32_t keyingtries, u_int32_t rekey_time, u_int32_t reauth_time, diff --git a/src/libcharon/config/proposal.c b/src/libcharon/config/proposal.c index 43b467f46..4803c7be2 100644 --- a/src/libcharon/config/proposal.c +++ b/src/libcharon/config/proposal.c @@ -19,7 +19,7 @@ #include "proposal.h" #include <daemon.h> -#include <utils/linked_list.h> +#include <collections/linked_list.h> #include <utils/identification.h> #include <crypto/transform.h> @@ -232,14 +232,21 @@ METHOD(proposal_t, has_dh_group, bool, } METHOD(proposal_t, strip_dh, void, - private_proposal_t *this) + private_proposal_t *this, diffie_hellman_group_t keep) { + enumerator_t *enumerator; algorithm_t *alg; - while (this->dh_groups->remove_last(this->dh_groups, (void**)&alg) == SUCCESS) + enumerator = this->dh_groups->create_enumerator(this->dh_groups); + while (enumerator->enumerate(enumerator, (void**)&alg)) { - free(alg); + if (alg->algorithm != keep) + { + this->dh_groups->remove_at(this->dh_groups, enumerator); + free(alg); + } } + enumerator->destroy(enumerator); } /** @@ -515,6 +522,23 @@ METHOD(proposal_t, clone_, proposal_t*, } /** + * Map integrity algorithms to the PRF functions using the same algorithm. + */ +static const struct { + integrity_algorithm_t integ; + pseudo_random_function_t prf; +} integ_prf_map[] = { + {AUTH_HMAC_SHA1_96, PRF_HMAC_SHA1 }, + {AUTH_HMAC_SHA2_256_128, PRF_HMAC_SHA2_256 }, + {AUTH_HMAC_SHA2_384_192, PRF_HMAC_SHA2_384 }, + {AUTH_HMAC_SHA2_512_256, PRF_HMAC_SHA2_512 }, + {AUTH_HMAC_MD5_96, PRF_HMAC_MD5 }, + {AUTH_AES_XCBC_96, PRF_AES128_XCBC }, + {AUTH_CAMELLIA_XCBC_96, PRF_CAMELLIA128_XCBC }, + {AUTH_AES_CMAC_96, PRF_AES128_CMAC }, +}; + +/** * Checks the proposal read from a string. */ static void check_proposal(private_proposal_t *this) @@ -522,6 +546,27 @@ static void check_proposal(private_proposal_t *this) enumerator_t *e; algorithm_t *alg; bool all_aead = TRUE; + int i; + + if (this->protocol == PROTO_IKE && + this->prf_algos->get_count(this->prf_algos) == 0) + { /* No explicit PRF found. We assume the same algorithm as used + * for integrity checking */ + e = this->integrity_algos->create_enumerator(this->integrity_algos); + while (e->enumerate(e, &alg)) + { + for (i = 0; i < countof(integ_prf_map); i++) + { + if (alg->algorithm == integ_prf_map[i].integ) + { + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, + integ_prf_map[i].prf, 0); + break; + } + } + } + e->destroy(e); + } e = this->encryption_algos->create_enumerator(this->encryption_algos); while (e->enumerate(e, &alg)) @@ -572,44 +617,6 @@ static bool add_string_algo(private_proposal_t *this, const char *alg) add_algorithm(this, token->type, token->algorithm, token->keysize); - if (this->protocol == PROTO_IKE && token->type == INTEGRITY_ALGORITHM) - { - pseudo_random_function_t prf; - - switch (token->algorithm) - { - case AUTH_HMAC_SHA1_96: - prf = PRF_HMAC_SHA1; - break; - case AUTH_HMAC_SHA2_256_128: - prf = PRF_HMAC_SHA2_256; - break; - case AUTH_HMAC_SHA2_384_192: - prf = PRF_HMAC_SHA2_384; - break; - case AUTH_HMAC_SHA2_512_256: - prf = PRF_HMAC_SHA2_512; - break; - case AUTH_HMAC_MD5_96: - prf = PRF_HMAC_MD5; - break; - case AUTH_AES_XCBC_96: - prf = PRF_AES128_XCBC; - break; - case AUTH_CAMELLIA_XCBC_96: - prf = PRF_CAMELLIA128_XCBC; - break; - case AUTH_AES_CMAC_96: - prf = PRF_AES128_CMAC; - break; - default: - prf = PRF_UNDEFINED; - } - if (prf != PRF_UNDEFINED) - { - add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0); - } - } return TRUE; } diff --git a/src/libcharon/config/proposal.h b/src/libcharon/config/proposal.h index 33abf006c..7733143a8 100644 --- a/src/libcharon/config/proposal.h +++ b/src/libcharon/config/proposal.h @@ -27,8 +27,8 @@ typedef struct proposal_t proposal_t; #include <library.h> #include <utils/identification.h> -#include <utils/linked_list.h> -#include <utils/host.h> +#include <collections/linked_list.h> +#include <networking/host.h> #include <crypto/transform.h> #include <crypto/crypters/crypter.h> #include <crypto/signers/signer.h> @@ -111,8 +111,10 @@ struct proposal_t { /** * Strip DH groups from proposal to use it without PFS. + * + * @param keep group to keep (MODP_NONE to remove all) */ - void (*strip_dh)(proposal_t *this); + void (*strip_dh)(proposal_t *this, diffie_hellman_group_t keep); /** * Compare two proposal, and select a matching subset. |