Merge branch '2.3' into develop
This commit is contained in:
106
server/core/test/rest-api/package-lock.json
generated
106
server/core/test/rest-api/package-lock.json
generated
@ -57,7 +57,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"tweetnacl": "^0.14.3"
|
||||
}
|
||||
@ -110,9 +109,9 @@
|
||||
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
||||
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
|
||||
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
@ -177,7 +176,6 @@
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
@ -214,12 +212,12 @@
|
||||
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "1.0.6",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
@ -260,12 +258,35 @@
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
|
||||
"integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
||||
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
|
||||
"requires": {
|
||||
"ajv": "^5.3.0",
|
||||
"ajv": "^6.5.5",
|
||||
"har-schema": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz",
|
||||
"integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
@ -315,8 +336,7 @@
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
|
||||
"optional": true
|
||||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.3",
|
||||
@ -345,21 +365,21 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.10",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz",
|
||||
"integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg=="
|
||||
"version": "4.17.11",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.35.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz",
|
||||
"integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg=="
|
||||
"version": "1.37.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
|
||||
"integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.19",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz",
|
||||
"integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==",
|
||||
"version": "2.1.21",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
|
||||
"integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
|
||||
"requires": {
|
||||
"mime-db": "~1.35.0"
|
||||
"mime-db": "~1.37.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
@ -430,14 +450,14 @@
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"psl": {
|
||||
"version": "1.1.29",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
|
||||
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
|
||||
"version": "1.1.31",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
|
||||
"integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw=="
|
||||
},
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
@ -500,9 +520,9 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.14.2",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
|
||||
"integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
"assert-plus": "^1.0.0",
|
||||
@ -535,6 +555,13 @@
|
||||
"requires": {
|
||||
"psl": "^1.1.24",
|
||||
"punycode": "^1.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"punycode": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||
}
|
||||
}
|
||||
},
|
||||
"tunnel-agent": {
|
||||
@ -548,14 +575,21 @@
|
||||
"tweetnacl": {
|
||||
"version": "0.14.5",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
|
||||
"optional": true
|
||||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||
},
|
||||
"type-detect": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz",
|
||||
"integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
||||
"requires": {
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"uuid": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
|
||||
|
@ -26,7 +26,8 @@ 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;
|
||||
const string FIELD_PROXY = "proxy_grant";
|
||||
const int NUM_FIELDS = 6;
|
||||
|
||||
/**
|
||||
* Initialize PAM authenticator
|
||||
|
@ -32,4 +32,5 @@ extern const string FIELD_HOST;
|
||||
extern const string FIELD_DB;
|
||||
extern const string FIELD_ANYDB;
|
||||
extern const string FIELD_AUTHSTR;
|
||||
extern const string FIELD_PROXY;
|
||||
extern const int NUM_FIELDS;
|
||||
|
@ -257,37 +257,62 @@ PamClientSession* PamClientSession::create(const PamInstance& inst)
|
||||
* @param session MySQL session
|
||||
* @param services_out Output for services
|
||||
*/
|
||||
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)
|
||||
{
|
||||
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;";
|
||||
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 + ")"
|
||||
+ " AND " + FIELD_PROXY + " = '0' 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, services_out, &err) != SQLITE_OK)
|
||||
{
|
||||
MXS_ERROR("Failed to execute query: '%s'", err);
|
||||
sqlite3_free(err);
|
||||
}
|
||||
MXS_DEBUG("User '%s' matched %lu rows in %s db.",
|
||||
session->user,
|
||||
services_out->size(),
|
||||
m_instance.m_tablename.c_str());
|
||||
|
||||
if (services_out->empty())
|
||||
auto word_entry = [](size_t num) -> const char* {
|
||||
return (num == 1) ? "entry" : "entries";
|
||||
};
|
||||
|
||||
if (!services_out->empty())
|
||||
{
|
||||
// No service found for user with correct username & password. Check if anonymous user exists.
|
||||
auto num_services = services_out->size();
|
||||
MXS_INFO("Found %lu valid PAM user %s for '%s'@'%s'.",
|
||||
num_services, word_entry(num_services), session->user, dcb->remote);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No service found for user with correct username & host.
|
||||
// Check if a matching anonymous user exists.
|
||||
const string anon_query = string("SELECT authentication_string FROM ") + m_instance.m_tablename
|
||||
+ " WHERE " + FIELD_USER + " = '' AND " + FIELD_HOST + " = '%';";
|
||||
+ " WHERE " + FIELD_USER + " = ''"
|
||||
+ " AND '" + dcb->remote + "' LIKE " + FIELD_HOST +
|
||||
+ " AND " + FIELD_PROXY + " = '1' ORDER BY authentication_string;";
|
||||
MXS_DEBUG("PAM proxy user services search sql: '%s'.", anon_query.c_str());
|
||||
|
||||
if (sqlite3_exec(m_dbhandle, anon_query.c_str(), user_services_cb, services_out, &err) != SQLITE_OK)
|
||||
{
|
||||
MXS_ERROR("Failed to execute query: '%s'", err);
|
||||
sqlite3_free(err);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto num_services = services_out->size();
|
||||
if (num_services == 0)
|
||||
{
|
||||
MXS_INFO("Found no PAM user entries for '%s'@'%s'.", session->user, dcb->remote);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_INFO("Found %lu matching anonymous PAM user %s for '%s'@'%s'.",
|
||||
num_services, word_entry(num_services), session->user, dcb->remote);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,9 +33,7 @@ public:
|
||||
bool extract(DCB* dcb, GWBUF* read_buffer);
|
||||
private:
|
||||
PamClientSession(sqlite3* dbhandle, const PamInstance& instance);
|
||||
void get_pam_user_services(const DCB* dcb,
|
||||
const MYSQL_session* session,
|
||||
StringVector* services_out);
|
||||
void get_pam_user_services(const DCB* dcb, const MYSQL_session* session, StringVector* services_out);
|
||||
maxscale::Buffer create_auth_change_packet() const;
|
||||
|
||||
pam_auth_state m_state; /**< Authentication state*/
|
||||
|
@ -35,16 +35,23 @@ PamInstance* PamInstance::create(char** options)
|
||||
const string pam_db_name = DEFAULT_PAM_DATABASE_NAME;
|
||||
/** The table name where we store the users */
|
||||
const string pam_table_name = DEFAULT_PAM_TABLE_NAME;
|
||||
/** Deletion statement for the in-memory table */
|
||||
const string drop_sql = string("DROP TABLE IF EXISTS ") + pam_table_name + ";";
|
||||
/** CREATE TABLE statement for the in-memory table */
|
||||
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);";
|
||||
const string create_sql = string("CREATE TABLE ") + pam_table_name
|
||||
+ " (" + FIELD_USER + " varchar(255), "
|
||||
+ FIELD_HOST + " varchar(255), "
|
||||
+ FIELD_DB + " varchar(255), "
|
||||
+ FIELD_ANYDB + " boolean, "
|
||||
+ FIELD_AUTHSTR + " text, "
|
||||
+ FIELD_PROXY + " boolean);";
|
||||
|
||||
if (sqlite3_threadsafe() == 0)
|
||||
{
|
||||
MXS_WARNING("SQLite3 was compiled with thread safety off. May cause "
|
||||
"corruption of in-memory database.");
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
/* This handle may be used from multiple threads, set full mutex. */
|
||||
sqlite3* dbhandle = NULL;
|
||||
@ -57,9 +64,15 @@ PamInstance* PamInstance::create(char** options)
|
||||
}
|
||||
|
||||
char* err;
|
||||
if (!error && sqlite3_exec(dbhandle, drop_sql.c_str(), NULL, NULL, &err) != SQLITE_OK)
|
||||
{
|
||||
MXS_ERROR("Failed to drop table: '%s'", err);
|
||||
sqlite3_free(err);
|
||||
error = true;
|
||||
}
|
||||
if (!error && sqlite3_exec(dbhandle, create_sql.c_str(), NULL, NULL, &err) != SQLITE_OK)
|
||||
{
|
||||
MXS_ERROR("Failed to create database: '%s'", err);
|
||||
MXS_ERROR("Failed to create table: '%s'", err);
|
||||
sqlite3_free(err);
|
||||
error = true;
|
||||
}
|
||||
@ -95,12 +108,10 @@ PamInstance::PamInstance(sqlite3* dbhandle, const string& dbname, const string&
|
||||
* @param db Database
|
||||
* @param anydb Global access to databases
|
||||
* @param pam_service The PAM service used
|
||||
* @param proxy Is the user anonymous with a proxy grant
|
||||
*/
|
||||
void PamInstance::add_pam_user(const char* user,
|
||||
const char* host,
|
||||
const char* db,
|
||||
bool anydb,
|
||||
const char* pam_service)
|
||||
void PamInstance::add_pam_user(const char* user, const char* host, const char* db, bool anydb,
|
||||
const char* pam_service, bool proxy)
|
||||
{
|
||||
/**
|
||||
* The insert query template which adds users to the pam_users table.
|
||||
@ -109,7 +120,7 @@ void PamInstance::add_pam_user(const char* user,
|
||||
* no quotes around them. The quotes for strings are added in this function.
|
||||
*/
|
||||
const string insert_sql_template =
|
||||
"INSERT INTO " + m_tablename + " VALUES ('%s', '%s', %s, '%s', %s)";
|
||||
"INSERT INTO " + m_tablename + " VALUES ('%s', '%s', %s, '%s', %s, '%s')";
|
||||
|
||||
/** Used for NULL value creation in the INSERT query */
|
||||
const char NULL_TOKEN[] = "NULL";
|
||||
@ -140,11 +151,10 @@ void PamInstance::add_pam_user(const char* user,
|
||||
char insert_sql[len + 1];
|
||||
sprintf(insert_sql,
|
||||
insert_sql_template.c_str(),
|
||||
user,
|
||||
host,
|
||||
db_str.c_str(),
|
||||
anydb ? "1" : "0",
|
||||
service_str.c_str());
|
||||
user, host,
|
||||
db_str.c_str(), anydb ? "1" : "0",
|
||||
service_str.c_str(),
|
||||
proxy ? "1" : "0");
|
||||
|
||||
char* err;
|
||||
if (sqlite3_exec(m_dbhandle, insert_sql, NULL, NULL, &err) != SQLITE_OK)
|
||||
@ -152,6 +162,18 @@ void PamInstance::add_pam_user(const char* user,
|
||||
MXS_ERROR("Failed to insert user: %s", err);
|
||||
sqlite3_free(err);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (proxy)
|
||||
{
|
||||
MXS_INFO("Added anonymous PAM user ''@'%s' with proxy grants using service %s.",
|
||||
host, service_str.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_INFO("Added normal PAM user '%s'@'%s' using service %s.", user, host, service_str.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -208,8 +230,7 @@ int PamInstance::load_users(SERVICE* service)
|
||||
if (mysql_query(mysql, PAM_USERS_QUERY))
|
||||
{
|
||||
MXS_ERROR("Failed to query server '%s' for PAM users: '%s'.",
|
||||
servers->server->name(),
|
||||
mysql_error(mysql));
|
||||
servers->server->name(), mysql_error(mysql));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -218,23 +239,20 @@ int PamInstance::load_users(SERVICE* service)
|
||||
if (res)
|
||||
{
|
||||
mxb_assert(mysql_num_fields(res) == PAM_USERS_QUERY_NUM_FIELDS);
|
||||
MXS_NOTICE("Loaded %llu users for service %s.",
|
||||
mysql_num_rows(res),
|
||||
service->name());
|
||||
MYSQL_ROW row;
|
||||
while ((row = mysql_fetch_row(res)))
|
||||
{
|
||||
add_pam_user(row[0],
|
||||
row[1],
|
||||
row[2],
|
||||
row[3] && strcasecmp(row[3], "Y") == 0,
|
||||
row[4]);
|
||||
add_pam_user(row[0], row[1], // user, host
|
||||
row[2], row[3] && strcasecmp(row[3], "Y") == 0, // db, anydb
|
||||
row[4], // pam service
|
||||
false); // not a proxy
|
||||
}
|
||||
mysql_free_result(res);
|
||||
if (query_anon_proxy_user(servers->server, mysql))
|
||||
{
|
||||
rval = MXS_AUTH_LOADUSERS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (fetch_anon_proxy_users(servers->server, mysql))
|
||||
{
|
||||
rval = MXS_AUTH_LOADUSERS_OK;
|
||||
}
|
||||
}
|
||||
mysql_close(mysql);
|
||||
@ -305,63 +323,68 @@ json_t* PamInstance::diagnostic_json()
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool PamInstance::query_anon_proxy_user(SERVER* server, MYSQL* conn)
|
||||
bool PamInstance::fetch_anon_proxy_users(SERVER* server, MYSQL* conn)
|
||||
{
|
||||
bool success = true;
|
||||
bool anon_user_found = false;
|
||||
string anon_pam_service;
|
||||
const char ANON_USER_QUERY[] = "SELECT authentication_string FROM mysql.user WHERE "
|
||||
"(plugin = 'pam' AND user = '' AND host = '%');";
|
||||
const char ANON_GRANT_QUERY[] = "SHOW GRANTS FOR ''@'%';";
|
||||
const char ANON_USER_QUERY[] = "SELECT host,authentication_string FROM mysql.user WHERE "
|
||||
"(plugin = 'pam' AND user = '');";
|
||||
|
||||
const char GRANT_PROXY[] = "GRANT PROXY ON";
|
||||
|
||||
// Query for the anonymous user which is used with group mappings
|
||||
if (mysql_query(conn, ANON_USER_QUERY))
|
||||
{
|
||||
MXS_ERROR("Failed to query server '%s' for the anonymous PAM user: '%s'.",
|
||||
server->name(),
|
||||
mysql_error(conn));
|
||||
MXS_ERROR("Failed to query server '%s' for anonymous PAM users: '%s'.",
|
||||
server->name(), mysql_error(conn));
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Temporary storage of host,authentication_string for anonymous pam users.
|
||||
std::vector<std::pair<string, string>> anon_users_info;
|
||||
MYSQL_RES* res = mysql_store_result(conn);
|
||||
if (res)
|
||||
{
|
||||
MYSQL_ROW row = mysql_fetch_row(res);
|
||||
if (row)
|
||||
MYSQL_ROW row;
|
||||
while ((row = mysql_fetch_row(res)))
|
||||
{
|
||||
anon_user_found = true;
|
||||
if (row[0])
|
||||
{
|
||||
anon_pam_service = row[0];
|
||||
}
|
||||
string host = row[0] ? row[0] : "";
|
||||
string auth_str = row[1] ? row[1] : "";
|
||||
anon_users_info.push_back(std::make_pair(host, auth_str));
|
||||
}
|
||||
mysql_free_result(res);
|
||||
}
|
||||
|
||||
if (anon_user_found)
|
||||
if (!anon_users_info.empty())
|
||||
{
|
||||
// Check that the anon user has a proxy grant
|
||||
if (mysql_query(conn, ANON_GRANT_QUERY))
|
||||
MXS_INFO("Found %lu anonymous PAM user(s). Checking them for proxy grants.",
|
||||
anon_users_info.size());
|
||||
}
|
||||
|
||||
for (const auto& elem : anon_users_info)
|
||||
{
|
||||
string query = "SHOW GRANTS FOR ''@'" + elem.first + "';";
|
||||
// Check that the anon user has a proxy grant.
|
||||
if (mysql_query(conn, query.c_str()))
|
||||
{
|
||||
MXS_ERROR("Failed to query server '%s' for the grants of the anonymous PAM user: '%s'.",
|
||||
server->name(),
|
||||
mysql_error(conn));
|
||||
MXS_ERROR("Failed to query server '%s' for grants of anonymous PAM user ''@'%s': '%s'.",
|
||||
server->name(), elem.first.c_str(), mysql_error(conn));
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((res = mysql_store_result(conn)))
|
||||
{
|
||||
// The user may have multiple proxy grants, but is only added once.
|
||||
MYSQL_ROW row;
|
||||
while ((row = mysql_fetch_row(res)))
|
||||
{
|
||||
if (row[0] && strncmp(row[0], GRANT_PROXY, sizeof(GRANT_PROXY) - 1) == 0)
|
||||
{
|
||||
MXS_NOTICE("Anonymous PAM user with proxy grant found. User account mapping "
|
||||
"enabled.");
|
||||
add_pam_user("", "%", NULL, false, anon_pam_service.c_str());
|
||||
add_pam_user("", elem.first.c_str(), // user, host
|
||||
NULL, false, // Unused
|
||||
elem.second.c_str(), true); // service, proxy
|
||||
break;
|
||||
}
|
||||
}
|
||||
mysql_free_result(res);
|
||||
|
@ -33,13 +33,10 @@ public:
|
||||
const std::string m_tablename; /**< The table where users are stored */
|
||||
private:
|
||||
PamInstance(sqlite3* dbhandle, const std::string& m_dbname, const std::string& tablename);
|
||||
void add_pam_user(const char* user,
|
||||
const char* host,
|
||||
const char* db,
|
||||
bool anydb,
|
||||
const char* pam_service);
|
||||
void add_pam_user(const char* user, const char* host, const char* db, bool anydb,
|
||||
const char* pam_service, bool proxy);
|
||||
void delete_old_users();
|
||||
bool query_anon_proxy_user(SERVER* server, MYSQL* conn);
|
||||
bool fetch_anon_proxy_users(SERVER* server, MYSQL* conn);
|
||||
|
||||
sqlite3* const m_dbhandle; /**< SQLite3 database handle */
|
||||
};
|
||||
|
Reference in New Issue
Block a user