mariadb/plugin/auth_mysql_sha2/ssl_stuff.c
Vladislav Vaintroub 6dd3decd28 MDEV-37339 errors about caching_sha2_password on server startup (WolfSSL)
With WolfSSL, the plugins is statically compiled, and enabled,
and defaults to autogenerating ssl keys, which was left unimplemented.
Thus, it spits out some [ERROR] on every startup.

Fixed by removing a couple some ifdefs. Allowed tcp_nossl to run on
Windows.

As WolfSSL is missing some APIs with FILE*, use related API that
accept BIO
, i.e
- BIO_new_file() instead of fopen()
- BIO_free instead of fclose()
- PEM_write_bio_PrivateKey() instead of PEM_write_PrivateKey()
- etc

A note about BIO and error reporting:
BIO_new_file sets the errno, therefore FILE_ERROR macro
produces good expected error messages, while SSL_ERROR unfortunately
creates something incomprehensible. Thus, FILE_ERROR is left in place
where it was used previously (fopen errors)

Curiously, removing APIs with FILE*, solves another bug MDEV-37343,
where server on Windows dies with obscure message as plugins tries to use
this function. OpenSSL_Applink supposed to be official solution against
such problems, but I could not get it to work properly, no matter how
much I tried. Avoiding APIs with FILE* in first place works best
2025-07-30 12:24:19 +02:00

126 lines
3.6 KiB
C

/*
Copyright (c) 2025, MariaDB plc
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#include "mysql_sha2.h"
#include <errno.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
/* openssl rsautl -decrypt -inkey private_key.pem -in src -out dst */
int ssl_decrypt(EVP_PKEY *pkey, unsigned char *src, size_t srclen,
unsigned char *dst, size_t *dstlen)
{
int res;
EVP_PKEY_CTX *ctx= EVP_PKEY_CTX_new(pkey, NULL);
if (!ctx)
return 1;
res= EVP_PKEY_decrypt_init(ctx) <= 0 ||
EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 ||
EVP_PKEY_decrypt(ctx, dst, dstlen, src, srclen) <= 0;
EVP_PKEY_CTX_free(ctx);
return res;
}
#define FILE_ERROR(op,file) \
do { \
my_printf_error(1, SELF ": failed to " op " %s: %iE", \
ME_ERROR_LOG_ONLY, file, errno); \
goto err; \
} while(0)
#define SSL_ERROR(op,file) \
do { \
unsigned long e= ERR_get_error(); \
my_printf_error(1, SELF ": failed to " op " %s: %lu - %s", \
ME_ERROR_LOG_ONLY, file, e, ERR_reason_error_string(e)); \
goto err; \
} while(0)
/*
openssl genrsa -out private_key.pem 2048
openssl rsa -in private_key.pem -pubout -out public_key.pem
*/
int ssl_genkeys()
{
EVP_PKEY *pkey;
BIO *bio= NULL;
if (!(pkey= EVP_RSA_gen(2048)))
goto err;
if (!(bio= BIO_new_file(private_key_path, "w")))
FILE_ERROR("write", private_key_path);
if (PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL) != 1)
SSL_ERROR("write", private_key_path);
BIO_free(bio);
if (!(bio= BIO_new_file(public_key_path, "w")))
FILE_ERROR("write", public_key_path);
if (PEM_write_bio_PUBKEY(bio, pkey) <= 0)
SSL_ERROR("write", public_key_path);
BIO_free(bio);
EVP_PKEY_free(pkey);
return 0;
err:
if (bio)
BIO_free(bio);
if (pkey)
EVP_PKEY_free(pkey);
return 1;
}
int ssl_loadkeys()
{
EVP_PKEY *pkey= 0;
BIO *bio;
size_t len;
if (!(bio= BIO_new_file(private_key_path, "r")))
FILE_ERROR("read", private_key_path);
if (!(pkey= PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)))
SSL_ERROR("read", private_key_path);
BIO_free(bio);
if (!(bio= BIO_new_file(public_key_path, "r")))
FILE_ERROR("read", public_key_path);
len= BIO_read(bio, public_key, sizeof(public_key));
if (len == sizeof(public_key))
{
my_printf_error(1, SELF ": failed to read %s: larger than %zu",
ME_ERROR_LOG_ONLY, private_key_path, sizeof(public_key)-1);
goto err;
}
BIO_free(bio);
public_key[len]= 0;
public_key_len= len;
private_key= pkey;
return 0;
err:
if (bio)
BIO_free(bio);
if (pkey)
EVP_PKEY_free(pkey);
return 1;
}