summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ssl.c83
-rw-r--r--ssl.h4
-rw-r--r--ssl_backend.h23
-rw-r--r--ssl_common.h4
-rw-r--r--ssl_openssl.c92
5 files changed, 120 insertions, 86 deletions
diff --git a/ssl.c b/ssl.c
index 4c22a97..559c252 100644
--- 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 1743346..0e8a7ae 100644
--- a/ssl.h
+++ b/ssl.h
@@ -57,10 +57,6 @@
/* 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
diff --git a/ssl_backend.h b/ssl_backend.h
index f3f7202..1bce80d 100644
--- a/ssl_backend.h
+++ b/ssl_backend.h
@@ -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.
*/
diff --git a/ssl_common.h b/ssl_common.h
index 6aa70d0..7a95274 100644
--- a/ssl_common.h
+++ b/ssl_common.h
@@ -38,6 +38,10 @@
#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)
diff --git a/ssl_openssl.c b/ssl_openssl.c
index 77dd077..1ba73ef 100644
--- a/ssl_openssl.c
+++ b/ssl_openssl.c
@@ -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 ()
{