Commit a0d5561b authored by DanmeiChen's avatar DanmeiChen

add new table and new request in SociAuthDb for supporting SHA-256

parent a8dd4686
......@@ -20,7 +20,7 @@
#
############################################################################
set(FLEXISIP_LIBS ${ORTP_LIBRARIES} ${SOFIASIPUA_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES})
set(FLEXISIP_LIBS ${ORTP_LIBRARIES} ${SOFIASIPUA_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES} ${SOCI_LIBRARIES} ${SOCI_mysql_PLUGIN} ${SOCI_sqlite3_PLUGIN})
set(FLEXISIP_INCLUDES )
......
......@@ -76,7 +76,7 @@ void FileAuthDb::getUserWithPhoneFromBackend(const std::string &phone, const std
}
void FileAuthDb::getPasswordFromBackend(const std::string &id, const std::string &domain,
const std::string &authid, AuthDbListener *listener) {
const std::string &authid, AuthDbListener *listener, AuthDbListener *listener_ref) {
AuthDbResult res = AuthDbResult::PASSWORD_NOT_FOUND;
time_t now = getCurrentTime();
......@@ -90,6 +90,7 @@ void FileAuthDb::getPasswordFromBackend(const std::string &id, const std::string
if (getCachedPassword(key, domain, passwd) == VALID_PASS_FOUND) {
res = AuthDbResult::PASSWORD_FOUND;
}
if(listener_ref) listener_ref->finish_verify_algos(passwd);
if (listener) listener->onResult(res, passwd);
}
......
......@@ -41,7 +41,14 @@ void SociAuthDB::declareConfig(GenericStruct *mc) {
"Named parameters are:\n -':id' : the user found in the from header,\n -':domain' : the authorization realm, "
"and\n -':authid' : the authorization username.\n"
"The use of the :id parameter is mandatory.",
"select password from accounts where id = :id and domain = :domain and authid=:authid"},
"select password from accounts where login = :id and domain = :domain"},
{String, "soci-password-algo-request",
"Soci SQL request to execute to obtain the password.\n"
"Named parameters are:\n -':id' : the user found in the from header,\n -':domain' : the authorization realm, "
"and\n -':authid' : the authorization username.\n"
"The use of the :id parameter is mandatory."
"select password,password_md5,password_sha256 from accounts_algo where id = (select id from accounts where login = :id and domain = :domain)",
""},
{String, "soci-user-with-phone-request",
"Soci SQL request to execute to obtain the username associated with a phone alias.\n"
"Named parameters are:\n -':phone' : the phone number to search for.\n"
......@@ -75,7 +82,7 @@ void SociAuthDB::declareConfig(GenericStruct *mc) {
"Please refer to the Soci documentation of your backend, for intance: "
"http://soci.sourceforge.net/doc/3.2/backends/mysql.html",
"db=mydb user=myuser password='mypass' host=myhost.com"},
{Integer, "soci-max-queue-size",
"Amount of queries that will be allowed to be queued before bailing password "
"requests.\n This value should be chosen accordingly with 'soci-poolsize', so "
......@@ -100,6 +107,8 @@ SociAuthDB::SociAuthDB() : conn_pool(NULL) {
get_user_with_phone_request = ma->get<ConfigString>("soci-user-with-phone-request")->read();
get_users_with_phones_request = ma->get<ConfigString>("soci-users-with-phones-request")->read();
unsigned int max_queue_size = (unsigned int)ma->get<ConfigInt>("soci-max-queue-size")->read();
get_password_algo_request = ma->get<ConfigString>("soci-password-algo-request")->read();
hashed_passwd = ma->get<ConfigBoolean>("hashed-passwords")->read();
conn_pool = new connection_pool(poolSize);
thread_pool = new ThreadPool(poolSize, max_queue_size);
......@@ -114,7 +123,7 @@ SociAuthDB::SociAuthDB() : conn_pool(NULL) {
SLOGE << "[SOCI] connection pool open MySQL error: " << e.err_num_ << " " << e.what() << endl;
} catch (exception const &e) {
SLOGE << "[SOCI] connection pool open error: " << e.what() << endl;
}
}
}
SociAuthDB::~SociAuthDB() {
......@@ -138,7 +147,7 @@ void SociAuthDB::reconnectSession(soci::session &session) {
#define DURATION_MS(start, stop) (unsigned long) duration_cast<milliseconds>((stop) - (start)).count()
void SociAuthDB::getPasswordWithPool(const std::string &id, const std::string &domain,
const std::string &authid, AuthDbListener *listener) {
const std::string &authid, AuthDbListener *listener, AuthDbListener *listener_ref) {
steady_clock::time_point start;
steady_clock::time_point stop;
passwd_algo_t passwd;
......@@ -157,14 +166,25 @@ void SociAuthDB::getPasswordWithPool(const std::string &id, const std::string &d
SLOGD << "[SOCI] Pool acquired in " << DURATION_MS(start, stop) << "ms";
start = stop;
*sql << get_password_request, into(passwd.pass), use(id, "id"), use(domain, "domain"), use(authid, "authid");
passwd.passmd5 = passwd.pass; // TODO
if(get_password_algo_request!=""){
*sql << get_password_algo_request, into(passwd.pass), into(passwd.passmd5),into(passwd.passsha256),use(id, "id"), use(domain, "domain");
}
else {
if(hashed_passwd){
*sql << get_password_request, into(passwd.passmd5), use(id, "id"), use(domain, "domain");
}
else {
*sql << get_password_request, into(passwd.pass), use(id, "id"), use(domain, "domain");
}
}
if(listener_ref) listener_ref->finish_verify_algos(passwd);
stop = steady_clock::now();
SLOGD << "[SOCI] Got pass for " << id << " in " << DURATION_MS(start, stop) << "ms";
cachePassword(createPasswordKey(id, authid), domain, passwd, mCacheExpire);
if (listener){
listener->onResult(passwd.pass.empty() ? PASSWORD_NOT_FOUND : PASSWORD_FOUND, passwd);
listener->onResult((passwd.pass.empty() && passwd.passmd5.empty() && passwd.passsha256.empty()) ? PASSWORD_NOT_FOUND : PASSWORD_FOUND, passwd);
}
errorCount = 0;
} catch (mysql_soci_error const &e) {
......@@ -333,10 +353,10 @@ void SociAuthDB::getUsersWithPhonesWithPool(list<tuple<std::string,std::string,A
#endif
void SociAuthDB::getPasswordFromBackend(const std::string &id, const std::string &domain,
const std::string &authid, AuthDbListener *listener) {
const std::string &authid, AuthDbListener *listener, AuthDbListener *listener_ref) {
// create a thread to grab a pool connection and use it to retrieve the auth information
auto func = bind(&SociAuthDB::getPasswordWithPool, this, id, domain, authid, listener);
auto func = bind(&SociAuthDB::getPasswordWithPool, this, id, domain, authid, listener, listener_ref);
bool success = thread_pool->Enqueue(func);
if (success == FALSE) {
......
......@@ -39,7 +39,7 @@ class FixedAuthDb : public AuthDbBackend {
if (listener) listener->onResult(PASSWORD_FOUND, "user@domain.com");
}
virtual void getPasswordFromBackend(const std::string &id, const std::string &domain,
const std::string &authid, AuthDbListener *listener) {
const std::string &authid, AuthDbListener *listener, AuthDbListener *listener_ref) {
if (listener) listener->onResult(PASSWORD_FOUND, "fixed");
}
static void declareConfig(GenericStruct *mc){};
......@@ -167,30 +167,18 @@ void AuthDbBackend::getPassword(const std::string &user, const std::string &host
}
// if we reach here, password wasn't cached: we have to grab the password from the actual backend
getPasswordFromBackend(user, host, auth_username, listener);
getPasswordFromBackend(user, host, auth_username, listener, NULL);
}
void AuthDbBackend::getPasswordForAlgo(const std::string &user, const std::string &host, const std::string &auth_username,
AuthDbListener *listener, std::list<std::string> &list_algorithm) {
AuthDbListener *listener, AuthDbListener *listener_ref) {
// 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);
else if(pass.pass==""){
for(auto algo = list_algorithm.begin(); algo != list_algorithm.end();)
{
auto algo_ref=algo++;
if((!strcmp(algo_ref->c_str(),"MD5")&&(pass.passmd5==""))||(!strcmp(algo_ref->c_str(),"SHA-256")&&(pass.passsha256=="")))
{
list_algorithm.remove(algo_ref->c_str());
if(list_algorithm.size()==0){
LOGA("There is no password for the given algorithm");
}
}
}
}
if(listener_ref) listener_ref->finish_verify_algos(pass);
return;
case EXPIRED_PASS_FOUND:
// Might check here if connection is failing
......@@ -202,7 +190,7 @@ void AuthDbBackend::getPasswordForAlgo(const std::string &user, const std::strin
}
// if we reach here, password wasn't cached: we have to grab the password from the actual backend
getPasswordFromBackend(user, host, auth_username, listener);
getPasswordFromBackend(user, host, auth_username, listener, listener_ref);
}
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) {
......@@ -235,6 +223,17 @@ string AuthDbBackend::syncMd5(const char* input,size_t size){
return out;
}
void AuthDbBackend::verifyAlgo(const passwd_algo_t &pass, std::list<std::string> &algorithms){
for(auto algo = algorithms.begin(); algo != algorithms.end();)
{
auto algo_ref=algo++;
if((!strcmp(algo_ref->c_str(),"MD5")&&(pass.passmd5==""))||(!strcmp(algo_ref->c_str(),"SHA-256")&&(pass.passsha256=="")))
{
algorithms.remove(algo_ref->c_str());
}
}
}
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) {
// Password here is in mod clrtxt. Calcul passmd5 and passsha256 before createCachedAccount.
......
......@@ -56,6 +56,7 @@ class AuthDbListener : public StatFinishListener {
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 void finish_verify_algos(const passwd_algo_t &pass)=0;
virtual ~AuthDbListener();
};
......@@ -91,7 +92,7 @@ class AuthDbBackend {
// warning: listener may be invoked on authdb backend thread, so listener must be threadsafe somehow!
void getPassword(const std::string & user, const std::string & domain, const std::string &auth_username, AuthDbListener *listener);
void getPasswordForAlgo(const std::string &user, const std::string &host, const std::string &auth_username,
AuthDbListener *listener, std::list<std::string> &list_algorithm);
AuthDbListener *listener, AuthDbListener *listener_ref);
void getUserWithPhone(const std::string &phone, const std::string &domain, AuthDbListener *listener);
void getUsersWithPhone(std::list<std::tuple<std::string,std::string,AuthDbListener *>> & creds, AuthDbListener *listener);
virtual void getUserWithPhoneFromBackend(const std::string &, const std::string &, AuthDbListener *listener) = 0;
......@@ -100,11 +101,12 @@ class AuthDbBackend {
virtual void createAccount(const std::string &user, const std::string & domain, const std::string &auth_username, const std::string &password, int expires, const std::string &phone_alias = "");
virtual void getPasswordFromBackend(const std::string &id, const std::string &domain,
const std::string &authid, AuthDbListener *listener) = 0;
const std::string &authid, AuthDbListener *listener, AuthDbListener *listener_ref) = 0;
static AuthDbBackend *get();
/* called by module_auth so that backends can declare their configuration to the ConfigurationManager */
static void declareConfig(GenericStruct *mc);
static void verifyAlgo(const passwd_algo_t &pass, std::list<std::string> &algorithms);
static std::string syncSha256(const char* input,size_t size);
static std::string syncMd5(const char* input,size_t size);
......@@ -123,7 +125,7 @@ class FileAuthDb : public AuthDbBackend {
FileAuthDb();
virtual void getUserWithPhoneFromBackend(const std::string &phone, const std::string & domain, AuthDbListener *listener);
virtual void getPasswordFromBackend(const std::string &id, const std::string &domain,
const std::string &authid, AuthDbListener *listener);
const std::string &authid, AuthDbListener *listener, AuthDbListener *listener_ref);
static void declareConfig(GenericStruct *mc){};
};
......@@ -196,7 +198,7 @@ class SociAuthDB : public AuthDbBackend {
virtual void getUserWithPhoneFromBackend(const std::string & , const std::string &, AuthDbListener *listener);
virtual void getUsersWithPhonesFromBackend(std::list<std::tuple<std::string,std::string,AuthDbListener*>> &creds, AuthDbListener *listener);
virtual void getPasswordFromBackend(const std::string &id, const std::string &domain,
const std::string &authid, AuthDbListener *listener);
const std::string &authid, AuthDbListener *listener, AuthDbListener *listener_ref);
static void declareConfig(GenericStruct *mc);
......@@ -204,9 +206,10 @@ class SociAuthDB : public AuthDbBackend {
void getUserWithPhoneWithPool(const std::string &phone, const std::string &domain, AuthDbListener *listener);
void getUsersWithPhonesWithPool(std::list<std::tuple<std::string,std::string,AuthDbListener*>> &creds, AuthDbListener *listener);
void getPasswordWithPool(const std::string &id, const std::string &domain,
const std::string &authid, AuthDbListener *listener);
const std::string &authid, AuthDbListener *listener, AuthDbListener *listener_ref);
void reconnectSession( soci::session &session );
size_t poolSize;
soci::connection_pool *conn_pool;
......@@ -216,6 +219,8 @@ class SociAuthDB : public AuthDbBackend {
std::string get_password_request;
std::string get_user_with_phone_request;
std::string get_users_with_phones_request;
std::string get_password_algo_request;
bool hashed_passwd;
};
#endif /* ENABLE_SOCI */
......
......@@ -244,6 +244,8 @@ private:
void onError();
void finish(); /*the listener is destroyed when calling this, careful*/
void finish_for_algorithm();
void finish_verify_algos(const passwd_algo_t &pass);
su_root_t *getRoot() {
return getAgent()->getRoot();
}
......@@ -493,9 +495,7 @@ public:
auto algo = mAlgorithm.begin();
algorithm.assign(algo->c_str());
}
if(mAlgorithm.size()==0){
mAlgorithm.push_back("MD5");
}
for (it = mDomains.begin(); it != mDomains.end(); ++it) {
auto domain = *it;
......@@ -870,7 +870,7 @@ public:
LOGF("Couldn't send auth async message to main thread.");
}
}
void Authentication::AuthenticationListener::finish_for_algorithm(){
if((mAlgoUsed.size()>1)&&(mAs->as_status == 401)){
msg_header_t* response;
......@@ -926,7 +926,12 @@ public:
}
delete this;
}
void Authentication::AuthenticationListener::finish_verify_algos(const passwd_algo_t &pass) {
AuthDbBackend::verifyAlgo(pass, mAlgoUsed);
finish();
}
int Authentication::AuthenticationListener::checkPasswordMd5(const char *passwd){
char const *a1;
auth_hexmd5_t a1buf, response;
......@@ -1142,9 +1147,19 @@ public:
as->as_allow = as->as_allow || auth_allow_check(am, as) == 0;
if (as->as_realm)
au = auth_digest_credentials(au, as->as_realm, am->am_opaque);
else
if (as->as_realm) {
if (au && au->au_next) {
auth_response_t r;
memset(&r, 0, sizeof(r));
r.ar_size = sizeof(r);
auth_digest_response_get(as->as_home, &r, au->au_next->au_params);
if(!strcmp(r.ar_algorithm, "MD5")) {
au->au_params = au->au_next->au_params;
}
}
au = auth_digest_credentials(au, as->as_realm, am->am_opaque);
}
else
au = NULL;
if (as->as_allow) {
......@@ -1175,9 +1190,9 @@ public:
SLOGD << "Searching for " << as->as_user_uri->url_user
<< " password to have it when the authenticated request comes";
//AuthDbBackend::get()->getPassword(as->as_user_uri->url_user, as->as_user_uri->url_host, as->as_user_uri->url_user, NULL);
AuthDbBackend::get()->getPasswordForAlgo(as->as_user_uri->url_user, as->as_user_uri->url_host, as->as_user_uri->url_user, NULL, listener->mAlgoUsed);
AuthDbBackend::get()->getPasswordForAlgo(as->as_user_uri->url_user, as->as_user_uri->url_host, as->as_user_uri->url_user, NULL, listener);
}
listener->finish();
//listener->finish();
return;
}
}
......
......@@ -125,12 +125,15 @@ class GatewayRegister {
virtual void onResult(AuthDbResult result, const passwd_algo_t &passwd) {
if (result == AuthDbResult::PASSWORD_FOUND) {
checkPassword(passwd.pass.c_str()); /* TODO */
checkPassword(passwd.pass.c_str());
} else {
LOGE("GatewayRegister onResult(): Can't find user password, give up.");
}
delete this;
}
virtual void finish_verify_algos(const passwd_algo_t &pass) {
return;
}
};
// Listener class NEED to copy the shared pointer
......
......@@ -40,6 +40,10 @@ public:
, "OnAuthListener to mainthread");
belle_sip_object_unref(timer);
}
virtual void finish_verify_algos(const passwd_algo_t &pass) {
return;
}
void onResults(list<std::string> &phones, set<std::string> &users) {
for(std::string phone : phones) {
......
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