mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-9804 Implement a caching_sha2_password plugin
but without caching
This commit is contained in:
1
debian/mariadb-server.install
vendored
1
debian/mariadb-server.install
vendored
@@ -36,6 +36,7 @@ usr/bin/wsrep_sst_mysqldump
|
|||||||
usr/bin/wsrep_sst_rsync
|
usr/bin/wsrep_sst_rsync
|
||||||
usr/bin/wsrep_sst_rsync_wan
|
usr/bin/wsrep_sst_rsync_wan
|
||||||
usr/lib/mysql/plugin/auth_ed25519.so
|
usr/lib/mysql/plugin/auth_ed25519.so
|
||||||
|
usr/lib/mysql/plugin/auth_mysql_sha2.so
|
||||||
usr/lib/mysql/plugin/auth_pam.so
|
usr/lib/mysql/plugin/auth_pam.so
|
||||||
usr/lib/mysql/plugin/auth_pam_tool_dir/auth_pam_tool
|
usr/lib/mysql/plugin/auth_pam_tool_dir/auth_pam_tool
|
||||||
usr/lib/mysql/plugin/auth_pam_v1.so
|
usr/lib/mysql/plugin/auth_pam_v1.so
|
||||||
|
@@ -8,6 +8,7 @@ typedef struct st_plugin_vio_info
|
|||||||
enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
|
enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
|
||||||
MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
|
MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
|
||||||
int socket;
|
int socket;
|
||||||
|
int tls;
|
||||||
} MYSQL_PLUGIN_VIO_INFO;
|
} MYSQL_PLUGIN_VIO_INFO;
|
||||||
typedef struct st_plugin_vio
|
typedef struct st_plugin_vio
|
||||||
{
|
{
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
#include <mysql/plugin.h>
|
#include <mysql/plugin.h>
|
||||||
|
|
||||||
#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0202
|
#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0203
|
||||||
|
|
||||||
#include <mysql/plugin_auth_common.h>
|
#include <mysql/plugin_auth_common.h>
|
||||||
|
|
||||||
|
@@ -707,6 +707,7 @@ typedef struct st_plugin_vio_info
|
|||||||
enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
|
enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET,
|
||||||
MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
|
MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol;
|
||||||
int socket;
|
int socket;
|
||||||
|
int tls;
|
||||||
} MYSQL_PLUGIN_VIO_INFO;
|
} MYSQL_PLUGIN_VIO_INFO;
|
||||||
typedef struct st_plugin_vio
|
typedef struct st_plugin_vio
|
||||||
{
|
{
|
||||||
|
@@ -98,6 +98,7 @@ typedef struct st_plugin_vio_info
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */
|
HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */
|
||||||
#endif
|
#endif
|
||||||
|
int tls;
|
||||||
} MYSQL_PLUGIN_VIO_INFO;
|
} MYSQL_PLUGIN_VIO_INFO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -8,6 +8,7 @@ plugins,^
|
|||||||
mariabackup,^
|
mariabackup,^
|
||||||
roles,^
|
roles,^
|
||||||
auth_gssapi,^
|
auth_gssapi,^
|
||||||
|
mysql_sha2,^
|
||||||
query_response_time,^
|
query_response_time,^
|
||||||
rocksdb,^
|
rocksdb,^
|
||||||
sysschema
|
sysschema
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
if ($CLIENT_TLS_LIBRARY != "OpenSSL") {
|
if ($CLIENT_TLS_LIBRARY != "OpenSSL") {
|
||||||
if ($CLIENT_TLS_LIBRARY != "LibreSSL") {
|
if ($CLIENT_TLS_LIBRARY != "LibreSSL") {
|
||||||
skip "Test requires Connector/C with OpenSSL library";
|
skip Test requires Connector/C with OpenSSL library;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -40,7 +40,7 @@ perl;
|
|||||||
test-sql-discovery query-cache-info password-reuse-check
|
test-sql-discovery query-cache-info password-reuse-check
|
||||||
query-response-time metadata-lock-info locales unix-socket
|
query-response-time metadata-lock-info locales unix-socket
|
||||||
wsrep file-key-management cracklib-password-check user-variables
|
wsrep file-key-management cracklib-password-check user-variables
|
||||||
provider-bzip2 provider-lzma provider-lzo
|
provider-bzip2 provider-lzma provider-lzo caching-sha2-password
|
||||||
thread-pool-groups thread-pool-queues thread-pool-stats
|
thread-pool-groups thread-pool-queues thread-pool-stats
|
||||||
thread-pool-waits hashicorp provider gssapi parsec/;
|
thread-pool-waits hashicorp provider gssapi parsec/;
|
||||||
|
|
||||||
|
@@ -25,7 +25,7 @@ PLUGIN_NAME ed25519
|
|||||||
PLUGIN_VERSION 1.1
|
PLUGIN_VERSION 1.1
|
||||||
PLUGIN_STATUS ACTIVE
|
PLUGIN_STATUS ACTIVE
|
||||||
PLUGIN_TYPE AUTHENTICATION
|
PLUGIN_TYPE AUTHENTICATION
|
||||||
PLUGIN_TYPE_VERSION 2.2
|
PLUGIN_TYPE_VERSION 2.3
|
||||||
PLUGIN_LIBRARY auth_ed25519.so
|
PLUGIN_LIBRARY auth_ed25519.so
|
||||||
PLUGIN_LIBRARY_VERSION 1.15
|
PLUGIN_LIBRARY_VERSION 1.15
|
||||||
PLUGIN_AUTHOR Sergei Golubchik
|
PLUGIN_AUTHOR Sergei Golubchik
|
||||||
|
8
plugin/auth_mysql_sha2/CMakeLists.txt
Normal file
8
plugin/auth_mysql_sha2/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
ADD_DEFINITIONS(${SSL_DEFINES})
|
||||||
|
IF(WITH_SSL STREQUAL "bundled")
|
||||||
|
# WolfSSL is static, we don't want it linked both into plugin and server
|
||||||
|
SET(static STATIC_ONLY DEFAULT)
|
||||||
|
ENDIF()
|
||||||
|
MYSQL_ADD_PLUGIN(auth_mysql_sha2
|
||||||
|
mysql_sha2.c sha256crypt.c ssl_stuff.c openssl1-compat.c
|
||||||
|
LINK_LIBRARIES ${SSL_LIBRARIES} ${static})
|
3
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/fini.inc
Normal file
3
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/fini.inc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
drop procedure checkme;
|
||||||
|
drop user test1@'%';
|
||||||
|
drop user test2@'%';
|
21
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/init.inc
Normal file
21
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/init.inc
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
source include/not_embedded.inc;
|
||||||
|
|
||||||
|
call mtr.add_suppression('failed to read private_key.pem: 2 "No such file or directory"');
|
||||||
|
|
||||||
|
if (`select count(*) = 0 from information_schema.plugins where plugin_name = 'caching_sha2_password'`)
|
||||||
|
{
|
||||||
|
--skip Needs caching_sha2_password plugin
|
||||||
|
}
|
||||||
|
|
||||||
|
show status like 'caching_sha2_password%';
|
||||||
|
|
||||||
|
create user test1@'%' identified via caching_sha2_password using PASSWORD('pwd');
|
||||||
|
create user test2@'%' identified via caching_sha2_password;
|
||||||
|
show grants for test2@'%';
|
||||||
|
|
||||||
|
create procedure checkme() sql security invoker
|
||||||
|
select user(), current_user(), variable_value > '' as 'have_ssl'
|
||||||
|
from information_schema.session_status
|
||||||
|
where variable_name='ssl_cipher';
|
||||||
|
|
||||||
|
grant execute on test.* to test1@'%', test2@'%';
|
3
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/init.opt
Normal file
3
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/init.opt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
--plugin-load-add=$AUTH_MYSQL_SHA2_SO
|
||||||
|
--loose-caching-sha2-password
|
||||||
|
--loose-disable-caching-sha2-password-auto-generate-rsa-keys
|
1
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/socket.opt
Normal file
1
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/socket.opt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
--loose-enable-named-pipe
|
39
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/socket.result
Normal file
39
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/socket.result
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
call mtr.add_suppression('failed to read private_key.pem: 2 "No such file or directory"');
|
||||||
|
show status like 'caching_sha2_password%';
|
||||||
|
Variable_name Value
|
||||||
|
Caching_sha2_password_rsa_public_key
|
||||||
|
create user test1@'%' identified via caching_sha2_password using PASSWORD('pwd');
|
||||||
|
create user test2@'%' identified via caching_sha2_password;
|
||||||
|
show grants for test2@'%';
|
||||||
|
Grants for test2@%
|
||||||
|
GRANT USAGE ON *.* TO `test2`@`%` IDENTIFIED VIA caching_sha2_password
|
||||||
|
create procedure checkme() sql security invoker
|
||||||
|
select user(), current_user(), variable_value > '' as 'have_ssl'
|
||||||
|
from information_schema.session_status
|
||||||
|
where variable_name='ssl_cipher';
|
||||||
|
grant execute on test.* to test1@'%', test2@'%';
|
||||||
|
connect con1, localhost,test1,pwd,,,,$proto NOSSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test1@localhost test1@% 0
|
||||||
|
disconnect con1;
|
||||||
|
connect con2, localhost,test1,pwd,,,,$proto NOSSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test1@localhost test1@% 0
|
||||||
|
disconnect con2;
|
||||||
|
connect(localhost,test1,wrong_pwd,test,MASTER_MYPORT,MASTER_MYSOCK);
|
||||||
|
connect con3, localhost,test1,wrong_pwd,,,,$proto NOSSL;
|
||||||
|
ERROR 28000: Access denied for user 'test1'@'localhost' (using password: YES)
|
||||||
|
connect con4, localhost,test2,,,,,$proto NOSSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test2@localhost test2@% 0
|
||||||
|
disconnect con4;
|
||||||
|
connect(localhost,test2 pwd,,test,MASTER_MYPORT,MASTER_MYSOCK);
|
||||||
|
connect con5, localhost,test2 pwd,,,,,$proto NOSSL;
|
||||||
|
ERROR 28000: Access denied for user 'test2 pwd'@'localhost' (using password: NO)
|
||||||
|
connection default;
|
||||||
|
drop procedure checkme;
|
||||||
|
drop user test1@'%';
|
||||||
|
drop user test2@'%';
|
27
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/socket.test
Normal file
27
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/socket.test
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
source include/platform.inc;
|
||||||
|
source init.inc;
|
||||||
|
|
||||||
|
let proto=SOCKET;
|
||||||
|
if ($MTR_COMBINATION_WIN) {
|
||||||
|
let proto=PIPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect con1, localhost,test1,pwd,,,,$proto NOSSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect con1;
|
||||||
|
connect con2, localhost,test1,pwd,,,,$proto NOSSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect con2;
|
||||||
|
replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT;
|
||||||
|
error ER_ACCESS_DENIED_ERROR;
|
||||||
|
connect con3, localhost,test1,wrong_pwd,,,,$proto NOSSL;
|
||||||
|
connect con4, localhost,test2,,,,,$proto NOSSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect con4;
|
||||||
|
replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT;
|
||||||
|
error ER_ACCESS_DENIED_ERROR;
|
||||||
|
connect con5, localhost,test2 pwd,,,,,$proto NOSSL;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
source fini.inc;
|
@@ -0,0 +1,3 @@
|
|||||||
|
--ssl-key=
|
||||||
|
--ssl-cert=
|
||||||
|
--ssl-ca=
|
29
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/ssl_auto.result
Normal file
29
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/ssl_auto.result
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
call mtr.add_suppression('failed to read private_key.pem: 2 "No such file or directory"');
|
||||||
|
show status like 'caching_sha2_password%';
|
||||||
|
Variable_name Value
|
||||||
|
Caching_sha2_password_rsa_public_key
|
||||||
|
create user test1@'%' identified via caching_sha2_password using PASSWORD('pwd');
|
||||||
|
create user test2@'%' identified via caching_sha2_password;
|
||||||
|
show grants for test2@'%';
|
||||||
|
Grants for test2@%
|
||||||
|
GRANT USAGE ON *.* TO `test2`@`%` IDENTIFIED VIA caching_sha2_password
|
||||||
|
create procedure checkme() sql security invoker
|
||||||
|
select user(), current_user(), variable_value > '' as 'have_ssl'
|
||||||
|
from information_schema.session_status
|
||||||
|
where variable_name='ssl_cipher';
|
||||||
|
grant execute on test.* to test1@'%', test2@'%';
|
||||||
|
# mysql -utest1 -ppwd --disable-ssl-verify-server-cert -e "call test.checkme()"
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test1@localhost test1@% 1
|
||||||
|
# mysql -utest1 -pwrong_pwd --disable-ssl-verify-server-cert -e "call test.checkme()"
|
||||||
|
ERROR 1045 (28000): Access denied for user 'test1'@'localhost' (using password: YES)
|
||||||
|
# mysql -utest2 --disable-ssl-verify-server-cert -e "call test.checkme()"
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test2@localhost test2@% 1
|
||||||
|
# mysql -utest2 -ppwd --disable-ssl-verify-server-cert -e "call test.checkme()"
|
||||||
|
ERROR 1045 (28000): Access denied for user 'test2'@'localhost' (using password: YES)
|
||||||
|
# mysql -utest1 -ppwd --ssl-verify-server-cert -e "call test.checkme()"
|
||||||
|
ERROR 2026 (HY000): TLS/SSL error: Certificate verification failure: The certificate is NOT trusted.
|
||||||
|
drop procedure checkme;
|
||||||
|
drop user test1@'%';
|
||||||
|
drop user test2@'%';
|
27
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/ssl_auto.test
Normal file
27
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/ssl_auto.test
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
source init.inc;
|
||||||
|
|
||||||
|
let MYSQL=$MYSQL --protocol tcp;
|
||||||
|
if ($MARIADB_UPGRADE_EXE) { # windows
|
||||||
|
# see ssl_autoverify.test
|
||||||
|
let MYSQL=$MYSQL --host=127.0.0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
--echo # mysql -utest1 -ppwd --disable-ssl-verify-server-cert -e "call test.checkme()"
|
||||||
|
--exec $MYSQL -utest1 -ppwd --disable-ssl-verify-server-cert -e "call test.checkme()" 2>&1
|
||||||
|
|
||||||
|
--echo # mysql -utest1 -pwrong_pwd --disable-ssl-verify-server-cert -e "call test.checkme()"
|
||||||
|
--error 1
|
||||||
|
--exec $MYSQL -utest1 -pwrong_pwd --disable-ssl-verify-server-cert -e "call test.checkme()" 2>&1
|
||||||
|
|
||||||
|
--echo # mysql -utest2 --disable-ssl-verify-server-cert -e "call test.checkme()"
|
||||||
|
--exec $MYSQL -utest2 --disable-ssl-verify-server-cert -e "call test.checkme()" 2>&1
|
||||||
|
|
||||||
|
--echo # mysql -utest2 -ppwd --disable-ssl-verify-server-cert -e "call test.checkme()"
|
||||||
|
--error 1
|
||||||
|
--exec $MYSQL -utest2 -ppwd --disable-ssl-verify-server-cert -e "call test.checkme()" 2>&1
|
||||||
|
|
||||||
|
--echo # mysql -utest1 -ppwd --ssl-verify-server-cert -e "call test.checkme()"
|
||||||
|
--error 1
|
||||||
|
--exec $MYSQL -utest1 -ppwd --ssl-verify-server-cert -e "call test.checkme()" 2>&1
|
||||||
|
|
||||||
|
source fini.inc;
|
@@ -0,0 +1,39 @@
|
|||||||
|
call mtr.add_suppression('failed to read private_key.pem: 2 "No such file or directory"');
|
||||||
|
show status like 'caching_sha2_password%';
|
||||||
|
Variable_name Value
|
||||||
|
Caching_sha2_password_rsa_public_key
|
||||||
|
create user test1@'%' identified via caching_sha2_password using PASSWORD('pwd');
|
||||||
|
create user test2@'%' identified via caching_sha2_password;
|
||||||
|
show grants for test2@'%';
|
||||||
|
Grants for test2@%
|
||||||
|
GRANT USAGE ON *.* TO `test2`@`%` IDENTIFIED VIA caching_sha2_password
|
||||||
|
create procedure checkme() sql security invoker
|
||||||
|
select user(), current_user(), variable_value > '' as 'have_ssl'
|
||||||
|
from information_schema.session_status
|
||||||
|
where variable_name='ssl_cipher';
|
||||||
|
grant execute on test.* to test1@'%', test2@'%';
|
||||||
|
connect con1, localhost,test1,pwd,,,,TCP SSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test1@localhost test1@% 1
|
||||||
|
disconnect con1;
|
||||||
|
connect con2, localhost,test1,pwd,,,,TCP SSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test1@localhost test1@% 1
|
||||||
|
disconnect con2;
|
||||||
|
connect(localhost,test1,wrong_pwd,test,MASTER_MYPORT,MASTER_MYSOCK);
|
||||||
|
connect con3, localhost,test1,wrong_pwd,,,,TCP SSL;
|
||||||
|
ERROR 28000: Access denied for user 'test1'@'localhost' (using password: YES)
|
||||||
|
connect con4, localhost,test2,,,,,TCP SSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test2@localhost test2@% 1
|
||||||
|
disconnect con4;
|
||||||
|
connect(localhost,test2 pwd,,test,MASTER_MYPORT,MASTER_MYSOCK);
|
||||||
|
connect con5, localhost,test2 pwd,,,,,TCP SSL;
|
||||||
|
ERROR 28000: Access denied for user 'test2 pwd'@'localhost' (using password: NO)
|
||||||
|
connection default;
|
||||||
|
drop procedure checkme;
|
||||||
|
drop user test1@'%';
|
||||||
|
drop user test2@'%';
|
21
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/ssl_manual.test
Normal file
21
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/ssl_manual.test
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
source init.inc;
|
||||||
|
|
||||||
|
connect con1, localhost,test1,pwd,,,,TCP SSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect con1;
|
||||||
|
connect con2, localhost,test1,pwd,,,,TCP SSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect con2;
|
||||||
|
replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT;
|
||||||
|
error ER_ACCESS_DENIED_ERROR;
|
||||||
|
connect con3, localhost,test1,wrong_pwd,,,,TCP SSL;
|
||||||
|
connect con4, localhost,test2,,,,,TCP SSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect con4;
|
||||||
|
replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT;
|
||||||
|
error ER_ACCESS_DENIED_ERROR;
|
||||||
|
connect con5, localhost,test2 pwd,,,,,TCP SSL;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
source fini.inc;
|
5
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/suite.pm
Normal file
5
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/suite.pm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package My::Suite::AuthSHA2;
|
||||||
|
@ISA = qw(My::Suite);
|
||||||
|
return "Not run for embedded server" if $::opt_embedded_server;
|
||||||
|
sub is_default { 1 }
|
||||||
|
bless { };
|
159
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/tcp_nossl.result
Normal file
159
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/tcp_nossl.result
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
call mtr.add_suppression('failed to read private_key.pem: 2 "No such file or directory"');
|
||||||
|
call mtr.add_suppression('Authentication requires either RSA keys or secure transport');
|
||||||
|
call mtr.add_suppression('failed to read private_key.pem: 2 "No such file or directory"');
|
||||||
|
show status like 'caching_sha2_password%';
|
||||||
|
Variable_name Value
|
||||||
|
Caching_sha2_password_rsa_public_key
|
||||||
|
create user test1@'%' identified via caching_sha2_password using PASSWORD('pwd');
|
||||||
|
create user test2@'%' identified via caching_sha2_password;
|
||||||
|
show grants for test2@'%';
|
||||||
|
Grants for test2@%
|
||||||
|
GRANT USAGE ON *.* TO `test2`@`%` IDENTIFIED VIA caching_sha2_password
|
||||||
|
create procedure checkme() sql security invoker
|
||||||
|
select user(), current_user(), variable_value > '' as 'have_ssl'
|
||||||
|
from information_schema.session_status
|
||||||
|
where variable_name='ssl_cipher';
|
||||||
|
grant execute on test.* to test1@'%', test2@'%';
|
||||||
|
select * from information_schema.system_variables where variable_name like 'caching_sha2_password%' order by 1;
|
||||||
|
VARIABLE_NAME CACHING_SHA2_PASSWORD_AUTO_GENERATE_RSA_KEYS
|
||||||
|
SESSION_VALUE NULL
|
||||||
|
GLOBAL_VALUE OFF
|
||||||
|
GLOBAL_VALUE_ORIGIN COMMAND-LINE
|
||||||
|
DEFAULT_VALUE ON
|
||||||
|
VARIABLE_SCOPE GLOBAL
|
||||||
|
VARIABLE_TYPE BOOLEAN
|
||||||
|
VARIABLE_COMMENT Auto generate RSA keys at server startup if key paths are not explicitly set and key files are not present at their default locations
|
||||||
|
NUMERIC_MIN_VALUE NULL
|
||||||
|
NUMERIC_MAX_VALUE NULL
|
||||||
|
NUMERIC_BLOCK_SIZE NULL
|
||||||
|
ENUM_VALUE_LIST OFF,ON
|
||||||
|
READ_ONLY YES
|
||||||
|
COMMAND_LINE_ARGUMENT OPTIONAL
|
||||||
|
GLOBAL_VALUE_PATH NULL
|
||||||
|
VARIABLE_NAME CACHING_SHA2_PASSWORD_DIGEST_ROUNDS
|
||||||
|
SESSION_VALUE NULL
|
||||||
|
GLOBAL_VALUE 5000
|
||||||
|
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||||
|
DEFAULT_VALUE 5000
|
||||||
|
VARIABLE_SCOPE GLOBAL
|
||||||
|
VARIABLE_TYPE INT UNSIGNED
|
||||||
|
VARIABLE_COMMENT Number of SHA2 rounds to be performed when computing a password hash
|
||||||
|
NUMERIC_MIN_VALUE 5000
|
||||||
|
NUMERIC_MAX_VALUE 4095000
|
||||||
|
NUMERIC_BLOCK_SIZE 1
|
||||||
|
ENUM_VALUE_LIST NULL
|
||||||
|
READ_ONLY YES
|
||||||
|
COMMAND_LINE_ARGUMENT REQUIRED
|
||||||
|
GLOBAL_VALUE_PATH NULL
|
||||||
|
VARIABLE_NAME CACHING_SHA2_PASSWORD_PRIVATE_KEY_PATH
|
||||||
|
SESSION_VALUE NULL
|
||||||
|
GLOBAL_VALUE private_key.pem
|
||||||
|
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||||
|
DEFAULT_VALUE private_key.pem
|
||||||
|
VARIABLE_SCOPE GLOBAL
|
||||||
|
VARIABLE_TYPE VARCHAR
|
||||||
|
VARIABLE_COMMENT A path to the private RSA key used for authentication
|
||||||
|
NUMERIC_MIN_VALUE NULL
|
||||||
|
NUMERIC_MAX_VALUE NULL
|
||||||
|
NUMERIC_BLOCK_SIZE NULL
|
||||||
|
ENUM_VALUE_LIST NULL
|
||||||
|
READ_ONLY YES
|
||||||
|
COMMAND_LINE_ARGUMENT REQUIRED
|
||||||
|
GLOBAL_VALUE_PATH NULL
|
||||||
|
VARIABLE_NAME CACHING_SHA2_PASSWORD_PUBLIC_KEY_PATH
|
||||||
|
SESSION_VALUE NULL
|
||||||
|
GLOBAL_VALUE public_key.pem
|
||||||
|
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||||
|
DEFAULT_VALUE public_key.pem
|
||||||
|
VARIABLE_SCOPE GLOBAL
|
||||||
|
VARIABLE_TYPE VARCHAR
|
||||||
|
VARIABLE_COMMENT A path to the public RSA key used for authentication
|
||||||
|
NUMERIC_MIN_VALUE NULL
|
||||||
|
NUMERIC_MAX_VALUE NULL
|
||||||
|
NUMERIC_BLOCK_SIZE NULL
|
||||||
|
ENUM_VALUE_LIST NULL
|
||||||
|
READ_ONLY YES
|
||||||
|
COMMAND_LINE_ARGUMENT REQUIRED
|
||||||
|
GLOBAL_VALUE_PATH NULL
|
||||||
|
create user test3@'%' identified via caching_sha2_password using 'pwd';
|
||||||
|
ERROR HY000: Password hash should be 70 characters long
|
||||||
|
create user test3@'%' identified via caching_sha2_password using '0000000000000000000000000000000000000000000000000000000000000000000000';
|
||||||
|
ERROR HY000: Invalid password hash
|
||||||
|
connect(localhost,test1,pwd,test,MASTER_MYPORT,MASTER_MYSOCK);
|
||||||
|
connect con1, localhost,test1,pwd,,,,TCP NOSSL;
|
||||||
|
ERROR HY000: Couldn't read RSA public key from server
|
||||||
|
connect(localhost,test1,wrong_pwd,test,MASTER_MYPORT,MASTER_MYSOCK);
|
||||||
|
connect con3, localhost,test1,wrong_pwd,,,,TCP NOSSL;
|
||||||
|
ERROR HY000: Couldn't read RSA public key from server
|
||||||
|
connect con4, localhost,test2,,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test2@localhost test2@% 0
|
||||||
|
disconnect con4;
|
||||||
|
connect(localhost,test2 pwd,,test,MASTER_MYPORT,MASTER_MYSOCK);
|
||||||
|
connect con5, localhost,test2 pwd,,,,,TCP NOSSL;
|
||||||
|
ERROR 28000: Access denied for user 'test2 pwd'@'localhost' (using password: NO)
|
||||||
|
connection default;
|
||||||
|
# restart: --caching_sha2_password-auto_generate_rsa_keys
|
||||||
|
select length(variable_value) from information_schema.global_status
|
||||||
|
where variable_name like 'caching_sha2_password%';
|
||||||
|
length(variable_value)
|
||||||
|
451
|
||||||
|
# restart: --caching_sha2_password-auto_generate_rsa_keys
|
||||||
|
select variable_value="$pubkey" as 'key did not change'
|
||||||
|
from information_schema.global_status
|
||||||
|
where variable_name like 'caching_sha2_password%';
|
||||||
|
key did not change
|
||||||
|
1
|
||||||
|
connect con1, localhost,test1,pwd,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test1@localhost test1@% 0
|
||||||
|
disconnect con1;
|
||||||
|
connect con2, localhost,test1,pwd,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test1@localhost test1@% 0
|
||||||
|
disconnect con2;
|
||||||
|
connect(localhost,test1,wrong_pwd,test,MASTER_MYPORT,MASTER_MYSOCK);
|
||||||
|
connect con3, localhost,test1,wrong_pwd,,,,TCP NOSSL;
|
||||||
|
ERROR 28000: Access denied for user 'test1'@'localhost' (using password: YES)
|
||||||
|
connect con4, localhost,test2,,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
test2@localhost test2@% 0
|
||||||
|
disconnect con4;
|
||||||
|
connect(localhost,test2 pwd,,test,MASTER_MYPORT,MASTER_MYSOCK);
|
||||||
|
connect con5, localhost,test2 pwd,,,,,TCP NOSSL;
|
||||||
|
ERROR 28000: Access denied for user 'test2 pwd'@'localhost' (using password: NO)
|
||||||
|
connection default;
|
||||||
|
create user u1@localhost identified via caching_sha2_password using '$A$005$5dx;X)z |kX]\ZNx7QTrl0oTy2C0/f4bggQMFIDnSDeZ7koLoO417jc9D';
|
||||||
|
create user u2@localhost identified via caching_sha2_password using '$A$005$dL\Zq]<7d[YAbk}x!;^.qMuuUUBmB5aF7x7GsAKZzpb24p94NCCs8qPgwAvwc1';
|
||||||
|
create user u3@localhost identified via caching_sha2_password using '$A$005$L9\ZKiwT''=%dMoqrPGFbywI9G8NecJqiy9D04S2abTLRvD32powG8nIxI9';
|
||||||
|
grant execute on test.* to u1@localhost, u2@localhost, u3@localhost;
|
||||||
|
connect u1,localhost,u1,abcd,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
u1@localhost u1@localhost 0
|
||||||
|
disconnect u1;
|
||||||
|
connect u2,localhost,u2,efghi,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
u2@localhost u2@localhost 0
|
||||||
|
disconnect u2;
|
||||||
|
connect u3,localhost,u3,xyz,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
user() current_user() have_ssl
|
||||||
|
u3@localhost u3@localhost 0
|
||||||
|
disconnect u3;
|
||||||
|
connection default;
|
||||||
|
drop user u1@localhost;
|
||||||
|
drop user u2@localhost;
|
||||||
|
drop user u3@localhost;
|
||||||
|
# restart
|
||||||
|
show status like 'caching_sha2_password%';
|
||||||
|
Variable_name Value
|
||||||
|
Caching_sha2_password_rsa_public_key
|
||||||
|
drop procedure checkme;
|
||||||
|
drop user test1@'%';
|
||||||
|
drop user test2@'%';
|
93
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/tcp_nossl.test
Normal file
93
plugin/auth_mysql_sha2/mysql-test/mysql_sha2/tcp_nossl.test
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
call mtr.add_suppression('failed to read private_key.pem: 2 "No such file or directory"');
|
||||||
|
call mtr.add_suppression('Authentication requires either RSA keys or secure transport');
|
||||||
|
|
||||||
|
source include/require_openssl_client.inc;
|
||||||
|
source init.inc;
|
||||||
|
|
||||||
|
query_vertical select * from information_schema.system_variables where variable_name like 'caching_sha2_password%' order by 1;
|
||||||
|
|
||||||
|
--error ER_PASSWD_LENGTH
|
||||||
|
create user test3@'%' identified via caching_sha2_password using 'pwd';
|
||||||
|
--error ER_PASSWD_LENGTH
|
||||||
|
create user test3@'%' identified via caching_sha2_password using '0000000000000000000000000000000000000000000000000000000000000000000000';
|
||||||
|
|
||||||
|
replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT;
|
||||||
|
error 2061;
|
||||||
|
connect con1, localhost,test1,pwd,,,,TCP NOSSL;
|
||||||
|
replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT;
|
||||||
|
error 2061;
|
||||||
|
connect con3, localhost,test1,wrong_pwd,,,,TCP NOSSL;
|
||||||
|
connect con4, localhost,test2,,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect con4;
|
||||||
|
replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT;
|
||||||
|
error ER_ACCESS_DENIED_ERROR;
|
||||||
|
connect con5, localhost,test2 pwd,,,,,TCP NOSSL;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
let $restart_parameters= --caching_sha2_password-auto_generate_rsa_keys;
|
||||||
|
source include/restart_mysqld.inc;
|
||||||
|
select length(variable_value) from information_schema.global_status
|
||||||
|
where variable_name like 'caching_sha2_password%';
|
||||||
|
let pubkey=`select variable_value from information_schema.global_status
|
||||||
|
where variable_name like 'caching_sha2_password%'`;
|
||||||
|
|
||||||
|
let $restart_parameters= --caching_sha2_password-auto_generate_rsa_keys;
|
||||||
|
source include/restart_mysqld.inc;
|
||||||
|
evalp select variable_value="$pubkey" as 'key did not change'
|
||||||
|
from information_schema.global_status
|
||||||
|
where variable_name like 'caching_sha2_password%';
|
||||||
|
|
||||||
|
|
||||||
|
# again, this time with keys
|
||||||
|
connect con1, localhost,test1,pwd,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect con1;
|
||||||
|
connect con2, localhost,test1,pwd,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect con2;
|
||||||
|
replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT;
|
||||||
|
error ER_ACCESS_DENIED_ERROR;
|
||||||
|
connect con3, localhost,test1,wrong_pwd,,,,TCP NOSSL;
|
||||||
|
connect con4, localhost,test2,,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect con4;
|
||||||
|
replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT;
|
||||||
|
error ER_ACCESS_DENIED_ERROR;
|
||||||
|
connect con5, localhost,test2 pwd,,,,,TCP NOSSL;
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Compatibility with MySQL password hashes
|
||||||
|
#
|
||||||
|
create user u1@localhost identified via caching_sha2_password using '$A$005$5dx;X)z |kX]\ZNx7QTrl0oTy2C0/f4bggQMFIDnSDeZ7koLoO417jc9D';
|
||||||
|
create user u2@localhost identified via caching_sha2_password using '$A$005$dL\Zq]<7d[YAbk}x!;^.qMuuUUBmB5aF7x7GsAKZzpb24p94NCCs8qPgwAvwc1';
|
||||||
|
create user u3@localhost identified via caching_sha2_password using '$A$005$L9\ZKiwT''=%dMoqrPGFbywI9G8NecJqiy9D04S2abTLRvD32powG8nIxI9';
|
||||||
|
|
||||||
|
grant execute on test.* to u1@localhost, u2@localhost, u3@localhost;
|
||||||
|
|
||||||
|
connect u1,localhost,u1,abcd,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect u1;
|
||||||
|
connect u2,localhost,u2,efghi,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect u2;
|
||||||
|
connect u3,localhost,u3,xyz,,,,TCP NOSSL;
|
||||||
|
call checkme();
|
||||||
|
disconnect u3;
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
connection default;
|
||||||
|
|
||||||
|
drop user u1@localhost;
|
||||||
|
drop user u2@localhost;
|
||||||
|
drop user u3@localhost;
|
||||||
|
|
||||||
|
let datadir=`select @@datadir`;
|
||||||
|
remove_file $datadir/private_key.pem;
|
||||||
|
remove_file $datadir/public_key.pem;
|
||||||
|
let $restart_parameters=;
|
||||||
|
source include/restart_mysqld.inc;
|
||||||
|
show status like 'caching_sha2_password%';
|
||||||
|
source fini.inc;
|
256
plugin/auth_mysql_sha2/mysql_sha2.c
Normal file
256
plugin/auth_mysql_sha2/mysql_sha2.c
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
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 */
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#include <io.h>
|
||||||
|
#define access _access
|
||||||
|
#define F_OK 0
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#include "mysql_sha2.h"
|
||||||
|
#include <mysql/plugin_auth.h>
|
||||||
|
#include <mysqld_error.h>
|
||||||
|
|
||||||
|
char *private_key_path, *public_key_path, public_key[1024]={0};
|
||||||
|
size_t public_key_len=0;
|
||||||
|
EVP_PKEY *private_key= 0;
|
||||||
|
|
||||||
|
static my_bool auto_generate_keys;
|
||||||
|
static unsigned int digest_rounds;
|
||||||
|
|
||||||
|
struct digest {
|
||||||
|
unsigned int iterations;
|
||||||
|
unsigned char salt[SCRAMBLE_LENGTH];
|
||||||
|
unsigned char crypted[SHA256CRYPT_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PASSWORD_LEN (SCRAMBLE_LENGTH + SHA256CRYPT_LEN + sizeof("$A$005$")-1)
|
||||||
|
|
||||||
|
#define ITERATION_MULTIPLIER 1000
|
||||||
|
|
||||||
|
static unsigned char request_public_key = '\2';
|
||||||
|
static unsigned char perform_full_authentication = '\4';
|
||||||
|
|
||||||
|
static void make_salt(unsigned char *to)
|
||||||
|
{
|
||||||
|
unsigned char *end= to + SCRAMBLE_LENGTH;
|
||||||
|
my_random_bytes(to, SCRAMBLE_LENGTH);
|
||||||
|
for (; to < end; to++)
|
||||||
|
*to = (*to % 90) + '$' + 1;
|
||||||
|
/* in MySQL: if (*to == '\0' || *to == '$') (*to)++; */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
|
||||||
|
{
|
||||||
|
struct digest *authstr;
|
||||||
|
unsigned char to[SHA256CRYPT_LEN];
|
||||||
|
unsigned char scramble[SCRAMBLE_LENGTH + 1], *pkt;
|
||||||
|
int pkt_len;
|
||||||
|
MYSQL_PLUGIN_VIO_INFO vio_info;
|
||||||
|
unsigned char plain_text[1025];
|
||||||
|
size_t plain_text_len= sizeof(plain_text)-1;
|
||||||
|
|
||||||
|
make_salt(scramble);
|
||||||
|
scramble[SCRAMBLE_LENGTH]= 0;
|
||||||
|
if (vio->write_packet(vio, scramble, sizeof(scramble)))
|
||||||
|
return CR_ERROR;
|
||||||
|
|
||||||
|
if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
|
||||||
|
return CR_ERROR;
|
||||||
|
|
||||||
|
if (!pkt_len || (pkt_len == 1 && *pkt == 0)) /* sic! */
|
||||||
|
{
|
||||||
|
if (info->auth_string_length == 0)
|
||||||
|
return CR_OK;
|
||||||
|
return CR_AUTH_USER_CREDENTIALS;
|
||||||
|
}
|
||||||
|
info->password_used= PASSWORD_USED_YES;
|
||||||
|
|
||||||
|
if (info->auth_string_length == 0)
|
||||||
|
return CR_AUTH_USER_CREDENTIALS;
|
||||||
|
|
||||||
|
if (pkt_len != SHA256_DIGEST_LENGTH)
|
||||||
|
return CR_ERROR;
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO support caching: user@host -> plaintext password
|
||||||
|
but for now - request full auth unconditionally
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (vio->write_packet(vio, &perform_full_authentication, 1))
|
||||||
|
return CR_ERROR;
|
||||||
|
|
||||||
|
if ((pkt_len= vio->read_packet(vio, &pkt)) <= 0)
|
||||||
|
return CR_ERROR;
|
||||||
|
|
||||||
|
vio->info(vio, &vio_info);
|
||||||
|
/* secure transport, as in MySQL. SSL is "secure" even if not verified */
|
||||||
|
if (vio_info.protocol == MYSQL_VIO_TCP && !vio_info.tls)
|
||||||
|
{
|
||||||
|
if (!private_key || !public_key_len)
|
||||||
|
{
|
||||||
|
my_printf_error(1, SELF ": Authentication requires either RSA keys "
|
||||||
|
"or secure transport", ME_ERROR_LOG_ONLY);
|
||||||
|
return CR_AUTH_PLUGIN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pkt_len == 1 && *pkt == request_public_key)
|
||||||
|
{
|
||||||
|
if (vio->write_packet(vio, (unsigned char *)public_key,
|
||||||
|
(int)public_key_len))
|
||||||
|
return CR_ERROR;
|
||||||
|
if ((pkt_len= vio->read_packet(vio, &pkt)) <= 0)
|
||||||
|
return CR_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssl_decrypt(private_key, pkt, pkt_len, plain_text, &plain_text_len))
|
||||||
|
return CR_ERROR;
|
||||||
|
|
||||||
|
for (size_t i=0; i < plain_text_len; i++)
|
||||||
|
plain_text[i]^= scramble[i % SCRAMBLE_LENGTH];
|
||||||
|
pkt= plain_text;
|
||||||
|
pkt_len= (int)plain_text_len;
|
||||||
|
}
|
||||||
|
/* now pkt contains plaintext password */
|
||||||
|
|
||||||
|
authstr= (struct digest*)info->auth_string;
|
||||||
|
sha256_crypt_r(pkt, pkt_len-1, authstr->salt, sizeof(authstr->salt),
|
||||||
|
to, authstr->iterations);
|
||||||
|
|
||||||
|
if (memcmp(to, authstr->crypted, SHA256CRYPT_LEN))
|
||||||
|
return CR_AUTH_USER_CREDENTIALS;
|
||||||
|
return CR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int password_hash(const char *password, size_t password_length,
|
||||||
|
char *hash, size_t *hash_length)
|
||||||
|
{
|
||||||
|
struct digest authstr;
|
||||||
|
|
||||||
|
if (*hash_length < PASSWORD_LEN)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!password_length)
|
||||||
|
return (int)(*hash_length= 0);
|
||||||
|
|
||||||
|
make_salt(authstr.salt);
|
||||||
|
sha256_crypt_r((unsigned char*)password, password_length,
|
||||||
|
authstr.salt, sizeof(authstr.salt),
|
||||||
|
authstr.crypted, digest_rounds);
|
||||||
|
*hash_length= my_snprintf(hash, *hash_length, "$A$%03X$%.20s%.43s",
|
||||||
|
digest_rounds/ITERATION_MULTIPLIER,
|
||||||
|
authstr.salt, authstr.crypted);
|
||||||
|
assert(*hash_length == PASSWORD_LEN);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int digest_to_binary(const char *hash, size_t hash_length,
|
||||||
|
unsigned char *out, size_t *out_length)
|
||||||
|
{
|
||||||
|
struct digest *authstr= (struct digest*)out;
|
||||||
|
assert(*out_length > sizeof(*authstr));
|
||||||
|
*out_length= sizeof(*authstr);
|
||||||
|
memset(out, 0, *out_length);
|
||||||
|
if (hash_length != PASSWORD_LEN)
|
||||||
|
{
|
||||||
|
my_printf_error(ER_PASSWD_LENGTH, "Password hash should be "
|
||||||
|
"%zu characters long", 0, PASSWORD_LEN);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (sscanf(hash, "$A$%X$%20c%43c", &authstr->iterations, authstr->salt,
|
||||||
|
authstr->crypted) < 3)
|
||||||
|
{
|
||||||
|
my_printf_error(ER_PASSWD_LENGTH, "Invalid password hash", 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
authstr->iterations*= ITERATION_MULTIPLIER;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct st_mysql_auth info=
|
||||||
|
{
|
||||||
|
MYSQL_AUTHENTICATION_INTERFACE_VERSION,
|
||||||
|
SELF, auth, password_hash, digest_to_binary
|
||||||
|
};
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_STR(private_key_path, private_key_path, PLUGIN_VAR_READONLY,
|
||||||
|
"A path to the private RSA key used for authentication",
|
||||||
|
NULL, NULL, "private_key.pem");
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_STR(public_key_path, public_key_path, PLUGIN_VAR_READONLY,
|
||||||
|
"A path to the public RSA key used for authentication",
|
||||||
|
NULL, NULL, "public_key.pem");
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_BOOL(auto_generate_rsa_keys, auto_generate_keys,
|
||||||
|
PLUGIN_VAR_READONLY | PLUGIN_VAR_OPCMDARG,
|
||||||
|
"Auto generate RSA keys at server startup if key paths "
|
||||||
|
"are not explicitly set and key files are not present "
|
||||||
|
"at their default locations", NULL, NULL, 1);
|
||||||
|
|
||||||
|
static MYSQL_SYSVAR_UINT(digest_rounds, digest_rounds, PLUGIN_VAR_READONLY,
|
||||||
|
"Number of SHA2 rounds to be performed when computing a password hash",
|
||||||
|
NULL, NULL, 5000, 5000, 0xfff * ITERATION_MULTIPLIER, 1);
|
||||||
|
|
||||||
|
static int init_keys(void *p)
|
||||||
|
{
|
||||||
|
if (private_key_path == MYSQL_SYSVAR_NAME(private_key_path).def_val &&
|
||||||
|
public_key_path == MYSQL_SYSVAR_NAME(public_key_path).def_val &&
|
||||||
|
access(private_key_path, F_OK) && access(public_key_path, F_OK) &&
|
||||||
|
auto_generate_keys)
|
||||||
|
ssl_genkeys();
|
||||||
|
ssl_loadkeys();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int free_keys(void *p)
|
||||||
|
{
|
||||||
|
EVP_PKEY_free(private_key);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct st_mysql_sys_var *sysvars[]=
|
||||||
|
{
|
||||||
|
MYSQL_SYSVAR(private_key_path),
|
||||||
|
MYSQL_SYSVAR(public_key_path),
|
||||||
|
MYSQL_SYSVAR(auto_generate_rsa_keys),
|
||||||
|
MYSQL_SYSVAR(digest_rounds),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct st_mysql_show_var status_variables[]=
|
||||||
|
{
|
||||||
|
{"rsa_public_key", public_key, SHOW_CHAR},
|
||||||
|
{NULL, NULL, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
maria_declare_plugin(auth_mysql_sha2)
|
||||||
|
{
|
||||||
|
MYSQL_AUTHENTICATION_PLUGIN,
|
||||||
|
&info,
|
||||||
|
SELF,
|
||||||
|
"Oracle Corporation, Sergei Golubchik",
|
||||||
|
"MySQL-compatible SHA2 authentication",
|
||||||
|
PLUGIN_LICENSE_GPL,
|
||||||
|
init_keys,
|
||||||
|
free_keys,
|
||||||
|
0x0100,
|
||||||
|
status_variables,
|
||||||
|
sysvars,
|
||||||
|
"1.0",
|
||||||
|
MariaDB_PLUGIN_MATURITY_GAMMA
|
||||||
|
}
|
||||||
|
maria_declare_plugin_end;
|
41
plugin/auth_mysql_sha2/mysql_sha2.h
Normal file
41
plugin/auth_mysql_sha2/mysql_sha2.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
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 <string.h>
|
||||||
|
#include <openssl/opensslv.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <mysql/plugin.h>
|
||||||
|
|
||||||
|
#define SELF "caching_sha2_password"
|
||||||
|
#define SHA256CRYPT_LEN 43
|
||||||
|
|
||||||
|
extern char *private_key_path, *public_key_path, public_key[1024];
|
||||||
|
extern size_t public_key_len;
|
||||||
|
extern EVP_PKEY *private_key;
|
||||||
|
|
||||||
|
int ssl_decrypt(EVP_PKEY *pkey, unsigned char *src, size_t srclen,
|
||||||
|
unsigned char *dst, size_t *dstlen);
|
||||||
|
int ssl_genkeys();
|
||||||
|
int ssl_loadkeys();
|
||||||
|
|
||||||
|
void sha256_crypt_r(const unsigned char *key, size_t key_len,
|
||||||
|
const unsigned char *salt, size_t salt_len,
|
||||||
|
unsigned char *buffer, size_t rounds);
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||||
|
EVP_PKEY *EVP_RSA_gen(unsigned int bits);
|
||||||
|
#endif
|
39
plugin/auth_mysql_sha2/openssl1-compat.c
Normal file
39
plugin/auth_mysql_sha2/openssl1-compat.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
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 <openssl/rsa.h>
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||||
|
EVP_PKEY *EVP_RSA_gen(unsigned int bits)
|
||||||
|
{
|
||||||
|
EVP_PKEY_CTX *ctx;
|
||||||
|
EVP_PKEY *pkey = NULL;
|
||||||
|
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
|
||||||
|
if (!ctx)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (EVP_PKEY_keygen_init(ctx) <= 0 ||
|
||||||
|
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
EVP_PKEY_keygen(ctx, &pkey);
|
||||||
|
|
||||||
|
err:
|
||||||
|
EVP_PKEY_CTX_free(ctx);
|
||||||
|
return pkey;
|
||||||
|
}
|
||||||
|
#endif
|
120
plugin/auth_mysql_sha2/sha256crypt.c
Normal file
120
plugin/auth_mysql_sha2/sha256crypt.c
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
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 <my_alloca.h>
|
||||||
|
#include "mysql_sha2.h"
|
||||||
|
|
||||||
|
/* based on https://www.akkadia.org/drepper/SHA-crypt.txt */
|
||||||
|
|
||||||
|
/* SHA256-based Unix crypt implementation.
|
||||||
|
Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>. */
|
||||||
|
|
||||||
|
void sha256_crypt_r(const unsigned char *key, size_t key_len,
|
||||||
|
const unsigned char *salt, size_t salt_len,
|
||||||
|
unsigned char *buffer, size_t rounds)
|
||||||
|
{
|
||||||
|
unsigned char tmp[SHA256_DIGEST_LENGTH];
|
||||||
|
unsigned char alt[SHA256_DIGEST_LENGTH];
|
||||||
|
size_t cnt;
|
||||||
|
static const char b64t[64] =
|
||||||
|
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
void *ctx = alloca(my_sha256_context_size());
|
||||||
|
unsigned char *p_bytes = alloca(key_len);
|
||||||
|
unsigned char *s_bytes = alloca(salt_len);
|
||||||
|
|
||||||
|
my_sha256_multi(alt, key, key_len, salt, salt_len, key, key_len, NULL);
|
||||||
|
|
||||||
|
my_sha256_init(ctx);
|
||||||
|
my_sha256_input(ctx, key, key_len);
|
||||||
|
my_sha256_input(ctx, salt, salt_len);
|
||||||
|
/* Add for every byte in the key one byte of the alternate sum. */
|
||||||
|
for (cnt = key_len; cnt > sizeof(alt); cnt -= sizeof(alt))
|
||||||
|
my_sha256_input(ctx, alt, sizeof(alt));
|
||||||
|
my_sha256_input(ctx, alt, cnt);
|
||||||
|
/* Take the binary representation of the length of the key and for every
|
||||||
|
1 add the alternate sum, for every 0 the key. */
|
||||||
|
for (cnt = key_len; cnt > 0; cnt >>= 1)
|
||||||
|
if ((cnt & 1) != 0)
|
||||||
|
my_sha256_input(ctx, alt, sizeof(alt));
|
||||||
|
else
|
||||||
|
my_sha256_input(ctx, key, key_len);
|
||||||
|
my_sha256_result(ctx, alt);
|
||||||
|
|
||||||
|
/* Start computing S byte sequence. */
|
||||||
|
my_sha256_init(ctx);
|
||||||
|
for (cnt = 0; cnt < 16u + alt[0]; ++cnt)
|
||||||
|
my_sha256_input(ctx, salt, salt_len);
|
||||||
|
my_sha256_result(ctx, tmp);
|
||||||
|
|
||||||
|
/* Create byte sequence S. */
|
||||||
|
for (cnt = salt_len; cnt >= sizeof(tmp); cnt -= sizeof(tmp))
|
||||||
|
memcpy(s_bytes + salt_len - cnt, tmp, sizeof(tmp));
|
||||||
|
memcpy(s_bytes + salt_len - cnt, tmp, cnt);
|
||||||
|
|
||||||
|
/* Start computing P byte sequence. */
|
||||||
|
my_sha256_init(ctx);
|
||||||
|
for (cnt = 0; cnt < key_len; ++cnt)
|
||||||
|
my_sha256_input(ctx, key, key_len);
|
||||||
|
my_sha256_result(ctx, tmp);
|
||||||
|
|
||||||
|
/* Create byte sequence P. */
|
||||||
|
for (cnt = key_len; cnt >= sizeof(tmp); cnt -= sizeof(tmp))
|
||||||
|
memcpy(p_bytes + key_len - cnt, tmp, sizeof(tmp));
|
||||||
|
memcpy(p_bytes + key_len - cnt, tmp, cnt);
|
||||||
|
|
||||||
|
/* Repeatedly run the collected hash value through SHA256 to burn
|
||||||
|
CPU cycles. */
|
||||||
|
for (cnt = 0; cnt < rounds; ++cnt)
|
||||||
|
{
|
||||||
|
my_sha256_init(ctx);
|
||||||
|
if ((cnt & 1) != 0)
|
||||||
|
my_sha256_input(ctx, p_bytes, key_len);
|
||||||
|
else
|
||||||
|
my_sha256_input(ctx, cnt ? tmp : alt, sizeof(tmp));
|
||||||
|
if (cnt % 3 != 0)
|
||||||
|
my_sha256_input(ctx, s_bytes, salt_len);
|
||||||
|
if (cnt % 7 != 0)
|
||||||
|
my_sha256_input(ctx, p_bytes, key_len);
|
||||||
|
if ((cnt & 1) != 0)
|
||||||
|
my_sha256_input(ctx, tmp, sizeof(tmp));
|
||||||
|
else
|
||||||
|
my_sha256_input(ctx, p_bytes, key_len);
|
||||||
|
my_sha256_result(ctx, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define b64_from_24bit(B2, B1, B0, N) \
|
||||||
|
do { \
|
||||||
|
unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
|
||||||
|
int n = (N); \
|
||||||
|
while (n-- > 0) \
|
||||||
|
{ \
|
||||||
|
*buffer++ = b64t[w & 0x3f]; \
|
||||||
|
w >>= 6; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
b64_from_24bit (tmp[0], tmp[10], tmp[20], 4);
|
||||||
|
b64_from_24bit (tmp[21], tmp[1], tmp[11], 4);
|
||||||
|
b64_from_24bit (tmp[12], tmp[22], tmp[2], 4);
|
||||||
|
b64_from_24bit (tmp[3], tmp[13], tmp[23], 4);
|
||||||
|
b64_from_24bit (tmp[24], tmp[4], tmp[14], 4);
|
||||||
|
b64_from_24bit (tmp[15], tmp[25], tmp[5], 4);
|
||||||
|
b64_from_24bit (tmp[6], tmp[16], tmp[26], 4);
|
||||||
|
b64_from_24bit (tmp[27], tmp[7], tmp[17], 4);
|
||||||
|
b64_from_24bit (tmp[18], tmp[28], tmp[8], 4);
|
||||||
|
b64_from_24bit (tmp[9], tmp[19], tmp[29], 4);
|
||||||
|
b64_from_24bit (0, tmp[31], tmp[30], 3); /* == 43 bytes in total */
|
||||||
|
}
|
136
plugin/auth_mysql_sha2/ssl_stuff.c
Normal file
136
plugin/auth_mysql_sha2/ssl_stuff.c
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
#ifdef OPENSSL_IS_WOLFSSL
|
||||||
|
/*
|
||||||
|
doesn't have few functions from below and libmariadb doesn't support RSA
|
||||||
|
encryption anyway, so not worth bothering
|
||||||
|
*/
|
||||||
|
my_printf_error(1, SELF ": cannot auto-generate keys with WolfSSL",
|
||||||
|
ME_ERROR_LOG_ONLY);
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
FILE *f= NULL;
|
||||||
|
|
||||||
|
if (!(pkey= EVP_RSA_gen(2048)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!(f= fopen(private_key_path, "w")))
|
||||||
|
FILE_ERROR("write", private_key_path);
|
||||||
|
|
||||||
|
if (PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL) != 1)
|
||||||
|
SSL_ERROR("write", private_key_path);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (!(f= fopen(public_key_path, "w")))
|
||||||
|
FILE_ERROR("write", public_key_path);
|
||||||
|
|
||||||
|
if (PEM_write_PUBKEY(f, pkey) != 1)
|
||||||
|
SSL_ERROR("write", public_key_path);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (f)
|
||||||
|
fclose(f);
|
||||||
|
if (pkey)
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int ssl_loadkeys()
|
||||||
|
{
|
||||||
|
EVP_PKEY *pkey= 0;
|
||||||
|
FILE *f;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (!(f= fopen(private_key_path, "r")))
|
||||||
|
FILE_ERROR("read", private_key_path);
|
||||||
|
|
||||||
|
if (!(pkey= PEM_read_PrivateKey(f, NULL, NULL, NULL)))
|
||||||
|
SSL_ERROR("read", private_key_path);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (!(f= fopen(public_key_path, "r")))
|
||||||
|
FILE_ERROR("read", public_key_path);
|
||||||
|
len= fread(public_key, 1, sizeof(public_key)-1, f);
|
||||||
|
|
||||||
|
if (!feof(f))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
public_key[len]= 0;
|
||||||
|
public_key_len= len;
|
||||||
|
private_key= pkey;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (f)
|
||||||
|
fclose(f);
|
||||||
|
if (pkey)
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return 1;
|
||||||
|
}
|
@@ -2395,6 +2395,7 @@ void mpvio_info(Vio *vio, MYSQL_PLUGIN_VIO_INFO *info)
|
|||||||
info->protocol= addr.sa_family == AF_UNIX ?
|
info->protocol= addr.sa_family == AF_UNIX ?
|
||||||
MYSQL_VIO_SOCKET : MYSQL_VIO_TCP;
|
MYSQL_VIO_SOCKET : MYSQL_VIO_TCP;
|
||||||
info->socket= (int)vio_fd(vio);
|
info->socket= (int)vio_fd(vio);
|
||||||
|
info->tls= 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
Reference in New Issue
Block a user