implementation of strictcrlpolicy=ifuri
authorAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 20 Apr 2007 11:12:08 +0000 (11:12 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 20 Apr 2007 11:12:08 +0000 (11:12 -0000)
src/charon/config/credentials/local_credential_store.c
src/charon/config/credentials/local_credential_store.h
src/charon/daemon.c
src/libstrongswan/crypto/ca.c
src/libstrongswan/crypto/ca.h
src/libstrongswan/library.h
src/starter/args.c
src/starter/confread.h
src/starter/invokecharon.c

index bee7fce..82ea787 100644 (file)
@@ -171,11 +171,6 @@ struct private_local_credential_store_t {
         * list of X.509 CA information records
         */
        linked_list_t *ca_infos;
-
-       /**
-        * enforce strict crl policy
-        */
-       bool strict;
 };
 
 
@@ -304,6 +299,29 @@ static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *th
 }
 
 /**
+ * Implementation of credential_store_t.get_issuer.
+ */
+static ca_info_t* get_issuer(private_local_credential_store_t *this, const x509_t *cert)
+{
+       ca_info_t *found = NULL;
+       ca_info_t *ca_info;
+
+       iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
+
+       while (iterator->iterate(iterator, (void**)&ca_info))
+       {
+               if (ca_info->is_cert_issuer(ca_info, cert))
+               {
+                       found = ca_info;
+                       break;
+               }
+       }
+       iterator->destroy(iterator);
+
+       return found;
+}
+
+/**
  * Implementation of local_credential_store_t.get_trusted_public_key.
  */
 static rsa_public_key_t *get_trusted_public_key(private_local_credential_store_t *this,
@@ -324,18 +342,30 @@ static rsa_public_key_t *get_trusted_public_key(private_local_credential_store_t
                return NULL;
        }
 
-       status = cert->get_status(cert);
-       if (status == CERT_REVOKED || status == CERT_UNTRUSTED || (this->strict && status != CERT_GOOD))
-       {
-               DBG1(DBG_CFG, "certificate status: %N", cert_status_names, status);
-               return NULL;
-       }
-       if (status == CERT_GOOD && cert->get_until(cert) < time(NULL))
+       if (!cert->is_self_signed(cert))
        {
-               DBG1(DBG_CFG, "certificate is good but crl is stale");
-               return NULL;
-       }
+               ca_info_t *issuer = get_issuer(this, cert);
 
+               if (issuer == NULL)
+               {
+                       DBG1(DBG_CFG, "issuer of public key not found");
+                       return NULL;
+               }
+               status = cert->get_status(cert);
+
+               if (status == CERT_REVOKED
+               ||  status == CERT_UNTRUSTED
+               || (issuer->is_strict(issuer) && status != CERT_GOOD))
+               {
+                       DBG1(DBG_CFG, "certificate status: %N", cert_status_names, status);
+                       return NULL;
+               }
+               if (status == CERT_GOOD && cert->get_until(cert) < time(NULL))
+               {
+                       DBG1(DBG_CFG, "certificate is good but crl is stale");
+                       return NULL;
+               }
+       }
        return cert->get_public_key(cert);
 }
 
@@ -437,29 +467,6 @@ static x509_t* get_ca_certificate_by_keyid(private_local_credential_store_t *thi
 }
 
 /**
- * Implementation of credential_store_t.get_issuer.
- */
-static ca_info_t* get_issuer(private_local_credential_store_t *this, const x509_t *cert)
-{
-       ca_info_t *found = NULL;
-       ca_info_t *ca_info;
-
-       iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
-
-       while (iterator->iterate(iterator, (void**)&ca_info))
-       {
-               if (ca_info->is_cert_issuer(ca_info, cert))
-               {
-                       found = ca_info;
-                       break;
-               }
-       }
-       iterator->destroy(iterator);
-
-       return found;
-}
-
-/**
  * Find an exact copy of a certificate in a linked list
  */
 static x509_t* find_certificate(linked_list_t *certs, x509_t *cert)
@@ -649,6 +656,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
                }
                else
                {
+                       bool strict;
                        time_t nextUpdate;
                        cert_status_t status;
                        certinfo_t *certinfo = certinfo_create(cert->get_serialNumber(cert));
@@ -661,11 +669,15 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
                                add_uris(issuer, cert);
                        }
 
