Add diagnostic entry point to authenticators

The authenticators should have a similar way to print diagnostic
information as filter and routers do. This allows the authenticators to
print the users in their own format.

In the future, all the diagnostic entry points should be changed so that
they return a structure that contains the information in a standard
form. This information can then be formatted in different ways by other
modules.
This commit is contained in:
Markus Mäkelä
2017-02-04 02:46:48 +02:00
parent a909fd0208
commit c6e1705f8d
16 changed files with 196 additions and 314 deletions

View File

@ -60,6 +60,11 @@ struct servlistener;
* entry point. * entry point.
* *
* loadusers Load or update authenticator user data * loadusers Load or update authenticator user data
*
* diagnostic Print diagnostic output to a DCB
*
* reauthenticate Reauthenticate a user
*
* @endverbatim * @endverbatim
* *
* This forms the "module object" for authenticator modules within the gateway. * This forms the "module object" for authenticator modules within the gateway.
@ -76,6 +81,7 @@ typedef struct mxs_authenticator
void (*free)(struct dcb *); void (*free)(struct dcb *);
void (*destroy)(void *); void (*destroy)(void *);
int (*loadusers)(struct servlistener *); int (*loadusers)(struct servlistener *);
void (*diagnostic)(struct dcb*, struct servlistener *);
/** This entry point was added to avoid calling authenticator functions /** This entry point was added to avoid calling authenticator functions
* directly when a COM_CHANGE_USER command is executed. */ * directly when a COM_CHANGE_USER command is executed. */

View File

@ -258,6 +258,15 @@ int service_refresh_users(SERVICE *service);
/** /**
* Diagnostics * Diagnostics
*/ */
/**
* @brief Print service authenticator diagnostics
*
* @param dcb DCB to print to
* @param service The service to diagnose
*/
void service_print_users(DCB *, const SERVICE *);
void dprintAllServices(DCB *dcb); void dprintAllServices(DCB *dcb);
void dprintService(DCB *dcb, SERVICE *service); void dprintService(DCB *dcb, SERVICE *service);
void dListServices(DCB *dcb); void dListServices(DCB *dcb);

View File

@ -40,27 +40,91 @@ typedef struct
} USERS_STATS; } USERS_STATS;
/** /**
* The user table, this contains the username and authentication data required * A generic user table containing the username and authentication data
* for the authentication implementation within the gateway.
*/ */
typedef struct users typedef struct users
{ {
HASHTABLE *data; /**< The hashtable containing the actual data */ HASHTABLE *data; /**< The hashtable containing the actual data */
char *(*usersCustomUserFormat)(void *); /**< Optional username format routine */
USERS_STATS stats; /**< The statistics for the users table */ USERS_STATS stats; /**< The statistics for the users table */
unsigned char cksum[SHA_DIGEST_LENGTH]; /**< The users' table ckecksum */
} USERS; } USERS;
extern USERS *users_alloc(); /**< Allocate a users table */
extern void users_free(USERS *); /**< Free a users table */ /**
extern int users_add(USERS *, const char *, const char *); /**< Add a user to the users table */ * Allocate a new users table
extern int users_delete(USERS *, const char *); /**< Delete a user from the users table */ *
extern const char *users_fetch(USERS *, const char *); /**< Fetch the authentication data for a user*/ * @return The users table
extern int users_update(USERS *, const char *, const char *); /**< Change the password data for a user in */
the users table */ USERS *users_alloc();
extern int users_default_loadusers(SERV_LISTENER *port); /**< A generic implementation of the
authenticator loadusers entry point */ /**
extern void usersPrint(const USERS *); /**< Print data about the users loaded */ * Remove the users table
extern void dcb_usersPrint(DCB *, const SERVICE *); /**< Print data about the users loaded */ *
* @param users The users table to remove
*/
void users_free(USERS *);
/**
* Add a new user to the user table. The user name must be unique
*
* @param users The users table
* @param user The user name
* @param auth The authentication data
* @return The number of users added to the table
*/
int users_add(USERS *, const char *, const char *);
/**
* Delete a user from the user table.
*
* @param users The users table
* @param user The user name
* @return The number of users deleted from the table
*/
int users_delete(USERS *, const char *);
/**
* Fetch the authentication data for a particular user from the users table
*
* @param users The users table
* @param user The user name
* @return The authentication data or NULL on error
*/
const char *users_fetch(USERS *, const char *);
/**
* Change the password data associated with a user in the users
* table.
*
* @param users The users table
* @param user The user name
* @param auth The new authentication details
* @return Number of users updated
*/
int users_update(USERS *, const char *, const char *);
/**
* @brief Default user loading function
*
* A generic key-value user table is allocated for the service.
*
* @param port Listener configuration
* @return Always AUTH_LOADUSERS_OK
*/
int users_default_loadusers(SERV_LISTENER *port);
/**
* @brief Default authenticator diagnostic function
*
* @param dcb DCB where data is printed
* @param port Port whose data is to be printed
*/
void users_default_diagnostic(DCB *dcb, SERV_LISTENER *port);
/**
* Print details of the users storage mechanism
*
* @param users The users table
*/
void usersPrint(const USERS *);
MXS_END_DECLS MXS_END_DECLS

