auth-cfg: Add support for identity based CA authentication constraints
Enforcing CA based constraints previously required the CA certificate file to be locally installed. This is problematic from a maintencance perspective when having many intermediate CAs, and is actually redundant if the client sends its intermediate cert in the request. The alternative was to use Distinguished Name matching in the subject identity to indirectly check for the issuing CA by some RDN field, such as OU. However, this requires trust in the intermediate CA to issue only certificates with legitime subject identities. This new approach checks for an intermediate CA by comparing the issuing identity. This does not require trust in the intermediate, as long as a path len constraint prevents that intermediate to issue further intermediate certificates.
This commit is contained in:
parent
7035340b21
commit
c70201f1e3
|
@ -42,6 +42,7 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_AC_CERT,
|
|||
"RULE_EAP_VENDOR",
|
||||
"RULE_XAUTH_BACKEND",
|
||||
"RULE_XAUTH_IDENTITY",
|
||||
"AUTH_RULE_CA_IDENTITY",
|
||||
"RULE_CA_CERT",
|
||||
"RULE_IM_CERT",
|
||||
"RULE_SUBJECT_CERT",
|
||||
|
@ -88,6 +89,7 @@ static inline bool is_multi_value_rule(auth_rule_t type)
|
|||
case AUTH_RULE_CRL_VALIDATION:
|
||||
case AUTH_RULE_GROUP:
|
||||
case AUTH_RULE_SUBJECT_CERT:
|
||||
case AUTH_RULE_CA_IDENTITY:
|
||||
case AUTH_RULE_CA_CERT:
|
||||
case AUTH_RULE_IM_CERT:
|
||||
case AUTH_RULE_CERT_POLICY:
|
||||
|
@ -226,6 +228,7 @@ static void init_entry(entry_t *this, auth_rule_t type, va_list args)
|
|||
case AUTH_RULE_XAUTH_BACKEND:
|
||||
case AUTH_RULE_XAUTH_IDENTITY:
|
||||
case AUTH_RULE_GROUP:
|
||||
case AUTH_RULE_CA_IDENTITY:
|
||||
case AUTH_RULE_CA_CERT:
|
||||
case AUTH_RULE_IM_CERT:
|
||||
case AUTH_RULE_SUBJECT_CERT:
|
||||
|
@ -287,6 +290,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2)
|
|||
return c1->equals(c1, c2);
|
||||
}
|
||||
case AUTH_RULE_IDENTITY:
|
||||
case AUTH_RULE_CA_IDENTITY:
|
||||
case AUTH_RULE_EAP_IDENTITY:
|
||||
case AUTH_RULE_AAA_IDENTITY:
|
||||
case AUTH_RULE_XAUTH_IDENTITY:
|
||||
|
@ -325,6 +329,7 @@ static void destroy_entry_value(entry_t *entry)
|
|||
switch (entry->type)
|
||||
{
|
||||
case AUTH_RULE_IDENTITY:
|
||||
case AUTH_RULE_CA_IDENTITY:
|
||||
case AUTH_RULE_EAP_IDENTITY:
|
||||
case AUTH_RULE_AAA_IDENTITY:
|
||||
case AUTH_RULE_GROUP:
|
||||
|
@ -406,6 +411,7 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator,
|
|||
entry->value = (void*)(uintptr_t)va_arg(args, u_int);
|
||||
break;
|
||||
case AUTH_RULE_IDENTITY:
|
||||
case AUTH_RULE_CA_IDENTITY:
|
||||
case AUTH_RULE_EAP_IDENTITY:
|
||||
case AUTH_RULE_AAA_IDENTITY:
|
||||
case AUTH_RULE_XAUTH_BACKEND:
|
||||
|
@ -486,6 +492,7 @@ METHOD(auth_cfg_t, get, void*,
|
|||
case AUTH_RULE_CERT_VALIDATION_SUSPENDED:
|
||||
return (void*)FALSE;
|
||||
case AUTH_RULE_IDENTITY:
|
||||
case AUTH_RULE_CA_IDENTITY:
|
||||
case AUTH_RULE_EAP_IDENTITY:
|
||||
case AUTH_RULE_AAA_IDENTITY:
|
||||
case AUTH_RULE_XAUTH_BACKEND:
|
||||
|
@ -808,8 +815,8 @@ METHOD(auth_cfg_t, complies, bool,
|
|||
enumerator_t *e1, *e2;
|
||||
bool success = TRUE, group_match = FALSE;
|
||||
bool ca_match = FALSE, cert_match = FALSE;
|
||||
identification_t *require_group = NULL;
|
||||
certificate_t *require_ca = NULL, *require_cert = NULL;
|
||||
identification_t *require_group = NULL, *require_ca = NULL;
|
||||
certificate_t *require_cert = NULL;
|
||||
signature_params_t *ike_scheme = NULL, *scheme = NULL;
|
||||
u_int strength = 0;
|
||||
auth_rule_t t1, t2;
|
||||
|
@ -824,16 +831,35 @@ METHOD(auth_cfg_t, complies, bool,
|
|||
case AUTH_RULE_CA_CERT:
|
||||
case AUTH_RULE_IM_CERT:
|
||||
{
|
||||
certificate_t *cert;
|
||||
certificate_t *cert, *ca;
|
||||
|
||||
/* for CA certs, a match of a single cert is sufficient */
|
||||
require_ca = (certificate_t*)value;
|
||||
ca = (certificate_t*)value;
|
||||
require_ca = ca->get_subject(ca);
|
||||
|
||||
e2 = create_enumerator(this);
|
||||
while (e2->enumerate(e2, &t2, &cert))
|
||||
{
|
||||
if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
|
||||
cert->equals(cert, require_ca))
|
||||
cert->equals(cert, ca))
|
||||
{
|
||||
ca_match = TRUE;
|
||||
}
|
||||
}
|
||||
e2->destroy(e2);
|
||||
break;
|
||||
}
|
||||
case AUTH_RULE_CA_IDENTITY:
|
||||
{
|
||||
certificate_t *cert;
|
||||
|
||||
require_ca = (identification_t*)value;
|
||||
|
||||
e2 = create_enumerator(this);
|
||||
while (e2->enumerate(e2, &t2, &cert))
|
||||
{
|
||||
if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
|
||||
cert->has_subject(cert, require_ca))
|
||||
{
|
||||
ca_match = TRUE;
|
||||
}
|
||||
|
@ -1138,8 +1164,7 @@ METHOD(auth_cfg_t, complies, bool,
|
|||
if (log_error)
|
||||
{
|
||||
DBG1(DBG_CFG, "constraint check failed: peer not "
|
||||
"authenticated by CA '%Y'",
|
||||
require_ca->get_subject(require_ca));
|
||||
"authenticated by CA '%Y'", require_ca);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1205,6 +1230,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
|
|||
break;
|
||||
}
|
||||
case AUTH_RULE_IDENTITY:
|
||||
case AUTH_RULE_CA_IDENTITY:
|
||||
case AUTH_RULE_EAP_IDENTITY:
|
||||
case AUTH_RULE_AAA_IDENTITY:
|
||||
case AUTH_RULE_GROUP:
|
||||
|
@ -1337,6 +1363,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
|
|||
switch (type)
|
||||
{
|
||||
case AUTH_RULE_IDENTITY:
|
||||
case AUTH_RULE_CA_IDENTITY:
|
||||
case AUTH_RULE_EAP_IDENTITY:
|
||||
case AUTH_RULE_AAA_IDENTITY:
|
||||
case AUTH_RULE_GROUP:
|
||||
|
|
|
@ -84,6 +84,8 @@ enum auth_rule_t {
|
|||
AUTH_RULE_XAUTH_BACKEND,
|
||||
/** XAuth identity to use or require, identification_t* */
|
||||
AUTH_RULE_XAUTH_IDENTITY,
|
||||
/** subject of certificate authority, identification_t* */
|
||||
AUTH_RULE_CA_IDENTITY,
|
||||
/** certificate authority, certificate_t* */
|
||||
AUTH_RULE_CA_CERT,
|
||||
/** intermediate certificate in trustchain, certificate_t* */
|
||||
|
|
Loading…
Reference in New Issue