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:
@ -167,7 +167,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
||||
cdc_auth_authenticate, /* Authenticate user credentials */
|
||||
cdc_auth_free_client_data, /* Free the client data held in DCB */
|
||||
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 =
|
||||
@ -484,11 +486,6 @@ cdc_read_users(USERS *users, char *usersfile)
|
||||
char *user_passwd;
|
||||
/* user maxlen ':' password hash '\n' '\0' */
|
||||
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;
|
||||
|
||||
@ -497,27 +494,11 @@ cdc_read_users(USERS *users, char *usersfile)
|
||||
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))
|
||||
{
|
||||
if (fgets(read_buffer, max_line_size, fp) != NULL)
|
||||
{
|
||||
char *tmp_ptr = read_buffer;
|
||||
/* append data for hash */
|
||||
strcat(all_users_data, read_buffer);
|
||||
|
||||
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);
|
||||
|
||||
return loaded;
|
||||
|
@ -664,7 +664,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
||||
gssapi_auth_authenticate, /* Authenticate user credentials */
|
||||
gssapi_auth_free_data, /* Free the client data held in DCB */
|
||||
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 =
|
||||
|
@ -276,7 +276,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
||||
gssapi_backend_auth_authenticate, /* Authenticate user credentials */
|
||||
NULL, /* Client plugin will free shared 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 =
|
||||
|
@ -66,7 +66,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
||||
http_auth_authenticate, /* Authenticate user credentials */
|
||||
http_auth_free_client_data, /* Free the client data held in DCB */
|
||||
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 =
|
||||
|
@ -60,7 +60,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
||||
max_admin_auth_authenticate, /* Authenticate user credentials */
|
||||
max_admin_auth_free_client_data, /* Free the client data held in DCB */
|
||||
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 =
|
||||
|
@ -49,12 +49,11 @@
|
||||
FROM mysql.user AS u LEFT JOIN mysql.tables_priv AS t \
|
||||
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 int gw_mysql_set_timeouts(MYSQL* handle);
|
||||
static char *mysql_format_user_entry(void *data);
|
||||
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)
|
||||
{
|
||||
@ -74,50 +73,9 @@ static char* get_new_users_query(const char *server_version, bool include_root)
|
||||
|
||||
int replace_mysql_users(SERV_LISTENER *listener)
|
||||
{
|
||||
USERS *newusers = mysql_users_alloc();
|
||||
|
||||
if (newusers == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
spinlock_acquire(&listener->lock);
|
||||
|
||||
/* 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);
|
||||
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;
|
||||
|
||||
int i = get_users(listener);
|
||||
spinlock_release(&listener->lock);
|
||||
|
||||
if (oldusers)
|
||||
{
|
||||
/* free the old table */
|
||||
users_free(oldusers);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -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.
|
||||
*
|
||||
@ -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
|
||||
* @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_passwd = NULL;
|
||||
|
@ -58,6 +58,8 @@ static int mysql_auth_set_client_data(
|
||||
MySQLProtocol *protocol,
|
||||
GWBUF *buffer);
|
||||
|
||||
void mysql_auth_diagnostic(DCB *dcb, SERV_LISTENER *port);
|
||||
|
||||
int mysql_auth_reauthenticate(DCB *dcb, const char *user,
|
||||
uint8_t *token, size_t token_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_destroy, /* Destroy entry point */
|
||||
mysql_auth_load_users, /* Load users from backend databases */
|
||||
mysql_auth_diagnostic,
|
||||
mysql_auth_reauthenticate /* Handle COM_CHANGE_USER */
|
||||
};
|
||||
|
||||
@ -630,4 +633,29 @@ int mysql_auth_reauthenticate(DCB *dcb, const char *user,
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
@ -169,7 +169,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
||||
auth_backend_authenticate, /* Authenticate user credentials */
|
||||
NULL, /* The shared data is freed by the client DCB */
|
||||
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 =
|
||||
|
@ -62,7 +62,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
||||
null_auth_authenticate, /* Authenticate user credentials */
|
||||
null_auth_free_client_data, /* Free the client data held in DCB */
|
||||
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 =
|
||||
|
@ -59,7 +59,9 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
||||
null_auth_authenticate, /* Authenticate user credentials */
|
||||
null_auth_free_client_data, /* Free the client data held in DCB */
|
||||
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 =
|
||||
|
Reference in New Issue
Block a user