Commit 041fa954 authored by jehan's avatar jehan

implement refresher for REGISTER

parent 7365fb79
......@@ -61,4 +61,31 @@ int belle_sip_auth_helper_fill_proxy_authorization(belle_sip_header_proxy_author
* return 0 in case of success
* */
int belle_sip_auth_helper_compute_ha1(const char* userid,const char* realm,const char* password, char ha1[33]);
/*
* compute HA2 (NULL terminated)
* HA2=MD5(method:uri)
* return 0 in case of success
* */
int belle_sip_auth_helper_compute_ha2(const char* method,const char* uri, char ha2[33]);
/*
* compute response(NULL terminated)
* res=MD5(ha1:nonce:ha2)
* return 0 in case of success
* */
int belle_sip_auth_helper_compute_response(const char* ha1,const char* nonce, const char* ha2, char response[33]);
/*
* compute response(NULL terminated)
* res=MD5(HA1:nonce:nonce_count:cnonce:qop:HA2)
* return 0 in case of success
* */
int belle_sip_auth_helper_compute_response_qop_auth( const char* ha1
, const char* nonce
, unsigned int nonce_count
, const char* cnonce
, const char* qop
, const char* ha2
, char response[33]);
#endif /* AUTHENTICATION_HELPER_H_ */
......@@ -51,7 +51,7 @@ void belle_sip_provider_send_request(belle_sip_provider_t *p, belle_sip_request_
void belle_sip_provider_send_response(belle_sip_provider_t *p, belle_sip_response_t *resp);
/*
* Add auth info the the request if found
* Add auth info to the request if found
* @param p object
* @param request to be updated
* @param resp response to take authentication values from, might be NULL
......
......@@ -48,13 +48,15 @@ belle_sip_request_t * belle_sip_client_transaction_create_cancel(belle_sip_clien
int belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t);
/**
* Creates an a sip refresher for transaction like REGISTER/SUBSCRIBE or INVITE which could be refreshed.
* Transaction must in be in stated BELLE_SIP_TRANSACTION_COMPLETED. Refresher is created and started
* Transaction must in be in stated BELLE_SIP_TRANSACTION_COMPLETED. Refresher is created and started. A ref is taken on object transaction
* */
belle_sip_refresher_t* belle_sip_client_transaction_create_refresher(belle_sip_client_transaction_t *t);
/**
* Create an authenticated request based on an existing terminated transaction
* Create an authenticated request based on an existing terminated transaction.
* <br>This function, update cseq, put route set and try to fill authorization headers. Initial request is not cloned.
* @param transaction . must be in state completed
* */
belle_sip_request_t* belle_sip_client_create_authenticated_request(belle_sip_client_transaction_t *t);
belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t);
#define BELLE_SIP_TRANSACTION(t) BELLE_SIP_CAST(t,belle_sip_transaction_t)
#define BELLE_SIP_SERVER_TRANSACTION(t) BELLE_SIP_CAST(t,belle_sip_server_transaction_t)
......
......@@ -72,22 +72,97 @@ int belle_sip_auth_helper_compute_ha1(const char* userid,const char* realm,const
md5_finish(&state,out);
for (di = 0; di < 16; ++di)
sprintf(ha1 + di * 2, "%02x", out[di]);
ha1[33]='\0';
ha1[32]='\0';
return 0;
}
int belle_sip_auth_helper_compute_ha2(const char* method,const char* uri, char ha2[33]) {
md5_byte_t out[16];
md5_state_t state;
int di;
ha2[32]='\0';
/*HA2=MD5(method:uri)*/
md5_init(&state);
md5_append(&state,(const md5_byte_t *)method,strlen(method));
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state,(const md5_byte_t *)uri,strlen(uri));
md5_finish(&state,out);
for (di = 0; di < 16; ++di)
sprintf(ha2 + di * 2, "%02x", out[di]);
return 0;
}
int belle_sip_auth_helper_compute_response(const char* ha1,const char* nonce, const char* ha2, char response[33]) {
md5_byte_t out[16];
md5_state_t state;
int di;
response[32]='\0';
md5_init(&state);
md5_append(&state,(const md5_byte_t *)ha1,strlen(ha1));
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state
,(const md5_byte_t *)nonce
,strlen(nonce));
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state,(const md5_byte_t *)ha2,strlen(ha2));
md5_finish(&state,out);
/*copy values*/
for (di = 0; di < 16; ++di)
sprintf(response + di * 2, "%02x", out[di]);
return 0;
}
int belle_sip_auth_helper_compute_response_qop_auth(const char* ha1
, const char* nonce
, unsigned int nonce_count
, const char* cnonce
, const char* qop
, const char* ha2, char response[33]) {
md5_byte_t out[16];
md5_state_t state;
response[32]='\0';
char nounce_count_as_string[9];
int di;
snprintf(nounce_count_as_string,sizeof(nounce_count_as_string),"%08x",nonce_count);
/*response=MD5(HA1:nonce:nonce_count:cnonce:qop:HA2)*/
md5_init(&state);
md5_append(&state,(const md5_byte_t *)ha1,strlen(ha1));
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state
,(const md5_byte_t *)nonce
,strlen(nonce));
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state
,(const md5_byte_t *)nounce_count_as_string
,strlen(nounce_count_as_string));
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state
,(const md5_byte_t *)cnonce
,strlen(cnonce));
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state
,(const md5_byte_t *)qop
,strlen(qop));
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state,(const md5_byte_t *)ha2,strlen(ha2));
md5_finish(&state,out);
/*copy values*/
for (di = 0; di < 16; ++di)
sprintf(response + di * 2, "%02x", out[di]);
return 0;
}
int belle_sip_auth_helper_fill_authorization(belle_sip_header_authorization_t* authorization
,const char* method
,const char* ha1) {
md5_byte_t out[16];
md5_state_t state;
int auth_mode=0;
char* uri;
char ha2[16*2 + 1];
char response[16*2 + 1];
response[33]=ha2[33]='\0';
int di;
char nonce_count[9];
response[32]=ha2[32]='\0';
char cnonce[9];
if (belle_sip_header_authorization_get_scheme(authorization) != NULL &&
......@@ -108,7 +183,7 @@ int belle_sip_auth_helper_fill_authorization(belle_sip_header_authorization_t* a
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);
snprintf(cnonce,sizeof(cnonce),"%08x",(short)(long)authorization^0x5555555); /*spseudo randomly genrated cnonce*/
belle_sip_header_authorization_set_cnonce(authorization,cnonce);
}
}
......@@ -118,48 +193,23 @@ int belle_sip_auth_helper_fill_authorization(belle_sip_header_authorization_t* a
}
/*HA2=MD5(method:uri)*/
md5_init(&state);
md5_append(&state,(const md5_byte_t *)method,strlen(method));
md5_append(&state,(const md5_byte_t *)":",1);
uri=belle_sip_uri_to_string(belle_sip_header_authorization_get_uri(authorization));
md5_append(&state,(const md5_byte_t *)uri,strlen(uri));
md5_finish(&state,out);
belle_sip_auth_helper_compute_ha2(method,uri,ha2);
belle_sip_free(uri);
for (di = 0; di < 16; ++di)
sprintf(ha2 + di * 2, "%02x", out[di]);
md5_init(&state);
md5_append(&state,(const md5_byte_t *)ha1,strlen(ha1));
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state
,(const md5_byte_t *)belle_sip_header_authorization_get_nonce(authorization)
,strlen(belle_sip_header_authorization_get_nonce(authorization)));
md5_append(&state,(const md5_byte_t *)":",1);
if (auth_mode) {
/*response=MD5(HA1:nonce:nonce_count:cnonce:qop:HA2)*/
belle_sip_header_authorization_get_nonce_count_as_string(authorization,nonce_count);
md5_append(&state
,(const md5_byte_t *)nonce_count
,sizeof(nonce_count)-1);
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state
,(const md5_byte_t *)belle_sip_header_authorization_get_cnonce(authorization)
,strlen(belle_sip_header_authorization_get_cnonce(authorization)));
md5_append(&state,(const md5_byte_t *)":",1);
md5_append(&state
,(const md5_byte_t *)belle_sip_header_authorization_get_qop(authorization)
,strlen(belle_sip_header_authorization_get_qop(authorization)));
md5_append(&state,(const md5_byte_t *)":",1);
} /*else response=MD5(HA1:nonce:HA2)*/
md5_append(&state,(const md5_byte_t *)ha2,strlen(ha2));
md5_finish(&state,out);
/*copy values*/
for (di = 0; di < 16; ++di)
sprintf(response + di * 2, "%02x", out[di]);
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;
}
......
......@@ -955,6 +955,7 @@ int belle_sip_header_authorization_get_nonce_count_as_string(const belle_sip_hea
return -1;
}
}
/**************************
*Proxy-Authorization header object inherent from parameters
****************************
......@@ -982,7 +983,7 @@ BELLE_SIP_PARSE(header_proxy_authorization)
struct _belle_sip_header_www_authenticate {
AUTH_BASE
const char* domain;
unsigned int stale;
int stale;
belle_sip_list_t* qop;
};
......@@ -1031,7 +1032,7 @@ void header##_set_##name(header##_t* obj, belle_sip_list_t* value) {\
} \
obj->name=value;\
}\
void header##_add_name(header##_t* obj, const char* value) {\
void header##_add_##name(header##_t* obj, const char* value) {\
obj->name=belle_sip_list_append(obj->name,strdup(value));\
}
......
......@@ -34,7 +34,7 @@ static void belle_sip_listening_point_uninit(belle_sip_listening_point_t *lp){
}
belle_sip_list_free_with_data(lp->channels,(void (*)(void*))belle_sip_object_unref);
belle_sip_object_unref(lp->listening_uri);
if (lp->channel_listener)belle_sip_object_unref(lp->channel_listener);
lp->channel_listener=NULL; /*does not unref provider*/
}
......@@ -122,7 +122,6 @@ belle_sip_channel_t *belle_sip_listening_point_get_channel(belle_sip_listening_p
void belle_sip_listener_set_channel_listener(belle_sip_listening_point_t *lp,belle_sip_channel_listener_t* channel_listener) {
lp->channel_listener=channel_listener;
belle_sip_object_ref(lp->channel_listener);
}
......@@ -671,7 +671,8 @@ int belle_sip_provider_add_authorization(belle_sip_provider_t *p, belle_sip_requ
belle_sip_header_authorization_set_qop(authorization,auth_context->qop);
belle_sip_header_authorization_set_opaque(authorization,auth_context->opaque);
belle_sip_header_authorization_set_uri(authorization,(belle_sip_uri_t*)belle_sip_object_ref(belle_sip_request_get_uri(request)));
belle_sip_header_authorization_set_nonce_count(authorization,++auth_context->nonce_count);
if (auth_context->qop)
belle_sip_header_authorization_set_nonce_count(authorization,++auth_context->nonce_count);
if (auth_event->ha1) {
ha1=auth_event->ha1;
} else {
......
......@@ -44,7 +44,7 @@ static int timer_cb(void *user_data, unsigned int events) ;
static void schedule_timer(belle_sip_refresher_t* refresher) {
if (refresher->expires>0) {
refresher->timer=belle_sip_timeout_source_new(timer_cb,refresher,refresher->expires);
refresher->timer=belle_sip_timeout_source_new(timer_cb,refresher,refresher->expires*1000);
belle_sip_object_set_name((belle_sip_object_t*)refresher->timer,"Refresher timeout");
belle_sip_main_loop_add_source(belle_sip_stack_get_main_loop(refresher->transaction->base.provider->stack),refresher->timer);
}
......@@ -69,7 +69,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
}
case 401:
case 407:{
refresh(refresher); /*authorization is spoosed to be available imediatly*/
refresh(refresher); /*authorization is supposed to be available immediately*/
return;
}
default:
......@@ -99,6 +99,7 @@ static void process_transaction_terminated(void *user_ctx, const belle_sip_trans
static void destroy(belle_sip_refresher_t *refresher){
if (refresher->transaction) belle_sip_object_unref(refresher->transaction);
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_refresher_t);
......@@ -112,23 +113,13 @@ void belle_sip_refresher_set_listener(belle_sip_refresher_t* refresher, belle_si
static int refresh(belle_sip_refresher_t* refresher) {
belle_sip_request_t*old_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(refresher->transaction));
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(old_request),BELLE_SIP_CSEQ);
belle_sip_dialog_t* dialog = belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(refresher->transaction));
belle_sip_client_transaction_t* client_transaction;
belle_sip_request_t* request;
belle_sip_provider_t* prov=refresher->transaction->base.provider;
if (!dialog) {
/*inc cseq*/
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
request=old_request;
/*remove auth headers*/
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION);
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION);
if (refresher->transaction->preset_route) {
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(refresher->transaction->preset_route));
}
/*create new request*/
request=belle_sip_client_transaction_create_authenticated_request(refresher->transaction);
} else if (dialog && belle_sip_dialog_get_state(dialog)==BELLE_SIP_DIALOG_CONFIRMED) {
request=belle_sip_dialog_create_request(dialog,belle_sip_request_get_method(old_request));
} else {
......@@ -141,10 +132,10 @@ static int refresh(belle_sip_refresher_t* refresher) {
client_transaction = belle_sip_provider_create_client_transaction(prov,request);
client_transaction->base.is_internal=1;
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),refresher);
belle_sip_provider_add_authorization(prov,request,client_transaction->base.last_response);
/*update reference transaction for next refresh*/
belle_sip_object_unref(refresher->transaction);
refresher->transaction=client_transaction;
belle_sip_object_ref(refresher->transaction);
if (belle_sip_client_transaction_send_request(client_transaction)) {
belle_sip_error("Cannot send refresh method [%s] for refresher [%p]"
......@@ -184,7 +175,7 @@ static belle_sip_header_contact_t* get_matching_contact(const belle_sip_transact
belle_sip_free(contact_string);
return NULL;
} else {
return BELLE_SIP_HEADER_CONTACT(contact_header_list->data);
return BELLE_SIP_HEADER_CONTACT(local_contact);
}
} else {
return NULL;
......@@ -205,8 +196,10 @@ static int set_expires_from_trans(belle_sip_refresher_t* refresher) {
* SUBSCRIBE and is explicitly not equivalent to an "Expires" header in
* a SUBSCRIBE request or response.
*/
if (strcmp("REGISTER",belle_sip_request_get_method(request))==0 && (contact_header=get_matching_contact(transaction))) {
refresher->expires=belle_sip_header_contact_get_expires(BELLE_SIP_HEADER_CONTACT(contact_header));
if (strcmp("REGISTER",belle_sip_request_get_method(request))==0
&& (contact_header=get_matching_contact(transaction))
&& (refresher->expires=belle_sip_header_contact_get_expires(BELLE_SIP_HEADER_CONTACT(contact_header)))>=0) {
/*great, we have an expire param from contact header*/
belle_sip_object_unref(contact_header);
contact_header=NULL;
} else {
......@@ -247,6 +240,8 @@ void belle_sip_refresher_stop(belle_sip_refresher_t* refresher) {
if (refresher->timer)
belle_sip_main_loop_cancel_source(belle_sip_stack_get_main_loop(refresher->transaction->base.provider->stack),refresher->timer->id);
refresher->timer=NULL;
}
belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* transaction) {
......
......@@ -364,4 +364,26 @@ belle_sip_refresher_t* belle_sip_client_transaction_create_refresher(belle_sip_c
return refresher;
}
belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t) {
belle_sip_request_t* req=BELLE_SIP_REQUEST(belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(t)))));
belle_sip_header_cseq_t* cseq=belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t);
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)) != BELLE_SIP_TRANSACTION_COMPLETED) {
belle_sip_error("Invalid state [%s] for transaction [%p], should be BELLE_SIP_TRANSACTION_COMPLETED"
,belle_sip_transaction_state_to_string(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)))
,t);
return NULL;
}
/*remove auth headers*/
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_AUTHORIZATION);
belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_PROXY_AUTHORIZATION);
/*add preset route if any*/
if (t->preset_route) {
belle_sip_object_ref(t->preset_route);
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(t->preset_route));
}
/*put auth header*/
belle_sip_provider_add_authorization(t->base.provider,req,t->base.last_response);
return req;
}
......@@ -76,18 +76,18 @@ int belle_sip_authentication_helper_suite () {
/* add a suite to the registry */
pSuite = CU_add_suite("authentication helper suite", NULL,NULL);
pSuite = CU_add_suite("Authentication-helper", NULL,NULL);
if (NULL == pSuite) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "test of simple digest authentication uri", test_authentication)) {
if (NULL == CU_add_test(pSuite, "test_authentication", test_authentication)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "auth digest authentication uri", test_authentication_qop_auth)) {
if (NULL == CU_add_test(pSuite, "test_authentication_qop_auth", test_authentication_qop_auth)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "test of simple digest proxy authentication", test_proxy_authentication)) {
if (NULL == CU_add_test(pSuite, "test_proxy_authentication", test_proxy_authentication)) {
return CU_get_error();
}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment