Commit ff971c0f authored by Simon Morlat's avatar Simon Morlat
Browse files

Finally fix the double MD5/SHA-256 authentication_requested() callback problem.

parent e128a643
......@@ -368,11 +368,15 @@ static void auth_failure(SalOp *op, SalAuthInfo* info) {
LinphoneAuthMethod method = info->mode == SalAuthModeHttpDigest ? LinphoneAuthHttpDigest : LinphoneAuthTls;
LinphoneAuthInfo *auth_info = linphone_core_create_auth_info(lc, info->username, NULL, NULL, NULL, info->realm, info->domain);
ms_message("%s/%s/%s/%s authentication fails.", info->realm, info->username, info->domain, info->mode == SalAuthModeHttpDigest ? "HttpDigest" : "Tls");
/*ask again for password if auth info was already supplied but apparently not working*/
linphone_core_notify_authentication_requested(lc, auth_info, method);
if (method == LinphoneAuthHttpDigest){
/*ask again for password if auth info was already supplied but apparently not working*/
L_GET_PRIVATE_FROM_C_OBJECT(lc)->getAuthStack().pushAuthRequested(AuthInfo::toCpp(ai)->getSharedFromThis());
}else{
linphone_core_notify_authentication_requested(lc, auth_info, method);
// Deprecated
linphone_core_notify_auth_info_requested(lc, info->realm, info->username, info->domain);
}
linphone_auth_info_unref(auth_info);
// Deprecated
linphone_core_notify_auth_info_requested(lc, info->realm, info->username, info->domain);
}
}
}
......@@ -402,8 +406,11 @@ static void register_failure(SalOp *op){
if ((ei->reason == SalReasonServiceUnavailable || ei->reason == SalReasonIOError)
&& linphone_proxy_config_get_state(cfg) == LinphoneRegistrationOk) {
linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress,"Service unavailable, retrying");
} else if (ei->protocol_code == 401 || ei->protocol_code == 407){
/* Do nothing. There will be an auth_requested() callback. If the callback doesn't provide an AuthInfo, then
* the proxy config will transition to the failed state.*/
} else {
linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,details);
linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed, details);
}
if (cfg->presence_publish_event){
/*prevent publish to be sent now until registration gets successful*/
......@@ -553,15 +560,13 @@ static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) {
sai->password = linphone_auth_info_get_passwd(ai)?ms_strdup(linphone_auth_info_get_passwd(ai)) : NULL;
sai->ha1 = linphone_auth_info_get_ha1(ai) ? ms_strdup(linphone_auth_info_get_ha1(ai)) : NULL;
#if 0
AuthStack & as = L_GET_PRIVATE_FROM_C_OBJECT(lc)->getAuthStack();
if (!as.empty()){
/* We have to construct the auth info as it was originally requested in auth_requested() below,
* so that the matching is made correctly.
*/
as.authFound(AuthInfo::create(sai->username, "", "", "", sai->realm, sai->domain));
}
#endif
/* We have to construct the auth info as it was originally requested in auth_requested() below,
* so that the matching is made correctly.
*/
as.authFound(AuthInfo::create(sai->username, "", "", "", sai->realm, sai->domain));
} else if (sai->mode == SalAuthModeTls) {
if (linphone_auth_info_get_tls_cert(ai) && linphone_auth_info_get_tls_key(ai)) {
sal_certificates_chain_parse(sai, linphone_auth_info_get_tls_cert(ai), SAL_CERTIFICATE_RAW_FORMAT_PEM);
......@@ -595,13 +600,11 @@ static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) {
} else {
LinphoneAuthMethod method = sai->mode == SalAuthModeHttpDigest ? LinphoneAuthHttpDigest : LinphoneAuthTls;
LinphoneAuthInfo *ai = linphone_core_create_auth_info(lc, sai->username, NULL, NULL, NULL, sai->realm, sai->domain);
#if 0
if (method == LinphoneAuthHttpDigest){
/* Request app for new authentication information, but later. */
L_GET_PRIVATE_FROM_C_OBJECT(lc)->getAuthStack().pushAuthRequested(AuthInfo::toCpp(ai)->getSharedFromThis());
}else
#endif
{
}else{
linphone_core_notify_authentication_requested(lc, ai, method);
// Deprecated callback
linphone_core_notify_auth_info_requested(lc, sai->realm, sai->username, sai->domain);
......
......@@ -47,42 +47,61 @@ void AuthStack::pushAuthRequested(const std::shared_ptr<AuthInfo> &ai){
}
void AuthStack::authFound(const std::shared_ptr<AuthInfo> &ai){
if (mAuthBeingRequested) return;
lInfo() << "AuthStack::authFound() for " << ai->toString();
for(auto it = mAuthQueue.begin(); it != mAuthQueue.end(); ){
const shared_ptr<AuthInfo> &authInfo = (*it);
mAuthFound.push_back(ai);
}
void AuthStack::notifyAuthFailures(){
auto pendingAuths = mCore.getSal()->getPendingAuths();
for (const auto &op : pendingAuths) {
const bctbx_list_t *elem;
/*proxy case*/
for (elem = linphone_core_get_proxy_config_list(mCore.getCCore()); elem != NULL; elem = elem->next) {
LinphoneProxyConfig *pcfg = (LinphoneProxyConfig*)elem->data;
if (pcfg == op->getUserPointer()) {
const SalErrorInfo *ei=op->getErrorInfo();
const char *details=ei->full_string;
linphone_proxy_config_set_state(pcfg, LinphoneRegistrationFailed, details);
break;
}
}
}
}
bool AuthStack::wasFound(const std::shared_ptr<AuthInfo>& authInfo){
for (auto &ai : mAuthFound){
if (authInfo->getRealm() == ai->getRealm() &&
authInfo->getUsername() == ai->getUsername() &&
authInfo->getDomain() == ai->getDomain()){
lInfo() << "Authentication request removed.";
it = mAuthQueue.erase(it);
}else ++it;
}
if (mAuthQueue.empty()){
lInfo() << "No need to request authentication information from application.";
if (mTimer){
mCore.getSal()->cancelTimer(mTimer);
belle_sip_object_unref(mTimer);
mTimer = nullptr;
lInfo() << "Authentication request not needed.";
return true;
}
}
return false;
}
void AuthStack::processAuthRequested(){
/* The auth_info_requested() callback may cause the application to directly call linphone_core_add_auth_info(), which
* will re-invoke the auth_requsted callback of the SAL, which may call authFound() here.
* The mAuthBeingRequested flag is to inhinit this behavior.
*/
mAuthBeingRequested = true;
for(const auto &authInfo : mAuthQueue){
linphone_core_notify_authentication_requested(mCore.getCCore(), authInfo->toC(), LinphoneAuthHttpDigest);
// Deprecated callback:
linphone_core_notify_auth_info_requested(mCore.getCCore(), authInfo->getRealm().c_str(), authInfo->getUsername().c_str(), authInfo->getDomain().c_str());
if (!wasFound(authInfo)){
linphone_core_notify_authentication_requested(mCore.getCCore(), authInfo->toC(), LinphoneAuthHttpDigest);
// Deprecated callback:
linphone_core_notify_auth_info_requested(mCore.getCCore(), authInfo->getRealm().c_str(), authInfo->getUsername().c_str(), authInfo->getDomain().c_str());
}
}
notifyAuthFailures();
mAuthQueue.clear();
belle_sip_object_unref(mTimer);
mTimer = nullptr;
mAuthFound.clear();
if (mTimer){
mCore.getSal()->cancelTimer(mTimer);
belle_sip_object_unref(mTimer);
mTimer = nullptr;
}
mAuthBeingRequested = false;
}
......
......@@ -50,10 +50,13 @@ public:
}
~AuthStack();
private:
void notifyAuthFailures();
void processAuthRequested();
bool wasFound(const std::shared_ptr<AuthInfo>& ai);
CorePrivate &mCore;
belle_sip_source_t *mTimer = nullptr;
std::list<std::shared_ptr<AuthInfo>> mAuthQueue;
std::list<std::shared_ptr<AuthInfo>> mAuthFound;
bool mAuthBeingRequested = false;
static int onTimeout(void *data, unsigned int events);
};
......
......@@ -34,8 +34,10 @@ public:
}
int unregister() { return refreshRegister(0); }
void authenticate (const SalAuthInfo *info) override {
refreshRegister(-1); }
void authenticate (const SalAuthInfo *info) override {
mRoot->removePendingAuth(this);
refreshRegister(-1);
}
private:
void fillCallbacks () override {};
......
......@@ -755,6 +755,7 @@ void Sal::addPendingAuth (SalOp *op) {
if (it == mPendingAuths.cend()) {
mPendingAuths.push_back(op);
op->mHasAuthPending = true;
lInfo() << "Op " << op << " added as pending authentication";
}
}
......@@ -762,6 +763,7 @@ void Sal::removePendingAuth (SalOp *op) {
if (op->mHasAuthPending) {
op->mHasAuthPending = false;
mPendingAuths.remove(op);
lInfo() << "Op " << op << " removed as pending authentication";
}
}
......
......@@ -341,6 +341,7 @@ static void simple_authenticated_register_for_algorithm(void){
linphone_auth_info_unref(info);
counters = &lcm->stat;
register_with_refresh_for_algo(lcm,FALSE,auth_domain,route,test_sha_username);
/* Because Flexisip asks a MD5 and SHA256 challenge, and the AuthInfo is only for SHA256, we will get one auth_info_requested per REGISTER message.*/
BC_ASSERT_EQUAL(counters->number_of_auth_info_requested,0, int, "%d");
linphone_core_manager_destroy(lcm);
}
......
......@@ -113,7 +113,7 @@ LinphoneAddress * create_linphone_address_for_algo(const char * domain, const ch
static void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) {
stats* counters;
ms_message("Auth info requested for user id [%s] at realm [%s]\n", username, realm);
ms_message("Auth info requested (deprecated callback) for user id [%s] at realm [%s]\n", username, realm);
counters = get_stats(lc);
counters->number_of_auth_info_requested++;
}
......
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