diff options
Diffstat (limited to 'src/libstrongswan')
19 files changed, 361 insertions, 165 deletions
diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt index c3ff1a9e7..51a29eb33 100644 --- a/src/libstrongswan/asn1/oid.txt +++ b/src/libstrongswan/asn1/oid.txt @@ -232,6 +232,9 @@ 0x02 "caIssuers" OID_CA_ISSUERS 0x03 "timeStamping" 0x05 "caRepository" + 0x08 "ipsec" + 0x02 "certificate" + 0x02 "iKEIntermediate" OID_IKE_INTERMEDIATE 0x0E "oiw" 0x03 "secsig" 0x02 "algorithms" diff --git a/src/libstrongswan/chunk.h b/src/libstrongswan/chunk.h index 3de02eee7..c7bc7a5e8 100644 --- a/src/libstrongswan/chunk.h +++ b/src/libstrongswan/chunk.h @@ -265,6 +265,15 @@ static inline bool chunk_equals(chunk_t a, chunk_t b) } /** + * Compare two chunks (given as pointers) for equality (useful as callback), + * NULL chunks are never equal. + */ +static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b) +{ + return a != NULL && b != NULL && chunk_equals(*a, *b); +} + +/** * Increment a chunk, as it would reprensent a network order integer. * * @param chunk chunk to increment diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c index 12f75b240..fd2cee607 100644 --- a/src/libstrongswan/credentials/auth_cfg.c +++ b/src/libstrongswan/credentials/auth_cfg.c @@ -23,11 +23,12 @@ #include <eap/eap.h> #include <credentials/certificates/certificate.h> -ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_EAP, +ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_XAUTH, "any", "public key", "pre-shared key", "EAP", + "XAuth", ); ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT, @@ -37,6 +38,8 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT, "RULE_EAP_IDENTITY", "RULE_EAP_TYPE", "RULE_EAP_VENDOR", + "RULE_XAUTH_BACKEND", + "RULE_XAUTH_IDENTITY", "RULE_CA_CERT", "RULE_IM_CERT", "RULE_SUBJECT_CERT", @@ -68,6 +71,8 @@ static inline bool is_multi_value_rule(auth_rule_t type) case AUTH_RULE_IDENTITY: case AUTH_RULE_EAP_IDENTITY: case AUTH_RULE_AAA_IDENTITY: + case AUTH_RULE_XAUTH_IDENTITY: + case AUTH_RULE_XAUTH_BACKEND: case AUTH_RULE_SUBJECT_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_SUBJECT_HASH_URL: @@ -203,6 +208,8 @@ static entry_t *entry_create(auth_rule_t type, va_list args) case AUTH_RULE_IDENTITY: case AUTH_RULE_EAP_IDENTITY: case AUTH_RULE_AAA_IDENTITY: + case AUTH_RULE_XAUTH_BACKEND: + case AUTH_RULE_XAUTH_IDENTITY: case AUTH_RULE_GROUP: case AUTH_RULE_CA_CERT: case AUTH_RULE_IM_CERT: @@ -261,6 +268,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2) case AUTH_RULE_IDENTITY: case AUTH_RULE_EAP_IDENTITY: case AUTH_RULE_AAA_IDENTITY: + case AUTH_RULE_XAUTH_IDENTITY: case AUTH_RULE_GROUP: { identification_t *id1, *id2; @@ -271,6 +279,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2) return id1->equals(id1, id2); } case AUTH_RULE_CERT_POLICY: + case AUTH_RULE_XAUTH_BACKEND: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: { @@ -293,6 +302,7 @@ static void destroy_entry_value(entry_t *entry) case AUTH_RULE_EAP_IDENTITY: case AUTH_RULE_AAA_IDENTITY: case AUTH_RULE_GROUP: + case AUTH_RULE_XAUTH_IDENTITY: { identification_t *id = (identification_t*)entry->value; id->destroy(id); @@ -310,6 +320,7 @@ static void destroy_entry_value(entry_t *entry) break; } case AUTH_RULE_CERT_POLICY: + case AUTH_RULE_XAUTH_BACKEND: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: { @@ -358,6 +369,8 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator, case AUTH_RULE_IDENTITY: case AUTH_RULE_EAP_IDENTITY: case AUTH_RULE_AAA_IDENTITY: + case AUTH_RULE_XAUTH_BACKEND: + case AUTH_RULE_XAUTH_IDENTITY: case AUTH_RULE_GROUP: case AUTH_RULE_CA_CERT: case AUTH_RULE_IM_CERT: @@ -429,6 +442,8 @@ METHOD(auth_cfg_t, get, void*, case AUTH_RULE_IDENTITY: case AUTH_RULE_EAP_IDENTITY: case AUTH_RULE_AAA_IDENTITY: + case AUTH_RULE_XAUTH_BACKEND: + case AUTH_RULE_XAUTH_IDENTITY: case AUTH_RULE_GROUP: case AUTH_RULE_CA_CERT: case AUTH_RULE_IM_CERT: @@ -571,6 +586,7 @@ METHOD(auth_cfg_t, complies, bool, case AUTH_RULE_IDENTITY: case AUTH_RULE_EAP_IDENTITY: case AUTH_RULE_AAA_IDENTITY: + case AUTH_RULE_XAUTH_IDENTITY: { identification_t *id1, *id2; @@ -668,6 +684,7 @@ METHOD(auth_cfg_t, complies, bool, "public keys, but %d bit key used", (uintptr_t)value, strength); } + break; } } else if (t2 == AUTH_RULE_RSA_STRENGTH) @@ -678,6 +695,7 @@ METHOD(auth_cfg_t, complies, bool, DBG1(DBG_CFG, "constraint requires %d bit ECDSA, " "but RSA used", (uintptr_t)value); } + break; } else if (t2 == AUTH_RULE_ECDSA_STRENGTH) { @@ -687,6 +705,7 @@ METHOD(auth_cfg_t, complies, bool, DBG1(DBG_CFG, "constraint requires %d bit RSA, " "but ECDSA used", (uintptr_t)value); } + break; } } e2->destroy(e2); @@ -714,6 +733,8 @@ METHOD(auth_cfg_t, complies, bool, } break; } + case AUTH_RULE_XAUTH_BACKEND: + /* not enforced, just a hint for local authentication */ case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_IM_HASH_URL: @@ -789,12 +810,14 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy case AUTH_RULE_EAP_IDENTITY: case AUTH_RULE_AAA_IDENTITY: case AUTH_RULE_GROUP: + case AUTH_RULE_XAUTH_IDENTITY: { identification_t *id = (identification_t*)value; add(this, type, id->clone(id)); break; } + case AUTH_RULE_XAUTH_BACKEND: case AUTH_RULE_CERT_POLICY: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: @@ -904,6 +927,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, case AUTH_RULE_EAP_IDENTITY: case AUTH_RULE_AAA_IDENTITY: case AUTH_RULE_GROUP: + case AUTH_RULE_XAUTH_IDENTITY: { identification_t *id = (identification_t*)entry->value; clone->add(clone, entry->type, id->clone(id)); @@ -920,6 +944,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, clone->add(clone, entry->type, cert->get_ref(cert)); break; } + case AUTH_RULE_XAUTH_BACKEND: case AUTH_RULE_CERT_POLICY: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: diff --git a/src/libstrongswan/credentials/auth_cfg.h b/src/libstrongswan/credentials/auth_cfg.h index 4d12a9c14..409ec4901 100644 --- a/src/libstrongswan/credentials/auth_cfg.h +++ b/src/libstrongswan/credentials/auth_cfg.h @@ -42,6 +42,8 @@ enum auth_class_t { AUTH_CLASS_PSK = 2, /** authentication using EAP */ AUTH_CLASS_EAP = 3, + /** authentication using IKEv1 XAUTH */ + AUTH_CLASS_XAUTH = 4, }; /** @@ -75,6 +77,10 @@ enum auth_rule_t { AUTH_RULE_EAP_TYPE, /** EAP vendor for vendor specific type, u_int32_t */ AUTH_RULE_EAP_VENDOR, + /** XAUTH backend name to use, char* */ + AUTH_RULE_XAUTH_BACKEND, + /** XAuth identity to use or require, identification_t* */ + AUTH_RULE_XAUTH_IDENTITY, /** certificate authority, certificate_t* */ AUTH_RULE_CA_CERT, /** intermediate certificate in trustchain, certificate_t* */ diff --git a/src/libstrongswan/credentials/certificates/x509.h b/src/libstrongswan/credentials/certificates/x509.h index 5125aca26..00171a718 100644 --- a/src/libstrongswan/credentials/certificates/x509.h +++ b/src/libstrongswan/credentials/certificates/x509.h @@ -56,6 +56,8 @@ enum x509_flag_t { X509_IP_ADDR_BLOCKS = (1<<6), /** cert has CRL sign key usage */ X509_CRL_SIGN = (1<<7), + /** cert has iKEIntermediate key usage */ + X509_IKE_INTERMEDIATE = (1<<8), }; /** diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c index b3461b810..d54359ebf 100644 --- a/src/libstrongswan/credentials/credential_manager.c +++ b/src/libstrongswan/credentials/credential_manager.c @@ -53,6 +53,11 @@ struct private_credential_manager_t { thread_value_t *local_sets; /** + * Exclusive local sets, linked_list_t with credential_set_t + */ + thread_value_t *exclusive_local_sets; + + /** * trust relationship and certificate cache */ cert_cache_t *cache; @@ -117,12 +122,23 @@ typedef struct { enumerator_t *global; /** enumerator over local sets */ enumerator_t *local; + /** enumerator over exclusive local sets */ + enumerator_t *exclusive; } sets_enumerator_t; METHOD(enumerator_t, sets_enumerate, bool, sets_enumerator_t *this, credential_set_t **set) { + if (this->exclusive) + { + if (this->exclusive->enumerate(this->exclusive, set)) + { /* only enumerate last added */ + this->exclusive->destroy(this->exclusive); + this->exclusive = NULL; + return TRUE; + } + } if (this->global) { if (this->global->enumerate(this->global, set)) @@ -145,6 +161,7 @@ METHOD(enumerator_t, sets_destroy, void, { DESTROY_IF(this->global); DESTROY_IF(this->local); + DESTROY_IF(this->exclusive); free(this); } @@ -154,19 +171,28 @@ METHOD(enumerator_t, sets_destroy, void, static enumerator_t *create_sets_enumerator(private_credential_manager_t *this) { sets_enumerator_t *enumerator; - linked_list_t *local; + linked_list_t *list; INIT(enumerator, .public = { .enumerate = (void*)_sets_enumerate, .destroy = _sets_destroy, }, - .global = this->sets->create_enumerator(this->sets), ); - local = this->local_sets->get(this->local_sets); - if (local) + + list = this->exclusive_local_sets->get(this->exclusive_local_sets); + if (list && list->get_count(list)) + { + enumerator->exclusive = list->create_enumerator(list); + } + else { - enumerator->local = local->create_enumerator(local); + enumerator->global = this->sets->create_enumerator(this->sets); + list = this->local_sets->get(this->local_sets); + if (list) + { + enumerator->local = list->create_enumerator(list); + } } return &enumerator->public; } @@ -373,26 +399,55 @@ METHOD(credential_manager_t, get_shared, shared_key_t*, } METHOD(credential_manager_t, add_local_set, void, - private_credential_manager_t *this, credential_set_t *set) + private_credential_manager_t *this, credential_set_t *set, bool exclusive) { linked_list_t *sets; + thread_value_t *tv; - sets = this->local_sets->get(this->local_sets); + if (exclusive) + { + tv = this->exclusive_local_sets; + } + else + { + tv = this->local_sets; + } + sets = tv->get(tv); if (!sets) - { /* first invocation */ + { sets = linked_list_create(); - this->local_sets->set(this->local_sets, sets); + tv->set(tv, sets); + } + if (exclusive) + { + sets->insert_first(sets, set); + } + else + { + sets->insert_last(sets, set); } - sets->insert_last(sets, set); } METHOD(credential_manager_t, remove_local_set, void, private_credential_manager_t *this, credential_set_t *set) { linked_list_t *sets; + thread_value_t *tv; - sets = this->local_sets->get(this->local_sets); - sets->remove(sets, set, NULL); + tv = this->local_sets; + sets = tv->get(tv); + if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0) + { + tv->set(tv, NULL); + sets->destroy(sets); + } + tv = this->exclusive_local_sets; + sets = tv->get(tv); + if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0) + { + tv->set(tv, NULL); + sets->destroy(sets); + } } METHOD(credential_manager_t, cache_cert, void, @@ -859,7 +914,7 @@ METHOD(credential_manager_t, create_public_enumerator, enumerator_t*, if (auth) { enumerator->wrapper = auth_cfg_wrapper_create(auth); - add_local_set(this, &enumerator->wrapper->set); + add_local_set(this, &enumerator->wrapper->set, FALSE); } this->lock->read_lock(this->lock); return &enumerator->public; @@ -992,42 +1047,45 @@ METHOD(credential_manager_t, get_private, private_key_t*, } } - /* if a specific certificate is preferred, check for a matching key */ - cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); - if (cert) + if (auth) { - private = get_private_by_cert(this, cert, type); - if (private) + /* if a specific certificate is preferred, check for a matching key */ + cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (cert) { - trustchain = build_trustchain(this, cert, auth); - if (trustchain) + private = get_private_by_cert(this, cert, type); + if (private) { - auth->merge(auth, trustchain, FALSE); - trustchain->destroy(trustchain); + trustchain = build_trustchain(this, cert, auth); + if (trustchain) + { + auth->merge(auth, trustchain, FALSE); + trustchain->destroy(trustchain); + } + return private; } - return private; } - } - /* try to build a trust chain for each certificate found */ - enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE); - while (enumerator->enumerate(enumerator, &cert)) - { - private = get_private_by_cert(this, cert, type); - if (private) + /* try to build a trust chain for each certificate found */ + enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE); + while (enumerator->enumerate(enumerator, &cert)) { - trustchain = build_trustchain(this, cert, auth); - if (trustchain) + private = get_private_by_cert(this, cert, type); + if (private) { - auth->merge(auth, trustchain, FALSE); - trustchain->destroy(trustchain); - break; + trustchain = build_trustchain(this, cert, auth); + if (trustchain) + { + auth->merge(auth, trustchain, FALSE); + trustchain->destroy(trustchain); + break; + } + private->destroy(private); + private = NULL; } - private->destroy(private); - private = NULL; } + enumerator->destroy(enumerator); } - enumerator->destroy(enumerator); /* if no valid trustchain was found, fall back to the first usable cert */ if (!private) @@ -1038,7 +1096,10 @@ METHOD(credential_manager_t, get_private, private_key_t*, private = get_private_by_cert(this, cert, type); if (private) { - auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert)); + if (auth) + { + auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert)); + } break; } } @@ -1100,6 +1161,7 @@ METHOD(credential_manager_t, destroy, void, this->sets->remove(this->sets, this->cache, NULL); this->sets->destroy(this->sets); this->local_sets->destroy(this->local_sets); + this->exclusive_local_sets->destroy(this->exclusive_local_sets); this->cache->destroy(this->cache); this->validators->destroy(this->validators); this->lock->destroy(this->lock); @@ -1144,6 +1206,7 @@ credential_manager_t *credential_manager_create() ); this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy); + this->exclusive_local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy); this->sets->insert_first(this->sets, this->cache); return &this->public; diff --git a/src/libstrongswan/credentials/credential_manager.h b/src/libstrongswan/credentials/credential_manager.h index 8e8f04b8c..ad789c718 100644 --- a/src/libstrongswan/credentials/credential_manager.h +++ b/src/libstrongswan/credentials/credential_manager.h @@ -89,7 +89,7 @@ struct credential_manager_t { * @param type kind of requested shared key * @param first first subject between key is shared * @param second second subject between key is shared - * @return enumerator over shared keys + * @return enumerator over (shared_key_t*,id_match_t,id_match_t) */ enumerator_t *(*create_shared_enumerator)(credential_manager_t *this, shared_key_type_t type, @@ -230,10 +230,14 @@ struct credential_manager_t { * operation, sets may be added for the calling thread only. This * does not require a write lock and is therefore a much cheaper * operation. + * The exclusive option allows to disable all other credential sets + * until the set is deregistered. * * @param set set to register + * @param exclusive TRUE to disable all other sets for this thread */ - void (*add_local_set)(credential_manager_t *this, credential_set_t *set); + void (*add_local_set)(credential_manager_t *this, credential_set_t *set, + bool exclusive); /** * Unregister a thread local credential set from the manager. diff --git a/src/libstrongswan/crypto/prf_plus.c b/src/libstrongswan/crypto/prf_plus.c index 8e815e608..0f06ede83 100644 --- a/src/libstrongswan/crypto/prf_plus.c +++ b/src/libstrongswan/crypto/prf_plus.c @@ -25,6 +25,7 @@ typedef struct private_prf_plus_t private_prf_plus_t; * */ struct private_prf_plus_t { + /** * Public interface of prf_plus_t. */ @@ -41,49 +42,50 @@ struct private_prf_plus_t { chunk_t seed; /** - * Buffer to store current PRF result. + * Octet which will be appended to the seed, 0 if not used */ - chunk_t buffer; + u_int8_t counter; /** * Already given out bytes in current buffer. */ - size_t given_out; + size_t used; /** - * Octet which will be appended to the seed. + * Buffer to store current PRF result. */ - u_int8_t appending_octet; + chunk_t buffer; }; METHOD(prf_plus_t, get_bytes, void, private_prf_plus_t *this, size_t length, u_int8_t *buffer) { - chunk_t appending_chunk; - size_t bytes_in_round; - size_t total_bytes_written = 0; - - appending_chunk.ptr = &(this->appending_octet); - appending_chunk.len = 1; + size_t round, written = 0; while (length > 0) - { /* still more to do... */ - if (this->buffer.len == this->given_out) - { /* no bytes left in buffer, get next*/ + { + if (this->buffer.len == this->used) + { /* buffer used, get next round */ this->prf->get_bytes(this->prf, this->buffer, NULL); - this->prf->get_bytes(this->prf, this->seed, NULL); - this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr); - this->given_out = 0; - this->appending_octet++; + if (this->counter) + { + this->prf->get_bytes(this->prf, this->seed, NULL); + this->prf->get_bytes(this->prf, chunk_from_thing(this->counter), + this->buffer.ptr); + this->counter++; + } + else + { + this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr); + } + this->used = 0; } - /* how many bytes can we write in this round ? */ - bytes_in_round = min(length, this->buffer.len - this->given_out); - /* copy bytes from buffer with offset */ - memcpy(buffer + total_bytes_written, this->buffer.ptr + this->given_out, bytes_in_round); - - length -= bytes_in_round; - this->given_out += bytes_in_round; - total_bytes_written += bytes_in_round; + round = min(length, this->buffer.len - this->used); + memcpy(buffer + written, this->buffer.ptr + this->used, round); + + length -= round; + this->used += round; + written += round; } } @@ -92,8 +94,7 @@ METHOD(prf_plus_t, allocate_bytes, void, { if (length) { - chunk->ptr = malloc(length); - chunk->len = length; + *chunk = chunk_alloc(length); get_bytes(this, length, chunk->ptr); } else @@ -113,10 +114,9 @@ METHOD(prf_plus_t, destroy, void, /* * Description in header. */ -prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed) +prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed) { private_prf_plus_t *this; - chunk_t appending_chunk; INIT(this, .public = { @@ -125,25 +125,22 @@ prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed) .destroy = _destroy, }, .prf = prf, + .seed = chunk_clone(seed), + .buffer = chunk_alloc(prf->get_block_size(prf)), ); - /* allocate buffer for prf output */ - this->buffer.len = prf->get_block_size(prf); - this->buffer.ptr = malloc(this->buffer.len); - - this->appending_octet = 0x01; - - /* clone seed */ - this->seed.ptr = clalloc(seed.ptr, seed.len); - this->seed.len = seed.len; - - /* do the first run */ - appending_chunk.ptr = &(this->appending_octet); - appending_chunk.len = 1; - this->prf->get_bytes(this->prf, this->seed, NULL); - this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr); - this->given_out = 0; - this->appending_octet++; + if (counter) + { + this->counter = 0x01; + this->prf->get_bytes(this->prf, this->seed, NULL); + this->prf->get_bytes(this->prf, chunk_from_thing(this->counter), + this->buffer.ptr); + this->counter++; + } + else + { + this->prf->get_bytes(this->prf, this->seed, this->buffer.ptr); + } - return &(this->public); + return &this->public; } diff --git a/src/libstrongswan/crypto/prf_plus.h b/src/libstrongswan/crypto/prf_plus.h index 4179f2695..668f12c02 100644 --- a/src/libstrongswan/crypto/prf_plus.h +++ b/src/libstrongswan/crypto/prf_plus.h @@ -27,19 +27,13 @@ typedef struct prf_plus_t prf_plus_t; #include <crypto/prfs/prf.h> /** - * Implementation of the prf+ function described in IKEv2 RFC. - * - * This class implements the prf+ algorithm. Internally it uses a pseudo random - * function, which implements the prf_t interface. - * See IKEv2 RFC 2.13. + * Implementation of the prf+ function used in IKEv1/IKEv2 keymat extension. */ struct prf_plus_t { + /** * Get pseudo random bytes. * - * Get the next few bytes of the prf+ output. Space - * must be allocated by the caller. - * * @param length number of bytes to get * @param buffer pointer where the generated bytes will be written */ @@ -48,9 +42,6 @@ struct prf_plus_t { /** * Allocate pseudo random bytes. * - * Get the next few bytes of the prf+ output. This function - * will allocate the required space. - * * @param length number of bytes to get * @param chunk chunk which will hold generated bytes */ @@ -65,14 +56,11 @@ struct prf_plus_t { /** * Creates a new prf_plus_t object. * - * Seed will be cloned. prf will - * not be cloned, must be destroyed outside after - * prf_plus_t usage. - * - * @param prf prf object to use + * @param prf prf object to use, must be destroyd after prf+. + * @param counter use an appending counter byte (for IKEv2 variant) * @param seed input seed for prf * @return prf_plus_t object */ -prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed); +prf_plus_t *prf_plus_create(prf_t *prf, bool counter, chunk_t seed); #endif /** PRF_PLUS_H_ @}*/ diff --git a/src/libstrongswan/plugins/plugin_feature.c b/src/libstrongswan/plugins/plugin_feature.c index 2a97205bb..330528885 100644 --- a/src/libstrongswan/plugins/plugin_feature.c +++ b/src/libstrongswan/plugins/plugin_feature.c @@ -40,6 +40,8 @@ ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM, "CERT_ENCODE", "EAP_SERVER", "EAP_CLIENT", + "XAUTH_SERVER", + "XAUTH_CLIENT", "DATABASE", "FETCHER", "CUSTOM", @@ -96,6 +98,9 @@ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b) streq(a->arg.fetcher, b->arg.fetcher); case FEATURE_CUSTOM: return streq(a->arg.custom, b->arg.custom); + case FEATURE_XAUTH_SERVER: + case FEATURE_XAUTH_PEER: + return streq(a->arg.xauth, b->arg.xauth); } } return FALSE; @@ -229,6 +234,14 @@ char* plugin_feature_get_string(plugin_feature_t *feature) return str; } break; + case FEATURE_XAUTH_SERVER: + case FEATURE_XAUTH_PEER: + if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type, + feature->arg.xauth) > 0) + { + return str; + } + break; } if (!str) { diff --git a/src/libstrongswan/plugins/plugin_feature.h b/src/libstrongswan/plugins/plugin_feature.h index b1500feba..344d1943d 100644 --- a/src/libstrongswan/plugins/plugin_feature.h +++ b/src/libstrongswan/plugins/plugin_feature.h @@ -129,6 +129,10 @@ struct plugin_feature_t { FEATURE_EAP_SERVER, /** EAP peer implementation */ FEATURE_EAP_PEER, + /** XAuth server implementation */ + FEATURE_XAUTH_SERVER, + /** XAuth peer implementation */ + FEATURE_XAUTH_PEER, /** database_t */ FEATURE_DATABASE, /** fetcher_t */ @@ -182,6 +186,8 @@ struct plugin_feature_t { char *fetcher; /** FEATURE_CUSTOM */ char *custom; + /** FEATURE_XAUTH_SERVER/CLIENT */ + char *xauth; /** FEATURE_REGISTER */ struct { @@ -266,6 +272,8 @@ struct plugin_feature_t { #define _PLUGIN_FEATURE_DATABASE(kind, type) __PLUGIN_FEATURE(kind, DATABASE, .database = type) #define _PLUGIN_FEATURE_FETCHER(kind, type) __PLUGIN_FEATURE(kind, FETCHER, .fetcher = type) #define _PLUGIN_FEATURE_CUSTOM(kind, name) __PLUGIN_FEATURE(kind, CUSTOM, .custom = name) +#define _PLUGIN_FEATURE_XAUTH_SERVER(kind, name) __PLUGIN_FEATURE(kind, XAUTH_SERVER, .xauth = name) +#define _PLUGIN_FEATURE_XAUTH_PEER(kind, name) __PLUGIN_FEATURE(kind, XAUTH_PEER, .xauth = name) #define __PLUGIN_FEATURE_REGISTER(type, _f) (plugin_feature_t){ FEATURE_REGISTER, FEATURE_##type, .arg.reg.f = _f } #define __PLUGIN_FEATURE_REGISTER_BUILDER(type, _f, _final) (plugin_feature_t){ FEATURE_REGISTER, FEATURE_##type, .arg.reg = {.f = _f, .final = _final, }} diff --git a/src/libstrongswan/plugins/random/random_plugin.c b/src/libstrongswan/plugins/random/random_plugin.c index 7f81e2622..418eeae28 100644 --- a/src/libstrongswan/plugins/random/random_plugin.c +++ b/src/libstrongswan/plugins/random/random_plugin.c @@ -15,9 +15,24 @@ #include "random_plugin.h" +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + #include <library.h> +#include <debug.h> #include "random_rng.h" +#ifndef DEV_RANDOM +# define DEV_RANDOM "/dev/random" +#endif + +#ifndef DEV_URANDOM +# define DEV_URANDOM "/dev/urandom" +#endif + typedef struct private_random_plugin_t private_random_plugin_t; /** @@ -31,6 +46,41 @@ struct private_random_plugin_t { random_plugin_t public; }; +/** /dev/random file descriptor */ +static int dev_random = -1; +/** /dev/urandom file descriptor */ +static int dev_urandom = -1; + +/** + * See header. + */ +int random_plugin_get_dev_random() +{ + return dev_random; +} + +/** + * See header. + */ +int random_plugin_get_dev_urandom() +{ + return dev_urandom; +} + +/** + * Open a random device file + */ +static bool open_dev(char *file, int *fd) +{ + *fd = open(file, O_RDONLY); + if (*fd == -1) + { + DBG1(DBG_LIB, "opening \"%s\" failed: %s", file, strerror(errno)); + return FALSE; + } + return TRUE; +} + METHOD(plugin_t, get_name, char*, private_random_plugin_t *this) { @@ -52,6 +102,14 @@ METHOD(plugin_t, get_features, int, METHOD(plugin_t, destroy, void, private_random_plugin_t *this) { + if (dev_random != -1) + { + close(dev_random); + } + if (dev_urandom != -1) + { + close(dev_urandom); + } free(this); } @@ -72,6 +130,13 @@ plugin_t *random_plugin_create() }, ); + if (!open_dev(DEV_URANDOM, &dev_urandom) || + !open_dev(DEV_RANDOM, &dev_random)) + { + destroy(this); + return NULL; + } + return &this->public.plugin; } diff --git a/src/libstrongswan/plugins/random/random_plugin.h b/src/libstrongswan/plugins/random/random_plugin.h index 7e22c3e5f..c34fa8196 100644 --- a/src/libstrongswan/plugins/random/random_plugin.h +++ b/src/libstrongswan/plugins/random/random_plugin.h @@ -39,4 +39,14 @@ struct random_plugin_t { plugin_t plugin; }; +/** + * Get the /dev/random file descriptor + */ +int random_plugin_get_dev_random(); + +/** + * Get the /dev/urandom file descriptor + */ +int random_plugin_get_dev_urandom(); + #endif /** RANDOM_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/random/random_rng.c b/src/libstrongswan/plugins/random/random_rng.c index 1d99a63d5..42eddbb09 100644 --- a/src/libstrongswan/plugins/random/random_rng.c +++ b/src/libstrongswan/plugins/random/random_rng.c @@ -15,22 +15,12 @@ */ #include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> #include <unistd.h> #include <errno.h> #include <debug.h> #include "random_rng.h" - -#ifndef DEV_RANDOM -# define DEV_RANDOM "/dev/random" -#endif - -#ifndef DEV_URANDOM -# define DEV_URANDOM "/dev/urandom" -#endif +#include "random_plugin.h" typedef struct private_random_rng_t private_random_rng_t; @@ -47,12 +37,7 @@ struct private_random_rng_t { /** * random device, depends on quality */ - int dev; - - /** - * file we read random bytes from - */ - char *file; + int fd; }; METHOD(rng_t, get_bytes, void, @@ -65,14 +50,12 @@ METHOD(rng_t, get_bytes, void, while (done < bytes) { - got = read(this->dev, buffer + done, bytes - done); + got = read(this->fd, buffer + done, bytes - done); if (got <= 0) { - DBG1(DBG_LIB, "reading from \"%s\" failed: %s, retrying...", - this->file, strerror(errno)); - close(this->dev); + DBG1(DBG_LIB, "reading from random FD %d failed: %s, retrying...", + this->fd, strerror(errno)); sleep(1); - this->dev = open(this->file, 0); } done += got; } @@ -88,7 +71,6 @@ METHOD(rng_t, allocate_bytes, void, METHOD(rng_t, destroy, void, private_random_rng_t *this) { - close(this->dev); free(this); } @@ -109,22 +91,18 @@ random_rng_t *random_rng_create(rng_quality_t quality) }, ); - if (quality == RNG_TRUE) + switch (quality) { - this->file = DEV_RANDOM; - } - else - { - this->file = DEV_URANDOM; + case RNG_TRUE: + this->fd = random_plugin_get_dev_random(); + break; + case RNG_STRONG: + case RNG_WEAK: + default: + this->fd = random_plugin_get_dev_urandom(); + break; } - this->dev = open(this->file, 0); - if (this->dev < 0) - { - DBG1(DBG_LIB, "opening \"%s\" failed: %s", this->file, strerror(errno)); - free(this); - return NULL; - } return &this->public; } diff --git a/src/libstrongswan/plugins/revocation/revocation_validator.c b/src/libstrongswan/plugins/revocation/revocation_validator.c index 34f347d1a..ff3ef14d8 100644 --- a/src/libstrongswan/plugins/revocation/revocation_validator.c +++ b/src/libstrongswan/plugins/revocation/revocation_validator.c @@ -103,7 +103,7 @@ static bool verify_ocsp(ocsp_response_t *response, auth_cfg_t *auth) bool verified = FALSE; wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response); - lib->credmgr->add_local_set(lib->credmgr, &wrapper->set); + lib->credmgr->add_local_set(lib->credmgr, &wrapper->set, FALSE); subject = &response->certificate; responder = subject->get_issuer(subject); diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index b7aee2e94..59f490025 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -752,6 +752,9 @@ static void parse_extendedKeyUsage(chunk_t blob, int level0, case OID_CLIENT_AUTH: this->flags |= X509_CLIENT_AUTH; break; + case OID_IKE_INTERMEDIATE: + this->flags |= X509_IKE_INTERMEDIATE; + break; case OID_OCSP_SIGNING: this->flags |= X509_OCSP_SIGNER; break; @@ -1105,19 +1108,19 @@ static void parse_policyConstraints(chunk_t blob, int level0, * ASN.1 definition of ipAddrBlocks according to RFC 3779 */ static const asn1Object_t ipAddrBlocksObjects[] = { - { 0, "ipAddrBlocks", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ + { 0, "ipAddrBlocks", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */ { 1, "ipAddressFamily", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ - { 2, "addressFamily", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */ - { 2, "inherit", ASN1_NULL, ASN1_OPT|ASN1_NONE }, /* 3 */ - { 2, "end choice", ASN1_EOC, ASN1_END }, /* 4 */ - { 2, "addressesOrRanges", ASN1_SEQUENCE, ASN1_OPT|ASN1_LOOP }, /* 5 */ - { 3, "addressPrefix", ASN1_BIT_STRING, ASN1_OPT|ASN1_BODY }, /* 6 */ - { 3, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ - { 3, "addressRange", ASN1_SEQUENCE, ASN1_OPT|ASN1_NONE }, /* 8 */ - { 4, "min", ASN1_BIT_STRING, ASN1_BODY }, /* 9 */ - { 4, "max", ASN1_BIT_STRING, ASN1_BODY }, /* 10 */ - { 3, "end choice", ASN1_EOC, ASN1_END }, /* 11 */ - { 2, "end opt/loop", ASN1_EOC, ASN1_END }, /* 12 */ + { 2, "addressFamily", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */ + { 2, "inherit", ASN1_NULL, ASN1_OPT|ASN1_NONE }, /* 3 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 4 */ + { 2, "addressesOrRanges", ASN1_SEQUENCE, ASN1_OPT|ASN1_LOOP }, /* 5 */ + { 3, "addressPrefix", ASN1_BIT_STRING, ASN1_OPT|ASN1_BODY }, /* 6 */ + { 3, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ + { 3, "addressRange", ASN1_SEQUENCE, ASN1_OPT|ASN1_NONE }, /* 8 */ + { 4, "min", ASN1_BIT_STRING, ASN1_BODY }, /* 9 */ + { 4, "max", ASN1_BIT_STRING, ASN1_BODY }, /* 10 */ + { 3, "end choice", ASN1_EOC, ASN1_END }, /* 11 */ + { 2, "end opt/loop", ASN1_EOC, ASN1_END }, /* 12 */ { 0, "end loop", ASN1_EOC, ASN1_END }, /* 13 */ { 0, "exit", ASN1_EOC, ASN1_EXIT } }; @@ -1994,6 +1997,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, chunk_t subjectKeyIdentifier = chunk_empty, authKeyIdentifier = chunk_empty; chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty; chunk_t policyConstraints = chunk_empty, inhibitAnyPolicy = chunk_empty; + chunk_t ikeIntermediate = chunk_empty; identification_t *issuer, *subject; chunk_t key_info; signature_scheme_t scheme; @@ -2107,7 +2111,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, asn1_wrap(ASN1_BIT_STRING, "c", keyUsageBits))); } - /* add serverAuth extendedKeyUsage flag */ + /* add extendedKeyUsage flags */ if (cert->flags & X509_SERVER_AUTH) { serverAuth = asn1_build_known_oid(OID_SERVER_AUTH); @@ -2116,20 +2120,24 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, { clientAuth = asn1_build_known_oid(OID_CLIENT_AUTH); } - - /* add ocspSigning extendedKeyUsage flag */ + if (cert->flags & X509_IKE_INTERMEDIATE) + { + ikeIntermediate = asn1_build_known_oid(OID_IKE_INTERMEDIATE); + } if (cert->flags & X509_OCSP_SIGNER) { ocspSigning = asn1_build_known_oid(OID_OCSP_SIGNING); } - if (serverAuth.ptr || clientAuth.ptr || ocspSigning.ptr) + if (serverAuth.ptr || clientAuth.ptr || ikeIntermediate.ptr || + ocspSigning.ptr) { extendedKeyUsage = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_EXTENDED_KEY_USAGE), asn1_wrap(ASN1_OCTET_STRING, "m", - asn1_wrap(ASN1_SEQUENCE, "mmm", - serverAuth, clientAuth, ocspSigning))); + asn1_wrap(ASN1_SEQUENCE, "mmmm", + serverAuth, clientAuth, ikeIntermediate, + ocspSigning))); } /* add subjectKeyIdentifier to CA and OCSP signer certificates */ diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c index b1bcf1b2d..8b862a8dc 100644 --- a/src/libstrongswan/selectors/traffic_selector.c +++ b/src/libstrongswan/selectors/traffic_selector.c @@ -571,7 +571,7 @@ METHOD(traffic_selector_t, includes, bool, return FALSE; } -METHOD(traffic_selector_t, to_subnet, void, +METHOD(traffic_selector_t, to_subnet, bool, private_traffic_selector_t *this, host_t **net, u_int8_t *mask) { /* there is no way to do this cleanly, as the address range may @@ -597,7 +597,7 @@ METHOD(traffic_selector_t, to_subnet, void, break; default: /* unreachable */ - return; + return FALSE; } net_chunk.ptr = malloc(net_chunk.len); @@ -616,6 +616,8 @@ METHOD(traffic_selector_t, to_subnet, void, *net = host_create_from_chunk(family, net_chunk, port); chunk_free(&net_chunk); + + return this->netbits != NON_SUBNET_ADDRESS_RANGE; } METHOD(traffic_selector_t, clone_, traffic_selector_t*, diff --git a/src/libstrongswan/selectors/traffic_selector.h b/src/libstrongswan/selectors/traffic_selector.h index 257da3f24..67b5da5bf 100644 --- a/src/libstrongswan/selectors/traffic_selector.h +++ b/src/libstrongswan/selectors/traffic_selector.h @@ -203,8 +203,9 @@ struct traffic_selector_t { * * @param net converted subnet (has to be freed) * @param mask converted net mask + * @return TRUE if traffic selector matches exactly to the subnet */ - void (*to_subnet) (traffic_selector_t *this, host_t **net, u_int8_t *mask); + bool (*to_subnet) (traffic_selector_t *this, host_t **net, u_int8_t *mask); /** * Destroys the ts object diff --git a/src/libstrongswan/utils.h b/src/libstrongswan/utils.h index cedfe8fd1..c5718d9f8 100644 --- a/src/libstrongswan/utils.h +++ b/src/libstrongswan/utils.h @@ -491,6 +491,11 @@ static inline void htoun32(void *network, u_int32_t host) static inline void htoun64(void *network, u_int64_t host) { char *unaligned = (char*)network; + +#ifdef be64toh + host = htobe64(host); + memcpy((char*)unaligned, &host, sizeof(host)); +#else u_int32_t high_part, low_part; high_part = host >> 32; @@ -501,6 +506,7 @@ static inline void htoun64(void *network, u_int64_t host) memcpy(unaligned, &high_part, sizeof(high_part)); unaligned += sizeof(high_part); memcpy(unaligned, &low_part, sizeof(low_part)); +#endif } /** @@ -542,6 +548,13 @@ static inline u_int32_t untoh32(void *network) static inline u_int64_t untoh64(void *network) { char *unaligned = (char*)network; + +#ifdef be64toh + u_int64_t tmp; + + memcpy(&tmp, unaligned, sizeof(tmp)); + return be64toh(tmp); +#else u_int32_t high_part, low_part; memcpy(&high_part, unaligned, sizeof(high_part)); @@ -552,6 +565,7 @@ static inline u_int64_t untoh64(void *network) low_part = ntohl(low_part); return (((u_int64_t)high_part) << 32) + low_part; +#endif } /** |