static void test_proxy_authentication(void) { const char* l_raw_header = "Proxy-Authenticate: Digest " "algorithm=MD5, realm=\"sip.linphone.org\", opaque=\"1bc7f9097684320\"," " qop=\"auth,auth-int\", nonce=\"cz3h0gAAAAC06TKKAABmTz1V9OcAAAAA\""; char ha1[33]; belle_sip_header_proxy_authenticate_t* proxy_authenticate=belle_sip_header_proxy_authenticate_parse(l_raw_header); belle_sip_header_proxy_authorization_t* proxy_authorization = belle_sip_auth_helper_create_proxy_authorization(proxy_authenticate); belle_sip_header_authorization_set_uri(BELLE_SIP_HEADER_AUTHORIZATION(proxy_authorization),belle_sip_uri_parse("sip:sip.linphone.org")); BC_ASSERT_EQUAL_FATAL(0,belle_sip_auth_helper_compute_ha1("jehan-mac","sip.linphone.org","toto",ha1), int, "%d"); BC_ASSERT_EQUAL_FATAL(0,belle_sip_auth_helper_fill_proxy_authorization(proxy_authorization,"REGISTER",ha1), int, "%d"); BC_ASSERT_STRING_EQUAL(belle_sip_header_authorization_get_response(BELLE_SIP_HEADER_AUTHORIZATION(proxy_authorization)) ,"77ebf3de72e41934d806175586086508"); belle_sip_object_unref(proxy_authenticate); belle_sip_object_unref(proxy_authorization); }
int belle_sip_auth_helper_fill_proxy_authorization(belle_sip_header_proxy_authorization_t* proxy_authorization ,const char* method ,const char* ha1) { return belle_sip_auth_helper_fill_authorization(BELLE_SIP_HEADER_AUTHORIZATION(proxy_authorization) ,method, ha1); }
static int http_channel_context_handle_authentication(belle_http_channel_context_t *ctx, belle_http_request_t *req){ const char *realm=NULL; belle_sip_auth_event_t *ev=NULL; belle_http_response_t *resp=belle_http_request_get_response(req); const char *username=NULL; const char *passwd=NULL; const char *ha1=NULL; char computed_ha1[33]; belle_sip_header_www_authenticate_t* authenticate; int ret=0; if (req->auth_attempt_count>1){ req->auth_attempt_count=0; return -1; } if (resp == NULL ) { belle_sip_error("Missing response for req [%p], cannot authenticate", req); return -1; } if (!(authenticate = belle_sip_message_get_header_by_type(resp,belle_sip_header_www_authenticate_t))) { if (belle_sip_message_get_header_by_type(resp,belle_sip_header_proxy_authenticate_t)) { belle_sip_error("Proxy authentication not supported yet, cannot authenticate for resp [%p]", resp); } belle_sip_error("Missing auth header in response [%p], cannot authenticate", resp); return -1; } if (strcasecmp("Digest",belle_sip_header_www_authenticate_get_scheme(authenticate)) != 0) { belle_sip_error("Unsupported auth scheme [%s] in response [%p], cannot authenticate", belle_sip_header_www_authenticate_get_scheme(authenticate),resp); return -1; } /*find if username, passwd were already supplied in original request uri*/ if (req->orig_uri){ username=belle_generic_uri_get_user(req->orig_uri); passwd=belle_generic_uri_get_user_password(req->orig_uri); } realm = belle_sip_header_www_authenticate_get_realm(authenticate); if (!username || !passwd) { ev=belle_sip_auth_event_create((belle_sip_object_t*)ctx->provider,realm,NULL); BELLE_HTTP_REQUEST_INVOKE_LISTENER(req,process_auth_requested,ev); username=ev->username; passwd=ev->passwd; ha1=ev->ha1; } if (!ha1 && username && passwd) { belle_sip_auth_helper_compute_ha1(username,realm,passwd, computed_ha1); ha1=computed_ha1; } else if (!ha1){ belle_sip_error("No auth info found for request [%p], cannot authenticate",req); ret=-1; } if (ha1) { belle_http_header_authorization_t* authorization; req->auth_attempt_count++; authorization = belle_http_auth_helper_create_authorization(authenticate); /*select first qop mode*/ belle_sip_header_authorization_set_qop(BELLE_SIP_HEADER_AUTHORIZATION(authorization),belle_sip_header_www_authenticate_get_qop_first(authenticate)); belle_sip_header_authorization_set_nonce_count(BELLE_SIP_HEADER_AUTHORIZATION(authorization),1); /*we don't store nonce count for now*/ belle_sip_header_authorization_set_username(BELLE_SIP_HEADER_AUTHORIZATION(authorization),username); belle_http_header_authorization_set_uri(authorization,belle_http_request_get_uri(req)); if (belle_sip_auth_helper_fill_authorization(BELLE_SIP_HEADER_AUTHORIZATION(authorization),belle_http_request_get_method(req),ha1)) { belle_sip_error("Cannot fill auth header for request [%p]",req); if (authorization) belle_sip_object_unref(authorization); ret=-1; } else { belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_HTTP_AUTHORIZATION); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(authorization)); belle_http_provider_send_request(ctx->provider,req,NULL); } } if (ev) belle_sip_auth_event_destroy(ev); return ret; }
belle_sip_header_proxy_authorization_t* belle_sip_auth_helper_create_proxy_authorization(const belle_sip_header_proxy_authenticate_t* proxy_authentication){ belle_sip_header_proxy_authorization_t* authorization = belle_sip_header_proxy_authorization_new(); belle_sip_auth_helper_clone_authorization(BELLE_SIP_HEADER_AUTHORIZATION(authorization),BELLE_SIP_HEADER_WWW_AUTHENTICATE(proxy_authentication)); return authorization; }
belle_http_header_authorization_t* belle_http_auth_helper_create_authorization(const belle_sip_header_www_authenticate_t* authentication) { belle_http_header_authorization_t* authorization = belle_http_header_authorization_new(); belle_sip_auth_helper_clone_authorization(BELLE_SIP_HEADER_AUTHORIZATION(authorization),authentication); return authorization; }
static void reuse_nonce(void) { belle_sip_request_t *register_request; int initial_auth_context_count=belle_sip_list_size(prov->auth_contexts); register_request=register_user_at_domain(stack, prov, "tcp",1,"marie","sip.linphone.org",NULL); if (register_request) { char * first_nonce_used; belle_sip_header_authorization_t * h = NULL; belle_sip_request_t *message_request; listener_callbacks.process_dialog_terminated=process_dialog_terminated; listener_callbacks.process_io_error=process_io_error; listener_callbacks.process_request_event=process_request_event; listener_callbacks.process_response_event=process_message_response_event; listener_callbacks.process_timeout=process_timeout; listener_callbacks.process_transaction_terminated=process_transaction_terminated; listener_callbacks.process_auth_requested=process_auth_requested; listener_callbacks.listener_destroyed=NULL; listener=belle_sip_listener_create_from_callbacks(&listener_callbacks,NULL); belle_sip_provider_add_sip_listener(prov,BELLE_SIP_LISTENER(listener)); /*currently only one nonce should have been used (the one for the REGISTER)*/ CU_ASSERT_EQUAL(belle_sip_list_size(prov->auth_contexts), initial_auth_context_count+1); /*this should reuse previous nonce*/ message_request=send_message(register_request, auth_domain); CU_ASSERT_EQUAL(is_register_ok, 404); h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type( BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t )); CU_ASSERT_PTR_NOT_NULL_FATAL(h); CU_ASSERT_EQUAL(2, belle_sip_header_authorization_get_nonce_count(h)); first_nonce_used = belle_sip_strdup(belle_sip_header_authorization_get_nonce(h)); belle_sip_object_unref(message_request); /*new nonce should be created when not using outbound proxy realm*/ message_request=send_message(register_request, NULL); CU_ASSERT_EQUAL(is_register_ok, 407); h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type( BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t )); CU_ASSERT_PTR_NULL_FATAL(h); belle_sip_object_unref(message_request); /*new nonce should be created here too*/ message_request=send_message(register_request, "wrongrealm"); CU_ASSERT_EQUAL(is_register_ok, 407); h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type( BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t )); CU_ASSERT_PTR_NULL_FATAL(h); belle_sip_object_unref(message_request); /*first nonce created should be reused*/ message_request=send_message(register_request, auth_domain); CU_ASSERT_EQUAL(is_register_ok, 404); h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type( BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t )); CU_ASSERT_PTR_NOT_NULL_FATAL(h); CU_ASSERT_EQUAL(3, belle_sip_header_authorization_get_nonce_count(h)); belle_sip_object_unref(message_request); belle_sip_provider_remove_sip_listener(prov,BELLE_SIP_LISTENER(listener)); unregister_user(stack,prov,register_request,1); belle_sip_object_unref(register_request); belle_sip_free(first_nonce_used); } }