View File

@ -2283,3 +2283,14 @@ bool service_serialize_servers(const SERVICE *service)
return rval; return rval;
} }
void service_print_users(DCB *dcb, const SERVICE *service)
{
for (SERV_LISTENER *port = service->ports; port; port = port->next)
{
if (port->listener && port->listener->authfunc.diagnostic)
{
port->listener->authfunc.diagnostic(dcb, port);
}
}
}

View File

@ -33,13 +33,7 @@
* @endverbatim * @endverbatim
*/ */
/** USERS *users_alloc()
* Allocate a new users table
*
* @return The users table
*/
USERS *
users_alloc()
{ {
USERS *rval; USERS *rval;
@ -63,13 +57,7 @@ users_alloc()
return rval; return rval;
} }
/** void users_free(USERS *users)
* Remove the users table
*
* @param users The users table to remove
*/
void
users_free(USERS *users)
{ {
if (users) if (users)
{ {
@ -78,16 +66,7 @@ users_free(USERS *users)
} }
} }
/** int users_add(USERS *users, const char *user, const char *auth)
* Add a new user to the user table. The user name must be unique
*
* @param users The users table
* @param user The user name
* @param auth The authentication data
* @return The number of users added to the table
*/
int
users_add(USERS *users, const char *user, const char *auth)
{ {
int add; int add;
@ -97,15 +76,7 @@ users_add(USERS *users, const char *user, const char *auth)
return add; return add;
} }
/** int users_delete(USERS *users, const char *user)
* Delete a user from the user table.
*
* @param users The users table
* @param user The user name
* @return The number of users deleted from the table
*/
int
users_delete(USERS *users, const char *user)
{ {
int del; int del;
@ -115,32 +86,14 @@ users_delete(USERS *users, const char *user)
return del; return del;
} }
/** const char *users_fetch(USERS *users, const char *user)
* Fetch the authentication data for a particular user from the users table
*
* @param users The users table
* @param user The user name
* @return The authentication data or NULL on error
*/
const char
*users_fetch(USERS *users, const char *user)
{ {
atomic_add(&users->stats.n_fetches, 1); atomic_add(&users->stats.n_fetches, 1);
// TODO: Returning data from the hashtable is not threadsafe. // TODO: Returning data from the hashtable is not threadsafe.
return hashtable_fetch(users->data, (char*)user); return hashtable_fetch(users->data, (char*)user);
} }
/** int users_update(USERS *users, const char *user, const char *auth)
* Change the password data associated with a user in the users
* table.
*
* @param users The users table
* @param user The user name
* @param auth The new authentication details
* @return Number of users updated
*/
int
users_update(USERS *users, const char *user, const char *auth)
{ {
if (hashtable_delete(users->data, (char*)user) == 0) if (hashtable_delete(users->data, (char*)user) == 0)
{ {
@ -149,28 +102,14 @@ users_update(USERS *users, const char *user, const char *auth)
return hashtable_add(users->data, (char*)user, (char*)auth); return hashtable_add(users->data, (char*)user, (char*)auth);
} }
/**
* Print details of the users storage mechanism void usersPrint(const USERS *users)
*
* @param users The users table
*/
void
usersPrint(const USERS *users)
{ {
printf("Users table data\n"); printf("Users table data\n");
hashtable_stats(users->data); hashtable_stats(users->data);
} }
/** void users_default_diagnostic(DCB *dcb, SERV_LISTENER *port)
* Print details of the users storage mechanism to a DCB
*
* @param dcb DCB to print to
* @param users The users table
*/
void
dcb_usersPrint(DCB *dcb, const SERVICE *service)
{
for (SERV_LISTENER *port = service->ports; port; port = port->next)
{ {
if (port->users && port->users->data) if (port->users && port->users->data)
{ {
@ -182,28 +121,13 @@ dcb_usersPrint(DCB *dcb, const SERVICE *service)
char *sep = ""; char *sep = "";
void *user; void *user;
if (port->users->usersCustomUserFormat != NULL)
{
while ((user = hashtable_next(iter)) != NULL)
{
char *custom_user = port->users->usersCustomUserFormat(user);
if (custom_user)
{
dcb_printf(dcb, "%s%s", sep, custom_user);
MXS_FREE(custom_user);
sep = ", ";
}
}
}
else
{
while ((user = hashtable_next(iter)) != NULL) while ((user = hashtable_next(iter)) != NULL)
{ {
dcb_printf(dcb, "%s%s", sep, (char *)user); dcb_printf(dcb, "%s%s", sep, (char *)user);
sep = ", "; sep = ", ";
} }
}
dcb_printf(dcb, "\n");
hashtable_iterator_free(iter); hashtable_iterator_free(iter);
} }
} }
@ -213,17 +137,6 @@ dcb_usersPrint(DCB *dcb, const SERVICE *service)
} }
} }
dcb_printf(dcb, "\n");
}
/**
* @brief Default user loading function
*
* A generic key-value user table is allocated for the service.
*
* @param port Listener configuration
* @return Always AUTH_LOADUSERS_OK
*/
int users_default_loadusers(SERV_LISTENER *port) int users_default_loadusers(SERV_LISTENER *port)
{ {
users_free(port->users); users_free(port->users);

View File

@ -167,7 +167,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
cdc_auth_authenticate, /* Authenticate user credentials */ cdc_auth_authenticate, /* Authenticate user credentials */
cdc_auth_free_client_data, /* Free the client data held in DCB */ cdc_auth_free_client_data, /* Free the client data held in DCB */
NULL, /* No destroy entry point */ NULL, /* No destroy entry point */
cdc_replace_users /* Load CDC users */ cdc_replace_users, /* Load CDC users */
users_default_diagnostic, /* Default diagnostic */
NULL /* No user reauthentication */
}; };
static MXS_MODULE info = static MXS_MODULE info =
@ -484,11 +486,6 @@ cdc_read_users(USERS *users, char *usersfile)
char *user_passwd; char *user_passwd;
/* user maxlen ':' password hash '\n' '\0' */ /* user maxlen ':' password hash '\n' '\0' */
char read_buffer[CDC_USER_MAXLEN + 1 + SHA_DIGEST_LENGTH + 1 + 1]; char read_buffer[CDC_USER_MAXLEN + 1 + SHA_DIGEST_LENGTH + 1 + 1];
char *all_users_data = NULL;
struct stat statb;
int fd;
int filelen = 0;
unsigned char hash[SHA_DIGEST_LENGTH] = "";
int max_line_size = sizeof(read_buffer) - 1; int max_line_size = sizeof(read_buffer) - 1;
@ -497,27 +494,11 @@ cdc_read_users(USERS *users, char *usersfile)
return -1; return -1;
} }
fd = fileno(fp);
if (fstat(fd, &statb) == 0)
{
filelen = statb.st_size;
}
if ((all_users_data = MXS_MALLOC(filelen + 1)) == NULL)
{
return -1;
}
*all_users_data = '\0';
while (!feof(fp)) while (!feof(fp))
{ {
if (fgets(read_buffer, max_line_size, fp) != NULL) if (fgets(read_buffer, max_line_size, fp) != NULL)
{ {
char *tmp_ptr = read_buffer; char *tmp_ptr = read_buffer;
/* append data for hash */
strcat(all_users_data, read_buffer);
if ((tmp_ptr = strchr(read_buffer, ':')) != NULL) if ((tmp_ptr = strchr(read_buffer, ':')) != NULL)
{ {
@ -537,13 +518,6 @@ cdc_read_users(USERS *users, char *usersfile)
} }
} }
/* compute SHA1 digest for users' data */
SHA1((const unsigned char *) all_users_data, strlen(all_users_data), hash);
memcpy(users->cksum, hash, SHA_DIGEST_LENGTH);
MXS_FREE(all_users_data);
fclose(fp); fclose(fp);
return loaded; return loaded;

View File

@ -664,7 +664,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
gssapi_auth_authenticate, /* Authenticate user credentials */ gssapi_auth_authenticate, /* Authenticate user credentials */
gssapi_auth_free_data, /* Free the client data held in DCB */ gssapi_auth_free_data, /* Free the client data held in DCB */
gssapi_auth_free, /* Free authenticator data */ gssapi_auth_free, /* Free authenticator data */
gssapi_auth_load_users /* Load database users */ gssapi_auth_load_users, /* Load database users */
users_default_diagnostic, /* Default user diagnostic */
NULL /* No user reauthentication */
}; };
static MXS_MODULE info = static MXS_MODULE info =

View File

@ -276,7 +276,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
gssapi_backend_auth_authenticate, /* Authenticate user credentials */ gssapi_backend_auth_authenticate, /* Authenticate user credentials */
NULL, /* Client plugin will free shared data */ NULL, /* Client plugin will free shared data */
gssapi_backend_auth_free, /* Free authenticator data */ gssapi_backend_auth_free, /* Free authenticator data */
NULL /* Load users from backend databases */ NULL, /* Load users from backend databases */
NULL, /* No diagnostic */
NULL /* No user reauthentication */
}; };
static MXS_MODULE info = static MXS_MODULE info =

View File

@ -66,7 +66,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
http_auth_authenticate, /* Authenticate user credentials */ http_auth_authenticate, /* Authenticate user credentials */
http_auth_free_client_data, /* Free the client data held in DCB */ http_auth_free_client_data, /* Free the client data held in DCB */
NULL, /* No destroy entry point */ NULL, /* No destroy entry point */
users_default_loadusers /* Load generic users */ users_default_loadusers, /* Load generic users */
users_default_diagnostic, /* Default user diagnostic */
NULL /* No user reauthentication */
}; };
static MXS_MODULE info = static MXS_MODULE info =

View File

@ -60,7 +60,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
max_admin_auth_authenticate, /* Authenticate user credentials */ max_admin_auth_authenticate, /* Authenticate user credentials */
max_admin_auth_free_client_data, /* Free the client data held in DCB */ max_admin_auth_free_client_data, /* Free the client data held in DCB */
NULL, /* No destroy entry point */ NULL, /* No destroy entry point */
users_default_loadusers /* Load generic users */ users_default_loadusers, /* Load generic users */
users_default_diagnostic, /* Default user diagnostic */
NULL /* No user reauthentication */
}; };
static MXS_MODULE info = static MXS_MODULE info =

