Add a cert_validator hook allowing plugins to provide custom lifetime checking

This commit is contained in:
Martin Willi 2013-02-19 11:26:21 +01:00
parent 790e00aaa9
commit de399f550d
2 changed files with 64 additions and 10 deletions

View File

@ -34,6 +34,22 @@ typedef struct cert_validator_t cert_validator_t;
*/
struct cert_validator_t {
/**
* Check the lifetime of a certificate.
*
* If this function returns SUCCESS or FAILED, the certificate lifetime is
* considered definitely (in-)valid, without asking other validators.
* If all registered validaters return NEED_MORE, the default
* lifetime check is performed.
*
* @param cert certificate to check lifetime
* @param pathlen the current length of the path bottom-up
* @param anchor is certificate trusted root anchor?
* @param auth container for resulting authentication info
* @return SUCCESS, FAILED or NEED_MORE to ask next validator
*/
status_t (*check_lifetime)(cert_validator_t *this, certificate_t *cert,
int pathlen, bool anchor, auth_cfg_t *auth);
/**
* Validate a subject certificate in relation to its issuer.
*

View File

@ -514,6 +514,52 @@ static void cache_queue(private_credential_manager_t *this)
this->queue_mutex->unlock(this->queue_mutex);
}
/**
* Use validators to check the lifetime of certificates
*/
static bool check_lifetime(private_credential_manager_t *this,
certificate_t *cert, char *label,
int pathlen, bool trusted, auth_cfg_t *auth)
{
time_t not_before, not_after;
cert_validator_t *validator;
enumerator_t *enumerator;
status_t status = NEED_MORE;
enumerator = this->validators->create_enumerator(this->validators);
while (enumerator->enumerate(enumerator, &validator))
{
if (!validator->check_lifetime)
{
continue;
}
status = validator->check_lifetime(validator, cert,
pathlen, trusted, auth);
if (status != NEED_MORE)
{
break;
}
}
enumerator->destroy(enumerator);
switch (status)
{
case NEED_MORE:
if (!cert->get_validity(cert, NULL, &not_before, &not_after))
{
DBG1(DBG_CFG, "%s certificate invalid (valid from %T to %T)",
label, &not_before, FALSE, &not_after, FALSE);
return FALSE;
}
return TRUE;
case SUCCESS:
return TRUE;
case FAILED:
default:
return FALSE;
}
}
/**
* check a certificate for its lifetime
*/
@ -521,20 +567,12 @@ static bool check_certificate(private_credential_manager_t *this,
certificate_t *subject, certificate_t *issuer, bool online,
int pathlen, bool trusted, auth_cfg_t *auth)
{
time_t not_before, not_after;
cert_validator_t *validator;
enumerator_t *enumerator;
if (!subject->get_validity(subject, NULL, &not_before, &not_after))
if (!check_lifetime(this, subject, "subject", pathlen, FALSE, auth) ||
!check_lifetime(this, issuer, "issuer", pathlen + 1, trusted, auth))
{
DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
&not_before, FALSE, &not_after, FALSE);
return FALSE;
}
if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
{
DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
&not_before, FALSE, &not_after, FALSE);
return FALSE;
}