Declare the server-side plugin with the usual general
descriptor format that is used for all server plugin types
(see Section 4.4.2.1, “Server Plugin Library and Plugin Descriptors”). For the
auth_simple
plugin, the descriptor looks
like this:
mysql_declare_plugin(auth_simple)
{
MYSQL_AUTHENTICATION_PLUGIN,
&auth_simple_handler, /* type-specific descriptor */
"auth_simple", /* plugin name */
"Author Name", /* author */
"Any-password authentication plugin", /* description */
PLUGIN_LICENSE_GPL, /* license type */
NULL, /* no init function */
NULL, /* no deinit function */
0x0100, /* version = 1.0 */
NULL, /* no status variables */
NULL, /* no system variables */
NULL, /* no reserved information */
0 /* no flags */
}
mysql_declare_plugin_end;
The name
member
(auth_simple
) indicates the name to use
for references to the plugin in statements such as
INSTALL PLUGIN
or
UNINSTALL PLUGIN
. This is
also the name displayed by SHOW
PLUGINS
or
INFORMATION_SCHEMA.PLUGINS
.
The auth_simple_handler
member of the
general descriptor points to the type-specific descriptor.
For an authentication plugin, the type-specific descriptor
is an instance of the st_mysql_auth
structure (defined in plugin_auth.h
):
struct st_mysql_auth
{
int interface_version;
const char *client_auth_plugin;
int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info);
int (*generate_authentication_string)(char *outbuf,
unsigned int *outbuflen, const char *inbuf, unsigned int inbuflen);
int (*validate_authentication_string)(char* const inbuf, unsigned int buflen);
int (*set_salt)(const char *password, unsigned int password_len,
unsigned char* salt, unsigned char *salt_len);
const unsigned long authentication_flags;
};
The st_mysql_auth
structure has these
members:
interface_version
: The type-specific API version number, alwaysMYSQL_AUTHENTICATION_INTERFACE_VERSION
client_auth_plugin
: The client plugin nameauthenticate_user
: A pointer to the main plugin function that communicates with the clientgenerate_authentication_string
: A pointer to a plugin function that generates a password digest from an authentication stringvalidate_authentication_string
: A pointer to a plugin function that validates a password digestset_salt
: A pointer to a plugin function that converts a scrambled password to binary formauthentication_flags
: A flags word
The client_auth_plugin
member should
indicate the name of the client plugin if a specific plugin
is required. A value of NULL
means
“any plugin.” In the latter case, whatever
plugin the client uses will do. This is useful if the server
plugin does not care about the client plugin or what user
name or password it sends. For example, this might be true
if the server plugin authenticates only local clients and
uses some property of the operating system rather than the
information sent by the client plugin.
For auth_simple
, the type-specific
descriptor looks like this:
static struct st_mysql_auth auth_simple_handler =
{
MYSQL_AUTHENTICATION_INTERFACE_VERSION,
"auth_simple", /* required client-side plugin name */
auth_simple_server /* server-side plugin main function */
generate_auth_string_hash, /* generate digest from password string */
validate_auth_string_hash, /* validate password digest */
set_salt, /* generate password salt value */
AUTH_FLAG_PRIVILEGED_USER_FOR_PASSWORD_CHANGE
};
The main function, auth_simple_server()
,
takes two arguments representing an I/O structure and a
MYSQL_SERVER_AUTH_INFO
structure. The
structure definition, found in
plugin_auth.h
, looks like this:
typedef struct st_mysql_server_auth_info
{
char *user_name;
unsigned int user_name_length;
const char *auth_string;
unsigned long auth_string_length;
char authenticated_as[MYSQL_USERNAME_LENGTH+1];
char external_user[512];
int password_used;
const char *host_or_ip;
unsigned int host_or_ip_length;
} MYSQL_SERVER_AUTH_INFO;
The character set for string members is UTF-8. If there is a
_length
member associated with a string,
it indicates the string length in bytes. Strings are also
null-terminated.
When an authentication plugin is invoked by the server, it
should interpret the
MYSQL_SERVER_AUTH_INFO
structure members
as follows. Some of these are used to set the value of SQL
functions or system variables within the client session, as
indicated.
user_name
: The user name sent by the client. The value becomes theUSER()
function value.user_name_length
: The length ofuser_name
in bytes.-
auth_string
: The value of theauthentication_string
column of the row in themysql.user
system table for the matching account name (that is, the row that matches the client user name and host name and that the server uses to determine how to authenticate the client).Suppose that you create an account using the following statement:
CREATE USER 'my_user'@'localhost' IDENTIFIED WITH my_plugin AS 'my_auth_string';
When
my_user
connects from the local host, the server invokesmy_plugin
and passes'
to it as themy_auth_string
'auth_string
value. auth_string_length
: The length ofauth_string
in bytes.authenticated_as
: The server sets this to the user name (the value ofuser_name
). The plugin can alter it to indicate that the client should have the privileges of a different user. For example, if the plugin supports proxy users, the initial value is the name of the connecting (proxy) user, and the plugin can change this member to the proxied user name. The server then treats the proxy user as having the privileges of the proxied user (assuming that the other conditions for proxy user support are satisfied; see Section 4.4.9.4, “Implementing Proxy User Support in Authentication Plugins”). The value is represented as a string at mostMYSQL_USER_NAME_LENGTH
bytes long, plus a terminating null. The value becomes theCURRENT_USER()
function value.external_user
: The server sets this to the empty string (null terminated). Its value becomes theexternal_user
system variable value. If the plugin wants that system variable to have a different value, it should set this member accordingly (for example, to the connecting user name). The value is represented as a string at most 511 bytes long, plus a terminating null.-
password_used
: This member applies when authentication fails. The plugin can set it or ignore it. The value is used to construct the failure error message ofAuthentication fails. Password used: %s
. The value ofpassword_used
determines how%s
is handled, as shown in the following table. host_or_ip
: The name of the client host if it can be resolved, or the IP address otherwise.host_or_ip_length
: The length ofhost_or_ip
in bytes.
The auth_simple
main function,
auth_simple_server()
, reads the password
(a null-terminated string) from the client and succeeds if
the password is nonempty (first byte not null):
static int auth_simple_server (MYSQL_PLUGIN_VIO *vio,
MYSQL_SERVER_AUTH_INFO *info)
{
unsigned char *pkt;
int pkt_len;
/* read the password as null-terminated string, fail on error */
if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
return CR_ERROR;
/* fail on empty password */
if (!pkt_len || *pkt == '\0')
{
info->password_used= PASSWORD_USED_NO;
return CR_ERROR;
}
/* accept any nonempty password */
info->password_used= PASSWORD_USED_YES;
return CR_OK;
}
The main function should return one of the error codes shown in the following table.
Error Code | Meaning |
---|---|
CR_OK |
Success |
CR_OK_HANDSHAKE_COMPLETE |
Do not send a status packet back to client |
CR_ERROR |
Error |
CR_AUTH_USER_CREDENTIALS |
Authentication failure |
CR_AUTH_HANDSHAKE |
Authentication handshake failure |
CR_AUTH_PLUGIN_ERROR |
Internal plugin error |
For an example of how the handshake works, see the
plugin/auth/dialog.c
source file.
The server counts plugin errors in the Performance Schema
host_cache
table.
auth_simple_server()
is so basic that it
does not use the authentication information structure except
to set the member that indicates whether a password was
received.
A plugin that supports proxy users must return to the server
the name of the proxied user (the MySQL user whose
privileges the client user should get). To do this, the
plugin must set the
info->authenticated_as
member to the
proxied user name. For information about proxying, see
Proxy Users, and
Section 4.4.9.4, “Implementing Proxy User Support in Authentication Plugins”.
The generate_authentication_string
member
of the plugin descriptor takes the password and generates a
password hash (digest) from it:
The first two arguments are pointers to the output buffer and its maximum length in bytes. The function should write the password hash to the output buffer and reset the length to the actual hash length.
The second two arguments indicate the password input buffer and its length in bytes.
The function returns 0 for success, 1 if an error occurred.
For the auth_simple
plugin, the
generate_auth_string_hash()
function
implements the
generate_authentication_string
member. It
just makes a copy of the password, unless it is too long to
fit in the output buffer.
int generate_auth_string_hash(char *outbuf, unsigned int *buflen,
const char *inbuf, unsigned int inbuflen)
{
/*
fail if buffer specified by server cannot be copied to output buffer
*/
if (*buflen < inbuflen)
return 1; /* error */
strncpy(outbuf, inbuf, inbuflen);
*buflen= strlen(inbuf);
return 0; /* success */
}
The validate_authentication_string
member
of the plugin descriptor validates a password hash:
The arguments are a pointer to the password hash and its length in bytes.
The function returns 0 for success, 1 if the password hash cannot be validated.
For the auth_simple
plugin, the
validate_auth_string_hash()
function
implements the
validate_authentication_string
member. It
returns success unconditionally:
int validate_auth_string_hash(char* const inbuf __attribute__((unused)),
unsigned int buflen __attribute__((unused)))
{
return 0; /* success */
}
The set_salt
member of the plugin
descriptor was used only by the
mysql_native_password
plugin, which is no
longer supported in MySQL 9.0. For other
authentication plugins, you can use this trivial
implementation:
int set_salt(const char* password __attribute__((unused)),
unsigned int password_len __attribute__((unused)),
unsigned char* salt __attribute__((unused)),
unsigned char* salt_len)
{
*salt_len= 0;
return 0; /* success */
}
The authentication_flags
member of the
plugin descriptor contains flags that affect plugin
operation. The permitted flags are:
AUTH_FLAG_PRIVILEGED_USER_FOR_PASSWORD_CHANGE
: Credential changes are a privileged operation. If this flag is set, the server requires that the user has the globalCREATE USER
privilege or theUPDATE
privilege for themysql
database.AUTH_FLAG_USES_INTERNAL_STORAGE
: Whether the plugin uses internal storage (in theauthentication_string
column ofmysql.user
rows). If this flag is not set, attempts to set the password fail and the server produces a warning.AUTH_FLAG_REQUIRES_REGISTRATION
: This flag is set for authentication plugins that require a registration process. It is checked forCREATE USER
andALTER USER
statements, and when theauthentication_policy
system variable is assigned a value.