Commit 3cc6f3b7 authored by jehan's avatar jehan

Better authenticatiion handling, thanks to

belle_sip_provider_add_authorization
parent 0ab402f0
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2010 Belledonne Communications SARL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AUTH_INFO_H_
#define AUTH_INFO_H_
typedef struct belle_sip_auth_info belle_sip_auth_info_t;
const char* belle_sip_auth_info_get_username(const belle_sip_auth_info_t info);
void belle_sip_auth_info_set_username(belle_sip_auth_info_t info, const char* value);
const char* belle_sip_auth_info_get_userid(const belle_sip_auth_info_t info);
void belle_sip_auth_info_set_userid(belle_sip_auth_info_t info, const char* value);
const char* belle_sip_auth_info_get_realm(const belle_sip_auth_info_t info);
void belle_sip_auth_info_set_realm(belle_sip_auth_info_t info, const char* value);
const char* belle_sip_auth_info_get_passwd(const belle_sip_auth_info_t info);
void belle_sip_auth_info_set_passwd(belle_sip_auth_info_t info, const char* value);
const char* belle_sip_auth_info_get_ha1(const belle_sip_auth_info_t info);
void belle_sip_auth_info_set_ha1(belle_sip_auth_info_t info, const char* value);
#endif /* AUTH_INFO_H_ */
......@@ -137,6 +137,7 @@ typedef struct _belle_sip_response belle_sip_response_t;
#include "belle-sip/utils.h"
#include "belle-sip/list.h"
#include "belle-sip/auth-info.h"
#include "belle-sip/listener.h"
#include "belle-sip/mainloop.h"
#include "belle-sip/uri.h"
......
......@@ -194,6 +194,11 @@ belle_sip_header_via_t* belle_sip_header_via_create(const char *host, int port,
belle_sip_header_via_t* belle_sip_header_via_parse (const char* via) ;
const char* belle_sip_header_via_get_branch(const belle_sip_header_via_t* via);
const char* belle_sip_header_via_get_transport(const belle_sip_header_via_t* via);
/**
* Get lower case version of the transport
* @return the lower case version of the transport if from tcp,udp,tls or dtls else, return the value from #belle_sip_header_via_get_transport
*/
const char* belle_sip_header_via_get_transport_lowercase(const belle_sip_header_via_t* via);
const char* belle_sip_header_via_get_host(const belle_sip_header_via_t* via);
int belle_sip_header_via_get_port(const belle_sip_header_via_t* via);
int belle_sip_header_via_get_listening_port(const belle_sip_header_via_t *via);
......@@ -226,7 +231,8 @@ belle_sip_header_call_id_t* belle_sip_header_call_id_new();
belle_sip_header_call_id_t* belle_sip_header_call_id_parse (const char* call_id) ;
const char* belle_sip_header_call_id_get_call_id(const belle_sip_header_call_id_t* call_id);
void belle_sip_header_call_id_set_call_id(belle_sip_header_call_id_t* via,const char* call_id);
void belle_sip_header_call_id_set_call_id(belle_sip_header_call_id_t* call_id,const char* id);
unsigned int belle_sip_header_call_id_equals(const belle_sip_header_call_id_t* a,const belle_sip_header_call_id_t* b);
#define BELLE_SIP_HEADER_CALL_ID(t) BELLE_SIP_CAST(t,belle_sip_header_call_id_t)
#define BELLE_SIP_CALL_ID "Call-ID"
/******************************
......@@ -374,6 +380,7 @@ void belle_sip_header_authorization_set_uri(belle_sip_header_authorization_t* au
void belle_sip_header_authorization_set_username(belle_sip_header_authorization_t* authorization, const char* username);
#define BELLE_SIP_HEADER_AUTHORIZATION(t) BELLE_SIP_CAST(t,belle_sip_header_authorization_t)
#define BELLE_SIP_AUTHORIZATION "Authorization"
/*******************************
* proxy_authorization inherit from Authorization
......@@ -382,6 +389,7 @@ typedef struct _belle_sip_header_proxy_authorization belle_sip_header_proxy_auth
belle_sip_header_proxy_authorization_t* belle_sip_header_proxy_authorization_new();
belle_sip_header_proxy_authorization_t* belle_sip_header_proxy_authorization_parse(const char* proxy_authorization);
#define BELLE_SIP_HEADER_PROXY_AUTHORIZATION(t) BELLE_SIP_CAST(t,belle_sip_header_proxy_authorization_t)
#define BELLE_SIP_PROXY_AUTHORIZATION "Proxy-Authorization"
/*******************************
* www_authenticate inherit from parameters
......@@ -393,6 +401,7 @@ const char* belle_sip_header_www_authenticate_get_algorithm(const belle_sip_head
const char* belle_sip_header_www_authenticate_get_nonce(const belle_sip_header_www_authenticate_t* www_authenticate);
const char* belle_sip_header_www_authenticate_get_opaque(const belle_sip_header_www_authenticate_t* www_authenticate);
belle_sip_list_t* belle_sip_header_www_authenticate_get_qop(const belle_sip_header_www_authenticate_t* www_authetication);
const char* belle_sip_header_www_authenticate_get_qop_first(const belle_sip_header_www_authenticate_t* www_authetication);
const char* belle_sip_header_www_authenticate_get_realm(const belle_sip_header_www_authenticate_t* www_authenticate);
const char* belle_sip_header_www_authenticate_get_scheme(const belle_sip_header_www_authenticate_t* www_authenticate);
const char* belle_sip_header_www_authenticate_get_domain(const belle_sip_header_www_authenticate_t* www_authenticate);
......
......@@ -26,6 +26,8 @@ typedef struct belle_sip_request_event belle_sip_request_event_t;
typedef struct belle_sip_response_event belle_sip_response_event_t;
typedef struct belle_sip_timeout_event belle_sip_timeout_event_t;
typedef struct belle_sip_transaction_terminated_event belle_sip_transaction_terminated_event_t;
typedef struct belle_sip_auth_event belle_sip_auth_event_t;
BELLE_SIP_DECLARE_INTERFACE_BEGIN(belle_sip_listener_t)
void (*process_dialog_terminated)(belle_sip_listener_t *user_ctx, const belle_sip_dialog_terminated_event_t *event);
......@@ -34,6 +36,7 @@ BELLE_SIP_DECLARE_INTERFACE_BEGIN(belle_sip_listener_t)
void (*process_response_event)(belle_sip_listener_t *user_ctx, const belle_sip_response_event_t *event);
void (*process_timeout)(belle_sip_listener_t *user_ctx, const belle_sip_timeout_event_t *event);
void (*process_transaction_terminated)(belle_sip_listener_t *user_ctx, const belle_sip_transaction_terminated_event_t *event);
void (*process_auth_requested)(belle_sip_listener_t *user_ctx, belle_sip_auth_event_t *event);
BELLE_SIP_DECLARE_INTERFACE_END
#define BELLE_SIP_LISTENER(obj) BELLE_SIP_INTERFACE_CAST(obj,belle_sip_listener_t)
......@@ -47,6 +50,22 @@ belle_sip_request_t* belle_sip_request_event_get_request(const belle_sip_request
belle_sip_server_transaction_t *belle_sip_request_event_get_server_transaction(const belle_sip_request_event_t* event);
belle_sip_dialog_t *belle_sip_request_event_get_dialog(const belle_sip_request_event_t* event);
/*auth event*/
const char* belle_sip_auth_event_get_username(const belle_sip_auth_event_t* event);
void belle_sip_auth_event_set_username(belle_sip_auth_event_t* event, const char* value);
const char* belle_sip_auth_event_get_userid(const belle_sip_auth_event_t* event);
void belle_sip_auth_event_set_userid(belle_sip_auth_event_t* event, const char* value);
const char* belle_sip_auth_event_get_realm(const belle_sip_auth_event_t* event);
void belle_sip_auth_event_set_realm(belle_sip_auth_event_t* event, const char* value);
const char* belle_sip_auth_event_get_passwd(const belle_sip_auth_event_t* event);
void belle_sip_auth_event_set_passwd(belle_sip_auth_event_t* event, const char* value);
const char* belle_sip_auth_event_get_ha1(const belle_sip_auth_event_t* event);
void belle_sip_auth_event_set_ha1(belle_sip_auth_event_t* event, const char* value);
struct belle_sip_listener_callbacks{
void (*process_dialog_terminated)(void *user_ctx, const belle_sip_dialog_terminated_event_t *event);
......@@ -55,6 +74,7 @@ struct belle_sip_listener_callbacks{
void (*process_response_event)(void *user_ctx, const belle_sip_response_event_t *event);
void (*process_timeout)(void *user_ctx, const belle_sip_timeout_event_t *event);
void (*process_transaction_terminated)(void *user_ctx, const belle_sip_transaction_terminated_event_t *event);
void (*process_auth_requested)(void *user_ctx, belle_sip_auth_event_t *auth_event);
};
typedef struct belle_sip_listener_callbacks belle_sip_listener_callbacks_t;
......
......@@ -50,6 +50,16 @@ 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
* @param p object
* @param request to be updated
* @param resp response to take authentication values from, might be NULL
* @returns 0 in case of success,
*
* */
int belle_sip_provider_add_authorization(belle_sip_provider_t *p, belle_sip_request_t* request,belle_sip_response_t *resp);
BELLE_SIP_END_DECLS
#define BELLE_SIP_PROVIDER(obj) BELLE_SIP_CAST(obj,belle_sip_provider_t)
......
......@@ -44,7 +44,10 @@ void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *
belle_sip_request_t * belle_sip_client_transaction_create_cancel(belle_sip_client_transaction_t *t);
void belle_sip_client_transaction_send_request(belle_sip_client_transaction_t *t);
/**
* Create an authenticated request based on an existing terminated transaction
* */
belle_sip_request_t* belle_sip_client_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)
......
......@@ -51,6 +51,7 @@ libbellesip_la_SOURCES= \
nict.c \
nist.c \
dialog.c \
auth_event.c \
transports/udp_listeningpoint.c \
transports/udp_channel.c \
transports/stream_channel.c \
......
/*
auth_info.c belle-sip - SIP (RFC3261) library.
Copyright (C) 2010 Belledonne Communications SARL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "belle-sip/auth-helper.h"
#include "belle_sip_internal.h"
GET_SET_STRING(belle_sip_auth_event,username)
GET_SET_STRING(belle_sip_auth_event,userid)
GET_SET_STRING(belle_sip_auth_event,realm)
GET_SET_STRING(belle_sip_auth_event,passwd)
GET_SET_STRING(belle_sip_auth_event,ha1)
belle_sip_auth_event_t* belle_sip_auth_event_create(const char* realm,const char* username) {
belle_sip_auth_event_t* result = belle_sip_malloc(sizeof(belle_sip_auth_event_t));
memset(result,0,sizeof(belle_sip_auth_event_t));
belle_sip_auth_event_set_realm(result,realm);
belle_sip_auth_event_set_username(result,username);
return result;
}
void belle_sip_auth_event_destroy(belle_sip_auth_event_t* event) {
DESTROY_STRING(event,username);
DESTROY_STRING(event,userid);
DESTROY_STRING(event,realm);
DESTROY_STRING(event,passwd);
DESTROY_STRING(event,ha1);
belle_sip_free(event);
}
......@@ -108,7 +108,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);
snprintf(cnonce,sizeof(cnonce),"%08x",(short)(long)authorization^0x5555555);
belle_sip_header_authorization_set_cnonce(authorization,cnonce);
}
}
......
......@@ -510,7 +510,16 @@ int belle_sip_header_via_get_listening_port(const belle_sip_header_via_t *via){
if (ret==-1) ret=belle_sip_listening_point_get_well_known_port(via->protocol);
return ret;
}
const char* belle_sip_header_via_get_transport_lowercase(const belle_sip_header_via_t* via) {
if (strcasecmp("udp",via->transport)==0) return "udp";
else if (strcasecmp("tcp",via->transport)==0) return "tcp";
else if (strcasecmp("tls",via->transport)==0) return "tls";
else if (strcasecmp("dtls",via->transport)==0) return "dtls";
else {
belle_sip_warning("Cannot convert [%s] to lower case",via->transport);
return via->transport;
}
}
/**************************
* call_id header object inherits from object
****************************
......@@ -533,7 +542,9 @@ int belle_sip_header_call_id_marshal(belle_sip_header_call_id_t* call_id, char*
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",call_id->call_id);
return current_offset-offset;
}
unsigned int belle_sip_header_call_id_equals(const belle_sip_header_call_id_t* a,const belle_sip_header_call_id_t* b) {
return strcasecmp(a->call_id,b->call_id) == 0;
}
BELLE_SIP_NEW_HEADER(header_call_id,header,BELLE_SIP_CALL_ID)
BELLE_SIP_PARSE(header_call_id)
GET_SET_STRING(belle_sip_header_call_id,call_id);
......@@ -917,7 +928,7 @@ int belle_sip_header_authorization_marshal(belle_sip_header_authorization_t* aut
}
return current_offset-offset;
}
BELLE_SIP_NEW_HEADER(header_authorization,parameters,"Authorization")
BELLE_SIP_NEW_HEADER(header_authorization,parameters,BELLE_SIP_AUTHORIZATION)
BELLE_SIP_PARSE(header_authorization)
GET_SET_STRING(belle_sip_header_authorization,scheme);
GET_SET_STRING(belle_sip_header_authorization,username);
......@@ -957,7 +968,7 @@ static void belle_sip_header_proxy_authorization_clone(belle_sip_header_proxy_au
int belle_sip_header_proxy_authorization_marshal(belle_sip_header_proxy_authorization_t* proxy_authorization, char* buff,unsigned int offset,unsigned int buff_size) {
return belle_sip_header_authorization_marshal(&proxy_authorization->authorization,buff,offset,buff_size);
}
BELLE_SIP_NEW_HEADER(header_proxy_authorization,header_authorization,"Proxy-Authorization")
BELLE_SIP_NEW_HEADER(header_proxy_authorization,header_authorization,BELLE_SIP_PROXY_AUTHORIZATION)
BELLE_SIP_PARSE(header_proxy_authorization)
/**************************
*WWW-Authenticate header object inherent from parameters
......@@ -1033,6 +1044,9 @@ GET_SET_BOOL(belle_sip_header_www_authenticate,stale,is)
belle_sip_list_t* belle_sip_header_www_authenticate_get_qop(const belle_sip_header_www_authenticate_t* www_authetication) {
return www_authetication->qop;
}
const char* belle_sip_header_www_authenticate_get_qop_first(const belle_sip_header_www_authenticate_t* www_authetication) {
return www_authetication->qop?(const char*)www_authetication->qop->data:NULL;
}
/**************************
*Proxy-authenticate header object inherent from www_authenticate
......
......@@ -508,6 +508,7 @@ struct belle_sip_provider{
belle_sip_list_t *client_transactions;
belle_sip_list_t *server_transactions;
belle_sip_list_t *dialogs;
belle_sip_list_t *auth_contexts;
};
belle_sip_provider_t *belle_sip_provider_new(belle_sip_stack_t *s, belle_sip_listening_point_t *lp);
......@@ -803,7 +804,15 @@ struct belle_sip_transaction_terminated_event{
int is_server_transaction;
};
struct belle_sip_auth_event {
char* username;
char* userid;
char* realm;
char* passwd;
char* ha1;
};
belle_sip_auth_event_t* belle_sip_auth_event_create(const char* realm,const char* username);
void belle_sip_auth_event_destroy(belle_sip_auth_event_t* event);
#ifdef __cplusplus
}
......
......@@ -164,7 +164,8 @@ belle_sip_list_t* belle_sip_list_new(void *data){
belle_sip_list_t* belle_sip_list_append_link(belle_sip_list_t* elem,belle_sip_list_t *new_elem){
belle_sip_list_t* it=elem;
if (elem==NULL) return new_elem;
if (elem==NULL) return new_elem;
if (new_elem==NULL) return elem;
while (it->next!=NULL) it=belle_sip_list_next(it);
it->next=new_elem;
new_elem->prev=it;
......
......@@ -297,7 +297,7 @@ belle_sip_uri_t* belle_sip_request_extract_origin(const belle_sip_request_t* req
belle_sip_uri_set_port(uri,belle_sip_header_via_get_port(via_header));
}
if (belle_sip_header_via_get_transport(via_header)) {
belle_sip_uri_set_transport_param(uri,belle_sip_header_via_get_transport(via_header));
belle_sip_uri_set_transport_param(uri,belle_sip_header_via_get_transport_lowercase(via_header));
}
return uri;
}
......@@ -515,7 +515,7 @@ void belle_sip_response_fill_for_dialog(belle_sip_response_t *obj, belle_sip_req
void belle_sip_response_get_return_hop(belle_sip_response_t *msg, belle_sip_hop_t *hop){
belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header(BELLE_SIP_MESSAGE(msg),"via"));
const char *host;
hop->transport=belle_sip_strdup(belle_sip_header_via_get_transport(via));
hop->transport=belle_sip_strdup(belle_sip_header_via_get_transport_lowercase(via));
host=belle_sip_header_via_get_received(via);
if (host==NULL)
host=belle_sip_header_via_get_host(via);
......
......@@ -19,12 +19,45 @@
#include "belle_sip_internal.h"
#include "listeningpoint_internal.h"
typedef struct authorization_context {
belle_sip_header_call_id_t* callid;
const char* scheme;
const char* realm;
const char* nonce;
const char* qop;
const char* opaque;
int nonce_count;
int is_proxy;
}authorization_context_t;
GET_SET_STRING(authorization_context,realm)
GET_SET_STRING(authorization_context,nonce)
GET_SET_STRING(authorization_context,qop)
GET_SET_STRING(authorization_context,scheme)
GET_SET_STRING(authorization_context,opaque)
GET_SET_INT(authorization_context,nonce_count,int)
static authorization_context_t* belle_sip_authorization_create(belle_sip_header_call_id_t* call_id) {
authorization_context_t* result = malloc(sizeof(authorization_context_t));
memset(result,0,sizeof(authorization_context_t));
result->callid=call_id;
belle_sip_object_ref(result->callid);
return result;
}
static void belle_sip_authorization_destroy(authorization_context_t* object) {
DESTROY_STRING(object,scheme);
DESTROY_STRING(object,realm);
DESTROY_STRING(object,nonce);
DESTROY_STRING(object,qop);
belle_sip_object_unref(object->callid);
belle_sip_free(object);
}
static void belle_sip_provider_uninit(belle_sip_provider_t *p){
belle_sip_list_free(p->listeners);
belle_sip_list_free_with_data(p->lps,belle_sip_object_unref);
belle_sip_list_free_with_data(p->client_transactions,belle_sip_object_unref);
belle_sip_list_free_with_data(p->server_transactions,belle_sip_object_unref);
belle_sip_list_free_with_data(p->auth_contexts,(void(*)(void*))belle_sip_authorization_destroy);
}
static void channel_state_changed(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_channel_state_t state){
......@@ -489,3 +522,142 @@ void belle_sip_provider_remove_server_transaction(belle_sip_provider_t *prov, be
prov->server_transactions=belle_sip_list_remove(prov->server_transactions,t);
belle_sip_object_unref(t);
}
static void authorization_context_fill_from_auth(authorization_context_t* auth_context,belle_sip_header_www_authenticate_t* authenticate) {
authorization_context_set_realm(auth_context,belle_sip_header_www_authenticate_get_realm(authenticate));
if (auth_context->nonce && strcmp(belle_sip_header_www_authenticate_get_nonce(authenticate),auth_context->nonce)!=0) {
/*new nonce, resetting nounce_count*/
auth_context->nonce_count=0;
}
authorization_context_set_nonce(auth_context,belle_sip_header_www_authenticate_get_nonce(authenticate));
authorization_context_set_qop(auth_context,belle_sip_header_www_authenticate_get_qop_first(authenticate));
authorization_context_set_scheme(auth_context,belle_sip_header_www_authenticate_get_scheme(authenticate));
authorization_context_set_opaque(auth_context,belle_sip_header_www_authenticate_get_opaque(authenticate));
if (belle_sip_object_is_instance_of(BELLE_SIP_OBJECT(authenticate),BELLE_SIP_TYPE_ID(belle_sip_header_proxy_authenticate_t))) {
auth_context->is_proxy=1;
}
}
static belle_sip_list_t* belle_sip_provider_get_auth_context_by_call_id(belle_sip_provider_t *p,belle_sip_header_call_id_t* call_id) {
belle_sip_list_t* auth_context_lst=NULL;
belle_sip_list_t* result=NULL;
authorization_context_t* auth_context;
for (auth_context_lst=p->auth_contexts;auth_context_lst!=NULL;auth_context_lst=auth_context_lst->next) {
auth_context=(authorization_context_t*)auth_context_lst->data;
if (belle_sip_header_call_id_equals(auth_context->callid,call_id) ) {
result=belle_sip_list_append(result,auth_context_lst->data);
}
}
return result;
}
static void belle_sip_provider_update_or_create_auth_context(belle_sip_provider_t *p,belle_sip_header_call_id_t* call_id,belle_sip_header_www_authenticate_t* authenticate) {
belle_sip_list_t* auth_context_lst = belle_sip_provider_get_auth_context_by_call_id(p,call_id);
authorization_context_t* auth_context;
for (;auth_context_lst!=NULL;auth_context_lst=auth_context_lst->next) {
auth_context= (authorization_context_t*)auth_context_lst->data;
if (strcmp(auth_context->realm,belle_sip_header_www_authenticate_get_realm(authenticate))==0) {
authorization_context_fill_from_auth(auth_context,authenticate);
if (auth_context_lst) belle_sip_free(auth_context_lst);
return; /*only one realm is supposed to be found for now*/
}
}
/*no auth context found, creating one*/
auth_context=belle_sip_authorization_create(call_id);
authorization_context_fill_from_auth(auth_context,authenticate);
p->auth_contexts=belle_sip_list_append(p->auth_contexts,auth_context);
if (auth_context_lst) belle_sip_free(auth_context_lst);
return;
}
int belle_sip_provider_add_authorization(belle_sip_provider_t *p, belle_sip_request_t* request,belle_sip_response_t *resp) {
belle_sip_header_call_id_t* call_id;
belle_sip_list_t* auth_context_lst;
belle_sip_list_t* authenticate_lst;
belle_sip_header_www_authenticate_t* authenticate;
belle_sip_header_authorization_t* authorization;
belle_sip_header_address_t* from;
belle_sip_auth_event_t* auth_event;
authorization_context_t* auth_context;
belle_sip_uri_t* from_uri;
const char* ha1;
char computed_ha1[33];
int result=0;
/*check params*/
if (!p || !request) {
belle_sip_error("belle_sip_provider_add_authorization bad parameters");
return-1;
}
/*get authenticates value from response*/
if (resp) {
call_id = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(resp),belle_sip_header_call_id_t);
/*searching for authentication headers*/
authenticate_lst = belle_sip_list_copy(belle_sip_message_get_headers(BELLE_SIP_MESSAGE(resp),BELLE_SIP_WWW_AUTHENTICATE));
/*search for proxy authenticate*/
authenticate_lst=belle_sip_list_append_link(authenticate_lst,belle_sip_list_copy(belle_sip_message_get_headers(BELLE_SIP_MESSAGE(resp),BELLE_SIP_PROXY_AUTHENTICATE)));
/*update auth contexts with authenticate headers from response*/
for (;authenticate_lst!=NULL;authenticate_lst=authenticate_lst->next) {
authenticate=BELLE_SIP_HEADER_WWW_AUTHENTICATE(authenticate_lst->data);
belle_sip_provider_update_or_create_auth_context(p,call_id,authenticate);
}
}
/*put authorization header if passwd found*/
call_id = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_call_id_t);
from = BELLE_SIP_HEADER_ADDRESS(belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_FROM));
from_uri = belle_sip_header_address_get_uri(from);
if ((auth_context_lst = belle_sip_provider_get_auth_context_by_call_id(p,call_id))) {
/*we assume there no existing auth headers*/
for (;auth_context_lst!=NULL;auth_context_lst=auth_context_lst->next) {
/*clear auth info*/
auth_context=(authorization_context_t*)auth_context_lst->data;
auth_event = belle_sip_auth_event_create(auth_context->realm,belle_sip_uri_get_user(from_uri));
/*put data*/
/*call listener*/
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(p,process_auth_requested,auth_event);
if (auth_event->passwd || auth_event->ha1) {
if (!auth_event->userid) {
/*if no userid, username = userid*/
belle_sip_auth_event_set_userid(auth_event,(const char*)auth_event->username);
}
belle_sip_message("Auth info found for [%s] realm [%s]",auth_event->userid,auth_event->realm);
if (auth_context->is_proxy) {
authorization=BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_header_proxy_authorization_new());
} else {
authorization=belle_sip_header_authorization_new();
}
belle_sip_header_authorization_set_scheme(authorization,auth_context->scheme);
belle_sip_header_authorization_set_realm(authorization,auth_context->realm);
belle_sip_header_authorization_set_username(authorization,auth_event->userid);
belle_sip_header_authorization_set_nonce(authorization,auth_context->nonce);
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_request_get_uri(request)/*belle_sip_uri_create(belle_sip_uri_get_user(belle_sip_request_get_uri(request))
,belle_sip_uri_get_host(belle_sip_request_get_uri(request)))*/);
belle_sip_header_authorization_set_nonce_count(authorization,++auth_context->nonce_count);
if (auth_event->ha1) {
ha1=auth_event->ha1;
} else {
belle_sip_auth_helper_compute_ha1(auth_event->userid,auth_context->realm,auth_event->passwd, computed_ha1);
ha1=computed_ha1;
}
if (belle_sip_auth_helper_fill_authorization(authorization
,belle_sip_request_get_method(request)
,ha1)) {
belle_sip_object_unref(authorization);
} else
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(authorization));
result=1;
} else {
belle_sip_message("No auth info found for call id [%s]",belle_sip_header_call_id_get_call_id(call_id));
}
}
belle_sip_list_free(auth_context_lst);
} else {
/*nothing to do*/
}
return result;
}
......@@ -345,3 +345,4 @@ belle_sip_dialog_t* belle_sip_transaction_get_dialog(const belle_sip_transactio
return t->dialog;
}
......@@ -225,7 +225,7 @@ static void test_extract_source() {
CU_ASSERT_PTR_NOT_NULL(source);
CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(source),"37.59.129.73");
CU_ASSERT_EQUAL(belle_sip_uri_get_port(source),0);
CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_transport_param(source),"TCP");
CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_transport_param(source),"tcp");
belle_sip_object_unref(message);
message = belle_sip_message_parse(invite_2);
......@@ -234,7 +234,7 @@ static void test_extract_source() {
CU_ASSERT_PTR_NOT_NULL(source);
CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(source),"81.56.113.2");
CU_ASSERT_EQUAL(belle_sip_uri_get_port(source),15060);
CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_transport_param(source),"UDP");
CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_transport_param(source),"udp");
belle_sip_object_unref(message);
}
......
......@@ -22,7 +22,9 @@
#include "pthread.h"
const char *test_domain="test.linphone.org";
const char *auth_domain="sip.linphone.org";
static int is_register_ok;
static int number_of_challange;
static int using_transaction;
belle_sip_stack_t * stack;
belle_sip_provider_t *prov;
......@@ -39,13 +41,31 @@ static void process_io_error(belle_sip_listener_t *obj, const belle_sip_io_error
static void process_request_event(belle_sip_listener_t *obj, const belle_sip_request_event_t *event){
belle_sip_message("process_request_event");
}
belle_sip_request_t* authorized_request;
static void process_response_event(belle_sip_listener_t *obj, const belle_sip_response_event_t *event){
belle_sip_message("process_response_event");
int status;
belle_sip_request_t* request;
CU_ASSERT_PTR_NOT_NULL_FATAL(belle_sip_response_event_get_response(event));
CU_ASSERT_EQUAL(belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)),200);
is_register_ok=1;
using_transaction=belle_sip_response_event_get_client_transaction(event)!=NULL;
belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack));
belle_sip_message("process_response_event [%i] [%s]"
,status=belle_sip_response_get_status_code(belle_sip_response_event_get_response(event))
,belle_sip_response_get_reason_phrase(belle_sip_response_event_get_response(event)));
if (status==401) {
CU_ASSERT_NOT_EQUAL_FATAL(number_of_challange,2);
CU_ASSERT_PTR_NOT_NULL_FATAL(belle_sip_response_event_get_client_transaction(event)); /*require transaction mode*/
request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(belle_sip_response_event_get_client_transaction(event)));
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CSEQ);
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
CU_ASSERT_TRUE_FATAL(belle_sip_provider_add_authorization(prov,request,belle_sip_response_event_get_response(event)));
belle_sip_client_transaction_t *t=belle_sip_provider_create_client_transaction(prov,request);
belle_sip_client_transaction_send_request(t);
number_of_challange++;
authorized_request=request;
} else {
CU_ASSERT_EQUAL(status,200);
is_register_ok=1;
using_transaction=belle_sip_response_event_get_client_transaction(event)!=NULL;
belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack));
}
}
static void process_timeout(belle_sip_listener_t *obj, const belle_sip_timeout_event_t *event){
belle_sip_message("process_timeout");
......@@ -53,7 +73,12 @@ static void process_timeout(belle_sip_listener_t *obj, const belle_sip_timeout_e
static void process_transaction_terminated(belle_sip_listener_t *obj, const belle_sip_transaction_terminated_event_t *event){
belle_sip_message("process_transaction_terminated");
}
static void process_auth_requested(belle_sip_listener_t *obj, belle_sip_auth_event_t *event){
belle_sip_message("process_auth_requested requested for [%s@%s]"
,belle_sip_auth_event_get_username(event)
,belle_sip_auth_event_get_realm(event));
belle_sip_auth_event_set_passwd(event,"secret");
}
/*this would normally go to a .h file*/
struct test_listener{
belle_sip_object_t base;
......@@ -76,7 +101,8 @@ BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(test_listener_t,belle_sip_listener_t)
process_request_event,
process_response_event,
process_timeout,
process_transaction_terminated
process_transaction_terminated,
process_auth_requested
BELLE_SIP_IMPLEMENT_INTERFACE_END
BELLE_SIP_DECLARE_IMPLEMENTED_INTERFACES_1(test_listener_t,belle_sip_listener_t);
......@@ -123,6 +149,9 @@ void unregister_user(belle_sip_stack_t * stack
belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_EXPIRES);
belle_sip_header_expires_set_expires(expires_header,0);
if (use_transaction){
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);
belle_sip_provider_add_authorization(prov,req,NULL); /*just in case*/
belle_sip_client_transaction_t *t=belle_sip_provider_create_client_transaction(prov,req);
belle_sip_client_transaction_send_request(t);
}else belle_sip_provider_send_request(prov,req);
......@@ -131,25 +160,26 @@ void unregister_user(belle_sip_stack_t * stack
CU_ASSERT_EQUAL(using_transaction,use_transaction);
belle_sip_provider_remove_sip_listener(prov,l);
}
belle_sip_request_t* register_user(belle_sip_stack_t * stack
belle_sip_request_t* register_user_at_domain(belle_sip_stack_t * stack
,belle_sip_provider_t *prov
,const char *transport
,int use_transaction
,const char* username) {
,const char* username
,const char* domain) {
belle_sip_request_t *req,*copy;
char identity[256];
char uri[256];
if (transport)
snprintf(uri,sizeof(uri),"sip:%s;transport=%s",test_domain,transport);
else snprintf(uri,sizeof(uri),"sip:%s",test_domain);
snprintf(uri,sizeof(uri),"sip:%s;transport=%s",domain,transport);
else snprintf(uri,sizeof(uri),"sip:%s",domain);
if (transport && strcasecmp("tls",transport)==0 && belle_sip_provider_get_listening_point(prov,"tls")==NULL){
belle_sip_error("No TLS support, test skipped.");
return NULL;
}
snprintf(identity,sizeof(identity),"Tester <sip:%s@%s>",username,test_domain);
snprintf(identity,sizeof(identity),"Tester <sip:%s@%s>",username,domain);
req=belle_sip_request_create(
belle_sip_uri_parse(uri),
"REGISTER",
......@@ -177,7 +207,13 @@ belle_sip_request_t* register_user(belle_sip_stack_t * stack
return copy;
}
belle_sip_request_t* register_user(belle_sip_stack_t * stack
,belle_sip_provider_t *prov
,const char *transport
,int use_transaction
,const char* username) {
return register_user_at_domain(stack,prov,transport,use_transaction,username,test_domain);
}
static void register_test(const char *transport, int use_transaction) {
belle_sip_request_t *req;
req=register_user(stack, prov, transport,use_transaction,"tester");
......@@ -257,14 +293,20 @@ static void test_bad_request() {
belle_sip_stack_sleep(stack,100);
belle_sip_provider_remove_sip_listener(prov,bad_req_listener);
}
static void test_register_authenticate() {
number_of_challange=0;
authorized_request=NULL;
register_user_at_domain(stack, prov, "udp",1,"bellesip",auth_domain);
if (authorized_request) unregister_user(stack,prov,authorized_request,1);
}
int belle_sip_register_test_suite(){
CU_pSuite pSuite = CU_add_suite("Register", register_init, register_uninit);
if (NULL == CU_add_test(pSuite, "stateful udp register", stateful_register_udp)) {
if (NULL == CU_add_test(pSuite, "stateful-udp-register", stateful_register_udp)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "stateful udp register with network delay", stateful_register_udp_delayed)) {
if (NULL == CU_add_test(pSuite, "stateful-udp-register-with-network-delay", stateful_register_udp_delayed)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "stateful tcp register", stateful_register_tcp)) {
......@@ -285,6 +327,9 @@ int belle_sip_register_test_suite(){
if (NULL == CU_add_test(pSuite, "Bad request tcp", test_bad_request)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "authenticate", test_register_authenticate)) {
return CU_get_error();
}
return 0;
}
......@@ -24,6 +24,7 @@
#include <belle-sip/belle-sip.h>
extern const char *test_domain;