]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Refactored CA and extra certs code
authorAdriaan de Jong <dejong@fox-it.com>
Wed, 29 Jun 2011 16:28:02 +0000 (18:28 +0200)
committerDavid Sommerseth <davids@redhat.com>
Fri, 21 Oct 2011 08:53:31 +0000 (10:53 +0200)
Signed-off-by: Adriaan de Jong <dejong@fox-it.com>
Acked-by: David Sommerseth <davids@redhat.com>
Signed-off-by: David Sommerseth <davids@redhat.com>
ssl.c
ssl_backend.h
ssl_openssl.c

diff --git a/ssl.c b/ssl.c
index fbc109be9bde80c1ce97566cec59e7a5e1da3a4a..99eca844c9eae605d10e331ac1104eaf95f20364 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -1602,114 +1602,6 @@ tls_deauthenticate (struct tls_multi *multi)
     }
 }
 
-#if ENABLE_INLINE_FILES
-
-static int
-use_inline_load_verify_locations (SSL_CTX *ctx, const char *ca_string)
-{
-  X509_STORE *store = NULL;
-  X509* cert = NULL;
-  BIO *in = NULL;
-  int ret = 0;
-
-  in = BIO_new_mem_buf ((char *)ca_string, -1);
-  if (!in)
-    goto err;
-
-  for (;;)
-    {
-      if (!PEM_read_bio_X509 (in, &cert, 0, NULL))
-       {
-         ret = 1;
-         break;
-       }
-      if (!cert)
-       break;
-
-      store = SSL_CTX_get_cert_store (ctx);
-      if (!store)
-       break;
-
-      if (!X509_STORE_add_cert (store, cert))
-       break;
-
-      if (cert)
-       {
-         X509_free (cert);
-         cert = NULL;
-       }
-    }
-
- err:
-  if (cert)
-    X509_free (cert);
-  if (in)
-    BIO_free (in);
-  return ret;  
-}
-
-static int
-xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
-{
-  return(X509_NAME_cmp(*a,*b));
-}
-
-static STACK_OF(X509_NAME) *
-use_inline_load_client_CA_file (SSL_CTX *ctx, const char *ca_string)
-{
-  BIO *in = NULL;
-  X509 *x = NULL;
-  X509_NAME *xn = NULL;
-  STACK_OF(X509_NAME) *ret = NULL, *sk;
-
-  sk=sk_X509_NAME_new(xname_cmp);
-
-  in = BIO_new_mem_buf ((char *)ca_string, -1);
-  if (!in)
-    goto err;
-
-  if ((sk == NULL) || (in == NULL))
-    goto err;
-       
-  for (;;)
-    {
-      if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
-       break;
-      if (ret == NULL)
-       {
-         ret = sk_X509_NAME_new_null();
-         if (ret == NULL)
-           goto err;
-       }
-      if ((xn=X509_get_subject_name(x)) == NULL) goto err;
-      /* check for duplicates */
-      xn=X509_NAME_dup(xn);
-      if (xn == NULL) goto err;
-      if (sk_X509_NAME_find(sk,xn) >= 0)
-       X509_NAME_free(xn);
-      else
-       {
-         sk_X509_NAME_push(sk,xn);
-         sk_X509_NAME_push(ret,xn);
-       }
-    }
-
-  if (0)
-    {
-    err:
-      if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free);
-      ret=NULL;
-    }
-  if (sk != NULL) sk_X509_NAME_free(sk);
-  if (in != NULL) BIO_free(in);
-  if (x != NULL) X509_free(x);
-  if (ret != NULL)
-    ERR_clear_error();
-  return(ret);
-}
-
-#endif
-
 /*
  * Initialize SSL context.
  * All files are in PEM format.
@@ -1735,8 +1627,6 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
 
   tls_ctx_set_options(new_ctx, options->ssl_flags);
 
-  ctx = new_ctx->ctx;
-
   if (options->pkcs12_file)
     {
       if (0 != tls_ctx_load_pkcs12(new_ctx, options->pkcs12_file,
@@ -1783,94 +1673,19 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
        }
     }
 
+  ctx = new_ctx->ctx;
+
   if (options->ca_file || options->ca_path)
     {
-      int status;
-
-#if ENABLE_INLINE_FILES
-      if (options->ca_file && !strcmp (options->ca_file, INLINE_FILE_TAG) && options->ca_file_inline)
-       {
-         status = use_inline_load_verify_locations (ctx, options->ca_file_inline);
-       }
-      else
-#endif
-       {
-         /* Load CA file for verifying peer supplied certificate */
-         status = SSL_CTX_load_verify_locations (ctx, options->ca_file, NULL);
-       }
-      
-      if (!status)
-       msg (M_SSLERR, "Cannot load CA certificate file %s path %s (SSL_CTX_load_verify_locations)", np(options->ca_file), np(options->ca_path));
-
-      /* Set a store for certs (CA & CRL) with a lookup on the "capath" hash directory */
-      if (options->ca_path) {
-        X509_STORE *store = SSL_CTX_get_cert_store(ctx);
-
-        if (store)
-         {
-           X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
-           if (!X509_LOOKUP_add_dir(lookup, options->ca_path, X509_FILETYPE_PEM))
-             X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
-           else
-             msg(M_WARN, "WARNING: experimental option --capath %s", options->ca_path);
-#if OPENSSL_VERSION_NUMBER >= 0x00907000L
-           X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
-#else
-           msg(M_WARN, "WARNING: this version of OpenSSL cannot handle CRL files in capath");
-#endif
-         }
-       else
-          msg(M_SSLERR, "Cannot get certificate store (SSL_CTX_get_cert_store)");
-      }
-
-      /* Load names of CAs from file and use it as a client CA list */
-      if (options->ca_file && options->tls_server) {
-        STACK_OF(X509_NAME) *cert_names = NULL;
-#if ENABLE_INLINE_FILES
-       if (!strcmp (options->ca_file, INLINE_FILE_TAG) && options->ca_file_inline)
-         {
-           cert_names = use_inline_load_client_CA_file (ctx, options->ca_file_inline);
-         }
-       else
-#endif
-         {
-           cert_names = SSL_load_client_CA_file (options->ca_file);
-         }
-        if (!cert_names)
-          msg (M_SSLERR, "Cannot load CA certificate file %s (SSL_load_client_CA_file)", options->ca_file);
-       SSL_CTX_set_client_CA_list (ctx, cert_names);
-      }
+      tls_ctx_load_ca(new_ctx, options->ca_file, options->ca_file_inline,
+         options->ca_path, options->tls_server);
     }
 
   /* Load extra certificates that are part of our own certificate
      chain but shouldn't be included in the verify chain */
   if (options->extra_certs_file || options->extra_certs_file_inline)
     {
-      BIO *bio;
-      X509 *cert;
-#if ENABLE_INLINE_FILES
-      if (!strcmp (options->extra_certs_file, INLINE_FILE_TAG) && options->extra_certs_file_inline)
-       {
-         bio = BIO_new_mem_buf ((char *)options->extra_certs_file_inline, -1);
-       }
-      else
-#endif
-       {
-         bio = BIO_new(BIO_s_file());
-         if (BIO_read_filename(bio, options->extra_certs_file) <= 0)
-           msg (M_SSLERR, "Cannot load extra-certs file: %s", options->extra_certs_file);
-       }
-      for (;;)
-       {
-         cert = NULL;
-         if (!PEM_read_bio_X509 (bio, &cert, 0, NULL)) /* takes ownership of cert */
-           break;
-         if (!cert)
-           msg (M_SSLERR, "Error reading extra-certs certificate");
-         if (SSL_CTX_add_extra_chain_cert(ctx, cert) != 1)
-           msg (M_SSLERR, "Error adding extra-certs certificate");
-       }
-      BIO_free (bio);
+      tls_ctx_load_extra_certs(new_ctx, options->extra_certs_file, options->extra_certs_file_inline);
     }
 
 #if P2MP_SERVER
