MySQL 8.4.2
Source Code Documentation
sql_authentication.cc File Reference

AUTHENTICATION CODE. More...

#include "sql/auth/sql_authentication.h"
#include <fcntl.h>
#include <mysql/components/my_service.h>
#include <sql/ssl_acceptor_context_operator.h>
#include <sql/ssl_init_callback.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string>
#include <utility>
#include <vector>
#include "crypt_genhash_impl.h"
#include "include/compression.h"
#include "m_string.h"
#include "map_helpers.h"
#include "mutex_lock.h"
#include "my_byteorder.h"
#include "my_command.h"
#include "my_compiler.h"
#include "my_dbug.h"
#include "my_dir.h"
#include "my_inttypes.h"
#include "my_io.h"
#include "my_psi_config.h"
#include "my_rnd.h"
#include "my_sys.h"
#include "my_time.h"
#include "mysql/components/services/bits/psi_bits.h"
#include "mysql/components/services/log_builtins.h"
#include "mysql/components/services/log_shared.h"
#include "mysql/my_loglevel.h"
#include "mysql/plugin.h"
#include "mysql/psi/mysql_mutex.h"
#include "mysql/service_my_plugin_log.h"
#include "mysql/service_mysql_alloc.h"
#include "mysql/service_mysql_password_policy.h"
#include "mysql/strings/m_ctype.h"
#include "mysql_time.h"
#include "mysqld_error.h"
#include "password.h"
#include "pfs_thread_provider.h"
#include "prealloced_array.h"
#include "sql/auth/auth_acls.h"
#include "sql/auth/auth_common.h"
#include "sql/auth/auth_internal.h"
#include "sql/auth/partial_revokes.h"
#include "sql/auth/sql_auth_cache.h"
#include "sql/auth/sql_security_ctx.h"
#include "sql/conn_handler/connection_handler_manager.h"
#include "sql/current_thd.h"
#include "sql/debug_sync.h"
#include "sql/derror.h"
#include "sql/hostname_cache.h"
#include "sql/log.h"
#include "sql/mysqld.h"
#include "sql/protocol.h"
#include "sql/protocol_classic.h"
#include "sql/psi_memory_key.h"
#include "sql/sql_class.h"
#include "sql/sql_connect.h"
#include "sql/sql_const.h"
#include "sql/sql_db.h"
#include "sql/sql_error.h"
#include "sql/sql_lex.h"
#include "sql/sql_plugin.h"
#include "sql/sql_time.h"
#include "sql/strfunc.h"
#include "sql/system_variables.h"
#include "sql/tztime.h"
#include "sql_common.h"
#include "sql_string.h"
#include "string_with_len.h"
#include "strmake.h"
#include "template_utils.h"
#include "violite.h"
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/x509v3.h>

Classes

class  FileCloser
 
class  File_IO
 FILE_IO : Wrapper around std::fstream 1> Provides READ/WRITE handle to a file 2> Records error on READ/WRITE operations 3> Closes file before destruction. More...
 
class  File_creator
 
class  RSA_gen
 
class  X509_gen
 

Macros

#define LOG_COMPONENT_TAG   "sha256_password"
 
#define AUTH_PACKET_HEADER_SIZE_PROTO_41   32
 Size of the header fields of an authentication packet. More...
 
#define AUTH_PACKET_HEADER_SIZE_PROTO_40   5
 
#define MAX_CIPHER_LENGTH   1024
 
#define SHA256_PASSWORD_MAX_PASSWORD_LENGTH   MAX_PLAINTEXT_LENGTH
 
#define DEFAULT_SSL_CLIENT_CERT   "client-cert.pem"
 
#define DEFAULT_SSL_CLIENT_KEY   "client-key.pem"
 
#define MAX_CN_NAME_LENGTH   64
 

Typedefs

typedef char *(* get_proto_string_func_t) (char **, size_t *, size_t *)
 Get a string according to the protocol of the underlying buffer. More...
 
typedef std::string Sql_string_t
 

Functions

const char * client_plugin_name (plugin_ref ref)
 
int security_level (void)
 
static bool do_auto_rsa_keys_generation ()
 
void optimize_plugin_compare_by_pointer (LEX_CSTRING *plugin_name)
 
bool auth_plugin_is_built_in (const char *plugin_name)
 
bool auth_plugin_supports_expiration (const char *plugin_name)
 Only the plugins that are known to use the mysql.user table to store their passwords support password expiration atm. More...
 
static void cannot_proxy_error (THD *thd, const MPVIO_EXT &mpvio, int server_error, int client_error)
 a helper function to report cannot proxy error in all the proper places More...
 
static void login_failed_error (THD *thd, MPVIO_EXT *mpvio, int passwd_used)
 a helper function to report an access denied error in all the proper places More...
 
static bool send_server_handshake_packet (MPVIO_EXT *mpvio, const char *data, uint data_len)
 Sends a server Protocol::HandshakeV10. More...
 
static bool send_plugin_request_packet (MPVIO_EXT *mpvio, const uchar *data, uint data_len)
 Sends a Protocol::AuthSwitchRequest:. More...
 
static bool send_auth_next_factor_packet (MPVIO_EXT *mpvio, const uchar *data, uint data_len)
 Sends a Protocol::AuthNextFactor:. More...
 
bool acl_check_host (THD *thd, const char *host, const char *ip)
 
