summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ssl.c195
-rw-r--r--ssl_backend.h35
-rw-r--r--ssl_openssl.c208
3 files changed, 248 insertions, 190 deletions
diff --git a/ssl.c b/ssl.c
index fbc109b..99eca84 100644
--- 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
diff --git a/ssl_backend.h b/ssl_backend.h
index 024b547..c36f92e 100644
--- a/ssl_backend.h
+++ b/ssl_backend.h
@@ -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.
*/
diff --git a/ssl_openssl.c b/ssl_openssl.c
index 45b83d2..e71c9ef 100644
--- a/ssl_openssl.c
+++ b/ssl_openssl.c
@@ -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 ()
{