Add a cert_validator hook allowing plugins to provide custom lifetime checking
authorMartin Willi <martin@revosec.ch>
Tue, 19 Feb 2013 10:26:21 +0000 (11:26 +0100)
committerMartin Willi <martin@revosec.ch>
Tue, 19 Feb 2013 13:31:18 +0000 (14:31 +0100)
src/libstrongswan/credentials/cert_validator.h
src/libstrongswan/credentials/credential_manager.c

index effc6b0..325fa0a 100644 (file)
@@ -35,6 +35,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.
         *
         * @param subject               subject certificate to check
index a427b57..44eaec6 100644 (file)
@@ -515,26 +515,64 @@ static void cache_queue(private_credential_manager_t *this)
 }
 
 /**
+ * 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
  */
 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))
-       {
-               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))
+       if (!check_lifetime(this, subject, "subject", pathlen, FALSE, auth) ||
+               !check_lifetime(this, issuer, "issuer", pathlen + 1, trusted, auth))
        {
-               DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
-                        &not_before, FALSE, &not_after, FALSE);
                return FALSE;
        }