diff --git a/server/modules/authenticator/PAM/PAMAuth/pam_auth.cc b/server/modules/authenticator/PAM/PAMAuth/pam_auth.cc index 78b85bda9..4c5e5d56d 100644 --- a/server/modules/authenticator/PAM/PAMAuth/pam_auth.cc +++ b/server/modules/authenticator/PAM/PAMAuth/pam_auth.cc @@ -12,6 +12,7 @@ */ #include"pam_auth.hh" +#include #include #include @@ -19,6 +20,14 @@ #include "pam_client_session.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 * @@ -131,6 +140,18 @@ static int pam_auth_load_users(SERV_LISTENER *listener) return inst->load_users(listener->service); } +static void pam_auth_diagnostic(DCB *dcb, SERV_LISTENER *listener) +{ + PamInstance *inst = static_cast(listener->auth_instance); + inst->diagnostic(dcb); +} + +static json_t* pam_auth_diagnostic_json(const SERV_LISTENER *listener) +{ + PamInstance *inst = static_cast(listener->auth_instance); + return inst->diagnostic_json(); +} + MXS_BEGIN_DECLS /** * 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, /* Free authenticator data */ pam_auth_load_users, /* Load database users */ - users_default_diagnostic, /* Default user diagnostic */ - users_default_diagnostic_json, /* Default user diagnostic */ + pam_auth_diagnostic, /* Default user diagnostic */ + pam_auth_diagnostic_json, /* Default user diagnostic */ NULL /* No user reauthentication */ }; diff --git a/server/modules/authenticator/PAM/PAMAuth/pam_auth.hh b/server/modules/authenticator/PAM/PAMAuth/pam_auth.hh index ae721fa41..9b1d50bcf 100644 --- a/server/modules/authenticator/PAM/PAMAuth/pam_auth.hh +++ b/server/modules/authenticator/PAM/PAMAuth/pam_auth.hh @@ -19,9 +19,17 @@ #include +#include #include #include #include #include +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; \ No newline at end of file diff --git a/server/modules/authenticator/PAM/PAMAuth/pam_client_session.cc b/server/modules/authenticator/PAM/PAMAuth/pam_client_session.cc index 20e02f248..229f0bb65 100644 --- a/server/modules/authenticator/PAM/PAMAuth/pam_client_session.cc +++ b/server/modules/authenticator/PAM/PAMAuth/pam_client_session.cc @@ -231,11 +231,11 @@ PamClientSession* PamClientSession::create(const PamInstance& inst) void PamClientSession::get_pam_user_services(const DCB* dcb, const MYSQL_session* session, StringVector* services_out) { - string services_query = string("SELECT authentication_string FROM ") + - m_instance.m_tablename + " WHERE user = '" + session->user + - "' AND '" + dcb->remote + "' LIKE host AND (anydb = '1' OR '" + - session->db + "' = '' OR '" + session->db + - "' LIKE db) ORDER BY authentication_string"; + string services_query = string("SELECT authentication_string FROM ") + m_instance.m_tablename + + " WHERE " + FIELD_USER + " = '" + session->user + "' AND '" + dcb->remote + + "' LIKE " + FIELD_HOST + " AND (" + FIELD_ANYDB + " = '1' OR '" + session->db + + "' = '' OR '" + session->db + "' LIKE " + FIELD_DB + + ") ORDER BY authentication_string;"; MXS_DEBUG("PAM services search sql: '%s'.", services_query.c_str()); char *err; if (sqlite3_exec(m_dbhandle, services_query.c_str(), user_services_cb, diff --git a/server/modules/authenticator/PAM/PAMAuth/pam_instance.cc b/server/modules/authenticator/PAM/PAMAuth/pam_instance.cc index 855d47a73..bc9447d28 100644 --- a/server/modules/authenticator/PAM/PAMAuth/pam_instance.cc +++ b/server/modules/authenticator/PAM/PAMAuth/pam_instance.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -36,9 +37,10 @@ PamInstance* PamInstance::create(char **options) /** The table name where we store the users */ const string pam_table_name = DEFAULT_PAM_TABLE_NAME; /** CREATE TABLE statement for the in-memory table */ - const string create_sql = "CREATE TABLE IF NOT EXISTS " + pam_table_name + - " (user varchar(255), host varchar(255), db varchar(255), " - "anydb boolean, authentication_string text)"; + const string create_sql = string("CREATE TABLE IF NOT EXISTS ") + pam_table_name + + " (" + FIELD_USER + " varchar(255), " + FIELD_HOST + " varchar(255), " + + FIELD_DB + " varchar(255), " + FIELD_ANYDB + " boolean, " + + FIELD_AUTHSTR + " text);"; if (sqlite3_threadsafe() == 0) { MXS_WARNING("SQLite3 was compiled with thread safety off. May cause " @@ -228,5 +230,60 @@ int PamInstance::load_users(SERVICE* service) } 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(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; } \ No newline at end of file diff --git a/server/modules/authenticator/PAM/PAMAuth/pam_instance.hh b/server/modules/authenticator/PAM/PAMAuth/pam_instance.hh index e0015fbcb..69ad0d737 100644 --- a/server/modules/authenticator/PAM/PAMAuth/pam_instance.hh +++ b/server/modules/authenticator/PAM/PAMAuth/pam_instance.hh @@ -26,6 +26,8 @@ public: static PamInstance* create(char **options); ~PamInstance(); 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_tablename; /**< The table where users are stored */