1 /***************************************************************************
2  *            authentication.c
3  *
4  *  Fri Jul 16 12:08:34 2004
5  *  Copyright  2004-2009  Simon MORLAT
6  *  simon.morlat@linphone.org
7  ****************************************************************************/
8 
9 /*
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU Library General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  */
24 
25 #include "linphone/core.h"
26 #include "private.h"
27 #include "linphone/lpconfig.h"
28 
29 static void _linphone_auth_info_uninit(LinphoneAuthInfo *obj);
30 static void _linphone_auth_info_copy(LinphoneAuthInfo *dst, const LinphoneAuthInfo *src);
31 
32 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAuthInfo);
33 BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAuthInfo);
34 BELLE_SIP_INSTANCIATE_VPTR(
35 	LinphoneAuthInfo,
36 	belle_sip_object_t,
37 	_linphone_auth_info_uninit, // destroy
38 	_linphone_auth_info_copy, // clone
39 	NULL, // marshal
40 	FALSE
41 );
42 
linphone_auth_info_new(const char * username,const char * userid,const char * passwd,const char * ha1,const char * realm,const char * domain)43 LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain){
44 	LinphoneAuthInfo *obj=belle_sip_object_new(LinphoneAuthInfo);
45 	if (username!=NULL && (strlen(username)>0) ) obj->username=ms_strdup(username);
46 	if (userid!=NULL && (strlen(userid)>0)) obj->userid=ms_strdup(userid);
47 	if (passwd!=NULL && (strlen(passwd)>0)) obj->passwd=ms_strdup(passwd);
48 	if (ha1!=NULL && (strlen(ha1)>0)) obj->ha1=ms_strdup(ha1);
49 	if (realm!=NULL && (strlen(realm)>0)) obj->realm=ms_strdup(realm);
50 	if (domain!=NULL && (strlen(domain)>0)) obj->domain=ms_strdup(domain);
51 	return obj;
52 }
53 
_linphone_auth_info_copy(LinphoneAuthInfo * dst,const LinphoneAuthInfo * src)54 static void _linphone_auth_info_copy(LinphoneAuthInfo *dst, const LinphoneAuthInfo *src) {
55 	if (src->username)      dst->username = ms_strdup(src->username);
56 	if (src->userid)        dst->userid = ms_strdup(src->userid);
57 	if (src->passwd)        dst->passwd = ms_strdup(src->passwd);
58 	if (src->ha1)           dst->ha1 = ms_strdup(src->ha1);
59 	if (src->realm)         dst->realm = ms_strdup(src->realm);
60 	if (src->domain)        dst->domain = ms_strdup(src->domain);
61 	if (src->tls_cert)      dst->tls_cert = ms_strdup(src->tls_cert);
62 	if (src->tls_key)       dst->tls_key = ms_strdup(src->tls_key);
63 	if (src->tls_cert_path) dst->tls_cert_path = ms_strdup(src->tls_cert_path);
64 	if (src->tls_key_path)  dst->tls_key_path = ms_strdup(src->tls_key_path);
65 }
66 
linphone_auth_info_clone(const LinphoneAuthInfo * ai)67 LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo *ai){
68 	return LINPHONE_AUTH_INFO(belle_sip_object_clone(BELLE_SIP_OBJECT(ai)));
69 }
70 
linphone_auth_info_ref(LinphoneAuthInfo * obj)71 LinphoneAuthInfo *linphone_auth_info_ref(LinphoneAuthInfo *obj) {
72 	return LINPHONE_AUTH_INFO(belle_sip_object_ref(obj));
73 }
74 
linphone_auth_info_unref(LinphoneAuthInfo * obj)75 void linphone_auth_info_unref(LinphoneAuthInfo *obj) {
76 	belle_sip_object_unref(obj);
77 }
78 
linphone_auth_info_get_username(const LinphoneAuthInfo * i)79 const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i) {
80 	return i->username;
81 }
82 
linphone_auth_info_get_passwd(const LinphoneAuthInfo * i)83 const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i) {
84 	return i->passwd;
85 }
86 
linphone_auth_info_get_userid(const LinphoneAuthInfo * i)87 const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *i) {
88 	return i->userid;
89 }
90 
linphone_auth_info_get_realm(const LinphoneAuthInfo * i)91 const char *linphone_auth_info_get_realm(const LinphoneAuthInfo *i) {
92 	return i->realm;
93 }
94 
linphone_auth_info_get_domain(const LinphoneAuthInfo * i)95 const char *linphone_auth_info_get_domain(const LinphoneAuthInfo *i) {
96 	return i->domain;
97 }
98 
linphone_auth_info_get_ha1(const LinphoneAuthInfo * i)99 const char *linphone_auth_info_get_ha1(const LinphoneAuthInfo *i) {
100 	return i->ha1;
101 }
102 
linphone_auth_info_get_tls_cert(const LinphoneAuthInfo * i)103 const char *linphone_auth_info_get_tls_cert(const LinphoneAuthInfo *i) {
104 	return i->tls_cert;
105 }
106 
linphone_auth_info_get_tls_key(const LinphoneAuthInfo * i)107 const char *linphone_auth_info_get_tls_key(const LinphoneAuthInfo *i) {
108 	return i->tls_key;
109 }
110 
linphone_auth_info_get_tls_cert_path(const LinphoneAuthInfo * i)111 const char *linphone_auth_info_get_tls_cert_path(const LinphoneAuthInfo *i) {
112 	return i->tls_cert_path;
113 }
114 
linphone_auth_info_get_tls_key_path(const LinphoneAuthInfo * i)115 const char *linphone_auth_info_get_tls_key_path(const LinphoneAuthInfo *i) {
116 	return i->tls_key_path;
117 }
118 
119 
linphone_auth_info_set_passwd(LinphoneAuthInfo * info,const char * passwd)120 void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd) {
121 	if (info->passwd) {
122 		ms_free(info->passwd);
123 		info->passwd = NULL;
124 	}
125 	if (passwd && strlen(passwd) > 0) info->passwd = ms_strdup(passwd);
126 }
127 
linphone_auth_info_set_username(LinphoneAuthInfo * info,const char * username)128 void linphone_auth_info_set_username(LinphoneAuthInfo *info, const char *username) {
129 	if (info->username) {
130 		ms_free(info->username);
131 		info->username = NULL;
132 	}
133 	if (username && strlen(username) > 0) info->username = ms_strdup(username);
134 }
135 
linphone_auth_info_set_userid(LinphoneAuthInfo * info,const char * userid)136 void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid) {
137 	if (info->userid) {
138 		ms_free(info->userid);
139 		info->userid = NULL;
140 	}
141 	if (userid && strlen(userid) > 0) info->userid = ms_strdup(userid);
142 }
143 
linphone_auth_info_set_realm(LinphoneAuthInfo * info,const char * realm)144 void linphone_auth_info_set_realm(LinphoneAuthInfo *info, const char *realm) {
145 	if (info->realm) {
146 		ms_free(info->realm);
147 		info->realm = NULL;
148 	}
149 	if (realm && strlen(realm) > 0) info->realm = ms_strdup(realm);
150 }
151 
linphone_auth_info_set_domain(LinphoneAuthInfo * info,const char * domain)152 void linphone_auth_info_set_domain(LinphoneAuthInfo *info, const char *domain) {
153 	if (info->domain) {
154 		ms_free(info->domain);
155 		info->domain = NULL;
156 	}
157 	if (domain && strlen(domain) > 0) info->domain = ms_strdup(domain);
158 }
159 
linphone_auth_info_set_ha1(LinphoneAuthInfo * info,const char * ha1)160 void linphone_auth_info_set_ha1(LinphoneAuthInfo *info, const char *ha1) {
161 	if (info->ha1) {
162 		ms_free(info->ha1);
163 		info->ha1 = NULL;
164 	}
165 	if (ha1 && strlen(ha1) > 0) info->ha1 = ms_strdup(ha1);
166 }
167 
linphone_auth_info_set_tls_cert(LinphoneAuthInfo * info,const char * tls_cert)168 void linphone_auth_info_set_tls_cert(LinphoneAuthInfo *info, const char *tls_cert) {
169 	if (info->tls_cert) {
170 		ms_free(info->tls_cert);
171 		info->tls_cert = NULL;
172 	}
173 	if (tls_cert && strlen(tls_cert) > 0) info->tls_cert = ms_strdup(tls_cert);
174 }
175 
linphone_auth_info_set_tls_key(LinphoneAuthInfo * info,const char * tls_key)176 void linphone_auth_info_set_tls_key(LinphoneAuthInfo *info, const char *tls_key) {
177 	if (info->tls_key) {
178 		ms_free(info->tls_key);
179 		info->tls_key = NULL;
180 	}
181 	if (tls_key && strlen(tls_key) > 0) info->tls_key = ms_strdup(tls_key);
182 }
183 
linphone_auth_info_set_tls_cert_path(LinphoneAuthInfo * info,const char * tls_cert_path)184 void linphone_auth_info_set_tls_cert_path(LinphoneAuthInfo *info, const char *tls_cert_path) {
185 	if (info->tls_cert_path) {
186 		ms_free(info->tls_cert_path);
187 		info->tls_cert_path = NULL;
188 	}
189 	if (tls_cert_path && strlen(tls_cert_path) > 0) info->tls_cert_path = ms_strdup(tls_cert_path);
190 }
191 
linphone_auth_info_set_tls_key_path(LinphoneAuthInfo * info,const char * tls_key_path)192 void linphone_auth_info_set_tls_key_path(LinphoneAuthInfo *info, const char *tls_key_path) {
193 	if (info->tls_key_path) {
194 		ms_free(info->tls_key_path);
195 		info->tls_key_path = NULL;
196 	}
197 	if (tls_key_path && strlen(tls_key_path) > 0) info->tls_key_path = ms_strdup(tls_key_path);
198 }
199 
_linphone_auth_info_uninit(LinphoneAuthInfo * obj)200 static void _linphone_auth_info_uninit(LinphoneAuthInfo *obj) {
201 	if (obj->username != NULL) ms_free(obj->username);
202 	if (obj->userid != NULL) ms_free(obj->userid);
203 	if (obj->passwd != NULL) ms_free(obj->passwd);
204 	if (obj->ha1 != NULL) ms_free(obj->ha1);
205 	if (obj->realm != NULL) ms_free(obj->realm);
206 	if (obj->domain != NULL) ms_free(obj->domain);
207 	if (obj->tls_cert != NULL) ms_free(obj->tls_cert);
208 	if (obj->tls_key != NULL) ms_free(obj->tls_key);
209 	if (obj->tls_cert_path != NULL) ms_free(obj->tls_cert_path);
210 	if (obj->tls_key_path != NULL) ms_free(obj->tls_key_path);
211 }
212 
213 /**
214  * Destroys a LinphoneAuthInfo object.
215 **/
linphone_auth_info_destroy(LinphoneAuthInfo * obj)216 void linphone_auth_info_destroy(LinphoneAuthInfo *obj){
217 	belle_sip_object_unref(obj);
218 }
219 
linphone_auth_info_write_config(LpConfig * config,LinphoneAuthInfo * obj,int pos)220 void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, int pos) {
221 	char key[50];
222 	bool_t store_ha1_passwd = lp_config_get_int(config, "sip", "store_ha1_passwd", 1);
223 
224 	sprintf(key, "auth_info_%i", pos);
225 	lp_config_clean_section(config, key);
226 
227 	if (obj == NULL || lp_config_get_int(config, "sip", "store_auth_info", 1) == 0) {
228 		return;
229 	}
230 	if (!obj->ha1 && obj->realm && obj->passwd && (obj->username || obj->userid) && store_ha1_passwd) {
231 		/*compute ha1 to avoid storing clear text password*/
232 		obj->ha1 = ms_malloc(33);
233 		sal_auth_compute_ha1(obj->userid ? obj->userid : obj->username, obj->realm, obj->passwd, obj->ha1);
234 	}
235 	if (obj->username != NULL) {
236 		lp_config_set_string(config, key, "username", obj->username);
237 	}
238 	if (obj->userid != NULL) {
239 		lp_config_set_string(config, key, "userid", obj->userid);
240 	}
241 	if (obj->ha1 != NULL) {
242 		lp_config_set_string(config, key, "ha1", obj->ha1);
243 	}
244 	if (obj->passwd != NULL) {
245 		if (store_ha1_passwd && obj->ha1) {
246 			/*if we have our ha1 and store_ha1_passwd set to TRUE, then drop the clear text password for security*/
247 			linphone_auth_info_set_passwd(obj, NULL);
248 		} else {
249 			/*we store clear text password only if store_ha1_passwd is FALSE AND we have an ha1 to store. Otherwise, passwd would simply be removed, which might bring major auth issue*/
250 			lp_config_set_string(config, key, "passwd", obj->passwd);
251 		}
252 	}
253 	if (obj->realm != NULL) {
254 		lp_config_set_string(config, key, "realm", obj->realm);
255 	}
256 	if (obj->domain != NULL) {
257 		lp_config_set_string(config, key, "domain", obj->domain);
258 	}
259 	if (obj->tls_cert_path != NULL) {
260 		lp_config_set_string(config, key, "client_cert_chain", obj->tls_cert_path);
261 	}
262 	if (obj->tls_key_path != NULL) {
263 		lp_config_set_string(config, key, "client_cert_key", obj->tls_key_path);
264 	}
265 }
266 
linphone_auth_info_new_from_config_file(LpConfig * config,int pos)267 LinphoneAuthInfo *linphone_auth_info_new_from_config_file(LpConfig * config, int pos)
268 {
269 	char key[50];
270 	const char *username,*userid,*passwd,*ha1,*realm,*domain,*tls_cert_path,*tls_key_path;
271 	LinphoneAuthInfo *ret;
272 
273 	sprintf(key, "auth_info_%i", pos);
274 	if (!lp_config_has_section(config, key)) {
275 		return NULL;
276 	}
277 
278 	username = lp_config_get_string(config, key, "username", NULL);
279 	userid = lp_config_get_string(config, key, "userid", NULL);
280 	passwd = lp_config_get_string(config, key, "passwd", NULL);
281 	ha1 = lp_config_get_string(config, key, "ha1", NULL);
282 	realm = lp_config_get_string(config, key, "realm", NULL);
283 	domain = lp_config_get_string(config, key, "domain", NULL);
284 	tls_cert_path = lp_config_get_string(config, key, "client_cert_chain", NULL);
285 	tls_key_path = lp_config_get_string(config, key, "client_cert_key", NULL);
286 	ret = linphone_auth_info_new(username, userid, passwd, ha1, realm, domain);
287 	linphone_auth_info_set_tls_cert_path(ret, tls_cert_path);
288 	linphone_auth_info_set_tls_key_path(ret, tls_key_path);
289 	return ret;
290 }
291 
remove_quotes(char * input)292 static char * remove_quotes(char * input){
293 	char *tmp;
294 	if (*input=='"') input++;
295 	tmp=strchr(input,'"');
296 	if (tmp) *tmp='\0';
297 	return input;
298 }
299 
realm_match(const char * realm1,const char * realm2)300 static bool_t realm_match(const char *realm1, const char *realm2){
301 	if (realm1==NULL && realm2==NULL) return TRUE;
302 	if (realm1!=NULL && realm2!=NULL){
303 		if (strcmp(realm1,realm2)==0) return TRUE;
304 		else{
305 			char tmp1[128];
306 			char tmp2[128];
307 			char *p1,*p2;
308 			strncpy(tmp1,realm1,sizeof(tmp1)-1);
309 			strncpy(tmp2,realm2,sizeof(tmp2)-1);
310 			p1=remove_quotes(tmp1);
311 			p2=remove_quotes(tmp2);
312 			return strcmp(p1,p2)==0;
313 		}
314 	}
315 	return FALSE;
316 }
317 
find_auth_info(LinphoneCore * lc,const char * username,const char * realm,const char * domain,bool_t ignore_realm)318 static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *username, const char *realm, const char *domain, bool_t ignore_realm){
319 	bctbx_list_t *elem;
320 	const LinphoneAuthInfo *ret=NULL;
321 
322 	for (elem=lc->auth_info;elem!=NULL;elem=elem->next) {
323 		LinphoneAuthInfo *pinfo = (LinphoneAuthInfo*)elem->data;
324 		if (username && pinfo->username && strcmp(username,pinfo->username)==0) {
325 			if (realm && domain){
326 				if (pinfo->realm && realm_match(realm,pinfo->realm)
327 					&& pinfo->domain && strcmp(domain,pinfo->domain)==0) {
328 					return pinfo;
329 				}
330 			} else if (realm) {
331 				if (pinfo->realm && realm_match(realm,pinfo->realm)) {
332 					if (ret!=NULL) {
333 						ms_warning("Non unique realm found for %s",username);
334 						return NULL;
335 					}
336 					ret=pinfo;
337 				}
338 			} else if (domain && pinfo->domain && strcmp(domain,pinfo->domain)==0 && (pinfo->ha1==NULL || ignore_realm)) {
339 				return pinfo;
340 			} else if (!domain && (pinfo->ha1==NULL || ignore_realm)) {
341 				return pinfo;
342 			}
343 		}
344 	}
345 	return ret;
346 }
347 
_linphone_core_find_tls_auth_info(LinphoneCore * lc)348 const LinphoneAuthInfo *_linphone_core_find_tls_auth_info(LinphoneCore *lc) {
349 	bctbx_list_t *elem;
350 	for (elem=lc->auth_info;elem!=NULL;elem=elem->next) {
351 		LinphoneAuthInfo *pinfo = (LinphoneAuthInfo*)elem->data;
352 		if (pinfo->tls_cert && pinfo->tls_key) {
353 			return pinfo;
354 		} else if (pinfo->tls_cert_path && pinfo->tls_key_path) {
355 			return pinfo;
356 		}
357 	}
358 	return NULL;
359 }
360 
_linphone_core_find_auth_info(LinphoneCore * lc,const char * realm,const char * username,const char * domain,bool_t ignore_realm)361 const LinphoneAuthInfo *_linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain, bool_t ignore_realm){
362 	const LinphoneAuthInfo *ai=NULL;
363 	if (realm){
364 		ai=find_auth_info(lc,username,realm,NULL, FALSE);
365 		if (ai==NULL && domain){
366 			ai=find_auth_info(lc,username,realm,domain, FALSE);
367 		}
368 	}
369 	if (ai == NULL && domain != NULL) {
370 		ai=find_auth_info(lc,username,NULL,domain, ignore_realm);
371 	}
372 	if (ai==NULL){
373 		ai=find_auth_info(lc,username,NULL,NULL, ignore_realm);
374 	}
375 	if (ai) ms_message("linphone_core_find_auth_info(): returning auth info username=%s, realm=%s", ai->username ? ai->username : "", ai->realm ? ai->realm : "");
376 	return ai;
377 }
378 
linphone_core_find_auth_info(LinphoneCore * lc,const char * realm,const char * username,const char * domain)379 const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain){
380 	return _linphone_core_find_auth_info(lc, realm, username, domain, TRUE);
381 }
382 
383 /*the auth info is expected to be in the core's list*/
linphone_core_write_auth_info(LinphoneCore * lc,LinphoneAuthInfo * ai)384 void linphone_core_write_auth_info(LinphoneCore *lc, LinphoneAuthInfo *ai){
385 	int i;
386 	bctbx_list_t *elem = lc->auth_info;
387 
388 	if (!lc->sip_conf.save_auth_info) return;
389 
390 	for (i=0; elem != NULL; elem = elem->next, i++){
391 		if (ai == elem->data){
392 			linphone_auth_info_write_config(lc->config, ai, i);
393 		}
394 	}
395 }
396 
write_auth_infos(LinphoneCore * lc)397 static void write_auth_infos(LinphoneCore *lc){
398 	bctbx_list_t *elem;
399 	int i;
400 
401 	if (!linphone_core_ready(lc)) return;
402 	if (!lc->sip_conf.save_auth_info) return;
403 	for(elem=lc->auth_info,i=0;elem!=NULL;elem=bctbx_list_next(elem),i++){
404 		LinphoneAuthInfo *ai=(LinphoneAuthInfo*)(elem->data);
405 		linphone_auth_info_write_config(lc->config,ai,i);
406 	}
407 	linphone_auth_info_write_config(lc->config,NULL,i); /* mark the end */
408 }
409 
linphone_core_create_auth_info(LinphoneCore * lc,const char * username,const char * userid,const char * passwd,const char * ha1,const char * realm,const char * domain)410 LinphoneAuthInfo * linphone_core_create_auth_info(LinphoneCore *lc, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain) {
411 	return linphone_auth_info_new(username, userid, passwd, ha1, realm, domain);
412 }
413 
linphone_core_add_auth_info(LinphoneCore * lc,const LinphoneAuthInfo * info)414 void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info){
415 	LinphoneAuthInfo *ai;
416 	bctbx_list_t *elem;
417 	bctbx_list_t *l;
418 	int restarted_op_count=0;
419 	bool_t updating=FALSE;
420 
421 	if (info->tls_key == NULL && info->tls_key_path == NULL
422 		&& info->ha1==NULL && info->passwd==NULL){
423 		ms_error("linphone_core_add_auth_info(): info supplied with empty password, ha1 or TLS client/key");
424 		return;
425 	}
426 	/* find if we are attempting to modify an existing auth info */
427 	ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
428 	if (ai!=NULL && ai->domain && info->domain && strcmp(ai->domain, info->domain)==0){
429 		lc->auth_info=bctbx_list_remove(lc->auth_info,ai);
430 		linphone_auth_info_unref(ai);
431 		updating=TRUE;
432 	}
433 	lc->auth_info=bctbx_list_append(lc->auth_info,linphone_auth_info_clone(info));
434 
435 	/* retry pending authentication operations */
436 	for(l=elem=sal_get_pending_auths(lc->sal);elem!=NULL;elem=elem->next){
437 		SalOp *op=(SalOp*)elem->data;
438 		LinphoneAuthInfo *ai;
439 		const SalAuthInfo *req_sai=sal_op_get_auth_requested(op);
440 		ai=(LinphoneAuthInfo*)_linphone_core_find_auth_info(lc,req_sai->realm,req_sai->username,req_sai->domain, FALSE);
441 		if (ai){
442 			SalAuthInfo sai;
443 			bctbx_list_t* proxy;
444 			sai.username=ai->username;
445 			sai.userid=ai->userid;
446 			sai.realm=ai->realm;
447 			sai.password=ai->passwd;
448 			sai.ha1=ai->ha1;
449 			if (ai->tls_cert && ai->tls_key) {
450 				sal_certificates_chain_parse(&sai, ai->tls_cert, SAL_CERTIFICATE_RAW_FORMAT_PEM);
451 				sal_signing_key_parse(&sai, ai->tls_key, "");
452 			} else if (ai->tls_cert_path && ai->tls_key_path) {
453 				sal_certificates_chain_parse_file(&sai, ai->tls_cert_path, SAL_CERTIFICATE_RAW_FORMAT_PEM);
454 				sal_signing_key_parse_file(&sai, ai->tls_key_path, "");
455 			}
456 			/*proxy case*/
457 			for (proxy=(bctbx_list_t*)linphone_core_get_proxy_config_list(lc);proxy!=NULL;proxy=proxy->next) {
458 				if (proxy->data == sal_op_get_user_pointer(op)) {
459 					linphone_proxy_config_set_state((LinphoneProxyConfig*)(proxy->data),LinphoneRegistrationProgress,"Authentication...");
460 					break;
461 				}
462 			}
463 			sal_op_authenticate(op,&sai);
464 			restarted_op_count++;
465 		}
466 	}
467 	if (l){
468 		ms_message("linphone_core_add_auth_info(): restarted [%i] operation(s) after %s auth info for\n"
469 			"\tusername: [%s]\n"
470 			"\trealm [%s]\n"
471 			"\tdomain [%s]\n",
472 			restarted_op_count,
473 			updating ? "updating" : "adding",
474 			info->username ? info->username : "",
475 			info->realm ? info->realm : "",
476 			info->domain ? info->domain : "");
477 	}
478 	bctbx_list_free(l);
479 	write_auth_infos(lc);
480 }
481 
linphone_core_abort_authentication(LinphoneCore * lc,LinphoneAuthInfo * info)482 void linphone_core_abort_authentication(LinphoneCore *lc,  LinphoneAuthInfo *info){
483 }
484 
linphone_core_remove_auth_info(LinphoneCore * lc,const LinphoneAuthInfo * info)485 void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info){
486 	LinphoneAuthInfo *r;
487 	r=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain);
488 	if (r){
489 		lc->auth_info=bctbx_list_remove(lc->auth_info,r);
490 		linphone_auth_info_unref(r);
491 		write_auth_infos(lc);
492 	}
493 }
494 
linphone_core_get_auth_info_list(const LinphoneCore * lc)495 const bctbx_list_t *linphone_core_get_auth_info_list(const LinphoneCore *lc){
496 	return lc->auth_info;
497 }
498 
linphone_core_clear_all_auth_info(LinphoneCore * lc)499 void linphone_core_clear_all_auth_info(LinphoneCore *lc){
500 	bctbx_list_t *elem;
501 	int i;
502 	for(i=0,elem=lc->auth_info;elem!=NULL;elem=bctbx_list_next(elem),i++){
503 		LinphoneAuthInfo *info=(LinphoneAuthInfo*)elem->data;
504 		linphone_auth_info_unref(info);
505 		linphone_auth_info_write_config(lc->config,NULL,i);
506 	}
507 	bctbx_list_free(lc->auth_info);
508 	lc->auth_info=NULL;
509 }
510