ACL_USERdecoy_user (const LEX_CSTRING &username, const LEX_CSTRING &hostname, MEM_ROOT *mem, struct rand_struct *rand, bool is_initialized)
 When authentication is attempted using an unknown username a dummy user account with no authentication capabilities is assigned to the connection. More...
 
static bool find_mpvio_user (THD *thd, MPVIO_EXT *mpvio)
 Finds acl entry in user database for authentication purposes. More...
 
static bool read_client_connect_attrs (THD *thd, char **ptr, size_t *max_bytes_available, MPVIO_EXT *mpvio)
 
static bool acl_check_ssl (THD *thd, const ACL_USER *acl_user)
 
bool sha256_rsa_auth_status ()
 Check if server has valid public key/private key pair for RSA communication. More...
 
static bool parse_com_change_user_packet (THD *thd, MPVIO_EXT *mpvio, size_t packet_length)
 Parses a COM_CHANGE_USER. More...
 
static char * get_41_protocol_string (char **buffer, size_t *max_bytes_available, size_t *string_length)
 Get a string formatted according to the 4.1 version of the MySQL protocol. More...
 
static char * get_40_protocol_string (char **buffer, size_t *max_bytes_available, size_t *string_length)
 Get a string formatted according to the 4.0 version of the MySQL protocol. More...
 
static char * get_56_lenc_string (char **buffer, size_t *max_bytes_available, size_t *string_length)
 Get a length encoded string from a user-supplied buffer. More...
 
static char * get_41_lenc_string (char **buffer, size_t *max_bytes_available, size_t *string_length)
 Get a length encoded string from a user-supplied buffer. More...
 
static size_t parse_client_handshake_packet (THD *thd, MPVIO_EXT *mpvio, uchar **buff, size_t pkt_len)
 
static int wrap_plguin_data_into_proper_command (NET *net, const uchar *packet, int packet_len)
 Wrap the extra auth data sent so that they can pass in the protocol. More...
 
static int server_mpvio_write_packet (MYSQL_PLUGIN_VIO *param, const uchar *packet, int packet_len)
 vio->write_packet() callback method for server authentication plugins More...
 
static int server_mpvio_read_packet (MYSQL_PLUGIN_VIO *param, uchar **buf)
 vio->read_packet() callback method for server authentication plugins More...
 
static void server_mpvio_info (MYSQL_PLUGIN_VIO *vio, MYSQL_PLUGIN_VIO_INFO *info)
 fills MYSQL_PLUGIN_VIO_INFO structure with the information about the connection More...
 
static int do_auth_once (THD *thd, const LEX_CSTRING &auth_plugin_name, MPVIO_EXT *mpvio)
 
static int do_multi_factor_auth (THD *thd, MPVIO_EXT *mpvio)
 Perform 2nd and 3rd factor authentication. More...
 
static void server_mpvio_initialize (THD *thd, MPVIO_EXT *mpvio, Thd_charset_adapter *charset_adapter)
 
static void server_mpvio_update_thd (THD *thd, MPVIO_EXT *mpvio)
 
static bool check_password_lifetime (THD *thd, const ACL_USER *acl_user)
 Calculate the timestamp difference for password expiry. More...
 
void acl_log_connect (const char *user, const char *host, const char *auth_as, const char *db, THD *thd, enum enum_server_command command)
 Logging connection for the general query log, extracted from acl_authenticate() as it's reused at different times based on whether proxy users are checked. More...
 
void assign_priv_user_host (Security_context *sctx, ACL_USER *user)
 
static bool check_restrictions_for_com_connect_command (THD *thd)
 Check that for command COM_CONNECT, either restriction on max number of concurrent connections not violated or in case the connection is admin connection the user has required privilege. More...
 
static void check_and_update_password_lock_state (MPVIO_EXT &mpvio, THD *thd, int &res)
 
int acl_authenticate (THD *thd, enum_server_command command)
 Perform the handshake, authorize the client and update thd sctx variables. More...
 
bool is_secure_transport (int vio_type)
 
static int generate_sha256_password (char *outbuf, unsigned int *buflen, const char *inbuf, unsigned int inbuflen)
 
static int validate_sha256_password_hash (char *const inbuf, unsigned int buflen)
 
static int set_sha256_salt (const char *password, unsigned int password_len, unsigned char *salt, unsigned char *salt_len)
 
static int my_vio_is_encrypted (MYSQL_PLUGIN_VIO *vio)
 Interface for querying the MYSQL_PUBLIC_VIO about encryption state. More...
 
int show_rsa_public_key (THD *, SHOW_VAR *var, char *)
 
void deinit_rsa_keys (void)
 
bool init_rsa_keys (void)
 Loads the RSA key pair from disk and store them in a global variable. More...
 
static int init_sha256_password_handler (MYSQL_PLUGIN plugin_ref)
 
static void auth_save_scramble (MYSQL_PLUGIN_VIO *vio, const char *scramble)
 
static int compare_sha256_password_with_hash (const char *hash, unsigned long hash_length, const char *cleartext, unsigned long cleartext_length, int *is_error)
 Compare a clear text password with a stored hash. More...
 
