diff options
Diffstat (limited to 'src/libstrongswan/credentials/auth_cfg.c')
-rw-r--r-- | src/libstrongswan/credentials/auth_cfg.c | 327 |
1 files changed, 222 insertions, 105 deletions
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c index 12f75b240..2203519e2 100644 --- a/src/libstrongswan/credentials/auth_cfg.c +++ b/src/libstrongswan/credentials/auth_cfg.c @@ -17,26 +17,30 @@ #include "auth_cfg.h" #include <library.h> -#include <debug.h> -#include <utils/linked_list.h> +#include <utils/debug.h> +#include <collections/array.h> #include <utils/identification.h> #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, "RULE_IDENTITY", + "RULE_IDENTITY_LOOSE", "RULE_AUTH_CLASS", "RULE_AAA_IDENTITY", "RULE_EAP_IDENTITY", "RULE_EAP_TYPE", "RULE_EAP_VENDOR", + "RULE_XAUTH_BACKEND", + "RULE_XAUTH_IDENTITY", "RULE_CA_CERT", "RULE_IM_CERT", "RULE_SUBJECT_CERT", @@ -45,6 +49,7 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT, "RULE_GROUP", "RULE_RSA_STRENGTH", "RULE_ECDSA_STRENGTH", + "RULE_SIGNATURE_SCHEME", "RULE_CERT_POLICY", "HELPER_IM_CERT", "HELPER_SUBJECT_CERT", @@ -66,9 +71,11 @@ static inline bool is_multi_value_rule(auth_rule_t type) case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: case AUTH_RULE_IDENTITY: + case AUTH_RULE_IDENTITY_LOOSE: case AUTH_RULE_EAP_IDENTITY: case AUTH_RULE_AAA_IDENTITY: - case AUTH_RULE_SUBJECT_CERT: + case AUTH_RULE_XAUTH_IDENTITY: + case AUTH_RULE_XAUTH_BACKEND: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_RULE_MAX: @@ -76,9 +83,11 @@ static inline bool is_multi_value_rule(auth_rule_t type) case AUTH_RULE_OCSP_VALIDATION: case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_GROUP: + case AUTH_RULE_SUBJECT_CERT: case AUTH_RULE_CA_CERT: case AUTH_RULE_IM_CERT: case AUTH_RULE_CERT_POLICY: + case AUTH_RULE_SIGNATURE_SCHEME: case AUTH_HELPER_IM_CERT: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: @@ -100,9 +109,9 @@ struct private_auth_cfg_t { auth_cfg_t public; /** - * list of entry_t + * Array of entry_t */ - linked_list_t *entries; + array_t *entries; }; typedef struct entry_t entry_t; @@ -175,21 +184,20 @@ METHOD(auth_cfg_t, create_enumerator, enumerator_t*, .enumerate = (void*)enumerate, .destroy = (void*)entry_enumerator_destroy, }, - .inner = this->entries->create_enumerator(this->entries), + .inner = array_create_enumerator(this->entries), ); return &enumerator->public; } /** - * Create an entry from the given arguments. + * Initialize an entry. */ -static entry_t *entry_create(auth_rule_t type, va_list args) +static void init_entry(entry_t *this, auth_rule_t type, va_list args) { - entry_t *this = malloc_thing(entry_t); - this->type = type; switch (type) { + case AUTH_RULE_IDENTITY_LOOSE: case AUTH_RULE_AUTH_CLASS: case AUTH_RULE_EAP_TYPE: case AUTH_RULE_EAP_VENDOR: @@ -197,12 +205,15 @@ static entry_t *entry_create(auth_rule_t type, va_list args) case AUTH_RULE_OCSP_VALIDATION: case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: + case AUTH_RULE_SIGNATURE_SCHEME: /* integer type */ this->value = (void*)(uintptr_t)va_arg(args, u_int); break; 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: @@ -220,7 +231,6 @@ static entry_t *entry_create(auth_rule_t type, va_list args) this->value = NULL; break; } - return this; } /** @@ -234,6 +244,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2) } switch (e1->type) { + case AUTH_RULE_IDENTITY_LOOSE: case AUTH_RULE_AUTH_CLASS: case AUTH_RULE_EAP_TYPE: case AUTH_RULE_EAP_VENDOR: @@ -241,6 +252,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2) case AUTH_RULE_OCSP_VALIDATION: case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: + case AUTH_RULE_SIGNATURE_SCHEME: { return e1->value == e2->value; } @@ -261,6 +273,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 +284,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 +307,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,12 +325,14 @@ 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: { free(entry->value); break; } + case AUTH_RULE_IDENTITY_LOOSE: case AUTH_RULE_AUTH_CLASS: case AUTH_RULE_EAP_TYPE: case AUTH_RULE_EAP_VENDOR: @@ -323,6 +340,7 @@ static void destroy_entry_value(entry_t *entry) case AUTH_RULE_OCSP_VALIDATION: case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: + case AUTH_RULE_SIGNATURE_SCHEME: case AUTH_RULE_MAX: break; } @@ -345,6 +363,7 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator, entry->type = type; switch (type) { + case AUTH_RULE_IDENTITY_LOOSE: case AUTH_RULE_AUTH_CLASS: case AUTH_RULE_EAP_TYPE: case AUTH_RULE_EAP_VENDOR: @@ -352,12 +371,15 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator, case AUTH_RULE_OCSP_VALIDATION: case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: + case AUTH_RULE_SIGNATURE_SCHEME: /* integer type */ entry->value = (void*)(uintptr_t)va_arg(args, u_int); break; 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: @@ -423,12 +445,18 @@ METHOD(auth_cfg_t, get, void*, case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: return (void*)0; + case AUTH_RULE_SIGNATURE_SCHEME: + return HASH_UNKNOWN; case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_OCSP_VALIDATION: return (void*)VALIDATION_FAILED; + case AUTH_RULE_IDENTITY_LOOSE: + return (void*)FALSE; 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: @@ -450,21 +478,21 @@ METHOD(auth_cfg_t, get, void*, */ static void add(private_auth_cfg_t *this, auth_rule_t type, ...) { - entry_t *entry; + entry_t entry; va_list args; va_start(args, type); - entry = entry_create(type, args); + init_entry(&entry, type, args); va_end(args); if (is_multi_value_rule(type)) { /* insert rules that may occur multiple times at the end */ - this->entries->insert_last(this->entries, entry); + array_insert(this->entries, ARRAY_TAIL, &entry); } else { /* insert rules we expect only once at the front (get() will return * the latest value) */ - this->entries->insert_first(this->entries, entry); + array_insert(this->entries, ARRAY_HEAD, &entry); } } @@ -472,7 +500,11 @@ METHOD(auth_cfg_t, complies, bool, private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error) { enumerator_t *e1, *e2; - bool success = TRUE, has_group = FALSE, group_match = FALSE; + bool success = TRUE, group_match = FALSE, cert_match = FALSE; + identification_t *require_group = NULL; + certificate_t *require_cert = NULL; + signature_scheme_t scheme = SIGN_UNKNOWN; + u_int strength = 0; auth_rule_t t1, t2; void *value; @@ -508,20 +540,21 @@ METHOD(auth_cfg_t, complies, bool, } case AUTH_RULE_SUBJECT_CERT: { - certificate_t *c1, *c2; + certificate_t *cert; - c1 = (certificate_t*)value; - c2 = get(this, AUTH_RULE_SUBJECT_CERT); - if (!c2 || !c1->equals(c1, c2)) + /* for certs, a match of a single cert is sufficient */ + require_cert = (certificate_t*)value; + + e2 = create_enumerator(this); + while (e2->enumerate(e2, &t2, &cert)) { - success = FALSE; - if (log_error) + if (t2 == AUTH_RULE_SUBJECT_CERT && + cert->equals(cert, require_cert)) { - DBG1(DBG_CFG, "constraint check failed: peer not " - "authenticated with peer cert '%Y'.", - c1->get_subject(c1)); + cert_match = TRUE; } } + e2->destroy(e2); break; } case AUTH_RULE_CRL_VALIDATION: @@ -571,6 +604,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; @@ -578,6 +612,17 @@ METHOD(auth_cfg_t, complies, bool, id2 = get(this, t1); if (!id2 || !id2->matches(id2, id1)) { + if (t1 == AUTH_RULE_IDENTITY && + constraints->get(constraints, AUTH_RULE_IDENTITY_LOOSE)) + { /* also verify identity against subjectAltNames */ + certificate_t *cert; + + cert = get(this, AUTH_HELPER_SUBJECT_CERT); + if (cert && cert->has_subject(cert, id1)) + { + break; + } + } success = FALSE; if (log_error) { @@ -633,15 +678,15 @@ METHOD(auth_cfg_t, complies, bool, } case AUTH_RULE_GROUP: { - identification_t *id1, *id2; + identification_t *group; /* for groups, a match of a single group is sufficient */ - has_group = TRUE; - id1 = (identification_t*)value; + require_group = (identification_t*)value; e2 = create_enumerator(this); - while (e2->enumerate(e2, &t2, &id2)) + while (e2->enumerate(e2, &t2, &group)) { - if (t2 == AUTH_RULE_GROUP && id2->matches(id2, id1)) + if (t2 == AUTH_RULE_GROUP && + group->matches(group, require_group)) { group_match = TRUE; } @@ -652,44 +697,12 @@ METHOD(auth_cfg_t, complies, bool, case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: { - uintptr_t strength; - - e2 = create_enumerator(this); - while (e2->enumerate(e2, &t2, &strength)) - { - if (t2 == t1) - { - if ((uintptr_t)value > strength) - { - success = FALSE; - if (log_error) - { - DBG1(DBG_CFG, "constraint requires %d bit " - "public keys, but %d bit key used", - (uintptr_t)value, strength); - } - } - } - else if (t2 == AUTH_RULE_RSA_STRENGTH) - { - success = FALSE; - if (log_error) - { - DBG1(DBG_CFG, "constraint requires %d bit ECDSA, " - "but RSA used", (uintptr_t)value); - } - } - else if (t2 == AUTH_RULE_ECDSA_STRENGTH) - { - success = FALSE; - if (log_error) - { - DBG1(DBG_CFG, "constraint requires %d bit RSA, " - "but ECDSA used", (uintptr_t)value); - } - } - } - e2->destroy(e2); + strength = (uintptr_t)value; + break; + } + case AUTH_RULE_SIGNATURE_SCHEME: + { + scheme = (uintptr_t)value; break; } case AUTH_RULE_CERT_POLICY: @@ -714,6 +727,10 @@ METHOD(auth_cfg_t, complies, bool, } break; } + case AUTH_RULE_IDENTITY_LOOSE: + /* just an indication when verifying AUTH_RULE_IDENTITY */ + 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: @@ -730,11 +747,94 @@ METHOD(auth_cfg_t, complies, bool, } e1->destroy(e1); - if (has_group && !group_match) + /* Check if we have a matching constraint (or none at all) for used + * 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); + } + + /* Check if we have a matching constraint (or none at all) for used + * public key strength */ + if (success && strength) + { + e2 = create_enumerator(this); + while (e2->enumerate(e2, &t2, &strength)) + { + if (t2 == AUTH_RULE_RSA_STRENGTH || + t2 == AUTH_RULE_ECDSA_STRENGTH) + { + success = FALSE; + e1 = constraints->create_enumerator(constraints); + while (e1->enumerate(e1, &t1, &value)) + { + if (t1 == t2 && (uintptr_t)value <= strength) + { + success = TRUE; + break; + } + } + e1->destroy(e1); + if (!success) + { + if (log_error) + { + DBG1(DBG_CFG, "%s-%d signatures not acceptable", + t2 == AUTH_RULE_RSA_STRENGTH ? "RSA" : "ECDSA", + strength); + } + break; + } + } + } + e2->destroy(e2); + } + + if (require_group && !group_match) { if (log_error) { - DBG1(DBG_CFG, "constraint check failed: group membership required"); + DBG1(DBG_CFG, "constraint check failed: group membership to " + "'%Y' required", require_group); + } + return FALSE; + } + + if (require_cert && !cert_match) + { + if (log_error) + { + DBG1(DBG_CFG, "constraint check failed: peer not " + "authenticated with peer cert '%Y'.", + require_cert->get_subject(require_cert)); } return FALSE; } @@ -774,6 +874,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy add(this, type, cert->get_ref(cert)); break; } + case AUTH_RULE_IDENTITY_LOOSE: case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_OCSP_VALIDATION: case AUTH_RULE_AUTH_CLASS: @@ -781,6 +882,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy case AUTH_RULE_EAP_VENDOR: case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: + case AUTH_RULE_SIGNATURE_SCHEME: { add(this, type, (uintptr_t)value); break; @@ -789,12 +891,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: @@ -810,20 +914,20 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy } else { - entry_t *entry; + entry_t entry; - while (other->entries->remove_first(other->entries, - (void**)&entry) == SUCCESS) + while (array_remove(other->entries, ARRAY_HEAD, &entry)) { - this->entries->insert_last(this->entries, entry); + array_insert(this->entries, ARRAY_TAIL, &entry); } + array_compress(other->entries); } } /** - * Implementation of auth_cfg_t.equals. + * Compare two auth_cfg_t objects for equality. */ -static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other) +static bool auth_cfg_equals(private_auth_cfg_t *this, private_auth_cfg_t *other) { enumerator_t *e1, *e2; entry_t *i1, *i2; @@ -831,12 +935,12 @@ static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other) /* the rule count does not have to be equal for the two, as we only compare * the first value found for some rules */ - e1 = this->entries->create_enumerator(this->entries); + e1 = array_create_enumerator(this->entries); while (e1->enumerate(e1, &i1)) { found = FALSE; - e2 = other->entries->create_enumerator(other->entries); + e2 = array_create_enumerator(other->entries); while (e2->enumerate(e2, &i2)) { if (entry_equals(i1, i2)) @@ -860,30 +964,38 @@ static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other) return equal; } +/** + * Implementation of auth_cfg_t.equals. + */ +static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other) +{ + if (auth_cfg_equals(this, other)) + { + /* as 'other' might contain entries that 'this' doesn't we also check + * the other way around */ + return auth_cfg_equals(other, this); + } + return FALSE; +} + METHOD(auth_cfg_t, purge, void, private_auth_cfg_t *this, bool keep_ca) { + enumerator_t *enumerator; entry_t *entry; - linked_list_t *cas; - cas = linked_list_create(); - while (this->entries->remove_last(this->entries, (void**)&entry) == SUCCESS) + enumerator = array_create_enumerator(this->entries); + while (enumerator->enumerate(enumerator, &entry)) { - if (keep_ca && entry->type == AUTH_RULE_CA_CERT) - { - cas->insert_first(cas, entry); - } - else + if (!keep_ca || entry->type != AUTH_RULE_CA_CERT) { + array_remove_at(this->entries, enumerator); destroy_entry_value(entry); - free(entry); } } - while (cas->remove_last(cas, (void**)&entry) == SUCCESS) - { - this->entries->insert_first(this->entries, entry); - } - cas->destroy(cas); + enumerator->destroy(enumerator); + + array_compress(this->entries); } METHOD(auth_cfg_t, clone_, auth_cfg_t*, @@ -891,22 +1003,24 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, { enumerator_t *enumerator; auth_cfg_t *clone; - entry_t *entry; + auth_rule_t type; + void *value; clone = auth_cfg_create(); /* this enumerator skips duplicates for rules we expect only once */ - enumerator = this->entries->create_enumerator(this->entries); - while (enumerator->enumerate(enumerator, &entry)) + enumerator = create_enumerator(this); + while (enumerator->enumerate(enumerator, &type, &value)) { - switch (entry->type) + switch (type) { case AUTH_RULE_IDENTITY: 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)); + identification_t *id = (identification_t*)value; + clone->add(clone, type, id->clone(id)); break; } case AUTH_RULE_CA_CERT: @@ -916,17 +1030,19 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_REVOCATION_CERT: { - certificate_t *cert = (certificate_t*)entry->value; - clone->add(clone, entry->type, cert->get_ref(cert)); + certificate_t *cert = (certificate_t*)value; + clone->add(clone, 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: { - clone->add(clone, entry->type, strdup(entry->value)); + clone->add(clone, type, strdup(value)); break; } + case AUTH_RULE_IDENTITY_LOOSE: case AUTH_RULE_AUTH_CLASS: case AUTH_RULE_EAP_TYPE: case AUTH_RULE_EAP_VENDOR: @@ -934,7 +1050,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, case AUTH_RULE_OCSP_VALIDATION: case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: - clone->add(clone, entry->type, (uintptr_t)entry->value); + case AUTH_RULE_SIGNATURE_SCHEME: + clone->add(clone, type, (uintptr_t)value); break; case AUTH_RULE_MAX: break; @@ -948,7 +1065,7 @@ METHOD(auth_cfg_t, destroy, void, private_auth_cfg_t *this) { purge(this, FALSE); - this->entries->destroy(this->entries); + array_destroy(this->entries); free(this); } @@ -972,7 +1089,7 @@ auth_cfg_t *auth_cfg_create() .clone = _clone_, .destroy = _destroy, }, - .entries = linked_list_create(), + .entries = array_create(sizeof(entry_t), 0), ); return &this->public; |