int belle_sip_auth_helper_fill_authorization(belle_sip_header_authorization_t* authorization ,const char* method ,const char* ha1) { int auth_mode=0; char* uri; char ha2[16*2 + 1]; char response[16*2 + 1]; char cnonce[9]; response[32]=ha2[32]='\0'; if (belle_sip_header_authorization_get_scheme(authorization) != NULL && strcmp("Digest",belle_sip_header_authorization_get_scheme(authorization))!=0) { belle_sip_error("belle_sip_fill_authorization_header, unsupported schema [%s]" ,belle_sip_header_authorization_get_scheme(authorization)); return -1; } if (belle_sip_header_authorization_get_qop(authorization) && !(auth_mode=strcmp("auth",belle_sip_header_authorization_get_qop(authorization))==0)) { belle_sip_error("belle_sip_fill_authorization_header, unsupported qop [%s], use auth or nothing instead" ,belle_sip_header_authorization_get_qop(authorization)); return -1; } CHECK_IS_PRESENT(authorization,authorization,realm) CHECK_IS_PRESENT(authorization,authorization,nonce) CHECK_IS_PRESENT(authorization,authorization,uri) if (auth_mode) { CHECK_IS_PRESENT(authorization,authorization,nonce_count) if (!belle_sip_header_authorization_get_cnonce(authorization)) { snprintf(cnonce,sizeof(cnonce),"%08x",(short)(long)authorization^0x5555555); /*spseudo randomly genrated cnonce*/ belle_sip_header_authorization_set_cnonce(authorization,cnonce); } } if (!method) { belle_sip_error("belle_sip_fill_authorization_header, method not found "); return -1; } uri=belle_sip_uri_to_string(belle_sip_header_authorization_get_uri(authorization)); belle_sip_auth_helper_compute_ha2(method,uri,ha2); belle_sip_free(uri); if (auth_mode) { /*response=MD5(HA1:nonce:nonce_count:cnonce:qop:HA2)*/ belle_sip_auth_helper_compute_response_qop_auth(ha1 ,belle_sip_header_authorization_get_nonce(authorization) ,belle_sip_header_authorization_get_nonce_count(authorization) ,belle_sip_header_authorization_get_cnonce(authorization) ,belle_sip_header_authorization_get_qop(authorization) ,ha2 ,response); } else { /*response=MD5(ha1:nonce:ha2)*/ belle_sip_auth_helper_compute_response(ha1,belle_sip_header_authorization_get_nonce(authorization),ha2,response); } belle_sip_header_authorization_set_response(authorization,(const char*)response); return 0; }
int belle_sip_auth_helper_fill_authorization(belle_sip_header_authorization_t* authorization ,const char* method ,const char* ha1) { int auth_mode=0; char* uri; char ha2[16*2 + 1]; char response[16*2 + 1]; char cnonce[9]; response[32]=ha2[32]='\0'; if (belle_sip_header_authorization_get_scheme(authorization) != NULL && strcmp("Digest",belle_sip_header_authorization_get_scheme(authorization))!=0) { belle_sip_error("belle_sip_fill_authorization_header, unsupported schema [%s]" ,belle_sip_header_authorization_get_scheme(authorization)); return -1; } if (belle_sip_header_authorization_get_qop(authorization) && !(auth_mode=strcmp("auth",belle_sip_header_authorization_get_qop(authorization))==0)) { belle_sip_error("belle_sip_fill_authorization_header, unsupported qop [%s], use auth or nothing instead" ,belle_sip_header_authorization_get_qop(authorization)); return -1; } CHECK_IS_PRESENT(authorization,authorization,realm) CHECK_IS_PRESENT(authorization,authorization,nonce) if (BELLE_SIP_IS_INSTANCE_OF(authorization,belle_http_header_authorization_t)) { /*http case*/ if (!belle_http_header_authorization_get_uri(BELLE_HTTP_HEADER_AUTHORIZATION(authorization))) { belle_sip_error("parameter uri not found for http header authorization"); return-1; } } else { CHECK_IS_PRESENT(authorization,authorization,uri) } if (auth_mode) { CHECK_IS_PRESENT(authorization,authorization,nonce_count) if (!belle_sip_header_authorization_get_cnonce(authorization)) { int cnonce_value=0; belle_sip_random_bytes((unsigned char*)&cnonce_value, sizeof(cnonce_value)); snprintf(cnonce, sizeof(cnonce), "%08x", cnonce_value); belle_sip_header_authorization_set_cnonce(authorization,cnonce); } } if (!method) { belle_sip_error("belle_sip_fill_authorization_header, method not found "); return -1; } if (BELLE_SIP_IS_INSTANCE_OF(authorization,belle_http_header_authorization_t)) { /*http case*/ uri=belle_generic_uri_to_string(belle_http_header_authorization_get_uri(BELLE_HTTP_HEADER_AUTHORIZATION(authorization))); } else { uri=belle_sip_uri_to_string(belle_sip_header_authorization_get_uri(authorization)); } belle_sip_auth_helper_compute_ha2(method,uri,ha2); belle_sip_free(uri); if (auth_mode) { /*response=MD5(HA1:nonce:nonce_count:cnonce:qop:HA2)*/ belle_sip_auth_helper_compute_response_qop_auth(ha1 ,belle_sip_header_authorization_get_nonce(authorization) ,belle_sip_header_authorization_get_nonce_count(authorization) ,belle_sip_header_authorization_get_cnonce(authorization) ,belle_sip_header_authorization_get_qop(authorization) ,ha2 ,response); } else { /*response=MD5(ha1:nonce:ha2)*/ belle_sip_auth_helper_compute_response(ha1,belle_sip_header_authorization_get_nonce(authorization),ha2,response); } belle_sip_header_authorization_set_response(authorization,(const char*)response); return 0; }
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); } }