Commit 36bf7431 authored by Danmei Chen's avatar Danmei Chen

add parse password in sync(), change command from bool to list string for...

add parse password in sync(), change command from bool to list string for different algorithms, change fonctions of  authdb.hh for using new struct of password
parent 7c04c5bd
......@@ -22,17 +22,45 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
using namespace std;
void FileAuthDb::parsePasswd(string* pass, string user, string domain, passwd_algo_t* password){
// parse password and calcul passmd5, passsha256 if there is clrtxt pass.
int i;
for(i=0;i<3;i++){
if(pass[i].substr(0,7)=="clrtxt:"){
password->pass = pass[i].substr(7);
}
}
if(password->pass!=""){
string input;
input = user+":"+domain+":"+password->pass;
password->passmd5=syncMd5(input.c_str(), 16);
password->passsha256=syncSha256(input.c_str(), 32);
return;
}
for(i=0;i<3;i++){
if(pass[i].substr(0,4)=="md5:"){
password->passmd5 = pass[i].substr(4);
}
if(pass[i].substr(0,7)=="sha256:"){
password->passsha256 = pass[i].substr(7);
}
}
}
FileAuthDb::FileAuthDb() {
GenericStruct *cr = GenericManager::get()->getRoot();
GenericStruct *ma = cr->get<GenericStruct>("module::Authentication");
mLastSync = 0;
mFileString = ma->get<ConfigString>("datasource")->read();
sync();
sync();
}
void FileAuthDb::getUserWithPhoneFromBackend(const std::string &phone, const std::string &domain, AuthDbListener *listener) {
......@@ -58,7 +86,7 @@ void FileAuthDb::getPasswordFromBackend(const std::string &id, const std::string
string key(createPasswordKey(id, authid));
std::string passwd;
passwd_algo_t passwd;
if (getCachedPassword(key, domain, passwd) == VALID_PASS_FOUND) {
res = AuthDbResult::PASSWORD_FOUND;
}
......@@ -66,70 +94,77 @@ void FileAuthDb::getPasswordFromBackend(const std::string &id, const std::string
}
void FileAuthDb::sync() {
LOGD("Syncing password file");
GenericStruct *cr = GenericManager::get()->getRoot();
GenericStruct *ma = cr->get<GenericStruct>("module::Authentication");
list<string> domains = ma->get<ConfigStringList>("auth-domains")->read();
mLastSync = getCurrentTime();
ifstream file;
stringstream ss;
ss.exceptions(ifstream::failbit | ifstream::badbit);
string line;
string user;
string domain;
string password;
string userid;
string phone;
LOGD("Opening file %s", mFileString.c_str());
file.open(mFileString);
if (file.is_open()) {
while (file.good() && getline(file, line)) {
if (line.empty()) continue;
ss.clear();
ss.str(line);
user.clear();
domain.clear();
password.clear();
userid.clear();
phone.clear();
try {
getline(ss, user, '@');
getline(ss, domain, ' ');
getline(ss, password, ' ');
if (!ss.eof()) {
getline(ss, userid, ' ');
if (!ss.eof()) {
getline(ss, phone);
} else {
phone = "";
}
} else {
userid = user;
phone = "";
}
cacheUserWithPhone(phone, domain, user);
if (find(domains.begin(), domains.end(), domain) != domains.end()) {
string key(createPasswordKey(user, userid));
cachePassword(key, domain, password, mCacheExpire);
} else if (find(domains.begin(), domains.end(), "*") != domains.end()) {
string key(createPasswordKey(user, userid));
cachePassword(key, domain, password, mCacheExpire);
} else {
LOGW("Not handled domain: %s", domain.c_str());
}
} catch (const stringstream::failure &e) {
LOGW("Incorrect line format: %s (error: %s)", line.c_str(), e.what());
}
}
} else {
LOGE("Can't open file %s", mFileString.c_str());
}
LOGD("Syncing done");
LOGD("Syncing password file");
GenericStruct *cr = GenericManager::get()->getRoot();
GenericStruct *ma = cr->get<GenericStruct>("module::Authentication");
list<string> domains = ma->get<ConfigStringList>("auth-domains")->read();
mLastSync = getCurrentTime();
ifstream file;
stringstream ss;
ss.exceptions(ifstream::failbit | ifstream::badbit);
string line;
string user;
string domain;
passwd_algo_t password;
string userid;
string phone;
string pass[3];
LOGD("Opening file %s", mFileString.c_str());
file.open(mFileString);
if (file.is_open()) {
while (file.good() && getline(file, line)) {
if (line.empty()) continue;
ss.clear();
ss.str(line);
user.clear();
domain.clear();
pass[0].clear();
pass[1].clear();
pass[2].clear();
userid.clear();
phone.clear();
try {
getline(ss, user, '@');
getline(ss, domain, ' ');
getline(ss, pass[0], ' ');
getline(ss, pass[1], ' ');
getline(ss, pass[2], ' ');
if (!ss.eof()) {
getline(ss, userid, ' ');
if (!ss.eof()) {
getline(ss, phone);
} else {
phone = "";
}
} else {
userid = user;
phone = "";
}
cacheUserWithPhone(phone, domain, user);
parsePasswd(pass,user,domain,&password);
if (find(domains.begin(), domains.end(), domain) != domains.end()) {
string key(createPasswordKey(user, userid));
cachePassword(key, domain, password, mCacheExpire);
} else if (find(domains.begin(), domains.end(), "*") != domains.end()) {
string key(createPasswordKey(user, userid));
cachePassword(key, domain, password, mCacheExpire);
} else {
LOGW("Not handled domain: %s", domain.c_str());
}
} catch (const stringstream::failure &e) {
LOGW("Incorrect line format: %s (error: %s)", line.c_str(), e.what());
}
}
} else {
LOGE("Can't open file %s", mFileString.c_str());
}
LOGD("Syncing done");
}
......@@ -17,6 +17,7 @@
*/
#include "authdb.hh"
#include "bctoolbox/crypto.h"
using namespace std;
......@@ -94,41 +95,43 @@ string AuthDbBackend::createPasswordKey(const string &user, const string &auth_u
return key.str();
}
AuthDbBackend::CacheResult AuthDbBackend::getCachedPassword(const string &key, const string &domain, string &pass) {
time_t now = getCurrentTime();
auto &passwords = mCachedPasswords[domain];
unique_lock<mutex> lck(mCachedPasswordMutex);
auto it = passwords.find(key);
if (it != passwords.end()) {
pass.assign(it->second.pass);
if (now < it->second.expire_date) {
return VALID_PASS_FOUND;
} else {
passwords.erase(it);
return EXPIRED_PASS_FOUND;
}
}
return NO_PASS_FOUND;
AuthDbBackend::CacheResult AuthDbBackend::getCachedPassword(const string &key, const string &domain, passwd_algo_t &pass) {
time_t now = getCurrentTime();
auto &passwords = mCachedPasswords[domain];
unique_lock<mutex> lck(mCachedPasswordMutex);
auto it = passwords.find(key);
if (it != passwords.end()) {
pass.pass.assign(it->second.pass.pass);
pass.passmd5.assign(it->second.pass.passmd5);
pass.passsha256.assign(it->second.pass.passsha256);
if (now < it->second.expire_date) {
return VALID_PASS_FOUND;
} else {
passwords.erase(it);
return EXPIRED_PASS_FOUND;
}
}
return NO_PASS_FOUND;
}
void AuthDbBackend::clearCache() {
mCachedPasswords.clear();
}
bool AuthDbBackend::cachePassword(const string &key, const string &domain, const string &pass, int expires) {
time_t now = getCurrentTime();
map<string, CachedPassword> &passwords = mCachedPasswords[domain];
unique_lock<mutex> lck(mCachedPasswordMutex);
map<string, CachedPassword>::iterator it = passwords.find(key);
if (expires == -1)
expires = mCacheExpire;
if (it != passwords.end()) {
it->second.pass = pass;
it->second.expire_date = now + expires;
} else {
passwords.insert(make_pair(key, CachedPassword(pass, now + expires)));
}
return true;
bool AuthDbBackend::cachePassword(const string &key, const string &domain, const passwd_algo_t &pass, int expires) {
time_t now = getCurrentTime();
map<string, CachedPassword> &passwords = mCachedPasswords[domain];
unique_lock<mutex> lck(mCachedPasswordMutex);
map<string, CachedPassword>::iterator it = passwords.find(key);
if (expires == -1)
expires = mCacheExpire;
if (it != passwords.end()) {
it->second.pass = pass;
it->second.expire_date = now + expires;
} else {
passwords.insert(make_pair(key, CachedPassword(pass, now + expires)));
}
return true;
}
bool AuthDbBackend::cacheUserWithPhone(const std::string &phone, const std::string &domain, const std::string &user) {
......@@ -146,39 +149,70 @@ bool AuthDbBackend::cacheUserWithPhone(const std::string &phone, const std::stri
}
void AuthDbBackend::getPassword(const std::string &user, const std::string &host, const std::string &auth_username,
AuthDbListener *listener) {
// Check for usable cached password
string key(createPasswordKey(user, auth_username));
string pass;
switch (getCachedPassword(key, host, pass)) {
case VALID_PASS_FOUND:
if (listener) listener->onResult(AuthDbResult::PASSWORD_FOUND, pass);
return;
case EXPIRED_PASS_FOUND:
// Might check here if connection is failing
// If it is the case use fallback password and
// return AuthDbResult::PASSWORD_FOUND;
break;
case NO_PASS_FOUND:
break;
}
AuthDbListener *listener) {
// Check for usable cached password
string key(createPasswordKey(user, auth_username));
passwd_algo_t pass;
switch (getCachedPassword(key, host, pass)) {
case VALID_PASS_FOUND:
if (listener) listener->onResult(AuthDbResult::PASSWORD_FOUND, pass);
return;
case EXPIRED_PASS_FOUND:
// Might check here if connection is failing
// If it is the case use fallback password and
// return AuthDbResult::PASSWORD_FOUND;
break;
case NO_PASS_FOUND:
break;
}
// if we reach here, password wasn't cached: we have to grab the password from the actual backend
getPasswordFromBackend(user, host, auth_username, listener);
}
// if we reach here, password wasn't cached: we have to grab the password from the actual backend
getPasswordFromBackend(user, host, auth_username, listener);
void AuthDbBackend::createCachedAccount(const std::string &user, const std::string &host, const std::string &auth_username, const passwd_algo_t &password,
int expires, const std::string & phone_alias) {
if (!user.empty() && !host.empty()) {
string key = createPasswordKey(user, auth_username);
cachePassword(key, host, password, expires);
cacheUserWithPhone(phone_alias, host, user);
}
}
void AuthDbBackend::createCachedAccount(const std::string &user, const std::string &host, const std::string &auth_username, const std::string &password,
int expires, const std::string & phone_alias) {
if (!user.empty() && !host.empty()) {
string key = createPasswordKey(user, auth_username);
cachePassword(key, host, password, expires);
cacheUserWithPhone(phone_alias, host, user);
}
string AuthDbBackend::syncSha256(const char* input,size_t size){
uint8_t a1buf[size];
int di;
char out[size*2+1];
bctbx_sha256((const unsigned char*)input, strlen(input),size, a1buf);
for (di = 0; di < size; ++di)
sprintf(out + di * 2, "%02x", a1buf[di]);
out[size*2]='\0';
return out;
}
string AuthDbBackend::syncMd5(const char* input,size_t size){
uint8_t a1buf[size];
int di;
char out[size*2+1];
bctbx_md5((const unsigned char*)input, strlen(input), a1buf);
for (di = 0; di < size; ++di)
sprintf(out + di * 2, "%02x", a1buf[di]);
out[size*2]='\0';
return out;
}
void AuthDbBackend::createAccount(const std::string & user, const std::string & host, const std::string &auth_username, const std::string &password,
int expires, const std::string & phone_alias) {
createCachedAccount(user, host, auth_username, password, expires, phone_alias);
// Password here is in mod clrtxt. Calcul passmd5 and passsha256 before createCachedAccount.
passwd_algo_t pass;
pass.pass = password;
if(pass.pass!=""){
string input;
input = user+":"+host+":"+pass.pass;
pass.passmd5=syncMd5(input.c_str(), 16);
pass.passsha256=syncSha256(input.c_str(), 32);
}
createCachedAccount(user, host, auth_username, pass, expires, phone_alias);
}
AuthDbBackend::CacheResult AuthDbBackend::getCachedUserWithPhone(const string &phone, const string &domain, string &user) {
......
......@@ -42,25 +42,32 @@
enum AuthDbResult { PENDING, PASSWORD_FOUND, PASSWORD_NOT_FOUND, AUTH_ERROR };
struct passwd_algo_t {
std::string pass;
std::string passmd5;
std::string passsha256;
};
// Fw declaration
struct AuthDbTimings;
class AuthDbListener : public StatFinishListener {
public:
virtual void onResult(AuthDbResult result, const std::string &passwd) = 0;
virtual void onResult(AuthDbResult result, const passwd_algo_t &passwd)=0;
virtual void onResults(std::list<std::string> &phones, std::set<std::string> &users);
virtual ~AuthDbListener();
};
class AuthDbBackend {
static AuthDbBackend *sUnique;
struct CachedPassword {
std::string pass;
time_t expire_date;
CachedPassword(const std::string &ipass, time_t idate) : pass(ipass), expire_date(idate) {
}
};
struct CachedPassword {
passwd_algo_t pass;
time_t expire_date;
CachedPassword(const passwd_algo_t &ipass, time_t idate) : pass(ipass), expire_date(idate) {
}
};
private:
std::map<std::string, std::map<std::string, CachedPassword>> mCachedPasswords;
......@@ -72,11 +79,11 @@ class AuthDbBackend {
AuthDbBackend();
enum CacheResult { VALID_PASS_FOUND, EXPIRED_PASS_FOUND, NO_PASS_FOUND };
std::string createPasswordKey(const std::string &user, const std::string &auth);
bool cachePassword(const std::string &key, const std::string &domain, const std::string &pass, int expires);
bool cachePassword(const std::string &key, const std::string &domain, const passwd_algo_t &pass, int expires);
bool cacheUserWithPhone(const std::string &phone, const std::string &domain, const std::string &user);
CacheResult getCachedPassword(const std::string &key, const std::string &domain, std::string &pass);
CacheResult getCachedPassword(const std::string &key, const std::string &domain, passwd_algo_t &pass);
CacheResult getCachedUserWithPhone(const std::string &phone, const std::string &domain, std::string &user);
void createCachedAccount(const std::string & user, const std::string & domain, const std::string &auth_username, const std::string &password, int expires, const std::string & phone_alias = "");
void createCachedAccount(const std::string & user, const std::string & domain, const std::string &auth_username, const passwd_algo_t &password, int expires, const std::string & phone_alias = "");
void clearCache();
int mCacheExpire;
public:
......@@ -96,6 +103,8 @@ class AuthDbBackend {
static AuthDbBackend *get();
/* called by module_auth so that backends can declare their configuration to the ConfigurationManager */
static void declareConfig(GenericStruct *mc);
static std::string syncSha256(const char* input,size_t size);
static std::string syncMd5(const char* input,size_t size);
};
......@@ -103,6 +112,7 @@ class FileAuthDb : public AuthDbBackend {
private:
std::string mFileString;
time_t mLastSync;
void parsePasswd(std::string* pass, std::string user, std::string domain, passwd_algo_t* password);
protected:
void sync();
......@@ -113,7 +123,7 @@ class FileAuthDb : public AuthDbBackend {
virtual void getPasswordFromBackend(const std::string &id, const std::string &domain,
const std::string &authid, AuthDbListener *listener);
static void declareConfig(GenericStruct *mc){};
static void declareConfig(GenericStruct *mc){};
};
#if ENABLE_ODBC
......
This diff is collapsed.
......@@ -123,6 +123,15 @@ class GatewayRegister {
}
delete this;
}
virtual void onResult(AuthDbResult result, const passwd_algo_t &passwd) {
if (result == AuthDbResult::PASSWORD_FOUND) {
checkPassword(passwd.pass.c_str()); /* TODO */
} else {
LOGE("GatewayRegister onResult(): Can't find user password, give up.");
}
delete this;
}
};
// Listener class NEED to copy the shared pointer
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment