40
40
using namespace std;
41
41
using namespace drizzled;
46
45
static const fs::path DEFAULT_USERS_FILE= SYSCONFDIR "/drizzle.users";
48
class AuthFile: public plugin::Authentication
47
class AuthFile : public plugin::Authentication
50
const fs::path users_file;
54
AuthFile(string name_arg, fs::path users_file_arg);
50
AuthFile(fs::path users_file_arg);
57
53
* Retrieve the last error encountered in the class.
59
string& getError(void);
55
const string& getError() const;
62
58
* Load the users file into a map cache.
89
85
const string &scrambled_password);
88
const fs::path users_file;
94
91
* Cache or username:password entries from the file.
96
std::map<string, string> users;
93
typedef std::map<string, string> users_t;
99
AuthFile::AuthFile(string name_arg, fs::path users_file_arg):
100
plugin::Authentication(name_arg),
101
users_file(users_file_arg),
97
AuthFile::AuthFile(fs::path users_file_arg) :
98
plugin::Authentication("auth_file"),
99
users_file(users_file_arg)
107
string& AuthFile::getError(void)
103
const string& AuthFile::getError() const
112
bool AuthFile::loadFile(void)
108
bool AuthFile::loadFile()
114
110
ifstream file(users_file.string().c_str());
116
112
if (!file.is_open())
118
error = "Could not open users file: ";
119
error += users_file.string();
114
error = "Could not open users file: " + users_file.string();
119
while (getline(file, line))
128
121
/* Ignore blank lines and lines starting with '#'. */
129
if (line == "" || line[line.find_first_not_of(" \t")] == '#')
122
if (line.empty() || line[line.find_first_not_of(" \t")] == '#')
140
133
password = string(line, password_offset + 1);
143
std::pair<std::map<std::string, std::string>::iterator, bool> result=
144
users.insert(std::pair<std::string, std::string>(username, password));
146
if (result.second == false)
136
if (not users.insert(pair<string, string>(username, password)).second)
148
error = "Duplicate entry found in users file: ";
138
error = "Duplicate entry found in users file: " + username;
160
146
const string &scramble_bytes,
161
147
const string &scrambled_password)
163
if (scramble_bytes.size() != SHA1_DIGEST_LENGTH ||
164
scrambled_password.size() != SHA1_DIGEST_LENGTH)
149
if (scramble_bytes.size() != SHA1_DIGEST_LENGTH || scrambled_password.size() != SHA1_DIGEST_LENGTH)
174
159
/* Generate the double SHA1 hash for the password stored locally first. */
176
SHA1Update(&ctx, reinterpret_cast<const uint8_t *>(password.c_str()),
161
SHA1Update(&ctx, reinterpret_cast<const uint8_t *>(password.c_str()), password.size());
178
162
SHA1Final(temp_hash, &ctx);
184
168
/* Hash the scramble that was sent to client with the local password. */
186
SHA1Update(&ctx, reinterpret_cast<const uint8_t*>(scramble_bytes.c_str()),
170
SHA1Update(&ctx, reinterpret_cast<const uint8_t*>(scramble_bytes.c_str()), SHA1_DIGEST_LENGTH);
188
171
SHA1Update(&ctx, local_scrambled_password, SHA1_DIGEST_LENGTH);
189
172
SHA1Final(temp_hash, &ctx);
205
188
bool AuthFile::authenticate(const identifier::User &sctx, const string &password)
207
std::map<std::string, std::string>::const_iterator user= users.find(sctx.username());
208
if (user == users.end())
190
string* user= find_ptr(users, sctx.username());
211
if (sctx.getPasswordType() == identifier::User::MYSQL_HASH)
212
return verifyMySQLHash(user->second, sctx.getPasswordContext(), password);
214
if (password == user->second)
193
return sctx.getPasswordType() == identifier::User::MYSQL_HASH
194
? verifyMySQLHash(*user, sctx.getPasswordContext(), password)
220
198
static int init(module::Context &context)
222
200
const module::option_map &vm= context.getOptions();
224
AuthFile *auth_file = new AuthFile("auth_file", fs::path(vm["users"].as<string>()));
202
AuthFile *auth_file = new AuthFile(fs::path(vm["users"].as<string>()));
225
203
if (not auth_file->loadFile())
227
errmsg_printf(error::ERROR, _("Could not load auth file: %s\n"),
228
auth_file->getError().c_str());
205
errmsg_printf(error::ERROR, _("Could not load auth file: %s\n"), auth_file->getError().c_str());
229
206
delete auth_file;