From 361715a0502b10d740f38886d85435e538c419c7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 25 Feb 2020 18:59:56 +0100 Subject: [PATCH 1/5] Abstract over crypto operations --- ext/mysqlnd/mysqlnd_auth.c | 136 +++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 59 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c index 14a65eed0dab0..c61ac2f8fec14 100644 --- a/ext/mysqlnd/mysqlnd_auth.c +++ b/ext/mysqlnd/mysqlnd_auth.c @@ -699,15 +699,56 @@ mysqlnd_xor_string(char * dst, const size_t dst_len, const char * xor_str, const #include #include +typedef RSA * mysqlnd_rsa_t; + +/* {{{ mysqlnd_sha256_get_rsa_from_pem */ +static mysqlnd_rsa_t +mysqlnd_sha256_get_rsa_from_pem(const char *buf, size_t len) +{ + RSA * ret = NULL; + BIO * bio = BIO_new_mem_buf(buf, len); + ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); + BIO_free(bio); + return ret; +} +/* }}} */ + +/* {{{ mysqlnd_sha256_public_encrypt */ +static zend_uchar * +mysqlnd_sha256_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t server_public_key, size_t passwd_len, size_t * auth_data_len, char *xor_str) +{ + zend_uchar * ret = NULL; + int server_public_key_len = RSA_size(server_public_key); + + DBG_ENTER("mysqlnd_sha256_public_encrypt"); + /* + Because RSA_PKCS1_OAEP_PADDING is used there is a restriction on the passwd_len. + RSA_PKCS1_OAEP_PADDING is recommended for new applications. See more here: + http://www.openssl.org/docs/crypto/RSA_public_encrypt.html + */ + if ((size_t) server_public_key_len - 41 <= passwd_len) { + /* password message is to long */ + SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long"); + DBG_ERR("password is too long"); + DBG_RETURN(NULL); + } + + *auth_data_len = server_public_key_len; + ret = malloc(*auth_data_len); + RSA_public_encrypt(passwd_len + 1, (zend_uchar *) xor_str, ret, server_public_key, RSA_PKCS1_OAEP_PADDING); + RSA_free(server_public_key); + DBG_RETURN(ret); +} +/* }}} */ /* {{{ mysqlnd_sha256_get_rsa_key */ -static RSA * +static mysqlnd_rsa_t mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn, const MYSQLND_SESSION_OPTIONS * const session_options, const MYSQLND_PFC_DATA * const pfc_data ) { - RSA * ret = NULL; + mysqlnd_rsa_t ret = NULL; const char * fname = (pfc_data->sha256_server_public_key && pfc_data->sha256_server_public_key[0] != '\0')? pfc_data->sha256_server_public_key: MYSQLND_G(sha256_server_public_key); @@ -739,11 +780,7 @@ mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn, } DBG_INF_FMT("Public key(%d):\n%s", pk_resp_packet.public_key_len, pk_resp_packet.public_key); /* now extract the public key */ - { - BIO * bio = BIO_new_mem_buf(pk_resp_packet.public_key, pk_resp_packet.public_key_len); - ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); - BIO_free(bio); - } + ret = mysqlnd_sha256_get_rsa_from_pem((const char *) pk_resp_packet.public_key, pk_resp_packet.public_key_len); } while (0); PACKET_FREE(&pk_req_packet); PACKET_FREE(&pk_resp_packet); @@ -762,9 +799,7 @@ mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn, if (stream) { if ((key_str = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0)) != NULL) { - BIO * bio = BIO_new_mem_buf(ZSTR_VAL(key_str), ZSTR_LEN(key_str)); - ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); - BIO_free(bio); + ret = mysqlnd_sha256_get_rsa_from_pem(ZSTR_VAL(key_str), ZSTR_LEN(key_str)); DBG_INF("Successfully loaded"); DBG_INF_FMT("Public key:%*.s", ZSTR_LEN(key_str), ZSTR_VAL(key_str)); zend_string_release_ex(key_str, 0); @@ -788,7 +823,7 @@ mysqlnd_sha256_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self const zend_ulong mysql_flags ) { - RSA * server_public_key; + mysqlnd_rsa_t server_public_key; zend_uchar * ret = NULL; DBG_ENTER("mysqlnd_sha256_auth_get_auth_data"); DBG_INF_FMT("salt(%d)=[%.*s]", auth_plugin_data_len, auth_plugin_data_len, auth_plugin_data); @@ -805,31 +840,12 @@ mysqlnd_sha256_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self server_public_key = mysqlnd_sha256_get_rsa_key(conn, session_options, pfc_data); if (server_public_key) { - int server_public_key_len; ALLOCA_FLAG(use_heap); char *xor_str = do_alloca(passwd_len + 1, use_heap); memcpy(xor_str, passwd, passwd_len); xor_str[passwd_len] = '\0'; mysqlnd_xor_string(xor_str, passwd_len, (char *) auth_plugin_data, auth_plugin_data_len); - - server_public_key_len = RSA_size(server_public_key); - /* - Because RSA_PKCS1_OAEP_PADDING is used there is a restriction on the passwd_len. - RSA_PKCS1_OAEP_PADDING is recommended for new applications. See more here: - http://www.openssl.org/docs/crypto/RSA_public_encrypt.html - */ - if ((size_t) server_public_key_len - 41 <= passwd_len) { - /* password message is to long */ - free_alloca(xor_str, use_heap); - SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long"); - DBG_ERR("password is too long"); - DBG_RETURN(NULL); - } - - *auth_data_len = server_public_key_len; - ret = malloc(*auth_data_len); - RSA_public_encrypt(passwd_len + 1, (zend_uchar *) xor_str, ret, server_public_key, RSA_PKCS1_OAEP_PADDING); - RSA_free(server_public_key); + ret = mysqlnd_sha256_public_encrypt(conn, server_public_key, passwd_len, auth_data_len, xor_str); free_alloca(xor_str, use_heap); } } @@ -901,6 +917,30 @@ void php_mysqlnd_scramble_sha2(zend_uchar * const buffer, const zend_uchar * con } /* }}} */ +/* {{{ mysqlnd_caching_sha2_public_encrypt */ +static size_t +mysqlnd_caching_sha2_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t server_public_key, size_t passwd_len, unsigned char **crypted, char *xor_str) +{ + int server_public_key_len = RSA_size(server_public_key); + + DBG_ENTER("mysqlnd_caching_sha2_public_encrypt"); + /* + Because RSA_PKCS1_OAEP_PADDING is used there is a restriction on the passwd_len. + RSA_PKCS1_OAEP_PADDING is recommended for new applications. See more here: + http://www.openssl.org/docs/crypto/RSA_public_encrypt.html + */ + if ((size_t) server_public_key_len - 41 <= passwd_len) { + /* password message is to long */ + SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long"); + DBG_ERR("password is too long"); + DBG_RETURN(0); + } + + *crypted = emalloc(server_public_key_len); + RSA_public_encrypt(passwd_len + 1, (zend_uchar *) xor_str, *crypted, server_public_key, RSA_PKCS1_OAEP_PADDING); + DBG_RETURN(server_public_key_len); +} +/* }}} */ /* {{{ mysqlnd_native_auth_get_auth_data */ static zend_uchar * @@ -938,10 +978,10 @@ mysqlnd_caching_sha2_get_auth_data(struct st_mysqlnd_authentication_plugin * sel } /* }}} */ -static RSA * +static mysqlnd_rsa_t mysqlnd_caching_sha2_get_key(MYSQLND_CONN_DATA *conn) { - RSA * ret = NULL; + mysqlnd_rsa_t ret = NULL; const MYSQLND_PFC_DATA * const pfc_data = conn->protocol_frame_codec->data; const char * fname = (pfc_data->sha256_server_public_key && pfc_data->sha256_server_public_key[0] != '\0')? pfc_data->sha256_server_public_key: @@ -975,11 +1015,7 @@ mysqlnd_caching_sha2_get_key(MYSQLND_CONN_DATA *conn) } DBG_INF_FMT("Public key(%d):\n%s", pk_resp_packet.public_key_len, pk_resp_packet.public_key); /* now extract the public key */ - { - BIO * bio = BIO_new_mem_buf(pk_resp_packet.public_key, pk_resp_packet.public_key_len); - ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); - BIO_free(bio); - } + ret = mysqlnd_sha256_get_rsa_from_pem((const char *) pk_resp_packet.public_key, pk_resp_packet.public_key_len); } while (0); PACKET_FREE(&req_packet); PACKET_FREE(&pk_resp_packet); @@ -998,9 +1034,7 @@ mysqlnd_caching_sha2_get_key(MYSQLND_CONN_DATA *conn) if (stream) { if ((key_str = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0)) != NULL) { - BIO * bio = BIO_new_mem_buf(ZSTR_VAL(key_str), ZSTR_LEN(key_str)); - ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); - BIO_free(bio); + ret = mysqlnd_sha256_get_rsa_from_pem(ZSTR_VAL(key_str), ZSTR_LEN(key_str)); DBG_INF("Successfully loaded"); DBG_INF_FMT("Public key:%*.s", ZSTR_LEN(key_str), ZSTR_VAL(key_str)); zend_string_release(key_str); @@ -1021,7 +1055,7 @@ mysqlnd_caching_sha2_get_and_use_key(MYSQLND_CONN_DATA *conn, const char * const passwd, const size_t passwd_len) { - static RSA *server_public_key; + static mysqlnd_rsa_t server_public_key; server_public_key = mysqlnd_caching_sha2_get_key(conn); DBG_ENTER("mysqlnd_caching_sha2_get_and_use_key("); @@ -1033,23 +1067,7 @@ mysqlnd_caching_sha2_get_and_use_key(MYSQLND_CONN_DATA *conn, memcpy(xor_str, passwd, passwd_len); xor_str[passwd_len] = '\0'; mysqlnd_xor_string(xor_str, passwd_len, (char *) auth_plugin_data, SCRAMBLE_LENGTH); - - server_public_key_len = RSA_size(server_public_key); - /* - Because RSA_PKCS1_OAEP_PADDING is used there is a restriction on the passwd_len. - RSA_PKCS1_OAEP_PADDING is recommended for new applications. See more here: - http://www.openssl.org/docs/crypto/RSA_public_encrypt.html - */ - if ((size_t) server_public_key_len - 41 <= passwd_len) { - /* password message is to long */ - free_alloca(xor_str, use_heap); - SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long"); - DBG_ERR("password is too long"); - DBG_RETURN(0); - } - - *crypted = emalloc(server_public_key_len); - RSA_public_encrypt(passwd_len + 1, (zend_uchar *) xor_str, *crypted, server_public_key, RSA_PKCS1_OAEP_PADDING); + server_public_key_len = mysqlnd_caching_sha2_public_encrypt(conn, server_public_key, passwd_len, crypted, xor_str); free_alloca(xor_str, use_heap); DBG_RETURN(server_public_key_len); } From 797a3fcc2ac8226bb0dd0eaf647b6f66d3c803c6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 25 Feb 2020 17:13:39 +0100 Subject: [PATCH 2/5] Native Windows support for mysqlnd sha256 authentification We implement that on top of Cryptography API: Next Generation (CNG). --- ext/mysqlnd/config.w32 | 3 + ext/mysqlnd/mysqlnd_auth.c | 131 +++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/ext/mysqlnd/config.w32 b/ext/mysqlnd/config.w32 index 1dac93578a497..5f191297d1196 100644 --- a/ext/mysqlnd/config.w32 +++ b/ext/mysqlnd/config.w32 @@ -36,6 +36,9 @@ if (PHP_MYSQLND != "no") { { AC_DEFINE("MYSQLND_COMPRESSION_ENABLED", 1, "Compression support"); AC_DEFINE("MYSQLND_SSL_SUPPORTED", 1, "SSL support"); + if (CHECK_LIB("crypt32.lib", "mysqlnd")) { + AC_DEFINE("MYSQLND_HAVE_SSL", 1, "Extended SSL support"); + } } PHP_INSTALL_HEADERS("", "ext/mysqlnd"); } diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c index c61ac2f8fec14..c2b531dd21577 100644 --- a/ext/mysqlnd/mysqlnd_auth.c +++ b/ext/mysqlnd/mysqlnd_auth.c @@ -694,6 +694,7 @@ mysqlnd_xor_string(char * dst, const size_t dst_len, const char * xor_str, const } } +#ifndef PHP_WIN32 #include #include @@ -741,6 +742,93 @@ mysqlnd_sha256_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t server_pub } /* }}} */ +#else + +#include +#include + +typedef HANDLE mysqlnd_rsa_t; + +/* {{{ mysqlnd_sha256_get_rsa_from_pem */ +static mysqlnd_rsa_t +mysqlnd_sha256_get_rsa_from_pem(const char *buf, size_t len) +{ + BCRYPT_KEY_HANDLE ret = 0; + LPCSTR der_buf = NULL; + DWORD der_len; + CERT_PUBLIC_KEY_INFO *key_info = NULL; + DWORD key_info_len; + + if (!CryptStringToBinaryA(buf, len, CRYPT_STRING_BASE64HEADER, NULL, &der_len, NULL, NULL)) { + goto finish; + } + der_buf = malloc(der_len); /* TODO alloca? */ + if (!der_buf) { + goto finish; + } + if (!CryptStringToBinaryA(buf, len, CRYPT_STRING_BASE64HEADER, der_buf, &der_len, NULL, NULL)) { + goto finish; + } + if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, der_buf, der_len, CRYPT_ENCODE_ALLOC_FLAG, NULL, &key_info, &key_info_len)) { + goto finish; + } + if (!CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, key_info, CRYPT_OID_INFO_PUBKEY_ENCRYPT_KEY_FLAG, NULL, &ret)) { + goto finish; + } + +finish: + if (key_info) { + LocalFree(key_info); + } + if (der_buf) { + free(der_buf); + } + return (mysqlnd_rsa_t) ret; +} +/* }}} */ + +/* {{{ mysqlnd_sha256_public_encrypt */ +static zend_uchar * +mysqlnd_sha256_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t server_public_key, size_t passwd_len, size_t * auth_data_len, char *xor_str) +{ + zend_uchar * ret = NULL; + DWORD server_public_key_len = passwd_len; + BCRYPT_OAEP_PADDING_INFO padding_info; + + DBG_ENTER("mysqlnd_sha256_public_encrypt"); + + ZeroMemory(&padding_info, sizeof padding_info); + padding_info.pszAlgId = BCRYPT_SHA1_ALGORITHM; + if (BCryptEncrypt((BCRYPT_KEY_HANDLE) server_public_key, xor_str, passwd_len + 1, &padding_info, + NULL, 0, NULL, 0, &server_public_key_len, BCRYPT_PAD_OAEP)) { + DBG_RETURN(0); + } + + /* + Because RSA_PKCS1_OAEP_PADDING is used there is a restriction on the passwd_len. + RSA_PKCS1_OAEP_PADDING is recommended for new applications. See more here: + http://www.openssl.org/docs/crypto/RSA_public_encrypt.html + */ + if ((size_t) server_public_key_len <= passwd_len + 41) { + /* password message is to long */ + SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long"); + DBG_ERR("password is too long"); + DBG_RETURN(0); + } + + *auth_data_len = server_public_key_len; + ret = malloc(*auth_data_len); + if (BCryptEncrypt((BCRYPT_KEY_HANDLE) server_public_key, xor_str, passwd_len + 1, &padding_info, + NULL, 0, ret, server_public_key_len, &server_public_key_len, BCRYPT_PAD_OAEP)) { + DBG_RETURN(0); + } + BCryptDestroyKey((BCRYPT_KEY_HANDLE) server_public_key); + DBG_RETURN(ret); +} +/* }}} */ + +#endif + /* {{{ mysqlnd_sha256_get_rsa_key */ static mysqlnd_rsa_t mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn, @@ -917,6 +1005,8 @@ void php_mysqlnd_scramble_sha2(zend_uchar * const buffer, const zend_uchar * con } /* }}} */ +#ifndef PHP_WIN32 + /* {{{ mysqlnd_caching_sha2_public_encrypt */ static size_t mysqlnd_caching_sha2_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t server_public_key, size_t passwd_len, unsigned char **crypted, char *xor_str) @@ -942,6 +1032,47 @@ mysqlnd_caching_sha2_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t serv } /* }}} */ +#else + +/* {{{ mysqlnd_caching_sha2_public_encrypt */ +static size_t +mysqlnd_caching_sha2_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t server_public_key, size_t passwd_len, unsigned char **crypted, char *xor_str) +{ + DWORD server_public_key_len = passwd_len; + BCRYPT_OAEP_PADDING_INFO padding_info; + + DBG_ENTER("mysqlnd_caching_sha2_public_encrypt"); + + ZeroMemory(&padding_info, sizeof padding_info); + padding_info.pszAlgId = BCRYPT_SHA1_ALGORITHM; + if (BCryptEncrypt((BCRYPT_KEY_HANDLE) server_public_key, xor_str, passwd_len + 1, &padding_info, + NULL, 0, NULL, 0, &server_public_key_len, BCRYPT_PAD_OAEP)) { + DBG_RETURN(0); + } + + /* + Because RSA_PKCS1_OAEP_PADDING is used there is a restriction on the passwd_len. + RSA_PKCS1_OAEP_PADDING is recommended for new applications. See more here: + http://www.openssl.org/docs/crypto/RSA_public_encrypt.html + */ + if ((size_t) server_public_key_len <= passwd_len + 41) { + /* password message is to long */ + SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long"); + DBG_ERR("password is too long"); + DBG_RETURN(0); + } + + *crypted = emalloc(server_public_key_len); + if (BCryptEncrypt((BCRYPT_KEY_HANDLE) server_public_key, xor_str, passwd_len + 1, &padding_info, + NULL, 0, *crypted, server_public_key_len, &server_public_key_len, BCRYPT_PAD_OAEP)) { + DBG_RETURN(0); + } + DBG_RETURN(server_public_key_len); +} +/* }}} */ + +#endif + /* {{{ mysqlnd_native_auth_get_auth_data */ static zend_uchar * mysqlnd_caching_sha2_get_auth_data(struct st_mysqlnd_authentication_plugin * self, From 05254be21e11edad832dd4ec3ecdc66a71122cac Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 26 Feb 2020 10:42:29 +0100 Subject: [PATCH 3/5] [*nix] Merge initialization and assignment --- ext/mysqlnd/mysqlnd_auth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c index c2b531dd21577..b06781c271543 100644 --- a/ext/mysqlnd/mysqlnd_auth.c +++ b/ext/mysqlnd/mysqlnd_auth.c @@ -706,9 +706,8 @@ typedef RSA * mysqlnd_rsa_t; static mysqlnd_rsa_t mysqlnd_sha256_get_rsa_from_pem(const char *buf, size_t len) { - RSA * ret = NULL; BIO * bio = BIO_new_mem_buf(buf, len); - ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); + RSA * ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); BIO_free(bio); return ret; } From bdccf660b3a2dae771f6f80113496dee8e794197 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 26 Feb 2020 16:56:57 +0100 Subject: [PATCH 4/5] Fixes/improvements --- ext/mysqlnd/mysqlnd_auth.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c index b06781c271543..f80d6d60240cc 100644 --- a/ext/mysqlnd/mysqlnd_auth.c +++ b/ext/mysqlnd/mysqlnd_auth.c @@ -718,7 +718,7 @@ static zend_uchar * mysqlnd_sha256_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t server_public_key, size_t passwd_len, size_t * auth_data_len, char *xor_str) { zend_uchar * ret = NULL; - int server_public_key_len = RSA_size(server_public_key); + size_t server_public_key_len = (size_t) RSA_size(server_public_key); DBG_ENTER("mysqlnd_sha256_public_encrypt"); /* @@ -726,7 +726,7 @@ mysqlnd_sha256_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t server_pub RSA_PKCS1_OAEP_PADDING is recommended for new applications. See more here: http://www.openssl.org/docs/crypto/RSA_public_encrypt.html */ - if ((size_t) server_public_key_len - 41 <= passwd_len) { + if (server_public_key_len <= passwd_len + 41) { /* password message is to long */ SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long"); DBG_ERR("password is too long"); @@ -1010,7 +1010,7 @@ void php_mysqlnd_scramble_sha2(zend_uchar * const buffer, const zend_uchar * con static size_t mysqlnd_caching_sha2_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t server_public_key, size_t passwd_len, unsigned char **crypted, char *xor_str) { - int server_public_key_len = RSA_size(server_public_key); + size_t server_public_key_len = (size_t) RSA_size(server_public_key); DBG_ENTER("mysqlnd_caching_sha2_public_encrypt"); /* @@ -1018,7 +1018,7 @@ mysqlnd_caching_sha2_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t serv RSA_PKCS1_OAEP_PADDING is recommended for new applications. See more here: http://www.openssl.org/docs/crypto/RSA_public_encrypt.html */ - if ((size_t) server_public_key_len - 41 <= passwd_len) { + if (server_public_key_len <= passwd_len + 41) { /* password message is to long */ SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long"); DBG_ERR("password is too long"); @@ -1177,7 +1177,7 @@ mysqlnd_caching_sha2_get_key(MYSQLND_CONN_DATA *conn) } -/* {{{ mysqlnd_caching_sha2_get_key */ +/* {{{ mysqlnd_caching_sha2_get_and_use_key */ static size_t mysqlnd_caching_sha2_get_and_use_key(MYSQLND_CONN_DATA *conn, const zend_uchar * auth_plugin_data, const size_t auth_plugin_data_len, @@ -1185,8 +1185,7 @@ mysqlnd_caching_sha2_get_and_use_key(MYSQLND_CONN_DATA *conn, const char * const passwd, const size_t passwd_len) { - static mysqlnd_rsa_t server_public_key; - server_public_key = mysqlnd_caching_sha2_get_key(conn); + mysqlnd_rsa_t server_public_key = mysqlnd_caching_sha2_get_key(conn); DBG_ENTER("mysqlnd_caching_sha2_get_and_use_key("); From 1920ec9beeb58927c5ccf8139b23f48535577f49 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 26 Feb 2020 17:01:37 +0100 Subject: [PATCH 5/5] Use alloca() --- ext/mysqlnd/mysqlnd_auth.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c index f80d6d60240cc..fa156fa0e1fb6 100644 --- a/ext/mysqlnd/mysqlnd_auth.c +++ b/ext/mysqlnd/mysqlnd_auth.c @@ -757,14 +757,12 @@ mysqlnd_sha256_get_rsa_from_pem(const char *buf, size_t len) DWORD der_len; CERT_PUBLIC_KEY_INFO *key_info = NULL; DWORD key_info_len; + ALLOCA_FLAG(use_heap); if (!CryptStringToBinaryA(buf, len, CRYPT_STRING_BASE64HEADER, NULL, &der_len, NULL, NULL)) { goto finish; } - der_buf = malloc(der_len); /* TODO alloca? */ - if (!der_buf) { - goto finish; - } + der_buf = do_alloca(der_len, use_heap); if (!CryptStringToBinaryA(buf, len, CRYPT_STRING_BASE64HEADER, der_buf, &der_len, NULL, NULL)) { goto finish; } @@ -780,7 +778,7 @@ mysqlnd_sha256_get_rsa_from_pem(const char *buf, size_t len) LocalFree(key_info); } if (der_buf) { - free(der_buf); + free_alloca(der_buf, use_heap); } return (mysqlnd_rsa_t) ret; }