View File

@ -49,12 +49,11 @@
FROM mysql.user AS u LEFT JOIN mysql.tables_priv AS t \ FROM mysql.user AS u LEFT JOIN mysql.tables_priv AS t \
ON (u.user = t.user AND u.host = t.host) %s" ON (u.user = t.user AND u.host = t.host) %s"
static int get_users(SERV_LISTENER *listener, USERS *users); static int get_users(SERV_LISTENER *listener);
static MYSQL *gw_mysql_init(void); static MYSQL *gw_mysql_init(void);
static int gw_mysql_set_timeouts(MYSQL* handle); static int gw_mysql_set_timeouts(MYSQL* handle);
static char *mysql_format_user_entry(void *data); static char *mysql_format_user_entry(void *data);
static bool get_hostname(const char *ip_address, char *client_hostname); static bool get_hostname(const char *ip_address, char *client_hostname);
USERS* mysql_users_alloc();
static char* get_new_users_query(const char *server_version, bool include_root) static char* get_new_users_query(const char *server_version, bool include_root)
{ {
@ -74,53 +73,12 @@ static char* get_new_users_query(const char *server_version, bool include_root)
int replace_mysql_users(SERV_LISTENER *listener) int replace_mysql_users(SERV_LISTENER *listener)
{ {
USERS *newusers = mysql_users_alloc();
if (newusers == NULL)
{
return -1;
}
spinlock_acquire(&listener->lock); spinlock_acquire(&listener->lock);
int i = get_users(listener);
/* load users and grants from the backend database */
int i = get_users(listener, newusers);
if (i <= 0)
{
/** Failed to load users */
if (listener->users)
{
/* Restore old users and resources */
users_free(newusers);
}
else
{
/* No users allocated, use the empty new one */
listener->users = newusers;
}
spinlock_release(&listener->lock); spinlock_release(&listener->lock);
return i; return i;
} }
/** TODO: Figure out a way to create a checksum function in the backend server
* so that we can avoid querying the complete list of users every time we
* need to refresh the users */
MXS_DEBUG("%lu [replace_mysql_users] users' tables replaced", pthread_self());
USERS *oldusers = listener->users;
listener->users = newusers;
spinlock_release(&listener->lock);
if (oldusers)
{
/* free the old table */
users_free(oldusers);
}
return i;
}
static bool check_password(const char *output, uint8_t *token, size_t token_len, static bool check_password(const char *output, uint8_t *token, size_t token_len,
uint8_t *scramble, size_t scramble_len, uint8_t *phase2_scramble) uint8_t *scramble, size_t scramble_len, uint8_t *phase2_scramble)
{ {
@ -375,108 +333,6 @@ static void add_database(sqlite3 *handle, const char *db)
} }
} }
/**
* Allocate a new MySQL users table for mysql specific users@host as key
*
* @return The users table
*/
USERS* mysql_users_alloc()
{
USERS *rval;
if ((rval = MXS_CALLOC(1, sizeof(USERS))) == NULL)
{
return NULL;
}
// TODO: Refactor the `show dbusers` functionality
/** This prevents a crash when dbusers are queried through maxadmin */
rval->data = hashtable_alloc(USERS_HASHTABLE_DEFAULT_SIZE,
hashtable_item_strhash, hashtable_item_strcmp);
if (rval->data == NULL)
{
MXS_FREE(rval);
return NULL;
}
/* set the MySQL user@host print routine for the debug interface */
rval->usersCustomUserFormat = mysql_format_user_entry;
return rval;
}
/**
* Format the mysql user as user@host
* The returned memory must be freed by the caller
*
* @param data Input data
* @return the MySQL user@host
*/
static char *mysql_format_user_entry(void *data)
{
MYSQL_USER_HOST *entry;
char *mysql_user;
/* the returned user string is "USER" + "@" + "HOST" + '\0' */
int mysql_user_len = MYSQL_USER_MAXLEN + 1 + INET_ADDRSTRLEN + 10 +
MYSQL_USER_MAXLEN + 1;
if (data == NULL)
{
return NULL;
}
entry = (MYSQL_USER_HOST *) data;
mysql_user = (char *) MXS_CALLOC(mysql_user_len, sizeof(char));
if (mysql_user == NULL)
{
return NULL;
}
/* format user@host based on wildcards */
if (entry->ipv4.sin_addr.s_addr == INADDR_ANY && entry->netmask == 0)
{
snprintf(mysql_user, mysql_user_len - 1, "%s@%%", entry->user);
}
else if ((entry->ipv4.sin_addr.s_addr & 0xFF000000) == 0 && entry->netmask == 24)
{
snprintf(mysql_user, mysql_user_len - 1, "%s@%i.%i.%i.%%", entry->user,
entry->ipv4.sin_addr.s_addr & 0x000000FF,
(entry->ipv4.sin_addr.s_addr & 0x0000FF00) / (256),
(entry->ipv4.sin_addr.s_addr & 0x00FF0000) / (256 * 256));
}
else if ((entry->ipv4.sin_addr.s_addr & 0xFFFF0000) == 0 && entry->netmask == 16)
{
snprintf(mysql_user, mysql_user_len - 1, "%s@%i.%i.%%.%%", entry->user,
entry->ipv4.sin_addr.s_addr & 0x000000FF,
(entry->ipv4.sin_addr.s_addr & 0x0000FF00) / (256));
}
else if ((entry->ipv4.sin_addr.s_addr & 0xFFFFFF00) == 0 && entry->netmask == 8)
{
snprintf(mysql_user, mysql_user_len - 1, "%s@%i.%%.%%.%%", entry->user,
entry->ipv4.sin_addr.s_addr & 0x000000FF);
}
else if (entry->netmask == 32)
{
strcpy(mysql_user, entry->user);
strcat(mysql_user, "@");
inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user + strlen(mysql_user),
INET_ADDRSTRLEN);
}
else
{
snprintf(mysql_user, MYSQL_USER_MAXLEN - 5, "Err: %s", entry->user);
strcat(mysql_user, "@");
inet_ntop(AF_INET, &(entry->ipv4).sin_addr, mysql_user + strlen(mysql_user),
INET_ADDRSTRLEN);
}
return mysql_user;
}
/** /**
* Returns a MYSQL object suitably configured. * Returns a MYSQL object suitably configured.
* *
@ -984,7 +840,7 @@ int get_users_from_server(MYSQL *con, SERVER_REF *server, SERVICE *service, SERV
* @param users The users table into which to load the users * @param users The users table into which to load the users
* @return -1 on any error or the number of users inserted * @return -1 on any error or the number of users inserted
*/ */
static int get_users(SERV_LISTENER *listener, USERS *users) static int get_users(SERV_LISTENER *listener)
{ {
char *service_user = NULL; char *service_user = NULL;
char *service_passwd = NULL; char *service_passwd = NULL;

View File

@ -58,6 +58,8 @@ static int mysql_auth_set_client_data(
MySQLProtocol *protocol, MySQLProtocol *protocol,
GWBUF *buffer); GWBUF *buffer);
void mysql_auth_diagnostic(DCB *dcb, SERV_LISTENER *port);
int mysql_auth_reauthenticate(DCB *dcb, const char *user, int mysql_auth_reauthenticate(DCB *dcb, const char *user,
uint8_t *token, size_t token_len, uint8_t *token, size_t token_len,
uint8_t *scramble, size_t scramble_len, uint8_t *scramble, size_t scramble_len,
@ -82,6 +84,7 @@ MXS_MODULE* MXS_CREATE_MODULE()
mysql_auth_free_client_data, /* Free the client data held in DCB */ mysql_auth_free_client_data, /* Free the client data held in DCB */
mysql_auth_destroy, /* Destroy entry point */ mysql_auth_destroy, /* Destroy entry point */
mysql_auth_load_users, /* Load users from backend databases */ mysql_auth_load_users, /* Load users from backend databases */
mysql_auth_diagnostic,
mysql_auth_reauthenticate /* Handle COM_CHANGE_USER */ mysql_auth_reauthenticate /* Handle COM_CHANGE_USER */
}; };
@ -630,4 +633,29 @@ int mysql_auth_reauthenticate(DCB *dcb, const char *user,
} }
return rval; return rval;
}
int diag_cb(void *data, int columns, char **row, char **field_names)
{
DCB *dcb = (DCB*)data;
dcb_printf(dcb, "%s@%s ", row[0], row[1]);
return 0;
}
void mysql_auth_diagnostic(DCB *dcb, SERV_LISTENER *port)
{
dcb_printf(dcb, "User names: ");
MYSQL_AUTH *instance = (MYSQL_AUTH*)port->auth_instance;
char *err;
if (sqlite3_exec(instance->handle, "SELECT user, host FROM " MYSQLAUTH_USERS_TABLE_NAME,
diag_cb, dcb, &err) != SQLITE_OK)
{
dcb_printf(dcb, "Failed to print users: %s\n", err);
MXS_ERROR("Failed to print users: %s", err);
sqlite3_free(err);
}
dcb_printf(dcb, "\n");
} }

