21 #include <drizzled/identifier.h>
22 #include <drizzled/util/convert.h>
24 #include <drizzled/execute.h>
25 #include <drizzled/sql/result_set.h>
26 #include <drizzled/plugin/listen.h>
27 #include <drizzled/plugin/client.h>
28 #include <drizzled/catalog/local.h>
29 #include "auth_schema.h"
31 namespace drizzle_plugin {
32 namespace auth_schema {
34 AuthSchema::AuthSchema(
bool enabled) :
35 plugin::Authentication(
"auth_schema"),
36 sysvar_enabled(enabled)
40 _ident_re= pcre_compile(
48 bool AuthSchema::setTable(
const string &table)
52 errmsg_printf(error::ERROR, _(
"auth_schema table cannot be an empty string"));
56 if (table.find(
".") == string::npos)
58 errmsg_printf(error::ERROR, _(
"auth_schema must be schema-qualified"));
62 sysvar_table= escapeQuoteAuthTable(table);
67 bool AuthSchema::verifyMySQLPassword(
const string &real_password,
68 const string &scramble_bytes,
69 const string &client_password)
71 if (scramble_bytes.size() != SHA1_DIGEST_LENGTH
72 || client_password.size() != SHA1_DIGEST_LENGTH)
75 uint8_t real_password_hash[SHA1_DIGEST_LENGTH];
76 drizzled_hex_to_string(
77 reinterpret_cast<char *>(real_password_hash),
78 real_password.c_str(),
79 SHA1_DIGEST_LENGTH * 2);
83 uint8_t temp_hash[SHA1_DIGEST_LENGTH];
85 SHA1Update(&ctx, reinterpret_cast<const uint8_t*>(scramble_bytes.c_str()), SHA1_DIGEST_LENGTH);
86 SHA1Update(&ctx, real_password_hash, SHA1_DIGEST_LENGTH);
87 SHA1Final(temp_hash, &ctx);
91 for (
int x= 0; x < SHA1_DIGEST_LENGTH; x++)
92 temp_hash[x]= temp_hash[x] ^ client_password[x];
95 uint8_t client_password_hash[SHA1_DIGEST_LENGTH];
97 SHA1Update(&ctx, temp_hash, SHA1_DIGEST_LENGTH);
98 SHA1Final(client_password_hash, &ctx);
101 return memcmp(real_password_hash, client_password_hash, SHA1_DIGEST_LENGTH) == 0;
107 if (not sysvar_enabled)
112 if (sctx.getPasswordType() != identifier::User::MYSQL_HASH)
116 string user= escapeString(sctx.username());
124 _session= Session::make_shared(plugin::Listen::getNullClient(), catalog::local());
125 identifier::user::mptr user_id= identifier::User::make_shared();
126 user_id->setUser(
"auth_schema");
127 _session->setUser(user_id);
132 string sql=
"SELECT password FROM " + sysvar_table +
" WHERE user='" + user +
"' LIMIT 1;";
133 Execute execute(*(_session.get()),
true);
135 execute.run(sql, result_set);
137 drizzled::error_t err= exception.getErrorCode();
138 if ((err != EE_OK) && (err != ER_EMPTY_QUERY))
140 errmsg_printf(error::ERROR,
141 _(
"Error querying authentication schema: %s (error code %d. Query: %s"),
142 exception.getErrorMessage().c_str(), exception.getErrorCode(), sql.c_str());
148 if (result_set.next() and not result_set.isNull(0))
150 string real_password= result_set.getString(0);
152 return verifyMySQLPassword(
154 sctx.getPasswordContext(),
162 string AuthSchema::escapeQuoteAuthTable(
const string &table)
164 int pos= table.find(
".");
165 string quoted_schema= escapeQuoteIdentifier(table.substr(0, pos));
166 string quoted_table= escapeQuoteIdentifier(table.substr(pos + 1, table.length() - pos));
167 return quoted_schema +
"." + quoted_table;
170 string AuthSchema::escapeQuoteIdentifier(
const string &input)
179 int match_result= pcre_exec(
180 _ident_re, NULL, input.c_str(), input.length(), 0, 0, NULL, 0);
181 if (match_result >= 0)
184 const char *pos= input.c_str();
185 const char *end= input.c_str()+input.length();
188 for (; pos != end ; pos++)
192 ident.push_back(
'\\');
193 ident.push_back(
'`');
196 ident.push_back(
'\\');
197 ident.push_back(
'\\');
200 ident.push_back(*pos);
205 ident.push_back(
'`');
210 string AuthSchema::escapeString(
const string &input)
215 const char *pos= input.c_str();
216 const char *end= input.c_str()+input.length();
219 for (; pos != end ; pos++)
251 AuthSchema::~AuthSchema()
253 if (_ident_re != NULL)
254 pcre_free(_ident_re);