index 024b547f9d09e85988185404ccef391ff213780b..c36f92ee9b8c4035123c15aab706f7cba6a76f64 100644 (file)
@@ -227,6 +227,41 @@ int tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, X509 *cert);
 #endif
 
 /**
+ * Load certificate authority certificates from the given file or path.
+ *
+ * Note that not all SSL libraries support loading from a path.
+ *
+ * @param ctx                  TLS context to use
+ * @param ca_file              The file name to load the CAs from, or
+ *                             "[[INLINE]]" in the case of inline files.
+ * @param ca_file_inline       A string containing the CAs
+ * @param ca_path              The path to load the CAs from
+ */
+void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
+#if ENABLE_INLINE_FILES
+    const char *ca_file_inline,
+#endif
+    const char *ca_path, bool tls_server
+    );
+
+/**
+ * Load extra certificate authority certificates from the given file or path.
+ * These Load extra certificates that are part of our own certificate
+ * chain but shouldn't be included in the verify chain.
+ *
+ *
+ * @param ctx                          TLS context to use
+ * @param extra_certs_file             The file name to load the certs from, or
+ *                                     "[[INLINE]]" in the case of inline files.
+ * @param extra_certs_file_inline      A string containing the certs
+ */
+void tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file
+#if ENABLE_INLINE_FILES
+    , const char *extra_certs_file_inline
+#endif
+    );
+
+/*
  * Show the TLS ciphers that are available for us to use in the OpenSSL
  * library.
  */
