]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Refactored PKCS#12 key loading
authorAdriaan de Jong <dejong@fox-it.com>
Wed, 29 Jun 2011 14:51:16 +0000 (16:51 +0200)
committerDavid Sommerseth <davids@redhat.com>
Wed, 19 Oct 2011 20:31:46 +0000 (22:31 +0200)
Signed-off-by: Adriaan de Jong <dejong@fox-it.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Acked-by: James Yonan <james@openvpn.net>
Signed-off-by: David Sommerseth <davids@redhat.com>
ssl.c
ssl.h
ssl_backend.h
ssl_common.h
ssl_openssl.c

diff --git a/ssl.c b/ssl.c
index 4c22a97706edb7e83802bdab703eb8483c49f351..559c2529a0da50620577af4f8a182535eb11dd06 100644 (file)
--- a/ssl.c
+++ b/ssl.c
@@ -1989,86 +1989,9 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
 
   if (options->pkcs12_file)
     {
-      /* Use PKCS #12 file for key, cert and CA certs */
-
-      FILE *fp;
-      EVP_PKEY *pkey;
-      X509 *cert;
-      STACK_OF(X509) *ca = NULL;
-      PKCS12 *p12=NULL;
-      int i;
-      char password[256];
-
-#if ENABLE_INLINE_FILES
-      if (!strcmp (options->pkcs12_file, INLINE_FILE_TAG) && options->pkcs12_file_inline)
-       {
-         BIO *b64 = BIO_new (BIO_f_base64());
-         BIO *bio = BIO_new_mem_buf ((void *)options->pkcs12_file_inline, (int)strlen(options->pkcs12_file_inline));
-         ASSERT(b64 && bio);
-         BIO_push (b64, bio);
-         p12 = d2i_PKCS12_bio(b64, NULL);
-         if (!p12)
-           msg (M_SSLERR, "Error reading inline PKCS#12 file");
-         BIO_free (b64);
-         BIO_free (bio);
-       }
-      else
-#endif
-       {
-         /* Load the PKCS #12 file */
-         if (!(fp = fopen(options->pkcs12_file, "rb")))
-           msg (M_SSLERR, "Error opening file %s", options->pkcs12_file);
-         p12 = d2i_PKCS12_fp(fp, NULL);
-         fclose (fp);
-         if (!p12)
-           msg (M_SSLERR, "Error reading PKCS#12 file %s", options->pkcs12_file);
-       }
-
-      /* Parse the PKCS #12 file */
-      if (!PKCS12_parse(p12, "", &pkey, &cert, &ca))
-        {
-          pem_password_callback (password, sizeof(password) - 1, 0, NULL);
-          /* Reparse the PKCS #12 file with password */
-          ca = NULL;
-          if (!PKCS12_parse(p12, password, &pkey, &cert, &ca))
-           {
-#ifdef ENABLE_MANAGEMENT
-             if (management && (ERR_GET_REASON (ERR_peek_error()) == PKCS12_R_MAC_VERIFY_FAILURE))
-               management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL);
-#endif
-             PKCS12_free(p12);
-             goto err;
-           }
-        }
-      PKCS12_free(p12);
-
-      /* Load Certificate */
-      if (!SSL_CTX_use_certificate (ctx, cert))
-        msg (M_SSLERR, "Cannot use certificate");
-
-      /* Load Private Key */
-      if (!SSL_CTX_use_PrivateKey (ctx, pkey))
-        msg (M_SSLERR, "Cannot use private key");
-      warn_if_group_others_accessible (options->pkcs12_file);
-
-      /* Check Private Key */
-      if (!SSL_CTX_check_private_key (ctx))
-        msg (M_SSLERR, "Private key does not match the certificate");
-
-      /* Set Certificate Verification chain */
-      if (!options->ca_file)
-        {
-          if (ca && sk_X509_num(ca))
-            {
-              for (i = 0; i < sk_X509_num(ca); i++)
-                {
-                 if (!X509_STORE_add_cert(ctx->cert_store,sk_X509_value(ca, i)))
-                    msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)");
-                  if (options->tls_server && !SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i)))
-                    msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)");
-                }
-            }
-        }
+      if (0 != tls_ctx_load_pkcs12(new_ctx, options->pkcs12_file,
+         options->pkcs12_file_inline, !options->ca_file))
+        goto err;
     }
   else
     {
diff --git a/ssl.h b/ssl.h
index 1743346b5a2960e613c8815b85f4ace15fab298f..0e8a7ae4fccca553663f7a0ee7a11ab6efca73f9 100644 (file)
--- a/ssl.h
+++ b/ssl.h
 /* Used in the TLS PRF function */
 #define KEY_EXPANSION_ID "OpenVPN"
 
-/* passwords */
-#define UP_TYPE_AUTH        "Auth"
-#define UP_TYPE_PRIVATE_KEY "Private Key"
-
 /* packet opcode (high 5 bits) and key-id (low 3 bits) are combined in one byte */
 #define P_KEY_ID_MASK                  0x07
 #define P_OPCODE_SHIFT                 3
index f3f7202ad2f1b9905664940c06af5919f1930e39..1bce80dc17c043464ce4a8483588c84622837645 100644 (file)
@@ -116,7 +116,7 @@ bool tls_ctx_initialised(struct tls_root_ctx *ctx);
  */
 void tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags);
 
