diff options
-rw-r--r-- | ssl.c | 195 | ||||
-rw-r--r-- | ssl_backend.h | 35 | ||||
-rw-r--r-- | ssl_openssl.c | 208 |
3 files changed, 248 insertions, 190 deletions
@@ -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 () { |