index 45b83d2546fe5a9112432a5b5e999743e9d1b0ee..e71c9ef1f8b123466472f85552aa8807dd8bf7cf 100644 (file)
@@ -645,6 +645,214 @@ tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, X509 *cert)
 
 #endif
 
+#if ENABLE_INLINE_FILES
+static int
+xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
+{
+  return(X509_NAME_cmp(*a,*b));
+}
+
+static STACK_OF(X509_NAME) *
+use_inline_load_client_CA_file (SSL_CTX *ctx, const char *ca_string)
+{
+  BIO *in = NULL;
+  X509 *x = NULL;
+  X509_NAME *xn = NULL;
+  STACK_OF(X509_NAME) *ret = NULL, *sk;
+
+  sk=sk_X509_NAME_new(xname_cmp);
+
+  in = BIO_new_mem_buf ((char *)ca_string, -1);
+  if (!in)
+    goto err;
+
+  if ((sk == NULL) || (in == NULL))
+    goto err;
+
+  for (;;)
+    {
+      if (PEM_read_bio_X509(in,&x,NULL,NULL) == NULL)
+       break;
+      if (ret == NULL)
+       {
+         ret = sk_X509_NAME_new_null();
+         if (ret == NULL)
+           goto err;
+       }
+      if ((xn=X509_get_subject_name(x)) == NULL) goto err;
+      /* check for duplicates */
+      xn=X509_NAME_dup(xn);
+      if (xn == NULL) goto err;
+      if (sk_X509_NAME_find(sk,xn) >= 0)
+       X509_NAME_free(xn);
+      else
+       {
+         sk_X509_NAME_push(sk,xn);
+         sk_X509_NAME_push(ret,xn);
+       }
+    }
+
+  if (0)
+    {
+    err:
+      if (ret != NULL) sk_X509_NAME_pop_free(ret,X509_NAME_free);
+      ret=NULL;
+    }
+  if (sk != NULL) sk_X509_NAME_free(sk);
+  if (in != NULL) BIO_free(in);
+  if (x != NULL) X509_free(x);
+  if (ret != NULL)
+    ERR_clear_error();
+  return(ret);
+}
+
+static int
+use_inline_load_verify_locations (SSL_CTX *ctx, const char *ca_string)
+{
+  X509_STORE *store = NULL;
+  X509* cert = NULL;
+  BIO *in = NULL;
+  int ret = 0;
+
+  in = BIO_new_mem_buf ((char *)ca_string, -1);
+  if (!in)
+    goto err;
+
+  for (;;)
+    {
+      if (!PEM_read_bio_X509 (in, &cert, 0, NULL))
+       {
+         ret = 1;
+         break;
+       }
+      if (!cert)
+       break;
+
+      store = SSL_CTX_get_cert_store (ctx);
+      if (!store)
+       break;
+
+      if (!X509_STORE_add_cert (store, cert))
+       break;
+
+      if (cert)
+       {
+         X509_free (cert);
+         cert = NULL;
+       }
+    }
+
+ err:
+  if (cert)
+    X509_free (cert);
+  if (in)
+    BIO_free (in);
+  return ret;
+}
+#endif /* ENABLE_INLINE_FILES */
+
+void
+tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file,
+#if ENABLE_INLINE_FILES
+    const char *ca_file_inline,
+#endif
+    const char *ca_path, bool tls_server
+    )
+{
+  int status;
+
+  ASSERT(NULL != ctx);
+
+#if ENABLE_INLINE_FILES
+  if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline)
+       {
+         status = use_inline_load_verify_locations (ctx->ctx, ca_file_inline);
+       }
+  else
+#endif
+       {
+         /* Load CA file for verifying peer supplied certificate */
+         status = SSL_CTX_load_verify_locations (ctx->ctx, ca_file, ca_path);
+       }
+
+  if (!status)
+       msg (M_SSLERR, "Cannot load CA certificate file %s path %s (SSL_CTX_load_verify_locations)", np(ca_file), np(ca_path));
+
+  /* Set a store for certs (CA & CRL) with a lookup on the "capath" hash directory */
+  if (ca_path) {
+    X509_STORE *store = SSL_CTX_get_cert_store(ctx->ctx);
+
+    if (store)
+         {
+           X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
+           if (!X509_LOOKUP_add_dir(lookup, ca_path, X509_FILETYPE_PEM))
+             X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
+           else
+             msg(M_WARN, "WARNING: experimental option --capath %s", ca_path);
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+           X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
+#else
+           msg(M_WARN, "WARNING: this version of OpenSSL cannot handle CRL files in capath");
+#endif
+         }
+       else
+      msg(M_SSLERR, "Cannot get certificate store (SSL_CTX_get_cert_store)");
+  }
+
+  /* Load names of CAs from file and use it as a client CA list */
+  if (ca_file && tls_server) {
+    STACK_OF(X509_NAME) *cert_names = NULL;
+#if ENABLE_INLINE_FILES
+       if (!strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline)
+         {
+           cert_names = use_inline_load_client_CA_file (ctx->ctx, ca_file_inline);
+         }
+       else
+#endif
+         {
+           cert_names = SSL_load_client_CA_file (ca_file);
+         }
+    if (!cert_names)
+      msg (M_SSLERR, "Cannot load CA certificate file %s (SSL_load_client_CA_file)", ca_file);
+    SSL_CTX_set_client_CA_list (ctx->ctx, cert_names);
+  }
+
+}
+
+void
+tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file
+#if ENABLE_INLINE_FILES
+    , const char *extra_certs_file_inline
+#endif
+    )
+{
+  BIO *bio;
+  X509 *cert;
+#if ENABLE_INLINE_FILES
+  if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_file_inline)
+    {
+      bio = BIO_new_mem_buf ((char *)extra_certs_file_inline, -1);
+    }
+  else
+#endif
+    {
+      bio = BIO_new(BIO_s_file());
+      if (BIO_read_filename(bio, extra_certs_file) <= 0)
+       msg (M_SSLERR, "Cannot load extra-certs file: %s", extra_certs_file);
+    }
+  for (;;)
+    {
+      cert = NULL;
+      if (!PEM_read_bio_X509 (bio, &cert, 0, NULL)) /* takes ownership of cert */
+       break;
+      if (!cert)
+       msg (M_SSLERR, "Error reading extra-certs certificate");
+      if (SSL_CTX_add_extra_chain_cert(ctx->ctx, cert) != 1)
+       msg (M_SSLERR, "Error adding extra-certs certificate");
+    }
+  BIO_free (bio);
+}
+
 void
 show_available_tls_ciphers ()
 {