-/*
+/**
  * Load Diffie Hellman Parameters, and load them into the library-specific
  * TLS context.
  *
@@ -131,7 +131,26 @@ void tls_ctx_load_dh_params(struct tls_root_ctx *ctx, const char *dh_file
 #endif /* ENABLE_INLINE_FILES */
     );
 
-/*
+/**
+ * Load PKCS #12 file for key, cert and (optionally) CA certs, and add to
+ * library-specific TLS context.
+ *
+ * @param ctx                  TLS context to use
+ * @param pkcs12_file          The file name to load the information from, or
+ *                             "[[INLINE]]" in the case of inline files.
+ * @param pkcs12_file_inline   A string containing the information
+ *
+ * @return                     1 if an error occurred, 0 if parsing was
+ *                             successful.
+ */
+int tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,
+#if ENABLE_INLINE_FILES
+    const char *pkcs12_file_inline,
+#endif /* ENABLE_INLINE_FILES */
+    bool load_ca_file
+    );
+
+/**
  * Show the TLS ciphers that are available for us to use in the OpenSSL
  * library.
  */
index 6aa70d0162a41e56fc6da461ff577b7782c8c6bd..7a95274d1a78ffc308511bdadbc92257ae226109 100644 (file)
 
 #include "ssl_backend.h"
 
+/* passwords */
+#define UP_TYPE_AUTH        "Auth"
+#define UP_TYPE_PRIVATE_KEY "Private Key"
+
   /* configuration file boolean options */
 # define SSLF_CLIENT_CERT_NOT_REQUIRED (1<<0)
 # define SSLF_USERNAME_AS_COMMON_NAME  (1<<1)
index 77dd077f1ce582d6e7ea0fc68ca007b0f210fe32..1ba73ef43b8e09872ffd885de34bfc2b8a6c3d4f 100644 (file)
@@ -221,6 +221,98 @@ tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const char *dh_file
   DH_free (dh);
 }
 
+int
+tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,
+#if ENABLE_INLINE_FILES
+    const char *pkcs12_file_inline,
+#endif /* ENABLE_INLINE_FILES */
+    bool load_ca_file
+    )
+{
+  FILE *fp;
+  EVP_PKEY *pkey;
+  X509 *cert;
+  STACK_OF(X509) *ca = NULL;
+  PKCS12 *p12;
+  int i;
+  char password[256];
+
+  ASSERT(NULL != ctx);
+
+#if ENABLE_INLINE_FILES
+  if (!strcmp (pkcs12_file, INLINE_FILE_TAG) && pkcs12_file_inline)
+    {
+      BIO *b64 = BIO_new(BIO_f_base64());
+      BIO *bio = BIO_new_mem_buf((void *) pkcs12_file_inline,
+         (int) strlen(pkcs12_file_inline));
+      ASSERT(b64 && bio);
+      BIO_push(b64, bio);
+      p12 = d2i_PKCS12_bio(b64, NULL);
+      if (!p12)
+       msg(M_SSLERR, "Error reading inline PKCS#12 file");
+      BIO_free(b64);
+      BIO_free(bio);
+    }
+  else
+#endif
+    {
+      /* Load the PKCS #12 file */
+      if (!(fp = fopen(pkcs12_file, "rb")))
+       msg(M_SSLERR, "Error opening file %s", pkcs12_file);
+      p12 = d2i_PKCS12_fp(fp, NULL);
+      fclose(fp);
+      if (!p12)
+       msg(M_SSLERR, "Error reading PKCS#12 file %s", pkcs12_file);
+    }
+
+  /* Parse the PKCS #12 file */
+  if (!PKCS12_parse(p12, "", &pkey, &cert, &ca))
+   {
+     pem_password_callback (password, sizeof(password) - 1, 0, NULL);
+     /* Reparse the PKCS #12 file with password */
+     ca = NULL;
+     if (!PKCS12_parse(p12, password, &pkey, &cert, &ca))
+      {
+#ifdef ENABLE_MANAGEMENT
+             if (management && (ERR_GET_REASON (ERR_peek_error()) == PKCS12_R_MAC_VERIFY_FAILURE))
+               management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL);
+#endif
+       PKCS12_free(p12);
+       return 1;
+      }
+   }
+  PKCS12_free(p12);
+
+  /* Load Certificate */
+  if (!SSL_CTX_use_certificate (ctx->ctx, cert))
+   msg (M_SSLERR, "Cannot use certificate");
+
+  /* Load Private Key */
+  if (!SSL_CTX_use_PrivateKey (ctx->ctx, pkey))
+   msg (M_SSLERR, "Cannot use private key");
+  warn_if_group_others_accessible (pkcs12_file);
+
+  /* Check Private Key */
+  if (!SSL_CTX_check_private_key (ctx->ctx))
+   msg (M_SSLERR, "Private key does not match the certificate");
+
+  /* Set Certificate Verification chain */
+  if (load_ca_file)
+   {
+     if (ca && sk_X509_num(ca))
+      {
+       for (i = 0; i < sk_X509_num(ca); i++)
+         {
+             if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i)))
+             msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)");
+           if (!SSL_CTX_add_client_CA(ctx->ctx, sk_X509_value(ca, i)))
+             msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)");
+         }
+      }
+   }
+  return 0;
+}
+
 void
 show_available_tls_ciphers ()
 {