diff options
Diffstat (limited to 'src/libstrongswan/credentials/auth_cfg.c')
-rw-r--r-- | src/libstrongswan/credentials/auth_cfg.c | 248 |
1 files changed, 217 insertions, 31 deletions
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c index 9988d8021..956ce08c9 100644 --- a/src/libstrongswan/credentials/auth_cfg.c +++ b/src/libstrongswan/credentials/auth_cfg.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2015 Tobias Brunner + * Copyright (C) 2008-2016 Tobias Brunner * Copyright (C) 2007-2009 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -46,11 +46,13 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_AC_CERT, "RULE_SUBJECT_CERT", "RULE_CRL_VALIDATION", "RULE_OCSP_VALIDATION", + "RULE_CERT_VALIDATION_SUSPENDED", "RULE_GROUP", "RULE_RSA_STRENGTH", "RULE_ECDSA_STRENGTH", "RULE_BLISS_STRENGTH", "RULE_SIGNATURE_SCHEME", + "RULE_IKE_SIGNATURE_SCHEME", "RULE_CERT_POLICY", "HELPER_IM_CERT", "HELPER_SUBJECT_CERT", @@ -79,6 +81,7 @@ static inline bool is_multi_value_rule(auth_rule_t type) case AUTH_RULE_AAA_IDENTITY: case AUTH_RULE_XAUTH_IDENTITY: case AUTH_RULE_XAUTH_BACKEND: + case AUTH_RULE_CERT_VALIDATION_SUSPENDED: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_RULE_MAX: @@ -91,6 +94,7 @@ static inline bool is_multi_value_rule(auth_rule_t type) case AUTH_RULE_IM_CERT: case AUTH_RULE_CERT_POLICY: case AUTH_RULE_SIGNATURE_SCHEME: + case AUTH_RULE_IKE_SIGNATURE_SCHEME: case AUTH_HELPER_IM_CERT: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: @@ -211,6 +215,8 @@ static void init_entry(entry_t *this, auth_rule_t type, va_list args) case AUTH_RULE_ECDSA_STRENGTH: case AUTH_RULE_BLISS_STRENGTH: case AUTH_RULE_SIGNATURE_SCHEME: + case AUTH_RULE_IKE_SIGNATURE_SCHEME: + case AUTH_RULE_CERT_VALIDATION_SUSPENDED: /* integer type */ this->value = (void*)(uintptr_t)va_arg(args, u_int); break; @@ -260,6 +266,8 @@ static bool entry_equals(entry_t *e1, entry_t *e2) case AUTH_RULE_ECDSA_STRENGTH: case AUTH_RULE_BLISS_STRENGTH: case AUTH_RULE_SIGNATURE_SCHEME: + case AUTH_RULE_IKE_SIGNATURE_SCHEME: + case AUTH_RULE_CERT_VALIDATION_SUSPENDED: { return e1->value == e2->value; } @@ -351,6 +359,8 @@ static void destroy_entry_value(entry_t *entry) case AUTH_RULE_ECDSA_STRENGTH: case AUTH_RULE_BLISS_STRENGTH: case AUTH_RULE_SIGNATURE_SCHEME: + case AUTH_RULE_IKE_SIGNATURE_SCHEME: + case AUTH_RULE_CERT_VALIDATION_SUSPENDED: case AUTH_RULE_MAX: break; } @@ -383,6 +393,8 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator, case AUTH_RULE_ECDSA_STRENGTH: case AUTH_RULE_BLISS_STRENGTH: case AUTH_RULE_SIGNATURE_SCHEME: + case AUTH_RULE_IKE_SIGNATURE_SCHEME: + case AUTH_RULE_CERT_VALIDATION_SUSPENDED: /* integer type */ entry->value = (void*)(uintptr_t)va_arg(args, u_int); break; @@ -459,11 +471,13 @@ METHOD(auth_cfg_t, get, void*, case AUTH_RULE_BLISS_STRENGTH: return (void*)0; case AUTH_RULE_SIGNATURE_SCHEME: + case AUTH_RULE_IKE_SIGNATURE_SCHEME: return (void*)HASH_UNKNOWN; case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_OCSP_VALIDATION: return (void*)VALIDATION_FAILED; case AUTH_RULE_IDENTITY_LOOSE: + case AUTH_RULE_CERT_VALIDATION_SUSPENDED: return (void*)FALSE; case AUTH_RULE_IDENTITY: case AUTH_RULE_EAP_IDENTITY: @@ -510,6 +524,183 @@ static void add(private_auth_cfg_t *this, auth_rule_t type, ...) } } +METHOD(auth_cfg_t, add_pubkey_constraints, void, + private_auth_cfg_t *this, char* constraints, bool ike) +{ + enumerator_t *enumerator; + bool is_ike = FALSE, ike_added = FALSE; + key_type_t expected_type = -1; + auth_rule_t expected_strength = AUTH_RULE_MAX; + int strength; + char *token; + auth_rule_t type; + void *value; + + enumerator = enumerator_create_token(constraints, "-", ""); + while (enumerator->enumerate(enumerator, &token)) + { + bool found = FALSE; + int i; + struct { + char *name; + signature_scheme_t scheme; + key_type_t key; + } schemes[] = { + { "md5", SIGN_RSA_EMSA_PKCS1_MD5, KEY_RSA, }, + { "sha1", SIGN_RSA_EMSA_PKCS1_SHA1, KEY_RSA, }, + { "sha224", SIGN_RSA_EMSA_PKCS1_SHA224, KEY_RSA, }, + { "sha256", SIGN_RSA_EMSA_PKCS1_SHA256, KEY_RSA, }, + { "sha384", SIGN_RSA_EMSA_PKCS1_SHA384, KEY_RSA, }, + { "sha512", SIGN_RSA_EMSA_PKCS1_SHA512, KEY_RSA, }, + { "sha1", SIGN_ECDSA_WITH_SHA1_DER, KEY_ECDSA, }, + { "sha256", SIGN_ECDSA_WITH_SHA256_DER, KEY_ECDSA, }, + { "sha384", SIGN_ECDSA_WITH_SHA384_DER, KEY_ECDSA, }, + { "sha512", SIGN_ECDSA_WITH_SHA512_DER, KEY_ECDSA, }, + { "sha256", SIGN_ECDSA_256, KEY_ECDSA, }, + { "sha384", SIGN_ECDSA_384, KEY_ECDSA, }, + { "sha512", SIGN_ECDSA_521, KEY_ECDSA, }, + { "sha256", SIGN_BLISS_WITH_SHA2_256, KEY_BLISS, }, + { "sha384", SIGN_BLISS_WITH_SHA2_384, KEY_BLISS, }, + { "sha512", SIGN_BLISS_WITH_SHA2_512, KEY_BLISS, }, + }; + + if (expected_strength != AUTH_RULE_MAX) + { /* expecting a key strength token */ + strength = atoi(token); + if (strength) + { + add(this, expected_strength, (uintptr_t)strength); + } + expected_strength = AUTH_RULE_MAX; + if (strength) + { + continue; + } + } + if (streq(token, "rsa") || streq(token, "ike:rsa")) + { + expected_type = KEY_RSA; + expected_strength = AUTH_RULE_RSA_STRENGTH; + is_ike = strpfx(token, "ike:"); + continue; + } + if (streq(token, "ecdsa") || streq(token, "ike:ecdsa")) + { + expected_type = KEY_ECDSA; + expected_strength = AUTH_RULE_ECDSA_STRENGTH; + is_ike = strpfx(token, "ike:"); + continue; + } + if (streq(token, "bliss") || streq(token, "ike:bliss")) + { + expected_type = KEY_BLISS; + expected_strength = AUTH_RULE_BLISS_STRENGTH; + is_ike = strpfx(token, "ike:"); + continue; + } + if (streq(token, "pubkey") || streq(token, "ike:pubkey")) + { + expected_type = KEY_ANY; + is_ike = strpfx(token, "ike:"); + continue; + } + if (is_ike && !ike) + { + continue; + } + + for (i = 0; i < countof(schemes); i++) + { + if (streq(schemes[i].name, token)) + { + if (expected_type == KEY_ANY || expected_type == schemes[i].key) + { + if (is_ike) + { + add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME, + (uintptr_t)schemes[i].scheme); + ike_added = TRUE; + } + else + { + add(this, AUTH_RULE_SIGNATURE_SCHEME, + (uintptr_t)schemes[i].scheme); + } + } + found = TRUE; + } + } + if (!found) + { + DBG1(DBG_CFG, "ignoring invalid auth token: '%s'", token); + } + } + enumerator->destroy(enumerator); + + /* if no explicit IKE signature contraints were added we add them for all + * configured signature contraints */ + if (ike && !ike_added && + lib->settings->get_bool(lib->settings, + "%s.signature_authentication_constraints", TRUE, + lib->ns)) + { + enumerator = create_enumerator(this); + while (enumerator->enumerate(enumerator, &type, &value)) + { + if (type == AUTH_RULE_SIGNATURE_SCHEME) + { + add(this, AUTH_RULE_IKE_SIGNATURE_SCHEME, + (uintptr_t)value); + } + } + enumerator->destroy(enumerator); + } +} + +/** + * Check if signature schemes of a specific type are compliant + */ +static bool complies_scheme(private_auth_cfg_t *this, auth_cfg_t *constraints, + auth_rule_t type, bool log_error) +{ + enumerator_t *e1, *e2; + auth_rule_t t1, t2; + signature_scheme_t scheme; + void *value; + bool success = TRUE; + + e2 = create_enumerator(this); + while (e2->enumerate(e2, &t2, &scheme)) + { + if (t2 == type) + { + success = FALSE; + e1 = constraints->create_enumerator(constraints); + while (e1->enumerate(e1, &t1, &value)) + { + if (t1 == type && (uintptr_t)value == scheme) + { + success = TRUE; + break; + } + } + e1->destroy(e1); + if (!success) + { + if (log_error) + { + DBG1(DBG_CFG, "%s signature scheme %N not acceptable", + AUTH_RULE_SIGNATURE_SCHEME == type ? "X.509" : "IKE", + signature_scheme_names, (int)scheme); + } + break; + } + } + } + e2->destroy(e2); + return success; +} + METHOD(auth_cfg_t, complies, bool, private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error) { @@ -518,7 +709,7 @@ METHOD(auth_cfg_t, complies, bool, bool ca_match = FALSE, cert_match = FALSE; identification_t *require_group = NULL; certificate_t *require_ca = NULL, *require_cert = NULL; - signature_scheme_t scheme = SIGN_UNKNOWN; + signature_scheme_t ike_scheme = SIGN_UNKNOWN, scheme = SIGN_UNKNOWN; u_int strength = 0; auth_rule_t t1, t2; char *key_type; @@ -573,6 +764,11 @@ METHOD(auth_cfg_t, complies, bool, { uintptr_t validated; + if (get(this, AUTH_RULE_CERT_VALIDATION_SUSPENDED)) + { /* skip validation, may happen later */ + break; + } + e2 = create_enumerator(this); while (e2->enumerate(e2, &t2, &validated)) { @@ -714,6 +910,11 @@ METHOD(auth_cfg_t, complies, bool, strength = (uintptr_t)value; break; } + case AUTH_RULE_IKE_SIGNATURE_SCHEME: + { + ike_scheme = (uintptr_t)value; + break; + } case AUTH_RULE_SIGNATURE_SCHEME: { scheme = (uintptr_t)value; @@ -745,6 +946,8 @@ METHOD(auth_cfg_t, complies, bool, /* just an indication when verifying AUTH_RULE_IDENTITY */ case AUTH_RULE_XAUTH_BACKEND: /* not enforced, just a hint for local authentication */ + case AUTH_RULE_CERT_VALIDATION_SUSPENDED: + /* not a constraint */ case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_IM_HASH_URL: @@ -766,35 +969,13 @@ METHOD(auth_cfg_t, complies, bool, * signature schemes. */ if (success && scheme != SIGN_UNKNOWN) { - e2 = create_enumerator(this); - while (e2->enumerate(e2, &t2, &scheme)) - { - if (t2 == AUTH_RULE_SIGNATURE_SCHEME) - { - success = FALSE; - e1 = constraints->create_enumerator(constraints); - while (e1->enumerate(e1, &t1, &value)) - { - if (t1 == AUTH_RULE_SIGNATURE_SCHEME && - (uintptr_t)value == scheme) - { - success = TRUE; - break; - } - } - e1->destroy(e1); - if (!success) - { - if (log_error) - { - DBG1(DBG_CFG, "signature scheme %N not acceptable", - signature_scheme_names, (int)scheme); - } - break; - } - } - } - e2->destroy(e2); + success = complies_scheme(this, constraints, + AUTH_RULE_SIGNATURE_SCHEME, log_error); + } + if (success && ike_scheme != SIGN_UNKNOWN) + { + success = complies_scheme(this, constraints, + AUTH_RULE_IKE_SIGNATURE_SCHEME, log_error); } /* Check if we have a matching constraint (or none at all) for used @@ -918,6 +1099,8 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy case AUTH_RULE_ECDSA_STRENGTH: case AUTH_RULE_BLISS_STRENGTH: case AUTH_RULE_SIGNATURE_SCHEME: + case AUTH_RULE_IKE_SIGNATURE_SCHEME: + case AUTH_RULE_CERT_VALIDATION_SUSPENDED: { add(this, type, (uintptr_t)value); break; @@ -1088,6 +1271,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, case AUTH_RULE_ECDSA_STRENGTH: case AUTH_RULE_BLISS_STRENGTH: case AUTH_RULE_SIGNATURE_SCHEME: + case AUTH_RULE_IKE_SIGNATURE_SCHEME: + case AUTH_RULE_CERT_VALIDATION_SUSPENDED: clone->add(clone, type, (uintptr_t)value); break; case AUTH_RULE_MAX: @@ -1116,6 +1301,7 @@ auth_cfg_t *auth_cfg_create() INIT(this, .public = { .add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add, + .add_pubkey_constraints = _add_pubkey_constraints, .get = _get, .create_enumerator = _create_enumerator, .replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace, |