View File

@ -169,7 +169,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
auth_backend_authenticate, /* Authenticate user credentials */ auth_backend_authenticate, /* Authenticate user credentials */
NULL, /* The shared data is freed by the client DCB */ NULL, /* The shared data is freed by the client DCB */
auth_backend_destroy, /* Destroy authenticator */ auth_backend_destroy, /* Destroy authenticator */
NULL /* We don't need to load users */ NULL, /* We don't need to load users */
NULL, /* No diagnostic */
NULL /* No user reauthentication */
}; };
static MXS_MODULE info = static MXS_MODULE info =

View File

@ -62,7 +62,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
null_auth_authenticate, /* Authenticate user credentials */ null_auth_authenticate, /* Authenticate user credentials */
null_auth_free_client_data, /* Free the client data held in DCB */ null_auth_free_client_data, /* Free the client data held in DCB */
NULL, /* No destroy entry point */ NULL, /* No destroy entry point */
users_default_loadusers /* Load generic users */ users_default_loadusers, /* Load generic users */
NULL, /* No diagnostic */
NULL /* No user reauthentication */
}; };
static MXS_MODULE info = static MXS_MODULE info =

View File

@ -59,7 +59,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
null_auth_authenticate, /* Authenticate user credentials */ null_auth_authenticate, /* Authenticate user credentials */
null_auth_free_client_data, /* Free the client data held in DCB */ null_auth_free_client_data, /* Free the client data held in DCB */
NULL, /* No destroy entry point */ NULL, /* No destroy entry point */
users_default_loadusers /* Load generic users */ users_default_loadusers, /* Load generic users */
NULL, /* No diagnostic */
NULL /* No user reauthentication */
}; };
static MXS_MODULE info = static MXS_MODULE info =

View File

@ -147,12 +147,19 @@ struct subcommand showoptions[] =
{0} {0}
}, },
{ {
"dbusers", 1, 1, dcb_usersPrint, "dbusers", 1, 1, service_print_users,
"Show user statistics", "[deprecated] Show user statistics",
"Show statistics and user names for a service's user table.\n" "Show statistics and user names for a service's user table.\n"
"\t\tExample : show dbusers <service name>", "\t\tExample : show dbusers <service name>",
{ARG_TYPE_SERVICE, 0, 0} {ARG_TYPE_SERVICE, 0, 0}
}, },
{
"authenticators", 1, 1, service_print_users,
"Show authenticator diagnostics",
"Show authenticator diagnostics for a service.\n"
"\t\tExample : show authenticators <service name>",
{ARG_TYPE_SERVICE, 0, 0}
},
{ {
"epoll", 0, 0, dprintPollStats, "epoll", 0, 0, dprintPollStats,
"Show the poll statistics", "Show the poll statistics",