diff --git a/coreapi/authentication.c b/coreapi/authentication.c index f0f5eec2e..c2ea06037 100644 --- a/coreapi/authentication.c +++ b/coreapi/authentication.c @@ -141,13 +141,16 @@ void linphone_auth_info_destroy(LinphoneAuthInfo *obj){ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, int pos) { char key[50]; + bool_t store_ha1_passwd = lp_config_get_int(config, "sip", "store_ha1_passwd", 1); + + sprintf(key,"auth_info_%i",pos); lp_config_clean_section(config,key); if (obj==NULL || lp_config_get_int(config, "sip", "store_auth_info", 1) == 0){ return; } - if (!obj->ha1 && obj->realm && obj->passwd && (obj->username||obj->userid) && lp_config_get_int(config, "sip", "store_ha1_passwd", 1) == 1) { + if (!obj->ha1 && obj->realm && obj->passwd && (obj->username||obj->userid) && store_ha1_passwd) { /*compute ha1 to avoid storing clear text password*/ obj->ha1=ms_malloc(33); sal_auth_compute_ha1(obj->userid?obj->userid:obj->username,obj->realm,obj->passwd,obj->ha1); @@ -160,8 +163,17 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in } if (obj->ha1!=NULL){ lp_config_set_string(config,key,"ha1",obj->ha1); - } else if (obj->passwd!=NULL){ /*only write passwd if no ha1*/ - lp_config_set_string(config,key,"passwd",obj->passwd); + } + if (obj->passwd != NULL){ + if (store_ha1_passwd){ + if (obj->ha1){ + /*if we have our ha1 and store_ha1_passwd set to TRUE, then drop the clear text password for security*/ + linphone_auth_info_set_passwd(obj, NULL); + } + }else{ + /*we store clear text password only if store_ha1_passwd is FALSE*/ + lp_config_set_string(config,key,"passwd",obj->passwd); + } } if (obj->realm!=NULL){ lp_config_set_string(config,key,"realm",obj->realm); @@ -275,11 +287,26 @@ const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const cha return ai; } +/*the auth info is expected to be in the core's list*/ +void linphone_core_write_auth_info(LinphoneCore *lc, LinphoneAuthInfo *ai){ + int i; + MSList *elem = lc->auth_info; + + if (!lc->sip_conf.save_auth_info) return; + + for (i=0; elem != NULL; elem = elem->next, i++){ + if (ai == elem->data){ + linphone_auth_info_write_config(lc->config, ai, i); + } + } +} + static void write_auth_infos(LinphoneCore *lc){ MSList *elem; int i; if (!linphone_core_ready(lc)) return; + if (!lc->sip_conf.save_auth_info) return; for(elem=lc->auth_info,i=0;elem!=NULL;elem=ms_list_next(elem),i++){ LinphoneAuthInfo *ai=(LinphoneAuthInfo*)(elem->data); linphone_auth_info_write_config(lc->config,ai,i); @@ -353,7 +380,7 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info) info->domain ? info->domain : ""); } ms_list_free(l); - if(lc->sip_conf.save_auth_info) write_auth_infos(lc); + write_auth_infos(lc); } @@ -373,7 +400,7 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in if (r){ lc->auth_info=ms_list_remove(lc->auth_info,r); linphone_auth_info_destroy(r); - if(lc->sip_conf.save_auth_info) write_auth_infos(lc); + write_auth_infos(lc); } } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index a26e39403..a0c117e12 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -1177,6 +1177,11 @@ static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) { sai->userid=ms_strdup(ai->userid?ai->userid:ai->username); sai->password=ai->passwd?ms_strdup(ai->passwd):NULL; sai->ha1=ai->ha1?ms_strdup(ai->ha1):NULL; + if (sai->realm && !ai->realm){ + /*if realm was not known, then set it so that ha1 may eventually be calculated and clear text password dropped*/ + linphone_auth_info_set_realm(ai, sai->realm); + linphone_core_write_auth_info(lc, ai); + } return TRUE; } else { return FALSE; diff --git a/coreapi/private.h b/coreapi/private.h index 62741a1cb..391ab222e 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -337,6 +337,7 @@ SalStreamDir get_audio_dir_from_call_params(const LinphoneCallParams *params); SalStreamDir get_video_dir_from_call_params(const LinphoneCallParams *params); void linphone_auth_info_write_config(struct _LpConfig *config, LinphoneAuthInfo *obj, int pos); +void linphone_core_write_auth_info(LinphoneCore *lc, LinphoneAuthInfo *ai); void linphone_core_update_proxy_register(LinphoneCore *lc); void linphone_core_refresh_subscribes(LinphoneCore *lc); diff --git a/tester/register_tester.c b/tester/register_tester.c index cce4045ad..890c4088a 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -358,8 +358,8 @@ static void authenticated_register_with_no_initial_credentials(){ static void authenticated_register_with_late_credentials(){ LinphoneCoreManager *lcm; stats* counters; - LCSipTransports transport = {5070,5070,0,5071}; char route[256]; + LCSipTransports transport = {5070,5070,0,5071}; sprintf(route,"sip:%s",test_route); @@ -371,6 +371,46 @@ static void authenticated_register_with_late_credentials(){ linphone_core_manager_destroy(lcm); } +static void authenticated_register_with_provided_credentials(){ + LinphoneCoreManager *lcm; + stats* counters; + LinphoneProxyConfig *cfg; + char route[256]; + LinphoneAddress *from; + char *addr; + LinphoneAuthInfo *ai; + + sprintf(route,"sip:%s",test_route); + + lcm = linphone_core_manager_new(NULL); + + counters = get_stats(lcm->lc); + cfg = linphone_core_create_proxy_config(lcm->lc); + from = create_linphone_address(auth_domain); + + linphone_proxy_config_set_identity(cfg, addr=linphone_address_as_string(from)); + ms_free(addr); + + linphone_proxy_config_enable_register(cfg,TRUE); + linphone_proxy_config_set_expires(cfg,1); + linphone_proxy_config_set_route(cfg, test_route); + linphone_proxy_config_set_server_addr(cfg,test_route); + linphone_address_destroy(from); + + ai = linphone_auth_info_new(test_username, NULL, test_password, NULL, NULL, NULL); + linphone_core_add_auth_info(lcm->lc, ai); + + linphone_core_add_proxy_config(lcm->lc, cfg); + + BC_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,1)); + BC_ASSERT_EQUAL(counters->number_of_auth_info_requested,0, int, "%d"); + + BC_ASSERT_PTR_NULL(lp_config_get_string(lcm->lc->config, "auth_info_0", "passwd", NULL)); + BC_ASSERT_PTR_NOT_NULL(lp_config_get_string(lcm->lc->config, "auth_info_0", "ha1", NULL)); + + linphone_core_manager_destroy(lcm); +} + static void authenticated_register_with_wrong_late_credentials(){ LinphoneCoreManager *lcm; stats* counters; @@ -877,6 +917,7 @@ test_t register_tests[] = { { "Digest auth with wrong credentials without 403", authenticated_register_with_wrong_credentials_without_403}, { "Authenticated register with wrong late credentials", authenticated_register_with_wrong_late_credentials}, { "Authenticated register with late credentials", authenticated_register_with_late_credentials }, + { "Authenticated register with provided credentials", authenticated_register_with_provided_credentials }, { "Register with refresh", simple_register_with_refresh }, { "Authenticated register with refresh", simple_auth_register_with_refresh }, { "Register with refresh and send error", register_with_refresh_with_send_error },