static int sha256_password_authenticate (MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
 
static MYSQL_SYSVAR_STR (private_key_path, auth_rsa_private_key_path, PLUGIN_VAR_READONLY|PLUGIN_VAR_NOPERSIST, "A fully qualified path to the private RSA key used for authentication", nullptr, nullptr, AUTH_DEFAULT_RSA_PRIVATE_KEY)
 
static MYSQL_SYSVAR_STR (public_key_path, auth_rsa_public_key_path, PLUGIN_VAR_READONLY|PLUGIN_VAR_NOPERSIST, "A fully qualified path to the public RSA key used for authentication", nullptr, nullptr, AUTH_DEFAULT_RSA_PUBLIC_KEY)
 
static MYSQL_SYSVAR_BOOL (auto_generate_rsa_keys, auth_rsa_auto_generate_rsa_keys, PLUGIN_VAR_READONLY|PLUGIN_VAR_OPCMDARG|PLUGIN_VAR_NOPERSIST, "Auto generate RSA keys at server startup if corresponding " "system variables are not specified and key files are not present " "at the default location.", nullptr, nullptr, true)
 
static bool resize_no_exception (Sql_string_t &content, size_t size)
 Exception free resize. More...
 
static EVP_PKEY * evp_pkey_generate (RSA *rsa)
 
static Sql_string_t rsa_priv_key_write (RSA *rsa)
 Write private key in a string buffer. More...
 
static Sql_string_t rsa_pub_key_write (RSA *rsa)
 Write public key in a string buffer. More...
 
static X509 * x509_cert_read (const Sql_string_t &input_string)
 Read a X509 certificate into X509 format. More...
 
static Sql_string_t x509_cert_write (X509 *cert)
 Write X509 certificate into a string. More...
 
static EVP_PKEY * x509_key_read (const Sql_string_t &input_string)
 Read Private key into EVP_PKEY structure. More...
 
static Sql_string_t x509_key_write (EVP_PKEY *pkey)
 Write X509 certificate into a string. More...
 
template<typename RSA_generator_func , typename File_creation_func >
bool create_x509_certificate (RSA_generator_func &rsa_gen, const Sql_string_t cn, uint32_t serial, const Sql_string_t cert_filename, const Sql_string_t key_filename, File_creation_func &filecr, const Sql_string_t ca_key_file="", const Sql_string_t ca_cert_file="")
 Algorithm to create X509 certificate. More...
 
template<typename RSA_generator_func , typename File_creation_func >
bool create_RSA_key_pair (RSA_generator_func &rsa_gen, const Sql_string_t priv_key_filename, const Sql_string_t pub_key_filename, File_creation_func &filecr)
 Algorithm to generate RSA key pair. More...
 
bool do_auto_cert_generation (ssl_artifacts_status auto_detection_status, const char **ssl_ca, const char **ssl_key, const char **ssl_cert)
 Check auto_generate_certs option and generate SSL certificates if required. More...
 
static bool generate_rsa_keys (bool auto_generate, const char *priv_key_path, const char *pub_key_path, const char *message)
 
 mysql_declare_plugin (sha256_password)
 

Variables

constexpr const std::array rsa_key_sizes {2048, 2048, 2048, 3072, 7680, 15360}
 
const uint MAX_UNKNOWN_ACCOUNTS = 1000
 
Map_with_rw_lock< Auth_id, uint > * unknown_accounts = nullptr
 Hash to map unknown accounts to an authentication plugin. More...
 
LEX_CSTRING validate_password_plugin_name
 
LEX_CSTRING default_auth_plugin_name {STRING_WITH_LEN("caching_sha2_password")}
 
Cached_authentication_pluginsg_cached_authentication_plugins = nullptr
 
bool disconnect_on_expired_password = true
 
bool initialized
 
bool opt_auto_generate_certs = true
 
bool auth_rsa_auto_generate_rsa_keys = true
 
char * auth_rsa_private_key_path
 
char * auth_rsa_public_key_path
 
Rsa_authentication_keysg_sha256_rsa_keys = nullptr
 
static MYSQL_PLUGIN plugin_info_ptr
 
static SYS_VARsha256_password_sysvars []
 
static struct st_mysql_auth sha256_password_handler
 
 mysql_declare_plugin_end
 

Detailed Description

AUTHENTICATION CODE.

including initial connect handshake, invoking appropriate plugins, client-server plugin negotiation, COM_CHANGE_USER, and native MySQL authentication plugins.

Macro Definition Documentation

◆ AUTH_PACKET_HEADER_SIZE_PROTO_40

#define AUTH_PACKET_HEADER_SIZE_PROTO_40   5

◆ AUTH_PACKET_HEADER_SIZE_PROTO_41

#define AUTH_PACKET_HEADER_SIZE_PROTO_41   32

Size of the header fields of an authentication packet.

◆ DEFAULT_SSL_CLIENT_CERT

#define DEFAULT_SSL_CLIENT_CERT   "client-cert.pem"

◆ DEFAULT_SSL_CLIENT_KEY

#define DEFAULT_SSL_CLIENT_KEY   "client-key.pem"

◆ LOG_COMPONENT_TAG

#define LOG_COMPONENT_TAG   "sha256_password"

◆ MAX_CIPHER_LENGTH

#define MAX_CIPHER_LENGTH   1024

◆ MAX_CN_NAME_LENGTH

#define MAX_CN_NAME_LENGTH   64

◆ SHA256_PASSWORD_MAX_PASSWORD_LENGTH

#define SHA256_PASSWORD_MAX_PASSWORD_LENGTH   MAX_PLAINTEXT_LENGTH

Typedef Documentation

◆ get_proto_string_func_t

typedef char *(* get_proto_string_func_t) (char **, size_t *, size_t *)

Get a string according to the protocol of the underlying buffer.

◆ Sql_string_t

typedef std::string Sql_string_t

Function Documentation

◆ acl_authenticate()

int acl_authenticate ( THD thd,
enum_server_command  command 
)

Perform the handshake, authorize the client and update thd sctx variables.

Parameters
thdthread handle
commandthe command to be executed, it can be either a COM_CHANGE_USER or COM_CONNECT (if it's a new connection)
Return values
0success, thd is updated.
1error

◆ acl_check_host()

bool acl_check_host ( THD thd,
const char *  host,
const char *  ip 
)

◆ acl_check_ssl()

static bool acl_check_ssl ( THD thd,
const ACL_USER acl_user 
)
static

◆ acl_log_connect()

void acl_log_connect ( const char *  user,
const char *  host,
const char *  auth_as,
const char *  db,
THD thd,
enum enum_server_command  command 
)

Logging connection for the general query log, extracted from acl_authenticate() as it's reused at different times based on whether proxy users are checked.

Parameters
userauthentication user name
hostauthentication user host or IP address
auth_asprivilege user name
dbdefault database
thdthread handle
commandtype of command(connect or change user)

◆ assign_priv_user_host()

void assign_priv_user_host ( Security_context sctx,
ACL_USER user 
)
inline

◆ auth_plugin_is_built_in()

bool auth_plugin_is_built_in ( const char *  plugin_name)

◆ auth_plugin_supports_expiration()

bool auth_plugin_supports_expiration ( const char *  plugin_name)

Only the plugins that are known to use the mysql.user table to store their passwords support password expiration atm.

TODO: create a service and extend the plugin API to support password expiration for external plugins.

Return values
falseexpiration not supported
trueexpiration supported

◆ auth_save_scramble()

static void auth_save_scramble ( MYSQL_PLUGIN_VIO vio,
const char *  scramble 
)
inlinestatic
Parameters
vioVirtual input-, output interface
scramble- Scramble to be saved

Save the scramble in mpvio for future re-use. It is useful when we need to pass the scramble to another plugin. Especially in case when old 5.1 client with no CLIENT_PLUGIN_AUTH capability tries to connect to server with default 1FA set to sha256_password

◆ cannot_proxy_error()

static void cannot_proxy_error ( THD thd,
const MPVIO_EXT mpvio,
int  server_error,
int  client_error 
)
static

a helper function to report cannot proxy error in all the proper places

◆ check_and_update_password_lock_state()

static void check_and_update_password_lock_state ( MPVIO_EXT mpvio,
THD thd,
int &  res 
)
static

◆ check_password_lifetime()

static bool check_password_lifetime ( THD thd,
const ACL_USER acl_user 
)
static

Calculate the timestamp difference for password expiry.

Parameters
thdthread handle
acl_userACL_USER handle
Return values
0password is valid
1password has expired

◆ check_restrictions_for_com_connect_command()

static bool check_restrictions_for_com_connect_command ( THD thd)
inlinestatic

Check that for command COM_CONNECT, either restriction on max number of concurrent connections not violated or in case the connection is admin connection the user has required privilege.

Parameters
thdThread context
Returns
Error status
Return values
falsesuccess
trueerror
Note
if connection is admin connection and a user doesn't have the privilege SERVICE_CONNECTION_ADMIN, the error ER_SPECIFIC_ACCESS_DENIED_ERROR is set in Diagnostics_area.
if a user doesn't have any of the privileges SUPER_ACL, CONNECTION_ADMIN, SERVICE_CONNECTION_ADMIN and a number of concurrent connections exceeds the limit max_connections the error ER_CON_COUNT_ERROR is set in Diagnostics_area.

◆ client_plugin_name()

const char * client_plugin_name ( plugin_ref  ref)
inline

◆ compare_sha256_password_with_hash()

static int compare_sha256_password_with_hash ( const char *  hash,
unsigned long  hash_length,
const char *  cleartext,
unsigned long  cleartext_length,
int *  is_error 
)
static

Compare a clear text password with a stored hash.

Checks if a stored hash is produced using a clear text password. To do that first it extracts the scramble from the hash. Then calculates a new hash using the extracted scramble and the supplied password. And finally compares the two scrambles.

  • hash pointer to the hashed data
  • hash_length length of the hashed data
  • cleartext pointer to the clear text password
  • cleartext_length length of the cleat text password
  • [out] is_error non-zero in case of error extracting the salt
    Return values
    0the hash was created with that password
    non-zerothe hash was created with a different password

◆ create_RSA_key_pair()

template<typename RSA_generator_func , typename File_creation_func >
bool create_RSA_key_pair ( RSA_generator_func &  rsa_gen,
const Sql_string_t  priv_key_filename,
const Sql_string_t  pub_key_filename,
File_creation_func &  filecr 
)

Algorithm to generate RSA key pair.

Relies on: 1> RSA generator 2> File reader/writer

Overwrites existing Private/Public key file if any.

Parameters
[in]rsa_genRSA key pair generator
[in]priv_key_filenameFile name of private key
[in]pub_key_filenameFile name of public key
[in]filecrFile creator
Returns
status of RSA key pair generation.
Return values
falseError in RSA key pair generation.
truePrivate/Public keys are successfully generated.

◆ create_x509_certificate()

template<typename RSA_generator_func , typename File_creation_func >
bool create_x509_certificate ( RSA_generator_func &  rsa_gen,
const Sql_string_t  cn,
uint32_t  serial,
const Sql_string_t  cert_filename,
const Sql_string_t  key_filename,
File_creation_func &  filecr,
const Sql_string_t  ca_key_file = "",
const Sql_string_t  ca_cert_file = "" 
)

Algorithm to create X509 certificate.

Relies on: 1> RSA key generator 2> X509 certificate generator 3> FILE reader/writer

Overwrites key/certificate files if already present.

Parameters
[in]rsa_genRSA generator
[in]cnCommon name field of X509 certificate.
[in]serialCertificate serial number
[in]cert_filenameFile name for X509 certificate
[in]key_filenameFile name for private key
[in]filecrFile creator
[in]ca_key_fileCA private key file
[in]ca_cert_fileCA certificate file
Returns
generation status
Return values
falseError in key/certificate generation.
truekey/certificate files are generated successfully.

◆ decoy_user()

ACL_USER * decoy_user ( const LEX_CSTRING username,
const LEX_CSTRING hostname,
MEM_ROOT mem,
struct rand_struct rand,
bool  is_initialized 
)

When authentication is attempted using an unknown username a dummy user account with no authentication capabilities is assigned to the connection.

When server is started with -skip-grant-tables, a dummy user account with authentication capabilities is assigned to the connection. Dummy user authenticates with the empty authentication string. This is done to decrease the cost of enumerating user accounts based on authentication protocol.

Parameters
[in]usernameA dummy user to be created.
[in]hostnameHost of the dummy user.
[in]memMemory in which the dummy ACL user will be created.
[in]randSeed value to generate random data
[in]is_initializedState of ACL caches
Return values
Adummy ACL USER

◆ deinit_rsa_keys()

void deinit_rsa_keys ( void  )

◆ do_auth_once()

static int do_auth_once ( THD thd,
const LEX_CSTRING auth_plugin_name,
MPVIO_EXT mpvio 
)
static

◆ do_auto_cert_generation()

bool do_auto_cert_generation ( ssl_artifacts_status  auto_detection_status,
const char **  ssl_ca,
const char **  ssl_key,
const char **  ssl_cert 
)

Check auto_generate_certs option and generate SSL certificates if required.

SSL Certificates are generated iff following conditions are met. 1> auto_generate_certs is set to ON. 2> None of the SSL system variables are specified. 3> Following files are not present in data directory. a> ca.pem b> server_cert.pem c> server_key.pem

If above mentioned conditions are satisfied, following action will be taken:

1> 6 File are generated and placed data directory: a> ca.pem b> ca_key.pem c> server_cert.pem d> server_key.pem e> client_cert.pem f> client_key.pem

ca.pem is self signed auto generated CA certificate. server_cert.pem and client_cert.pem are signed using auto generated CA.

ca_key.pem, client_cert.pem and client_key.pem are overwritten if they are present in data directory.

Path of following system variables are set if certificates are either generated or already present in data directory. a> ssl-ca b> ssl-cert c> ssl-key

Assumption : auto_detect_ssl() is called before control reaches to do_auto_cert_generation().

Parameters
[in]auto_detection_statusStatus of SSL artifacts detection process
[out]ssl_capointer to the generated CA certificate file
[out]ssl_keypointer to the generated key file
[out]ssl_certpointer to the generated certificate file.
Return values
truei Generation is successful or skipped
falseGeneration failed.

◆ do_auto_rsa_keys_generation()

static bool do_auto_rsa_keys_generation ( )
static

◆ do_multi_factor_auth()

static int do_multi_factor_auth ( THD thd,
MPVIO_EXT mpvio 
)
static

Perform 2nd and 3rd factor authentication.

Once 1FA method succeeds, server checks if connecting user requires more authentication methods to do the authentication.

Refer to Multi Factor Authentication for server-client communication in various cases

Parameters
thdthread handle
mpviothe communications channel
Return values
0success
1error

◆ evp_pkey_generate()

static EVP_PKEY * evp_pkey_generate ( RSA rsa)
static

◆ find_mpvio_user()

static bool find_mpvio_user ( THD thd,
MPVIO_EXT mpvio 
)
static

Finds acl entry in user database for authentication purposes.

Finds a user and copies it into mpvio. Reports an authentication failure if a user is not found.

Note
find_acl_user is not the same, because it doesn't take into account the case when user is not empty, but acl_user->user is empty
Return values
0found
1not found

◆ generate_rsa_keys()

static bool generate_rsa_keys ( bool  auto_generate,
const char *  priv_key_path,
const char *  pub_key_path,
const char *  message 
)
static

◆ generate_sha256_password()

static int generate_sha256_password ( char *  outbuf,
unsigned int *  buflen,
const char *  inbuf,
unsigned int  inbuflen 
)
static

◆ get_40_protocol_string()

static char * get_40_protocol_string ( char **  buffer,
size_t *  max_bytes_available,
size_t *  string_length 
)
static

Get a string formatted according to the 4.0 version of the MySQL protocol.

Parameters
[in,out]bufferPointer to the user-supplied buffer to be scanned.
[in,out]max_bytes_availableLimit the bytes to scan.
[out]string_lengthThe number of characters scanned not including the null character.
Note
If there are not enough bytes left after the current position of the buffer to satisfy the current string, the string is considered to be empty and a pointer to empty_c_string is returned.
A string at the end of the packet is not null terminated.
Returns
Pointer to beginning of the string scanned, or a pointer to a empty string.

◆ get_41_lenc_string()

static char * get_41_lenc_string ( char **  buffer,
size_t *  max_bytes_available,
size_t *  string_length 
)
static

Get a length encoded string from a user-supplied buffer.

Parameters
[in,out]bufferThe buffer to scan; updates position after scan.
[in,out]max_bytes_availableLimit the number of bytes to scan
[out]string_lengthNumber of characters scanned
Note
In case the length is zero, then the total size of the string is considered to be 1 byte; the size byte.
the maximum size of the string is 255 because the header is always 1 byte.
Returns
pointer to first byte after the header in buffer.
Return values
NULLThe buffer content is malformed

◆ get_41_protocol_string()

static char * get_41_protocol_string ( char **  buffer,
size_t *  max_bytes_available,
size_t *  string_length 
)
static

Get a string formatted according to the 4.1 version of the MySQL protocol.

Parameters
[in,out]bufferPointer to the user-supplied buffer to be scanned.
[in,out]max_bytes_availableLimit the bytes to scan.
[out]string_lengthThe number of characters scanned not including the null character.
Note
Strings are always null character terminated in this version of the protocol.
The string_length does not include the terminating null character. However, after the call, the buffer is increased by string_length+1 bytes, beyond the null character if there still available bytes to scan.
Returns
pointer to beginning of the string scanned.
Return values
NULLThe buffer content is malformed

◆ get_56_lenc_string()

static char * get_56_lenc_string ( char **  buffer,
size_t *  max_bytes_available,
size_t *  string_length 
)
static

Get a length encoded string from a user-supplied buffer.

Parameters
[in,out]bufferThe buffer to scan; updates position after scan.
[in,out]max_bytes_availableLimit the number of bytes to scan
[out]string_lengthNumber of characters scanned
Note
In case the length is zero, then the total size of the string is considered to be 1 byte; the size byte.
Returns
pointer to first byte after the header in buffer.
Return values
NULLThe buffer content is malformed

◆ init_rsa_keys()

bool init_rsa_keys ( void  )

Loads the RSA key pair from disk and store them in a global variable.

See also
init_ssl()
Returns
Error code
Return values
falseSuccess
trueError

Presence of only a private key file and a public temp file implies that server crashed after creating the private key file and could not create a public key file. Hence removing the private key file.

◆ init_sha256_password_handler()

static int init_sha256_password_handler ( MYSQL_PLUGIN  plugin_ref)
static

◆ is_secure_transport()

bool is_secure_transport ( int  vio_type)

◆ login_failed_error()

static void login_failed_error ( THD thd,
MPVIO_EXT mpvio,
int  passwd_used 
)
static

a helper function to report an access denied error in all the proper places

◆ my_vio_is_encrypted()

static int my_vio_is_encrypted ( MYSQL_PLUGIN_VIO vio)
static

Interface for querying the MYSQL_PUBLIC_VIO about encryption state.

◆ mysql_declare_plugin()

mysql_declare_plugin ( sha256_password  )

◆ MYSQL_SYSVAR_BOOL()

static MYSQL_SYSVAR_BOOL ( auto_generate_rsa_keys  ,
auth_rsa_auto_generate_rsa_keys  ,
PLUGIN_VAR_READONLY|PLUGIN_VAR_OPCMDARG PLUGIN_VAR_NOPERSIST,
"Auto generate RSA keys at server startup if corresponding " "system variables are not specified and key files are not present " "at the default location."  ,
nullptr  ,
nullptr  ,
true   
)
static

◆ MYSQL_SYSVAR_STR() [1/2]

static MYSQL_SYSVAR_STR ( private_key_path  ,
auth_rsa_private_key_path  ,
PLUGIN_VAR_READONLY PLUGIN_VAR_NOPERSIST,
"A fully qualified path to the private RSA key used for authentication"  ,
nullptr  ,
nullptr  ,
AUTH_DEFAULT_RSA_PRIVATE_KEY   
)
static

◆ MYSQL_SYSVAR_STR() [2/2]

static MYSQL_SYSVAR_STR ( public_key_path  ,
auth_rsa_public_key_path  ,
PLUGIN_VAR_READONLY PLUGIN_VAR_NOPERSIST,
"A fully qualified path to the public RSA key used for authentication"  ,
nullptr  ,
nullptr  ,
AUTH_DEFAULT_RSA_PUBLIC_KEY   
)
static

◆ optimize_plugin_compare_by_pointer()

void optimize_plugin_compare_by_pointer ( LEX_CSTRING plugin_name)

◆ parse_client_handshake_packet()

static size_t parse_client_handshake_packet ( THD thd,
MPVIO_EXT mpvio,
uchar **  buff,
size_t  pkt_len 
)
static

Old clients didn't have their own charset. Instead the assumption was that they used what ever the server used.

Old clients didn't have their own charset. Instead the assumption was that they used what ever the server used.

◆ parse_com_change_user_packet()

static bool parse_com_change_user_packet ( THD thd,
MPVIO_EXT mpvio,
size_t  packet_length 
)
static

Parses a COM_CHANGE_USER.

Parameters
thdcurrent thread
mpviothe communications channel
packet_lengthlength of the packet in mpvio's buffer
Return values
trueerror
falsesuccess

◆ read_client_connect_attrs()

static bool read_client_connect_attrs ( THD thd,
char **  ptr,
size_t *  max_bytes_available,
MPVIO_EXT mpvio 
)
static

◆ resize_no_exception()

static bool resize_no_exception ( Sql_string_t content,
size_t  size 
)
static

Exception free resize.

Parameters
[in,out]contentstring handle
[in]sizeNew size
Return values
falseError
trueSuccessfully resized

◆ rsa_priv_key_write()

static Sql_string_t rsa_priv_key_write ( RSA rsa)
static

Write private key in a string buffer.

Parameters
[in]rsaHandle to RSA structure where private key is stored
Returns
Sql_string_t object with private key stored in it.

◆ rsa_pub_key_write()

static Sql_string_t rsa_pub_key_write ( RSA rsa)
static

Write public key in a string buffer.

Parameters
[in]rsaHandle to RSA structure where public key is stored
Returns
Sql_string_t object with public key stored in it.

◆ security_level()

int security_level ( void  )

◆ send_auth_next_factor_packet()

static bool send_auth_next_factor_packet ( MPVIO_EXT mpvio,
const uchar data,
uint  data_len 
)
static

Sends a Protocol::AuthNextFactor:.

Used by the server to request that a client should initiate authentication for next authentication methods in the plugin chain of user definition.

See Protocol::AuthNextFactor: for more details.

Parameters
[in]mpvioThe communications channel
[in]dataClient plugin data
[in]data_lenLength of client plugin data
Return values
falseok
trueerror

◆ send_plugin_request_packet()

static bool send_plugin_request_packet ( MPVIO_EXT mpvio,
const uchar data,
uint  data_len 
)
static

Sends a Protocol::AuthSwitchRequest:.

Used by the server to request that a client should restart authentication using a different authentication plugin.

See Protocol::AuthSwitchRequest: for more details.

Return values
falseok
trueerror

◆ send_server_handshake_packet()

static bool send_server_handshake_packet ( MPVIO_EXT mpvio,
const char *  data,
uint  data_len 
)
static

Sends a server Protocol::HandshakeV10.

Return values
0ok
1error

◆ server_mpvio_info()

static void server_mpvio_info ( MYSQL_PLUGIN_VIO vio,
MYSQL_PLUGIN_VIO_INFO info 
)
static

fills MYSQL_PLUGIN_VIO_INFO structure with the information about the connection

◆ server_mpvio_initialize()

static void server_mpvio_initialize ( THD thd,
MPVIO_EXT mpvio,
Thd_charset_adapter charset_adapter 
)
static

◆ server_mpvio_read_packet()

static int server_mpvio_read_packet ( MYSQL_PLUGIN_VIO param,
uchar **  buf 
)
static

vio->read_packet() callback method for server authentication plugins

This function is called by a server authentication plugin, when it wants to read data from the client.

It transparently extracts the client plugin data, if embedded into a client authentication handshake packet, and handles plugin negotiation with the client, if necessary.

RETURN -1 Protocol failure >= 0 Success and also the packet length

◆ server_mpvio_update_thd()

static void server_mpvio_update_thd ( THD thd,
MPVIO_EXT mpvio 
)
static

◆ server_mpvio_write_packet()

static int server_mpvio_write_packet ( MYSQL_PLUGIN_VIO param,
const uchar packet,
int  packet_len 
)
static

vio->write_packet() callback method for server authentication plugins

This function is called by a server authentication plugin, when it wants to send data to the client.

It transparently wraps the data into a handshake packet, and handles plugin negotiation with the client. If necessary, it escapes the plugin data, if it starts with a mysql protocol packet byte.

◆ set_sha256_salt()

static int set_sha256_salt ( const char *  password,
unsigned int  password_len,
unsigned char *  salt,
unsigned char *  salt_len 
)
static

◆ sha256_password_authenticate()

static int sha256_password_authenticate ( MYSQL_PLUGIN_VIO vio,
MYSQL_SERVER_AUTH_INFO info 
)
static
Parameters
vioVirtual input-, output interface
[out]infoConnection information

Authenticate the user by receiving a RSA or TLS encrypted password and calculate a hash digest which should correspond to the user record digest

RSA keys are assumed to be pre-generated and supplied when server starts. If the client hasn't got a public key it can request one.

TLS certificates and keys are assumed to be pre-generated and supplied when server starts.

◆ sha256_rsa_auth_status()

bool sha256_rsa_auth_status ( )

Check if server has valid public key/private key pair for RSA communication.

Return values
falseRSA support is available
trueRSA support is not available

◆ show_rsa_public_key()

int show_rsa_public_key ( THD thd,
SHOW_VAR var,
char *  buff 
)

◆ validate_sha256_password_hash()

static int validate_sha256_password_hash ( char *const  inbuf,
unsigned int  buflen 
)
static

◆ wrap_plguin_data_into_proper_command()

static int wrap_plguin_data_into_proper_command ( NET net,
const uchar packet,
int  packet_len 
)
inlinestatic

Wrap the extra auth data sent so that they can pass in the protocol.

Check Protocol::AuthMoreData: for the format description.

Return values
0ok
1error
Parameters
netthe network abstraction to use
packetdata to transmit
packet_lenlength of packet
See also
net_write_command, client_mpvio_write_packet

◆ x509_cert_read()

static X509 * x509_cert_read ( const Sql_string_t input_string)
static

Read a X509 certificate into X509 format.

Parameters
[in]input_stringContent of X509 certificate file.
Returns
Handle to X509 structure.

Assumption : Caller will free X509 object

◆ x509_cert_write()

static Sql_string_t x509_cert_write ( X509 *  cert)
static

Write X509 certificate into a string.

Parameters
[in]certCertificate information in X509 format.
Returns
certificate information in string format.

◆ x509_key_read()

static EVP_PKEY * x509_key_read ( const Sql_string_t input_string)
static

Read Private key into EVP_PKEY structure.

Parameters
[in]input_stringContent of private key file.
Returns
Handle to EVP_PKEY structure.

Assumption : Caller will free EVP_PKEY object

◆ x509_key_write()

static Sql_string_t x509_key_write ( EVP_PKEY *  pkey)
static

Write X509 certificate into a string.

Parameters
[in]pkeyPrivate key information.
Returns
private key information in string format.

Variable Documentation

◆ auth_rsa_auto_generate_rsa_keys

bool auth_rsa_auto_generate_rsa_keys = true

◆ auth_rsa_private_key_path

char* auth_rsa_private_key_path

◆ auth_rsa_public_key_path

char* auth_rsa_public_key_path

◆ default_auth_plugin_name

LEX_CSTRING default_auth_plugin_name {STRING_WITH_LEN("caching_sha2_password")}

◆ disconnect_on_expired_password

bool disconnect_on_expired_password = true

◆ g_cached_authentication_plugins

Cached_authentication_plugins* g_cached_authentication_plugins = nullptr

◆ g_sha256_rsa_keys

Rsa_authentication_keys* g_sha256_rsa_keys = nullptr

◆ initialized

bool initialized
extern

◆ MAX_UNKNOWN_ACCOUNTS

const uint MAX_UNKNOWN_ACCOUNTS = 1000

◆ mysql_declare_plugin_end

mysql_declare_plugin_end

◆ opt_auto_generate_certs

bool opt_auto_generate_certs = true

◆ plugin_info_ptr

MYSQL_PLUGIN plugin_info_ptr
static

◆ rsa_key_sizes

constexpr const std::array rsa_key_sizes {2048, 2048, 2048, 3072, 7680, 15360}
constexpr

◆ sha256_password_handler

struct st_mysql_auth sha256_password_handler
static
Initial value:
= {
}
static const char * get_plugin_name(cached_plugins_enum plugin_index)
Get name of the plugin at given index.
Definition: sql_authentication.h:212
#define AUTH_FLAG_USES_INTERNAL_STORAGE
Definition: plugin_auth.h:50
#define MYSQL_AUTHENTICATION_INTERFACE_VERSION
Definition: plugin_auth.h:37
static int validate_sha256_password_hash(char *const inbuf, unsigned int buflen)
Definition: sql_authentication.cc:4443
static int compare_sha256_password_with_hash(const char *hash, unsigned long hash_length, const char *cleartext, unsigned long cleartext_length, int *is_error)
Compare a clear text password with a stored hash.
Definition: sql_authentication.cc:4598
static int set_sha256_salt(const char *password, unsigned int password_len, unsigned char *salt, unsigned char *salt_len)
Definition: sql_authentication.cc:4452
static int sha256_password_authenticate(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
Definition: sql_authentication.cc:4651
static int generate_sha256_password(char *outbuf, unsigned int *buflen, const char *inbuf, unsigned int inbuflen)
Definition: sql_authentication.cc:4405
@ PLUGIN_SHA256_PASSWORD
Definition: sql_authentication.h:162

◆ sha256_password_sysvars

SYS_VAR* sha256_password_sysvars[]
static
Initial value:
= {
MYSQL_SYSVAR(private_key_path), MYSQL_SYSVAR(public_key_path),
MYSQL_SYSVAR(auto_generate_rsa_keys), nullptr}
#define MYSQL_SYSVAR(name)
Definition: plugin.h:255

◆ unknown_accounts

Map_with_rw_lock<Auth_id, uint>* unknown_accounts = nullptr

Hash to map unknown accounts to an authentication plugin.

If unknown accounts always map to default authentication plugin, server's reply to switch authentication plugin would indicate that user in question is indeed a valid user.

To counter this, one of the built-in authentication plugins is chosen at random. Thus, a request to switch authentication plugin is not and indicator of a valid user account.

For same unknown account, if different plugin is chosen every time, that again is an indicator. To resolve this, a hashmap is used to store information about unknown account => authentication plugin. This way, if same unknown account appears again, same authentication plugin is chosen again.

However, size of such a hash has to be kept under control. Hence, once MAX_UNKNOWN_ACCOUNTS lim

◆ validate_password_plugin_name

LEX_CSTRING validate_password_plugin_name
Initial value:
= {
STRING_WITH_LEN("validate_password")}
#define STRING_WITH_LEN(X)
Definition: string_with_len.h:29