27 #include <boost/program_options.hpp>
28 #include <boost/filesystem.hpp>
30 #include <drizzled/item.h>
31 #include <drizzled/configmake.h>
32 #include <drizzled/plugin/authentication.h>
33 #include <drizzled/identifier.h>
34 #include <drizzled/util/convert.h>
38 namespace po= boost::program_options;
39 namespace fs= boost::filesystem;
42 using namespace drizzled;
46 static const fs::path DEFAULT_USERS_FILE= SYSCONFDIR
"/drizzle.users";
47 typedef std::map<string, string> users_t;
49 bool parseUsersFile(std::string, users_t&);
54 AuthFile(std::string users_file_arg);
59 const string& getError()
const;
61 std::string& getUsersFile();
62 bool setUsersFile(std::string& usersFile);
82 bool verifyMySQLHash(
const string &password,
83 const string &scramble_bytes,
84 const string &scrambled_password);
88 std::string sysvar_users_file;
98 void setUsers(users_t);
107 AuthFile::AuthFile(std::string users_file_arg) :
108 plugin::Authentication(
"auth_file"),
109 users_file(users_file_arg), sysvar_users_file(users_file_arg)
118 std::string& AuthFile::getUsersFile()
120 return sysvar_users_file;
123 bool AuthFile::setUsersFile(std::string& usersFile)
125 if (usersFile.empty())
127 errmsg_printf(error::ERROR, _(
"users file cannot be an empty string"));
131 if(parseUsersFile(usersFile, users_dummy))
135 sysvar_users_file= usersFile;
136 fs::path newUsersFile(getUsersFile());
137 users_file= newUsersFile;
144 const string &scramble_bytes,
145 const string &scrambled_password)
147 if (scramble_bytes.size() != SHA1_DIGEST_LENGTH || scrambled_password.size() != SHA1_DIGEST_LENGTH)
153 uint8_t local_scrambled_password[SHA1_DIGEST_LENGTH];
154 uint8_t temp_hash[SHA1_DIGEST_LENGTH];
155 uint8_t scrambled_password_check[SHA1_DIGEST_LENGTH];
159 SHA1Update(&ctx, reinterpret_cast<const uint8_t *>(password.c_str()), password.size());
160 SHA1Final(temp_hash, &ctx);
163 SHA1Update(&ctx, temp_hash, SHA1_DIGEST_LENGTH);
164 SHA1Final(local_scrambled_password, &ctx);
168 SHA1Update(&ctx, reinterpret_cast<const uint8_t*>(scramble_bytes.c_str()), SHA1_DIGEST_LENGTH);
169 SHA1Update(&ctx, local_scrambled_password, SHA1_DIGEST_LENGTH);
170 SHA1Final(temp_hash, &ctx);
174 for (
int x= 0; x < SHA1_DIGEST_LENGTH; x++)
175 temp_hash[x]= temp_hash[x] ^ scrambled_password[x];
179 SHA1Update(&ctx, temp_hash, SHA1_DIGEST_LENGTH);
180 SHA1Final(scrambled_password_check, &ctx);
183 return memcmp(local_scrambled_password, scrambled_password_check, SHA1_DIGEST_LENGTH) == 0;
188 string* user= find_ptr(
users, sctx.username());
191 return sctx.getPasswordType() == identifier::User::MYSQL_HASH
198 users.insert(users_dummy.begin(), users_dummy.end());
215 std::string newUsersFile(var->value->
str_value.data());
216 if (auth_file->setUsersFile(newUsersFile))
221 errmsg_printf(error::ERROR, _(
"auth_file file cannot be NULL"));
231 bool parseUsersFile(std::string new_users_file, users_t& users_dummy)
233 ifstream file(new_users_file.c_str());
237 string error_msg=
"Could not open users file: " + new_users_file;
238 errmsg_printf(error::ERROR,
"%s", _(error_msg.c_str()));
245 while (getline(file, line))
248 if (line.empty() || line[line.find_first_not_of(
" \t")] ==
'#')
253 size_t password_offset = line.find(
":");
254 if (password_offset == string::npos)
258 username = string(line, 0, password_offset);
259 password = string(line, password_offset + 1);
262 if (not users_dummy.insert(pair<string, string>(username, password)).second)
264 string error_msg=
"Duplicate entry found in users file: " + username;
265 errmsg_printf(error::ERROR,
"%s", _(error_msg.c_str()));
271 catch (
const std::exception &e)
274 string error_msg=
"Unable to parse users file " + new_users_file +
":" + e.what();
275 errmsg_printf(error::ERROR,
"%s", _(error_msg.c_str()));
284 auth_file=
new AuthFile(vm[
"users"].as<string>());
285 if (!auth_file->setUsersFile(auth_file->getUsersFile()))
287 errmsg_printf(error::ERROR, _(
"Could not load auth file: %s\n"), auth_file->
getError().c_str());
292 context.add(auth_file);
293 context.registerVariable(
new sys_var_std_string(
"users", auth_file->getUsersFile(), NULL, &updateUsersFile));
302 po::value<string>()->default_value(DEFAULT_USERS_FILE.string()),
303 N_(
"File to load for usernames and passwords"));
308 DRIZZLE_DECLARE_PLUGIN
314 N_(
"Authentication against a plain text file"),
318 auth_file::init_options
320 DRIZZLE_DECLARE_PLUGIN_END;
bool verifyMySQLHash(const string &password, const string &scramble_bytes, const string &scrambled_password)
A set of Session members describing the current authenticated user.
An Proxy Wrapper around boost::program_options::variables_map.
bool authenticate(const identifier::User &sctx, const string &password)
const string & getError() const