1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-31855 validate ssl certificates using client password

if the client enabled --ssl-verify-server-cert, then
the server certificate is verified as follows:

* if --ssl-ca or --ssl-capath were specified, the cert must have
  a proper signature by the specified CA (or CA in the path)
  and the cert's hostname must match the server's hostname.
  If the cert isn't signed or a hostname is wrong - the
  connection is aborted.

* if MARIADB_OPT_TLS_PEER_FP was used and the fingerprint matches,
  the connection is allowed, if it doesn't match - aborted.

* If the connection uses unix socket or named pipes - it's allowed.
  (consistent with server's --require-secure-transport behavior)

otherwise the cert is still in doubt, we don't know if we can trust
it or there's an active MitM in progress.

* If the user has provided no password or the server requested an
  authentication plugin that sends the password in cleartext -
  the connection is aborted.

* Perform the authentication. If the server accepts the password,
  it'll send SHA2(scramble || password hash || cert fingerprint)
  with the OK packet.

* Verify the SHA2 digest, if it matches - the connection is allowed,
  otherwise it's aborted.
This commit is contained in:
Sergei Golubchik
2023-08-21 16:25:56 +02:00
parent 585c096aa5
commit 1ef1bab99e
13 changed files with 196 additions and 18 deletions

View File

@ -201,15 +201,11 @@ public:
};
class ACL_USER :public ACL_USER_BASE,
public ACL_USER_PARAM
class ACL_USER :public ACL_USER_BASE, public ACL_USER_PARAM
{
public:
ACL_USER() = default;
ACL_USER(THD *thd, const LEX_USER &combo,
const Account_options &options,
const privilege_t privileges);
ACL_USER(THD *, const LEX_USER &, const Account_options &, const privilege_t);
ACL_USER *copy(MEM_ROOT *root)
{
@ -14390,6 +14386,29 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
return 1;
}
static void make_ssl_info(THD *thd, LEX_CSTRING salt, char *info)
{
#ifdef HAVE_OPENSSL
uchar digest[256/8];
if (!salt.length)
return;
/*
mark that it's after-auth mysql->info version 1.
meaning, it contains sha2(salt, scramble, sha2_cert_fingerprint)
encoded in 64 lowercase letters 'a'..'p', one letter per 4 bits (0..15)
*/
*info++= 1; // Version 1
DBUG_ASSERT(thd->scramble[SCRAMBLE_LENGTH] == 0);
LEX_CUSTRING fp= ssl_acceptor_fingerprint();
my_sha256_multi(digest, salt.str, salt.length, thd->scramble,
(size_t)SCRAMBLE_LENGTH, fp.str, fp.length, NULL);
octet2hex(info, digest, sizeof(digest));
#endif
}
static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name,
MPVIO_EXT *mpvio)
@ -14507,6 +14526,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
{
int res= CR_OK;
MPVIO_EXT mpvio;
char ssl_info[256/4 + 2]= {0}; // '\1', SHA256 (1 char per 4 bits), '\0'
enum enum_server_command command= com_change_user_pkt_len ? COM_CHANGE_USER
: COM_CONNECT;
DBUG_ENTER("acl_authenticate");
@ -14844,7 +14864,10 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
sctx->external_user= my_strdup(key_memory_MPVIO_EXT_auth_info,
mpvio.auth_info.external_user, MYF(0));
my_ok(thd);
if (initialized && !com_change_user_pkt_len)
make_ssl_info(thd, acl_user->auth[mpvio.curr_auth-1].salt, ssl_info);
my_ok(thd, 0, 0, ssl_info[0] == '\1' ? ssl_info : NULL);
PSI_CALL_set_thread_account
(thd->main_security_ctx.user, static_cast<uint>(strlen(thd->main_security_ctx.user)),