diff options
-rw-r--r-- | ssl.c | 83 | ||||
-rw-r--r-- | ssl.h | 4 | ||||
-rw-r--r-- | ssl_backend.h | 23 | ||||
-rw-r--r-- | ssl_common.h | 4 | ||||
-rw-r--r-- | ssl_openssl.c | 92 |
5 files changed, 120 insertions, 86 deletions
@@ -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 { @@ -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 () { |