mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Native Windows support for mysqlnd sha256 authentification
We implement that on top of Cryptography API: Next Generation (CNG).
This commit is contained in:
parent
a7400d5fd3
commit
a0377021c5
3 changed files with 136 additions and 0 deletions
4
NEWS
4
NEWS
|
@ -40,6 +40,10 @@ PHP NEWS
|
|||
- MySQLi:
|
||||
. Fixed bug #64032 (mysqli reports different client_version). (cmb)
|
||||
|
||||
- MySQLnd:
|
||||
. Implemented FR #79275 (Support auth_plugin_caching_sha2_password on
|
||||
Windows). (cmb)
|
||||
|
||||
- Opcache:
|
||||
. Fixed bug #79252 (preloading causes php-fpm to segfault during exit).
|
||||
(Nikita)
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -694,6 +694,7 @@ mysqlnd_xor_string(char * dst, const size_t dst_len, const char * xor_str, const
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef PHP_WIN32
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/pem.h>
|
||||
|
@ -740,6 +741,91 @@ mysqlnd_sha256_public_encrypt(MYSQLND_CONN_DATA * conn, mysqlnd_rsa_t server_pub
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
#else
|
||||
|
||||
#include <wincrypt.h>
|
||||
#include <bcrypt.h>
|
||||
|
||||
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;
|
||||
ALLOCA_FLAG(use_heap);
|
||||
|
||||
if (!CryptStringToBinaryA(buf, len, CRYPT_STRING_BASE64HEADER, NULL, &der_len, NULL, NULL)) {
|
||||
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;
|
||||
}
|
||||
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_alloca(der_buf, use_heap);
|
||||
}
|
||||
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,
|
||||
|
@ -916,6 +1002,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)
|
||||
|
@ -941,6 +1029,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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue