MySQL  8.0.18
Source Code Documentation
sql_authentication.cc File Reference

AUTHENTICATION CODE. More...

#include "sql/auth/sql_authentication.h"
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string>
#include <utility>
#include <vector>
#include "include/compression.h"
#include <mysql/components/my_service.h>
#include <sql/ssl_acceptor_context.h>
#include "crypt_genhash_impl.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_loglevel.h"
#include "my_psi_config.h"
#include "my_sys.h"
#include "my_time.h"
#include "mysql/components/services/log_builtins.h"
#include "mysql/components/services/log_shared.h"
#include "mysql/plugin.h"
#include "mysql/psi/mysql_mutex.h"
#include "mysql/psi/psi_base.h"
#include "mysql/service_my_plugin_log.h"
#include "mysql/service_mysql_alloc.h"
#include "mysql/service_mysql_password_policy.h"
#include "mysql_com.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/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 "violite.h"

Macros

#define LOG_COMPONENT_TAG   "mysql_native_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
 

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...
 

Functions

void optimize_plugin_compare_by_pointer (LEX_CSTRING *plugin_name)
 
int set_default_auth_plugin (char *plugin_name, size_t plugin_name_length)
 
Initialize default authentication plugin based on command line options or configuration file settings. More...
 
std::string get_default_autnetication_plugin_name ()
 Return the default authentication plugin name. More...
 
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 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...
 
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 capabilites 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 (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 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...
 
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_native_password (char *outbuf, unsigned int *buflen, const char *inbuf, unsigned int inbuflen)
 
static int validate_native_password_hash (char *const inbuf, unsigned int buflen)
 
static int set_native_salt (const char *password, unsigned int password_len, unsigned char *salt, unsigned char *salt_len)
 
static int compare_native_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 for the native password plugin. More...
 
static int native_password_authenticate (MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
 MySQL Server Password Authentication Plugin. More...
 
 mysql_declare_plugin (mysql_password)
 

Variables

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
 
Cached_authentication_pluginsg_cached_authentication_plugins = 0
 
bool disconnect_on_expired_password = true
 
bool initialized
 
static struct st_mysql_auth native_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.

◆ LOG_COMPONENT_TAG

#define LOG_COMPONENT_TAG   "mysql_native_password"

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.

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

◆ 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.

◆ compare_native_password_with_hash()

static int compare_native_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 for the native password plugin.

If the password is non-empty it calculates a hash from the cleartext and compares it with the supplied hash.

if the password is empty checks if the hash is empty too.

  • 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

empty password results in an empty hash

◆ 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 capabilites 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

◆ do_auth_once()

static int do_auth_once ( THD thd,
const LEX_CSTRING auth_plugin_name,
MPVIO_EXT mpvio 
)
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_native_password()

static int generate_native_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

◆ get_default_autnetication_plugin_name()

std::string get_default_autnetication_plugin_name ( )

Return the default authentication plugin name.

Return values
Astring containing the default authentication plugin name

◆ 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

◆ mysql_declare_plugin()

mysql_declare_plugin ( mysql_password  )

◆ native_password_authenticate()

static int native_password_authenticate ( MYSQL_PLUGIN_VIO vio,
MYSQL_SERVER_AUTH_INFO info 
)
static

MySQL Server Password Authentication Plugin.

In the MySQL authentication protocol:

  1. the server sends the random scramble to the client
  2. client sends the encrypted password back to the server
  3. the server checks the password.

◆ 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.

◆ 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 ( char **  ptr,
size_t *  max_bytes_available,
MPVIO_EXT mpvio 
)
static

◆ 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_default_auth_plugin()

int set_default_auth_plugin ( char *  plugin_name,
size_t  plugin_name_length 
)


Initialize default authentication plugin based on command line options or configuration file settings.

Parameters
plugin_nameName of the plugin
plugin_name_lengthLength of the string

◆ set_native_salt()

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

◆ sha256_rsa_auth_status()

bool sha256_rsa_auth_status ( )

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

Returns
Return values
falseRSA support is available
trueRSA support is not available

◆ validate_native_password_hash()

static int validate_native_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

Variable Documentation

◆ default_auth_plugin_name

LEX_CSTRING default_auth_plugin_name

◆ disconnect_on_expired_password

bool disconnect_on_expired_password = true

◆ g_cached_authentication_plugins

Cached_authentication_plugins* g_cached_authentication_plugins = 0

◆ initialized

bool initialized

◆ MAX_UNKNOWN_ACCOUNTS

const uint MAX_UNKNOWN_ACCOUNTS = 1000

◆ mysql_declare_plugin_end

mysql_declare_plugin_end

◆ native_password_handler

struct st_mysql_auth native_password_handler
static
Initial value:
= {
static int validate_native_password_hash(char *const inbuf, unsigned int buflen)
Definition: sql_authentication.cc:3662
static int compare_native_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 for the native password plugin.
Definition: sql_authentication.cc:3760
#define MYSQL_AUTHENTICATION_INTERFACE_VERSION
Definition: plugin_auth.h:36
static int generate_native_password(char *outbuf, unsigned int *buflen, const char *inbuf, unsigned int inbuflen)
Definition: sql_authentication.cc:3633
Definition: sql_authentication.h:150
static int native_password_authenticate(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
MySQL Server Password Authentication Plugin.
Definition: sql_authentication.cc:3843
static int set_native_salt(const char *password, unsigned int password_len, unsigned char *salt, unsigned char *salt_len)
Definition: sql_authentication.cc:3671
static const char * get_plugin_name(cached_plugins_enum plugin_index)
Get name of the plugin at given index.
Definition: sql_authentication.h:203
#define AUTH_FLAG_USES_INTERNAL_STORAGE
Definition: plugin_auth.h:49

◆ 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 everytime, 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: m_string.h:315