+                       strict = issuer->is_strict(issuer);
+                       DBG1(DBG_CFG, "issuer %s a strict crl policy",
+                                strict ? "enforces":"does not enforce");
+
                        /* first check certificate revocation using ocsp */
                        status = issuer->verify_by_ocsp(issuer, certinfo, &this->public.credential_store);
 
                        /* if ocsp service is not available then fall back to crl */
-                       if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && this->strict))
+                       if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && strict))
                        {
                                status = issuer->verify_by_crl(issuer, certinfo, CRL_DIR);
                        }
@@ -680,7 +692,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
                                        cert->set_until(cert, nextUpdate);
 
                                        /* if status information is stale */
-                                       if (this->strict && nextUpdate < time(NULL))
+                                       if (strict && nextUpdate < time(NULL))
                                        {
                                                DBG2(DBG_CFG, "certificate is good but status is stale");
                                                certinfo->destroy(certinfo);
@@ -691,7 +703,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
                                        /* with strict crl policy the public key must have the same
                                         * lifetime as the validity of the ocsp status or crl lifetime
                                         */
-                                       if (this->strict && nextUpdate < until)
+                                       if (strict && nextUpdate < until)
                                        until = nextUpdate;
                                        break;
                                case CERT_REVOKED:
@@ -726,7 +738,7 @@ static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *f
                                case CERT_UNDEFINED:
                                default:
                                        DBG1(DBG_CFG, "certificate status unknown");
-                                       if (this->strict)
+                                       if (strict)
                                        {
                                                /* update status of end certificate in the credential store */
                                                if (cert_copy)
@@ -1391,7 +1403,7 @@ static void destroy(private_local_credential_store_t *this)
 /**
  * Described in header.
  */
-local_credential_store_t * local_credential_store_create(bool strict)
+local_credential_store_t * local_credential_store_create(void)
 {
        private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t);
        
@@ -1429,7 +1441,6 @@ local_credential_store_t * local_credential_store_create(bool strict)
        this->certs = linked_list_create();
        this->auth_certs = linked_list_create();
        this->ca_infos = linked_list_create();
-       this->strict = strict;
 
        return (&this->public);
 }
index 88a94d6..87a1266 100644 (file)
@@ -54,11 +54,10 @@ struct local_credential_store_t {
 /**
  * @brief Creates a local_credential_store_t instance.
  *
- * @param  strict              enforce a strict crl policy
  * @return                             credential store instance.
  *
  * @ingroup config
  */
-local_credential_store_t *local_credential_store_create(bool strict);
+local_credential_store_t *local_credential_store_create(void);
 
 #endif /* LOCAL_CREDENTIAL_H_ */
index fb8acc5..d2b8d34 100644 (file)
@@ -220,8 +220,7 @@ static void kill_daemon(private_daemon_t *this, char *reason)
 /**
  * Initialize the daemon, optional with a strict crl policy
  */
-static void initialize(private_daemon_t *this, bool strict, bool syslog,
-                                          level_t levels[])
+static void initialize(private_daemon_t *this, bool syslog, level_t levels[])
 {
        credential_store_t* credentials;
        signal_t signal;
@@ -262,7 +261,7 @@ static void initialize(private_daemon_t *this, bool strict, bool syslog,
        this->public.ike_sa_manager = ike_sa_manager_create();
        this->public.job_queue = job_queue_create();
        this->public.event_queue = event_queue_create();
-       this->public.credentials = (credential_store_t*)local_credential_store_create(strict);
+       this->public.credentials = (credential_store_t*)local_credential_store_create();
        this->public.cfg_store = cfg_store_create();
        this->public.local_backend = local_backend_create();
        this->public.cfg_store->register_backend(this->public.cfg_store,
@@ -402,7 +401,7 @@ static void usage(const char *msg)
 int main(int argc, char *argv[])
 {
        u_int crl_check_interval = 0;
-       bool strict_crl_policy = FALSE;
+       strict_t strict_crl_policy = STRICT_NO;
        bool cache_crls = FALSE;
        bool use_syslog = FALSE;
        char *eapdir = IPSEC_EAPDIR;
@@ -428,7 +427,7 @@ int main(int argc, char *argv[])
                        { "help", no_argument, NULL, 'h' },
                        { "version", no_argument, NULL, 'v' },
                        { "use-syslog", no_argument, NULL, 'l' },
-                       { "strictcrlpolicy", no_argument, NULL, 'r' },
+                       { "strictcrlpolicy", required_argument, NULL, 'r' },
                        { "cachecrls", no_argument, NULL, 'C' },
                        { "crlcheckinterval", required_argument, NULL, 'x' },
                        { "eapdir", required_argument, NULL, 'e' },
@@ -461,7 +460,7 @@ int main(int argc, char *argv[])
                                use_syslog = TRUE;
                                continue;
                        case 'r':
-                               strict_crl_policy = TRUE;
+                               strict_crl_policy = atoi(optarg);
                                continue;
                        case 'C':
                                cache_crls = TRUE;
@@ -487,13 +486,13 @@ int main(int argc, char *argv[])
        charon = (daemon_t*)private_charon;
        
        /* initialize daemon */
-       initialize(private_charon, strict_crl_policy, use_syslog, levels);
+       initialize(private_charon, use_syslog, levels);
 
        /* load pluggable EAP modules */
        eap_method_load(eapdir);
        
-       /* set cache_crls and crl_check_interval options */
-       ca_info_set_options(cache_crls, crl_check_interval);
+       /* set strict_crl_policy, cache_crls and crl_check_interval options */
+       ca_info_set_options(strict_crl_policy, cache_crls, crl_check_interval);
 
        /* check/setup PID file */
        if (stat(PID_FILE, &stb) == 0)
index f08dba0..bb35b37 100644 (file)
@@ -100,6 +100,7 @@ struct private_ca_info_t {
 /**
  * static options set by ca_info_set_options()
  */
+static strict_t strict_crl_policy = STRICT_NO;
 static bool cache_crls = FALSE;
 static u_int crl_check_interval = 0;
 
@@ -157,6 +158,23 @@ static bool is_crl_issuer(private_ca_info_t *this, const crl_t *crl)
 }
 
 /**
+ * Implements ca_info_t.is_strict
+ */
+static bool is_strict(private_ca_info_t *this)
+{
+       bool strict = strict_crl_policy != STRICT_NO;
+
+       if (strict_crl_policy == STRICT_IFURI)
+       {
+               pthread_mutex_lock(&(this->mutex));
+               strict = this->crluris->get_count(this->crluris)   > 0 ||
+                                this->ocspuris->get_count(this->ocspuris) > 0;
+               pthread_mutex_unlock(&(this->mutex));
+       }
+       return strict;
+}
+
+/**
  * Implements ca_info_t.has_crl
  */
 static bool has_crl(private_ca_info_t *this)
@@ -728,8 +746,9 @@ static void list(private_ca_info_t* this, FILE* out, bool utc)
 /*
  * Described in header.
  */
-void ca_info_set_options(bool cache, u_int interval)
+void ca_info_set_options(strict_t strict, bool cache, u_int interval)
 {
+       strict_crl_policy = strict;
        cache_crls = cache;
        crl_check_interval = interval;
 }
@@ -759,6 +778,7 @@ ca_info_t *ca_info_create(const char *name, x509_t *cacert)
        this->public.equals_name_release_info = (bool (*) (ca_info_t*,const char*))equals_name_release_info;
        this->public.is_cert_issuer = (bool (*) (ca_info_t*,const x509_t*))is_cert_issuer;
        this->public.is_crl_issuer = (bool (*) (ca_info_t*,const crl_t*))is_crl_issuer;
+       this->public.is_strict = (bool (*) (ca_info_t*))is_strict;
        this->public.add_info = (void (*) (ca_info_t*,const ca_info_t*))add_info;
        this->public.add_crl = (void (*) (ca_info_t*,crl_t*))add_crl;
        this->public.has_crl = (bool (*) (ca_info_t*))has_crl;
index 46a1037..bce39fb 100644 (file)
@@ -26,7 +26,6 @@
 typedef struct ca_info_t ca_info_t;
 
 #include <library.h>
-#include <chunk.h>
 
 #include <credential_store.h>
 
@@ -81,6 +80,14 @@ struct ca_info_t {
        bool (*is_crl_issuer) (ca_info_t *this, const crl_t *crl);
 
        /**
+        * @brief Checks if the ca enforces a strict crl policy
+        * 
+        * @param this                  ca info object
+        * @return                              TRUE if the crl policy is strict
+        */
+       bool (*is_strict) (ca_info_t *this);
+
+       /**
         * @brief Merges info from a secondary ca info object
         * 
         * @param this                  primary ca info object
@@ -209,7 +216,7 @@ struct ca_info_t {
  * 
  * @ingroup crypto
  */
-void ca_info_set_options(bool cache, u_int interval);
+void ca_info_set_options(strict_t strict, bool cache, u_int interval);
 
 /**
  * @brief Create a ca info record
index 7c7f087..67a05f1 100644 (file)
@@ -234,6 +234,15 @@ enum status_t {
 };
 
 /**
+ * used by strict_crl_policy
+ */
+typedef enum {
+       STRICT_NO,
+       STRICT_YES,
+       STRICT_IFURI
+} strict_t;
+
+/**
  * enum_names for type status_t.
  */
 extern enum_name_t *status_names;
index 82e957f..fb84248 100644 (file)
@@ -61,6 +61,12 @@ static const char *LST_sendcert[] = {
      NULL
 };
 
+static const char *LST_strict[] = {
+    "no",
+    "yes",
+    "ifuri",
+     NULL
+};
 static const char *LST_dpd_action[] = {
     "none",
     "clear",
@@ -160,7 +166,7 @@ static const token_info_t token_info[] =
     { ARG_UINT, offsetof(starter_config_t, setup.overridemtu), NULL                },
     { ARG_TIME, offsetof(starter_config_t, setup.crlcheckinterval), NULL           },
     { ARG_ENUM, offsetof(starter_config_t, setup.cachecrls), LST_bool              },
-    { ARG_ENUM, offsetof(starter_config_t, setup.strictcrlpolicy), LST_bool        },
+    { ARG_ENUM, offsetof(starter_config_t, setup.strictcrlpolicy), LST_strict      },
     { ARG_ENUM, offsetof(starter_config_t, setup.nocrsend), LST_bool               },
     { ARG_ENUM, offsetof(starter_config_t, setup.nat_traversal), LST_bool          },
     { ARG_TIME, offsetof(starter_config_t, setup.keep_alive), NULL                 },
index e0de683..2fe75fc 100644 (file)
@@ -46,6 +46,12 @@ typedef enum {
        KEY_EXCHANGE_IKEV2
 } keyexchange_t;
 
+typedef enum {
+       STRICT_NO,
+       STRICT_YES,
+       STRICT_IFURI
+} strict_t;
+
 typedef struct starter_end starter_end_t;
 
 struct starter_end {
@@ -156,23 +162,23 @@ struct starter_config {
                bool    plutostart;
 
                /* pluto/charon keywords */
-               char    **plutodebug;
-               char    *charondebug;
-               char    *prepluto;
-               char    *postpluto;
-               bool    uniqueids;
-               u_int   overridemtu;
-               u_int   crlcheckinterval;
-               bool    cachecrls;
-               bool    strictcrlpolicy;
-               bool    nocrsend;
-               bool    nat_traversal;
-               u_int   keep_alive;
-               char    *virtual_private;
-               char    *eapdir;
-               char    *pkcs11module;
-               bool    pkcs11keepstate;
-               bool    pkcs11proxy;
+               char     **plutodebug;
+               char     *charondebug;
+               char     *prepluto;
+               char     *postpluto;
+               bool     uniqueids;
+               u_int    overridemtu;
+               u_int    crlcheckinterval;
+               bool     cachecrls;
+               strict_t strictcrlpolicy;
+               bool     nocrsend;
+               bool     nat_traversal;
+               u_int    keep_alive;
+               char     *virtual_private;
+               char     *eapdir;
+               char     *pkcs11module;
+               bool     pkcs11keepstate;
+               bool     pkcs11proxy;
 
                /* KLIPS keywords */
                char    **klipsdebug;
index 94d046d..7e93b9a 100644 (file)
@@ -116,6 +116,7 @@ starter_start_charon (starter_config_t *cfg, bool debug)
     if (cfg->setup.strictcrlpolicy)
     {
        arg[argc++] = "--strictcrlpolicy";
+       arg[argc++] = cfg->setup.strictcrlpolicy == STRICT_IFURI ? "2":"1";
     }
     if (cfg->setup.cachecrls)
     {