diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-07-01 18:15:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-07-01 18:15:00 +0000 |
commit | a2a2e32c02643a0cec111511220227703fda1cd5 (patch) | |
tree | 69cc2b631234c2a8e026b9cd4d72676c61c594df /vio | |
parent | Releasing progress-linux version 1:10.11.8-1~progress7.99u1. (diff) | |
download | mariadb-a2a2e32c02643a0cec111511220227703fda1cd5.tar.xz mariadb-a2a2e32c02643a0cec111511220227703fda1cd5.zip |
Merging upstream version 1:11.4.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vio')
-rw-r--r-- | vio/viosslfactories.c | 243 |
1 files changed, 129 insertions, 114 deletions
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 289c28d4..8e76c814 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -20,10 +20,15 @@ #ifdef HAVE_OPENSSL #include <openssl/dh.h> #include <openssl/bn.h> +#include <openssl/x509.h> static my_bool ssl_algorithms_added = FALSE; static my_bool ssl_error_strings_loaded= FALSE; +#ifndef X509_VERSION_3 +#define X509_VERSION_3 2 +#endif + /* the function below was generated with "openssl dhparam -2 -C 2048" */ #ifndef HAVE_WOLFSSL static @@ -95,6 +100,61 @@ sslGetErrString(enum enum_ssl_init_error e) return ssl_error_string[e]; } +static EVP_PKEY *vio_keygen() +{ + EVP_PKEY_CTX *ctx; + EVP_PKEY *pkey = NULL; + + if (!(ctx= EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL))) + return NULL; + + if (EVP_PKEY_keygen_init(ctx) <= 0) + goto end; + + if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 4096) <= 0) + goto end; + + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) + pkey= NULL; /* just in case */ + +end: + EVP_PKEY_CTX_free(ctx); + return pkey; +} + +static X509 *vio_gencert(EVP_PKEY *pkey) +{ + X509 *x; + X509_NAME *name; + + if (!(x= X509_new())) + goto err; + + if (!X509_set_version(x, X509_VERSION_3)) + goto err; + if (!(name= X509_get_subject_name(x))) + goto err; + if (!X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, + (uchar*)STRING_WITH_LEN("MariaDB Server"), -1, 0)) + goto err; + if (!X509_set_issuer_name(x, name)) + goto err; + if (!X509_gmtime_adj(X509_get_notBefore(x), 0)) + goto err; + if (!X509_gmtime_adj(X509_get_notAfter(x), 60*60*24*365*10)) + goto err; + if (!X509_set_pubkey(x, pkey)) + goto err; + if (!X509_sign(x, pkey, EVP_sha256())) + goto err; + + return x; + +err: + X509_free(x); + return NULL; +} + static int vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file, my_bool is_client, enum enum_ssl_init_error* error) @@ -103,14 +163,38 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file, DBUG_PRINT("enter", ("ctx: %p cert_file: %s key_file: %s", ctx, cert_file, key_file)); - if (!cert_file && key_file) + if (!cert_file && !key_file) + { + if (!is_client) + { + EVP_PKEY *pkey; + X509 *x509; + if (!(pkey= vio_keygen()) || SSL_CTX_use_PrivateKey(ctx, pkey) < 1) + { + *error= SSL_INITERR_KEY; + fprintf(stderr, "SSL error: %s\n", sslGetErrString(*error)); + DBUG_RETURN(1); + } + + if (!(x509= vio_gencert(pkey)) || SSL_CTX_use_certificate(ctx, x509) < 1) + { + *error= SSL_INITERR_CERT; + fprintf(stderr, "SSL error: %s\n", sslGetErrString(*error)); + DBUG_RETURN(1); + } + EVP_PKEY_free(pkey); /* decrement refcnt */ + X509_free(x509); /* ditto */ + } + DBUG_RETURN(0); + } + + /* cert and key can be combined in one file */ + if (!cert_file) cert_file= key_file; - - if (!key_file && cert_file) + else if (!key_file) key_file= cert_file; - if (cert_file && - SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0) + if (SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0) { *error= SSL_INITERR_CERT; DBUG_PRINT("error",("%s from file '%s'", sslGetErrString(*error), cert_file)); @@ -121,8 +205,7 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file, DBUG_RETURN(1); } - if (key_file && - SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) + if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { *error= SSL_INITERR_KEY; DBUG_PRINT("error", ("%s from file '%s'", sslGetErrString(*error), key_file)); @@ -137,7 +220,7 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file, If certificate is used check if private key matches. Note, that server side has to use certificate. */ - if ((cert_file != NULL || !is_client) && !SSL_CTX_check_private_key(ctx)) + if (!SSL_CTX_check_private_key(ctx)) { *error= SSL_INITERR_NOMATCH; DBUG_PRINT("error", ("%s",sslGetErrString(*error))); @@ -221,52 +304,38 @@ static long vio_tls_protocol_options(ulonglong tls_version) return (disabled_tls_protocols | disabled_ssl_protocols); } +/* + If some optional parameters indicate empty strings, then + for compatibility with SSL libraries, replace them with NULL, + otherwise these libraries will try to open files with an empty + name, etc., and they will return an error code instead of performing + the necessary operations: +*/ +#define fix_value(X) if (X && !X[0]) X= NULL + /************************ VioSSLFd **********************************/ static struct st_VioSSLFd * -new_VioSSLFd(const char *key_file, const char *cert_file, - const char *ca_file, const char *ca_path, - const char *cipher, my_bool is_client_method, - enum enum_ssl_init_error *error, - const char *crl_file, const char *crl_path, ulonglong tls_version) +new_VioSSLFd(const char *key_file, const char *cert_file, const char *ca_file, + const char *ca_path, const char *cipher, my_bool is_client_method, + enum enum_ssl_init_error *error, const char *crl_file, + const char *crl_path, ulonglong tls_version) { struct st_VioSSLFd *ssl_fd; long ssl_ctx_options; DBUG_ENTER("new_VioSSLFd"); - /* - If some optional parameters indicate empty strings, then - for compatibility with SSL libraries, replace them with NULL, - otherwise these libraries will try to open files with an empty - name, etc., and they will return an error code instead performing - the necessary operations: - */ - if (ca_file && !ca_file[0]) - { - ca_file = NULL; - } - if (ca_path && !ca_path[0]) - { - ca_path = NULL; - } - if (crl_file && !crl_file[0]) - { - crl_file = NULL; - } - if (crl_path && !crl_path[0]) - { - crl_path = NULL; - } + fix_value(key_file); + fix_value(cert_file); + fix_value(ca_file); + fix_value(ca_path); + fix_value(crl_file); + fix_value(crl_path); + fix_value(cipher); DBUG_PRINT("enter", ("key_file: '%s' cert_file: '%s' ca_file: '%s' ca_path: '%s' " - "cipher: '%s' crl_file: '%s' crl_path: '%s'", - key_file ? key_file : "NULL", - cert_file ? cert_file : "NULL", - ca_file ? ca_file : "NULL", - ca_path ? ca_path : "NULL", - cipher ? cipher : "NULL", - crl_file ? crl_file : "NULL", - crl_path ? crl_path : "NULL")); + "cipher: '%s' crl_file: '%s' crl_path: '%s'", key_file, + cert_file, ca_file, ca_path, cipher, crl_file, crl_path)); vio_check_ssl_init(); @@ -395,6 +464,10 @@ err0: DBUG_RETURN(0); } +int always_ok(int preverify, X509_STORE_CTX* store) +{ + return 1; +} /************************ VioSSLConnectorFd **********************************/ struct st_VioSSLFd * @@ -404,55 +477,23 @@ new_VioSSLConnectorFd(const char *key_file, const char *cert_file, const char *crl_file, const char *crl_path) { struct st_VioSSLFd *ssl_fd; - int verify= SSL_VERIFY_PEER; - - if (ca_file && ! ca_file[0]) ca_file = NULL; - if (ca_path && ! ca_path[0]) ca_path = NULL; - if (crl_file && ! crl_file[0]) crl_file = NULL; - if (crl_path && ! crl_path[0]) crl_path = NULL; - - /* - If some optional parameters indicate empty strings, then - for compatibility with SSL libraries, replace them with NULL, - otherwise these libraries will try to open files with an empty - name, etc., and they will return an error code instead performing - the necessary operations: - */ - if (ca_file && !ca_file[0]) - { - ca_file = NULL; - } - if (ca_path && !ca_path[0]) - { - ca_path = NULL; - } - if (crl_file && !crl_file[0]) - { - crl_file = NULL; - } - if (crl_path && !crl_path[0]) - { - crl_path = NULL; - } + int (*cb)(int, X509_STORE_CTX *) = NULL; /* - Turn off verification of servers certificate if both - ca_file and ca_path is set to NULL + Don't abort when the certificate cannot be verified if neither + ca_file nor ca_path were set. */ - if (ca_file == 0 && ca_path == 0) - verify= SSL_VERIFY_NONE; + if ((ca_file == 0 || ca_file[0] == 0) && (ca_path == 0 || ca_path[0] == 0)) + cb= always_ok; - if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, - ca_path, cipher, TRUE, error, - crl_file, crl_path, 0))) + /* Init the VioSSLFd as a "connector" ie. the client side */ + if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, ca_path, cipher, + TRUE, error, crl_file, crl_path, 0))) { return 0; } - /* Init the VioSSLFd as a "connector" ie. the client side */ - - SSL_CTX_set_verify(ssl_fd->ssl_context, verify, NULL); - + SSL_CTX_set_verify(ssl_fd->ssl_context, SSL_VERIFY_PEER, cb); return ssl_fd; } @@ -468,38 +509,12 @@ new_VioSSLAcceptorFd(const char *key_file, const char *cert_file, struct st_VioSSLFd *ssl_fd; int verify= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; - /* - If some optional parameters indicate empty strings, then - for compatibility with SSL libraries, replace them with NULL, - otherwise these libraries will try to open files with an empty - name, etc., and they will return an error code instead performing - the necessary operations: - */ - if (ca_file && !ca_file[0]) - { - ca_file = NULL; - } - if (ca_path && !ca_path[0]) - { - ca_path = NULL; - } - if (crl_file && !crl_file[0]) - { - crl_file = NULL; - } - if (crl_path && !crl_path[0]) - { - crl_path = NULL; - } - - if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, - ca_path, cipher, FALSE, error, - crl_file, crl_path, tls_version))) + /* Init the the VioSSLFd as a "acceptor" ie. the server side */ + if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file, ca_path, cipher, + FALSE, error, crl_file, crl_path, tls_version))) { return 0; } - /* Init the the VioSSLFd as a "acceptor" ie. the server side */ - /* Set max number of cached sessions, returns the previous size */ SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128); |