MXS-1716 Add diagnostic functions to PAM Authenticator
The functions print the user information. Normal version just prints user@host, the json-version prints the whole array.
This commit is contained in:
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
#include"pam_auth.hh"
|
#include"pam_auth.hh"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <maxscale/authenticator.h>
|
#include <maxscale/authenticator.h>
|
||||||
#include <maxscale/users.h>
|
#include <maxscale/users.h>
|
||||||
|
|
||||||
@ -19,6 +20,14 @@
|
|||||||
#include "pam_client_session.hh"
|
#include "pam_client_session.hh"
|
||||||
#include "../pam_auth_common.hh"
|
#include "../pam_auth_common.hh"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
const string FIELD_USER = "user";
|
||||||
|
const string FIELD_HOST = "host";
|
||||||
|
const string FIELD_DB = "db";
|
||||||
|
const string FIELD_ANYDB = "anydb";
|
||||||
|
const string FIELD_AUTHSTR = "authentication_string";
|
||||||
|
const int NUM_FIELDS = 5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize PAM authenticator
|
* Initialize PAM authenticator
|
||||||
*
|
*
|
||||||
@ -131,6 +140,18 @@ static int pam_auth_load_users(SERV_LISTENER *listener)
|
|||||||
return inst->load_users(listener->service);
|
return inst->load_users(listener->service);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pam_auth_diagnostic(DCB *dcb, SERV_LISTENER *listener)
|
||||||
|
{
|
||||||
|
PamInstance *inst = static_cast<PamInstance*>(listener->auth_instance);
|
||||||
|
inst->diagnostic(dcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static json_t* pam_auth_diagnostic_json(const SERV_LISTENER *listener)
|
||||||
|
{
|
||||||
|
PamInstance *inst = static_cast<PamInstance*>(listener->auth_instance);
|
||||||
|
return inst->diagnostic_json();
|
||||||
|
}
|
||||||
|
|
||||||
MXS_BEGIN_DECLS
|
MXS_BEGIN_DECLS
|
||||||
/**
|
/**
|
||||||
* Module handle entry point
|
* Module handle entry point
|
||||||
@ -147,8 +168,8 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
|||||||
pam_auth_free_data, /* Free the client data held in DCB */
|
pam_auth_free_data, /* Free the client data held in DCB */
|
||||||
pam_auth_free, /* Free authenticator data */
|
pam_auth_free, /* Free authenticator data */
|
||||||
pam_auth_load_users, /* Load database users */
|
pam_auth_load_users, /* Load database users */
|
||||||
users_default_diagnostic, /* Default user diagnostic */
|
pam_auth_diagnostic, /* Default user diagnostic */
|
||||||
users_default_diagnostic_json, /* Default user diagnostic */
|
pam_auth_diagnostic_json, /* Default user diagnostic */
|
||||||
NULL /* No user reauthentication */
|
NULL /* No user reauthentication */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,9 +19,17 @@
|
|||||||
|
|
||||||
#include <maxscale/cppdefs.hh>
|
#include <maxscale/cppdefs.hh>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <maxscale/alloc.h>
|
#include <maxscale/alloc.h>
|
||||||
#include <maxscale/buffer.hh>
|
#include <maxscale/buffer.hh>
|
||||||
#include <maxscale/dcb.h>
|
#include <maxscale/dcb.h>
|
||||||
#include <maxscale/protocol/mysql.h>
|
#include <maxscale/protocol/mysql.h>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
extern const string FIELD_USER;
|
||||||
|
extern const string FIELD_HOST;
|
||||||
|
extern const string FIELD_DB;
|
||||||
|
extern const string FIELD_ANYDB;
|
||||||
|
extern const string FIELD_AUTHSTR;
|
||||||
|
extern const int NUM_FIELDS;
|
@ -231,11 +231,11 @@ PamClientSession* PamClientSession::create(const PamInstance& inst)
|
|||||||
void PamClientSession::get_pam_user_services(const DCB* dcb, const MYSQL_session* session,
|
void PamClientSession::get_pam_user_services(const DCB* dcb, const MYSQL_session* session,
|
||||||
StringVector* services_out)
|
StringVector* services_out)
|
||||||
{
|
{
|
||||||
string services_query = string("SELECT authentication_string FROM ") +
|
string services_query = string("SELECT authentication_string FROM ") + m_instance.m_tablename +
|
||||||
m_instance.m_tablename + " WHERE user = '" + session->user +
|
" WHERE " + FIELD_USER + " = '" + session->user + "' AND '" + dcb->remote +
|
||||||
"' AND '" + dcb->remote + "' LIKE host AND (anydb = '1' OR '" +
|
"' LIKE " + FIELD_HOST + " AND (" + FIELD_ANYDB + " = '1' OR '" + session->db +
|
||||||
session->db + "' = '' OR '" + session->db +
|
"' = '' OR '" + session->db + "' LIKE " + FIELD_DB +
|
||||||
"' LIKE db) ORDER BY authentication_string";
|
") ORDER BY authentication_string;";
|
||||||
MXS_DEBUG("PAM services search sql: '%s'.", services_query.c_str());
|
MXS_DEBUG("PAM services search sql: '%s'.", services_query.c_str());
|
||||||
char *err;
|
char *err;
|
||||||
if (sqlite3_exec(m_dbhandle, services_query.c_str(), user_services_cb,
|
if (sqlite3_exec(m_dbhandle, services_query.c_str(), user_services_cb,
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <maxscale/jansson.hh>
|
||||||
#include <maxscale/log_manager.h>
|
#include <maxscale/log_manager.h>
|
||||||
#include <maxscale/secrets.h>
|
#include <maxscale/secrets.h>
|
||||||
#include <maxscale/mysql_utils.h>
|
#include <maxscale/mysql_utils.h>
|
||||||
@ -36,9 +37,10 @@ PamInstance* PamInstance::create(char **options)
|
|||||||
/** The table name where we store the users */
|
/** The table name where we store the users */
|
||||||
const string pam_table_name = DEFAULT_PAM_TABLE_NAME;
|
const string pam_table_name = DEFAULT_PAM_TABLE_NAME;
|
||||||
/** CREATE TABLE statement for the in-memory table */
|
/** CREATE TABLE statement for the in-memory table */
|
||||||
const string create_sql = "CREATE TABLE IF NOT EXISTS " + pam_table_name +
|
const string create_sql = string("CREATE TABLE IF NOT EXISTS ") + pam_table_name +
|
||||||
" (user varchar(255), host varchar(255), db varchar(255), "
|
" (" + FIELD_USER + " varchar(255), " + FIELD_HOST + " varchar(255), " +
|
||||||
"anydb boolean, authentication_string text)";
|
FIELD_DB + " varchar(255), " + FIELD_ANYDB + " boolean, " +
|
||||||
|
FIELD_AUTHSTR + " text);";
|
||||||
if (sqlite3_threadsafe() == 0)
|
if (sqlite3_threadsafe() == 0)
|
||||||
{
|
{
|
||||||
MXS_WARNING("SQLite3 was compiled with thread safety off. May cause "
|
MXS_WARNING("SQLite3 was compiled with thread safety off. May cause "
|
||||||
@ -228,5 +230,60 @@ int PamInstance::load_users(SERVICE* service)
|
|||||||
}
|
}
|
||||||
MXS_FREE(pw);
|
MXS_FREE(pw);
|
||||||
}
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PamInstance::diagnostic(DCB* dcb)
|
||||||
|
{
|
||||||
|
json_t* array = diagnostic_json();
|
||||||
|
ss_dassert(json_is_array(array));
|
||||||
|
|
||||||
|
string result, separator;
|
||||||
|
size_t index;
|
||||||
|
json_t* value;
|
||||||
|
json_array_foreach(array, index, value)
|
||||||
|
{
|
||||||
|
// Only print user@host for the non-json version, as this should fit nicely on the console. Add the
|
||||||
|
// other fields if deemed useful.
|
||||||
|
const char* user = json_string_value(json_object_get(value, FIELD_USER.c_str()));
|
||||||
|
const char* host = json_string_value(json_object_get(value, FIELD_HOST.c_str()));
|
||||||
|
if (user && host)
|
||||||
|
{
|
||||||
|
result += separator + user + "@" + host;
|
||||||
|
separator = " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.empty())
|
||||||
|
{
|
||||||
|
dcb_printf(dcb, "%s", result.c_str());
|
||||||
|
}
|
||||||
|
json_decref(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int diag_cb_json(void *data, int columns, char **row, char **field_names)
|
||||||
|
{
|
||||||
|
ss_dassert(columns == NUM_FIELDS);
|
||||||
|
json_t* obj = json_object();
|
||||||
|
for (int i = 0; i < columns; i++)
|
||||||
|
{
|
||||||
|
json_object_set_new(obj, field_names[i], json_string(row[i]));
|
||||||
|
}
|
||||||
|
json_t* arr = static_cast<json_t*>(data);
|
||||||
|
json_array_append_new(arr, obj);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_t* PamInstance::diagnostic_json()
|
||||||
|
{
|
||||||
|
json_t* rval = json_array();
|
||||||
|
char *err;
|
||||||
|
string select = "SELECT * FROM " + m_tablename + ";";
|
||||||
|
if (sqlite3_exec(m_dbhandle, select.c_str(), diag_cb_json, rval, &err) != SQLITE_OK)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Failed to print users: %s", err);
|
||||||
|
sqlite3_free(err);
|
||||||
|
}
|
||||||
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
@ -26,6 +26,8 @@ public:
|
|||||||
static PamInstance* create(char **options);
|
static PamInstance* create(char **options);
|
||||||
~PamInstance();
|
~PamInstance();
|
||||||
int load_users(SERVICE* service);
|
int load_users(SERVICE* service);
|
||||||
|
void diagnostic(DCB* dcb);
|
||||||
|
json_t* diagnostic_json();
|
||||||
|
|
||||||
const std::string m_dbname; /**< Name of the in-memory database */
|
const std::string m_dbname; /**< Name of the in-memory database */
|
||||||
const std::string m_tablename; /**< The table where users are stored */
|
const std::string m_tablename; /**< The table where users are stored */
|
||||||
|
Reference in New Issue
Block a user