diff --git a/coreapi/authentication.c b/coreapi/authentication.c index bd7849832..3b7db3122 100644 --- a/coreapi/authentication.c +++ b/coreapi/authentication.c @@ -57,7 +57,7 @@ LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *useri return obj; } -static LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo *ai){ +LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo *ai){ LinphoneAuthInfo *obj=ms_new0(LinphoneAuthInfo,1); if (ai->username) obj->username=ms_strdup(ai->username); if (ai->userid) obj->userid=ms_strdup(ai->userid); diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index ffabcc1e4..81519e542 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -116,8 +116,7 @@ void sal_process_authentication(SalOp *op) { belle_sip_auth_event_t* auth_event; belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction); - sal_add_pending_auth(op->base.root,op); - + if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_CONFIRMED) { new_request = belle_sip_dialog_create_request_from(op->dialog,initial_request); if (!new_request) @@ -142,6 +141,8 @@ void sal_process_authentication(SalOp *op) { sal_remove_pending_auth(op->base.root,op); }else { ms_message("No auth info found for [%s]",sal_op_get_from(op)); + sal_add_pending_auth(op->base.root,op); + if (is_within_dialog) { belle_sip_object_unref(new_request); } @@ -326,15 +327,25 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even belle_sip_object_unref(op->pending_auth_transaction); op->pending_auth_transaction=NULL; } - op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction); - sal_process_authentication(op); - return; + if (++op->auth_requests > 2) { + ms_warning("Auth info cannot be found for op [%s] after 2 attempts, giving up",sal_op_get_from(op)); + op->base.root->callbacks.auth_failure(op,op->auth_info); + sal_remove_pending_auth(op->base.root,op); + } else { + op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction); + sal_process_authentication(op); + return; + } } break; case 403: if (op->auth_info) op->base.root->callbacks.auth_failure(op,op->auth_info); break; } + if (response_code !=401 && response_code !=407 && response_code !=403) { + /*not an auth request*/ + op->auth_requests=0; + } op->callbacks.process_response_event(op,event); } else { ms_error("Unhandled event response [%p]",event); diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index aa68feecc..5a0faa82a 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -98,6 +98,7 @@ struct SalOp{ bool_t sdp_offering; bool_t call_released; bool_t manual_refresher; + int auth_requests; /*number of auth requested for this op*/ }; diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c index c02546019..2f12d4533 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -63,7 +63,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher if (op->auth_info) { /*add pending auth*/ sal_add_pending_auth(op->base.root,op); - if (status_code==403) + if (status_code==403 || status_code==401 || status_code==407 ) op->base.root->callbacks.auth_failure(op,op->auth_info); } } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 0ad6030da..56f33b0d2 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -918,6 +918,13 @@ typedef struct _LinphoneAuthInfo LinphoneAuthInfo; LINPHONE_PUBLIC LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid, const char *passwd, const char *ha1,const char *realm, const char *domain); +/** + * @addtogroup authentication + * Instanciate a new auth info with values from source + * @param source auth info object to be cloned + * @return newly created auth info + */ +LINPHONE_PUBLIC LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo* source); LINPHONE_PUBLIC void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd); LINPHONE_PUBLIC void linphone_auth_info_set_username(LinphoneAuthInfo *info, const char *username); LINPHONE_PUBLIC void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid); diff --git a/tester/call_tester.c b/tester/call_tester.c index 05a394423..0333df962 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1479,6 +1479,43 @@ static void call_established_with_rejected_reinvite_with_error(void) { linphone_core_manager_destroy(pauline); } +static void call_rejected_because_wrong_credentials_with_params(const char* user_agent) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneAuthInfo* good_auth_info=linphone_auth_info_clone((LinphoneAuthInfo*)(linphone_core_get_auth_info_list(marie->lc)->data)); + LinphoneAuthInfo* wrong_auth_info=linphone_auth_info_clone(good_auth_info); + + if (user_agent) { + linphone_core_set_user_agent(marie->lc,user_agent,NULL); + } + linphone_core_clear_all_auth_info(marie->lc); + + CU_ASSERT_PTR_NOT_NULL(linphone_core_invite_address(marie->lc,marie->identity)); + + CU_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_auth_info_requested,1)); + + linphone_auth_info_set_passwd(wrong_auth_info,"passecretdutout"); + + /*automatically re-inititae the call*/ + linphone_core_add_auth_info(marie->lc,wrong_auth_info); + + + CU_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphoneCallError,1)); + CU_ASSERT_EQUAL(marie->stat.number_of_auth_info_requested,2); + + /*to make sure unregister will work*/ + linphone_core_clear_all_auth_info(marie->lc); + linphone_core_add_auth_info(marie->lc,good_auth_info); + + linphone_core_manager_destroy(marie); +} +static void call_rejected_because_wrong_credentials() { + call_rejected_because_wrong_credentials_with_params(NULL); +} + +static void call_rejected_without_403_because_wrong_credentials() { + call_rejected_because_wrong_credentials_with_params("tester-no-403"); +} + #ifdef VIDEO_ENABLED #endif @@ -1511,6 +1548,8 @@ test_t call_tests[] = { { "SRTP ice call", srtp_ice_call }, #endif { "Call with privacy", call_with_privacy }, + { "Call rejected because of wrong credential", call_rejected_because_wrong_credentials}, + { "Call rejected without 403 because of wrong credential", call_rejected_without_403_because_wrong_credentials}, { "Simple conference", simple_conference }, { "Simple call transfer", simple_call_transfer }, { "Unattended call transfer", unattended_call_transfer }, diff --git a/tester/flexisip.conf b/tester/flexisip.conf index b4d39a5c0..af571c1c3 100755 --- a/tester/flexisip.conf +++ b/tester/flexisip.conf @@ -86,9 +86,6 @@ ban-duration=60 # Default value: 20 packets-limit=20 -# Maximal amount of simultaneous connections to accept. -# Default value: 1000 -maximum-connections=1000 ## ## The NatHelper module executes small tasks to make SIP work smoothly @@ -123,6 +120,9 @@ contact-verified-param=verified # Default value: false enabled=true + +no-403=user-agent contains 'tester-no-403' + # A request/response enters module if the boolean filter evaluates # to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain # in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org') @@ -345,59 +345,7 @@ generated-contact-route= # Default value: generated-contact-expected-realm= -## -## This module performs push notifications -## -[module::PushNotification] -# Indicate whether the module is activated. -# Default value: false -enabled=false -# A request/response enters module if the boolean filter evaluates -# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain -# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org') -# && (user-agent == 'Linphone v2') -# Default value: -filter= - -# Number of second to wait before sending a push notification to -# device(if <=0 then disabled) -# Default value: 5 -timeout=5 - -# Maximum number of notifications queued for each client -# Default value: 10 -max-queue-size=10 - -# Enable push notification for apple devices -# Default value: true -apple=true - -# Path to directory where to find Apple Push Notification service -# certificates. They should bear the appid of the application, suffixed -# by the release mode and .pem extension. For example: org.linphone.dev.pem -# org.linphone.prod.pem com.somephone.dev.pem etc... The files should -# be .pem format, and made of certificate followed by private key. -# Default value: /etc/flexisip/apn -apple-certificate-dir=/etc/flexisip/apn - -# Enable push notification for android devices -# Default value: true -google=true - -# List of couple projectId:ApiKey for each android project which -# support push notifications -# Default value: -google-projects-api-keys= - -## -## The purpose of the ContactRouteInserter module is to masquerade -## the contact header of incoming registers that are not handled -## locally (think about flexisip used as a SBC gateway) in such a -## way that it is then possible to route back outgoing invites to -## the original address. It is a kind of similar mechanism as Record-Route, -## but for REGISTER. -## [module::ContactRouteInserter] # Indicate whether the module is activated. # Default value: true diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index dbbba9a46..8a889157a 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -70,17 +70,13 @@ LinphoneAddress * create_linphone_address(const char * domain) { return addr; } -void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { +static void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { stats* counters; - LinphoneAuthInfo *info; ms_message("Auth info requested for user id [%s] at realm [%s]\n" ,username ,realm); counters = get_stats(lc); counters->number_of_auth_info_requested++; - info=linphone_auth_info_new(test_username,NULL,test_password,NULL,realm,domain); /*create authentication structure from identity*/ - linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ - } diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 93bde611a..ac5302458 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -198,7 +198,6 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room); void info_message_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg); void new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url); -void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain); void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *ev, LinphoneSubscriptionState state); void linphone_publish_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state); void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content); diff --git a/tester/register_tester.c b/tester/register_tester.c index 6ee79f9cd..6e5c929a5 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -22,6 +22,26 @@ #include "private.h" #include "liblinphone_tester.h" +static void auth_info_requested2(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); + counters = get_stats(lc); + counters->number_of_auth_info_requested++; + +} + +static void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { + LinphoneAuthInfo *info; + auth_info_requested2(lc,realm,username,domain); + info=linphone_auth_info_new(test_username,NULL,test_password,NULL,realm,domain); /*create authentication structure from identity*/ + linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ +} + + + static LinphoneCoreManager* create_lcm_with_auth(unsigned int with_auth) { LinphoneCoreManager* mgr=linphone_core_manager_new(NULL); @@ -108,7 +128,8 @@ static void register_with_refresh_base_3(LinphoneCore* lc linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ } } - if (linphone_proxy_config_get_error(proxy_cfg) == LinphoneReasonBadCredentials) + if (linphone_proxy_config_get_error(proxy_cfg) == LinphoneReasonBadCredentials + || (counters->number_of_auth_info_requested>2 &&linphone_proxy_config_get_error(proxy_cfg) == LinphoneReasonUnauthorized)) /*no need to continue if auth cannot be found*/ break; /*no need to continue*/ ms_usleep(100000); } @@ -261,6 +282,8 @@ static void authenticated_register_with_no_initial_credentials(){ mgr = linphone_core_manager_new(NULL); + mgr->lc->vtable.auth_info_requested=auth_info_requested; + counters= get_stats(mgr->lc); counters->number_of_auth_info_requested=0; register_with_refresh(mgr,FALSE,auth_domain,route); @@ -268,14 +291,6 @@ static void authenticated_register_with_no_initial_credentials(){ linphone_core_manager_destroy(mgr); } -static void auth_info_requested2(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); - counters = get_stats(lc); - counters->number_of_auth_info_requested++; -} static void authenticated_register_with_late_credentials(){ LinphoneCoreManager *mgr; @@ -286,10 +301,10 @@ static void authenticated_register_with_late_credentials(){ sprintf(route,"sip:%s",test_route); mgr = linphone_core_manager_new(NULL); - mgr->lc->vtable.auth_info_requested=auth_info_requested2; + counters = get_stats(mgr->lc); register_with_refresh_base_2(mgr->lc,FALSE,auth_domain,route,TRUE,transport); - CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,1); + CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,2); /*1 registration error = 2 auth requested*/ linphone_core_manager_destroy(mgr); } @@ -306,10 +321,10 @@ static void authenticated_register_with_wrong_late_credentials(){ sprintf(route,"sip:%s",test_route); mgr = linphone_core_manager_new(NULL); - mgr->lc->vtable.auth_info_requested=auth_info_requested2; + counters = get_stats(mgr->lc); register_with_refresh_base_3(mgr->lc,FALSE,auth_domain,route,TRUE,transport,LinphoneRegistrationFailed); - CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,2); + CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,3); CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,2); CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationProgress,2); test_password=saved_test_passwd; @@ -317,7 +332,7 @@ static void authenticated_register_with_wrong_late_credentials(){ linphone_core_manager_destroy(mgr); } -static void authenticated_register_with_wrong_credentials(){ +static void authenticated_register_with_wrong_credentials_with_params(const char* user_agent) { LinphoneCoreManager *mgr; stats* counters; LCSipTransports transport = {5070,5070,0,5071}; @@ -327,15 +342,28 @@ static void authenticated_register_with_wrong_credentials(){ sprintf(route,"sip:%s",test_route); mgr=linphone_core_manager_new(NULL); + mgr->lc->vtable.auth_info_requested=auth_info_requested2; - + + sal_set_refresher_retry_after(mgr->lc->sal,500); + if (user_agent) { + linphone_core_set_user_agent(mgr->lc,user_agent,NULL); + } linphone_core_add_auth_info(mgr->lc,info); /*add wrong authentication info to LinphoneCore*/ counters = get_stats(mgr->lc); - register_with_refresh_base_3(mgr->lc,TRUE,auth_domain,route,TRUE,transport,LinphoneRegistrationFailed); - CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,1); + register_with_refresh_base_3(mgr->lc,TRUE,auth_domain,route,FALSE,transport,LinphoneRegistrationFailed); + //CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,3); register_with_refresh_base_3 does not alow to precisely check number of number_of_auth_info_requested + /*wait for retry*/ + CU_ASSERT_TRUE(wait_for(mgr->lc,mgr->lc,&counters->number_of_auth_info_requested,4)); + CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,1); linphone_core_manager_destroy(mgr); } - +static void authenticated_register_with_wrong_credentials() { + authenticated_register_with_wrong_credentials_with_params(NULL); +} +static void authenticated_register_with_wrong_credentials_without_403() { + authenticated_register_with_wrong_credentials_with_params("tester-no-403"); +} static LinphoneCoreManager* configure_lcm(void) { LinphoneCoreManager *mgr=linphone_core_manager_new( "multi_account_lrc"); stats *counters=&mgr->stat; @@ -611,6 +639,7 @@ test_t register_tests[] = { { "Ha1 authenticated register", ha1_authenticated_register }, { "Digest auth without initial credentials", authenticated_register_with_no_initial_credentials }, { "Digest auth with wrong credentials", authenticated_register_with_wrong_credentials }, + { "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 }, { "Register with refresh", simple_register_with_refresh },