Commit 7b7049be authored by Simon Morlat's avatar Simon Morlat

work in progress

parent 445c1364
......@@ -110,6 +110,8 @@ BELLESIP_EXPORT void belle_sip_message_remove_header(belle_sip_message_t *msg, c
BELLESIP_EXPORT char *belle_sip_message_to_string(belle_sip_message_t *msg);
BELLESIP_EXPORT const char* belle_sip_message_get_body(belle_sip_message_t *msg);
BELLESIP_EXPORT unsigned int belle_sip_message_get_body_size(const belle_sip_message_t *msg);
BELLESIP_EXPORT void belle_sip_message_set_body(belle_sip_message_t *msg,const char* body,unsigned int size);
BELLESIP_EXPORT void belle_sip_message_assign_body(belle_sip_message_t *msg, char* body, unsigned int size);
......
......@@ -4,7 +4,7 @@ SUBDIRS=grammars
noinst_LTLIBRARIES=libbellesip_tls.la
#to disable warning introduced by compatibility between polar 1.2 and 1.3
libbellesip_tls_la_SOURCES= transports/tls_listeningpoint_polarssl.c transports/tls_channel_polarssl.c http-listener.c
libbellesip_tls_la_SOURCES= transports/tls_listeningpoint_polarssl.c transports/tls_channel_polarssl.c
libbellesip_tls_la_CFLAGS=$(LESS_STRICT_OPTIONS) $(TLS_CFLAGS) $(LIBBELLESIP_CFLAGS)
......@@ -48,7 +48,8 @@ libbellesip_la_SOURCES= \
belle_sip_dict.c \
generic-uri.c \
http-provider.c \
http-message.c
http-message.c \
http-listener.c
if BUILD_TUNNEL
......
......@@ -607,6 +607,7 @@ struct belle_http_request{
belle_http_request_listener_t *listener;
belle_generic_uri_t *orig_uri;/*original uri before removing host and user/passwd*/
belle_http_response_t *response;
int auth_attempt_count;
};
void belle_http_request_set_listener(belle_http_request_t *req, belle_http_request_listener_t *l);
......
......@@ -814,7 +814,7 @@ belle_sip_channel_t *belle_sip_channel_find_from_list_with_addrinfo(belle_sip_li
for(elem=l;elem!=NULL;elem=elem->next){
chan=(belle_sip_channel_t*)elem->data;
if (belle_sip_channel_matches(chan,hop,addr)){
if (!chan->about_to_be_closed && belle_sip_channel_matches(chan,hop,addr)){
return chan;
}
}
......
......@@ -100,6 +100,7 @@ struct belle_sip_channel{
unsigned char force_close; /* when channel is intentionnaly disconnected, in order to prevent looping notifications*/
unsigned char learnt_ip_port;
unsigned char has_name; /*set when the name of the peer is known, which is not the case of inboud connections*/
unsigned char about_to_be_closed;
};
#define BELLE_SIP_CHANNEL(obj) BELLE_SIP_CAST(obj,belle_sip_channel_t)
......
......@@ -53,6 +53,10 @@ static int http_channel_context_handle_authentication(belle_http_channel_context
int ret=0;
(void)resp;
if (req->auth_attempt_count>1){
req->auth_attempt_count=0;
return -1;
}
/*find if username, passwd were already supplied in original request uri*/
if (req->orig_uri){
......@@ -71,7 +75,7 @@ static int http_channel_context_handle_authentication(belle_http_channel_context
if (username && passwd){
/*TODO resubmit the request to the provider with authentication added*/
req->auth_attempt_count++;
belle_http_provider_send_request(ctx->provider,req,NULL);
}else ret=-1;
......@@ -79,16 +83,21 @@ static int http_channel_context_handle_authentication(belle_http_channel_context
return ret;
}
static void http_channel_context_handle_response(belle_http_channel_context_t *ctx , belle_http_response_t *response){
static void http_channel_context_handle_response(belle_http_channel_context_t *ctx , belle_sip_channel_t *chan, belle_http_response_t *response){
belle_http_request_t *req=NULL;
belle_http_response_event_t ev={0};
int code;
belle_sip_header_t *connection;
/*pop the request matching this response*/
ctx->pending_requests=belle_sip_list_pop_front(ctx->pending_requests,(void**)&req);
if (req==NULL){
belle_sip_error("Receiving http response not matching any request.");
return;
}
connection=belle_sip_message_get_header((belle_sip_message_t *)response,"Connection");
if (connection && strstr(belle_sip_header_get_unparsed_value(connection),"close")!=NULL)
chan->about_to_be_closed=TRUE;
belle_http_request_set_response(req,response);
code=belle_http_response_get_status_code(response);
if ((code==401 || code==407) && http_channel_context_handle_authentication(ctx,req)==0 ){
......@@ -109,7 +118,7 @@ static int channel_on_event(belle_sip_channel_listener_t *obj, belle_sip_channel
belle_sip_message_t *msg;
while((msg=belle_sip_channel_pick_message(chan))!=NULL){
if (msg && BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_http_response_t)){
http_channel_context_handle_response(ctx,(belle_http_response_t*)msg);
http_channel_context_handle_response(ctx,chan,(belle_http_response_t*)msg);
}
belle_sip_object_unref(msg);
}
......@@ -122,7 +131,7 @@ static int channel_on_auth_requested(belle_sip_channel_listener_t *obj, belle_si
if (BELLE_SIP_IS_INSTANCE_OF(chan,belle_sip_tls_channel_t)) {
belle_sip_auth_event_t* auth_event = belle_sip_auth_event_create((belle_sip_object_t*)ctx->provider,NULL,NULL);
belle_sip_tls_channel_t *tls_chan=BELLE_SIP_TLS_CHANNEL(chan);
belle_http_request_t *req=(belle_http_request_t*)ctx->pending_requests->data;
belle_http_request_t *req=(belle_http_request_t*)chan->outgoing_messages->data;
auth_event->mode=BELLE_SIP_AUTH_MODE_TLS;
belle_sip_auth_event_set_distinguished_name(auth_event,distinguished_name);
......@@ -137,6 +146,7 @@ static int channel_on_auth_requested(belle_sip_channel_listener_t *obj, belle_si
static void channel_on_sending(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
belle_http_channel_context_t *ctx=BELLE_HTTP_CHANNEL_CONTEXT(obj);
ctx->pending_requests=belle_sip_list_append(ctx->pending_requests,belle_sip_object_ref(msg));
}
static void channel_state_changed(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_channel_state_t state){
......@@ -211,11 +221,16 @@ belle_http_provider_t *belle_http_provider_new(belle_sip_stack_t *s, const char
static void split_request_url(belle_http_request_t *req){
belle_generic_uri_t *uri=belle_http_request_get_uri(req);
belle_generic_uri_t *new_uri=belle_generic_uri_new();
belle_generic_uri_t *new_uri;
char *host_value;
const char *path;
belle_sip_message("Path is: %s",belle_generic_uri_get_path(uri));
belle_generic_uri_set_path(new_uri,belle_generic_uri_get_path(uri));
if (belle_generic_uri_get_host(uri)==NULL && req->orig_uri!=NULL) return;/*already processed request uri*/
path=belle_generic_uri_get_path(uri);
if (path==NULL) path="/";
new_uri=belle_generic_uri_new();
belle_generic_uri_set_path(new_uri,path);
if (belle_generic_uri_get_port(uri)>0)
host_value=belle_sip_strdup_printf("%s:%i",belle_generic_uri_get_host(uri),belle_generic_uri_get_port(uri));
else
......@@ -226,6 +241,14 @@ static void split_request_url(belle_http_request_t *req){
belle_http_request_set_uri(req,new_uri);
}
static void fix_request(belle_http_request_t *req){
unsigned int size=belle_sip_message_get_body_size((belle_sip_message_t*)req);
belle_sip_header_content_length_t *ctlen=belle_sip_message_get_header_by_type(req, belle_sip_header_content_length_t);
if (size>0 && !ctlen){
belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_length_create((int)size));
}
}
static belle_sip_list_t **provider_get_channels(belle_http_provider_t *obj, const char *transport_name){
if (strcasecmp(transport_name,"tcp")==0) return &obj->tcp_channels;
else if (strcasecmp(transport_name,"tls")==0) return &obj->tls_channels;
......@@ -244,7 +267,7 @@ static void provider_remove_channel(belle_http_provider_t *obj, belle_sip_channe
int belle_http_provider_send_request(belle_http_provider_t *obj, belle_http_request_t *req, belle_http_request_listener_t *listener){
belle_sip_channel_t *chan;
belle_sip_hop_t *hop=belle_sip_hop_new_from_generic_uri(belle_http_request_get_uri(req));
belle_sip_hop_t *hop=belle_sip_hop_new_from_generic_uri(req->orig_uri ? req->orig_uri : req->req_uri);
belle_sip_list_t **channels=provider_get_channels(obj,hop->transport);
if (listener) belle_http_request_set_listener(req,listener);
......@@ -254,14 +277,23 @@ int belle_http_provider_send_request(belle_http_provider_t *obj, belle_http_requ
if (!chan){
if (strcasecmp(hop->transport,"tcp")==0){
chan=belle_sip_stream_channel_new_client(obj->stack,obj->bind_ip,0,hop->cname,hop->host,hop->port);
}else if (strcasecmp(hop->transport,"tls")==0){
}
#ifdef HAVE_POLARSSL
else if (strcasecmp(hop->transport,"tls")==0){
chan=belle_sip_channel_new_tls(obj->stack,obj->verify_ctx,obj->bind_ip,0,hop->cname,hop->host,hop->port);
}
#endif
if (!chan){
belle_sip_error("belle_http_provider_send_request(): cannot create channel for [%s:%s:%i]",hop->transport,hop->cname,hop->port);
belle_sip_object_unref(hop);
return -1;
}
belle_http_channel_context_new(chan,obj);
*channels=belle_sip_list_prepend(*channels,chan);
}
belle_sip_object_unref(hop);
split_request_url(req);
fix_request(req);
belle_sip_channel_queue_message(chan,BELLE_SIP_MESSAGE(req));
return 0;
}
......
......@@ -370,6 +370,10 @@ const char* belle_sip_message_get_body(belle_sip_message_t *msg) {
return msg->body;
}
unsigned int belle_sip_message_get_body_size(const belle_sip_message_t *msg){
return msg->body_length;
}
void belle_sip_message_set_body(belle_sip_message_t *msg, const char* body, unsigned int size) {
if (msg->body) {
belle_sip_free(msg->body);
......
......@@ -89,7 +89,9 @@ static int tls_channel_send(belle_sip_channel_t *obj, const void *buf, size_t bu
belle_sip_tls_channel_t* channel = (belle_sip_tls_channel_t*)obj;
int err = ssl_write(&channel->sslctx,buf,buflen);
if (err<0){
belle_sip_error("Channel [%p]: error in ssl_write().",obj);
char tmp[256]={0};
error_strerror(err,tmp,sizeof(tmp));
belle_sip_error("Channel [%p]: ssl_write() error [%i]: %s",obj,err,tmp);
}
return err;
}
......@@ -97,8 +99,11 @@ static int tls_channel_send(belle_sip_channel_t *obj, const void *buf, size_t bu
static int tls_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
belle_sip_tls_channel_t* channel = (belle_sip_tls_channel_t*)obj;
int err = ssl_read(&channel->sslctx,buf,buflen);
if (err==POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) return 0;
if (err<0){
belle_sip_error("Channel [%p]: error in ssl_read().",obj);
char tmp[256]={0};
error_strerror(err,tmp,sizeof(tmp));
belle_sip_error("Channel [%p]: ssl_read() error [%i]: %s",obj, err, tmp);
}
return err;
}
......
......@@ -55,18 +55,40 @@ static void process_io_error(void *data, const belle_sip_io_error_event_t *event
}
static void process_auth_requested(void *data, belle_sip_auth_event_t *event){
if (belle_sip_auth_event_get_mode(event)==BELLE_SIP_AUTH_MODE_TLS){
belle_sip_certificates_chain_t* cert = belle_sip_certificates_chain_parse(belle_sip_tester_client_cert,strlen(belle_sip_tester_client_cert),BELLE_SIP_CERTIFICATE_RAW_FORMAT_PEM);
belle_sip_signing_key_t* key = belle_sip_signing_key_parse(belle_sip_tester_private_key,strlen(belle_sip_tester_private_key),belle_sip_tester_private_key_passwd);
belle_sip_auth_event_set_client_certificates_chain(event,cert);
belle_sip_auth_event_set_signing_key(event,key);
belle_sip_message("process_auth_requested requested for DN [%s]"
,belle_sip_auth_event_get_distinguished_name(event));
}
}
static belle_sip_stack_t *stack=NULL;
static belle_http_provider_t *prov=NULL;
static int http_init(void){
stack=belle_sip_stack_new(NULL);
prov=belle_sip_stack_create_http_provider(stack,"0.0.0.0");
return 0;
}
static int http_cleanup(void){
belle_sip_object_unref(prov);
belle_sip_object_unref(stack);
return 0;
}
static void one_get(int secure, const char *keyfile, const char *certfile){
belle_sip_stack_t *stack=belle_sip_stack_new(NULL);
belle_http_provider_t *prov=belle_sip_stack_create_http_provider(stack,"0.0.0.0");
static void one_get(const char *url){
belle_http_request_listener_callbacks_t cbs={0};
http_counters_t counters={0};
belle_http_request_listener_t *l;
belle_generic_uri_t *uri=belle_generic_uri_parse("http://smtp.linphone.org/");
belle_generic_uri_t *uri;
belle_http_request_t *req;
if (secure) belle_generic_uri_set_scheme(uri,"https");
uri=belle_generic_uri_parse(url);
req=belle_http_request_create("GET",
uri,
belle_sip_header_create("User-Agent","belle-sip/"PACKAGE_VERSION),
......@@ -81,27 +103,40 @@ static void one_get(int secure, const char *keyfile, const char *certfile){
CU_ASSERT_TRUE(counters.io_error_count==0);
belle_sip_object_unref(l);
belle_sip_object_unref(prov);
belle_sip_object_unref(stack);
}
static void one_http_get(void){
one_get(FALSE,NULL,NULL);
one_get("http://smtp.linphone.org");
}
static void one_https_get(void){
one_get(TRUE,NULL,NULL);
one_get("https://smtp.linphone.org");
}
static void https_digest_get(void){
one_get("https://pauline:pouet@smtp.linphone.org/restricted");
}
static void https_client_cert_connection(void){
belle_tls_verify_policy_t *policy=belle_tls_verify_policy_new();
belle_tls_verify_policy_set_exceptions(policy,BELLE_TLS_VERIFY_ANY_REASON);/*ignore the server verification because we don't have a true certificate*/
belle_http_provider_set_tls_verify_policy(prov,policy);
one_get("https://sip2.linphone.org:5063");
belle_tls_verify_policy_set_exceptions(policy,0);
belle_sip_object_unref(policy);
}
test_t http_tests[] = {
{ "One http GET", one_http_get },
{ "One https GET", one_https_get },
{ "https digest GET", https_digest_get },
{ "https with client certificate", https_client_cert_connection },
};
test_suite_t http_test_suite = {
"http",
NULL,
NULL,
http_init,
http_cleanup,
sizeof(http_tests) / sizeof(http_tests[0]),
http_tests
};
......
......@@ -28,7 +28,7 @@
const char *test_domain="test.linphone.org";
const char *auth_domain="sip.linphone.org";
const char *client_auth_domain="client.example.org";
const char *client_auth_outband_proxy="sips:sip2.linphone.org:5063";
const char *client_auth_outbound_proxy="sips:sip2.linphone.org:5063";
static int is_register_ok;
static int number_of_challenge;
......@@ -103,7 +103,7 @@ static void process_transaction_terminated(void *user_ctx, const belle_sip_trans
belle_sip_message("process_transaction_terminated");
}
static const char* client_cert = /*for URI:sip:tester@client.example.org*/
const char* belle_sip_tester_client_cert = /*for URI:sip:tester@client.example.org*/
"-----BEGIN CERTIFICATE-----\n"
"MIIDYzCCAsygAwIBAgIBCDANBgkqhkiG9w0BAQUFADCBuzELMAkGA1UEBhMCRlIx\n"
"EzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAcMCEdyZW5vYmxlMSIwIAYDVQQK\n"
......@@ -127,7 +127,7 @@ static const char* client_cert = /*for URI:sip:tester@client.example.org*/
"-----END CERTIFICATE-----";
static const char* private_key =
const char* belle_sip_tester_private_key =
"-----BEGIN ENCRYPTED PRIVATE KEY-----\n"
"MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIbEHnQwhgRwoCAggA\n"
"MBQGCCqGSIb3DQMHBAgmrtCEBCP9kASCAoCq9EKInROalaBSLWY44U4RVAC+CKdx\n"
......@@ -146,7 +146,7 @@ static const char* private_key =
"WEuSefVM4xgB+mfQauAJu2N9yKhzXOytslZflpa06qJedlLYFk9njvcv\n"
"-----END ENCRYPTED PRIVATE KEY-----\n";
static const char* private_key_passwd="secret";
const char* belle_sip_tester_private_key_passwd="secret";
static void process_auth_requested(void *user_ctx, belle_sip_auth_event_t *event){
......@@ -157,8 +157,8 @@ static void process_auth_requested(void *user_ctx, belle_sip_auth_event_t *event
,belle_sip_auth_event_get_realm(event));
belle_sip_auth_event_set_passwd(event,"secret");
} else if (belle_sip_auth_event_get_mode(event) == BELLE_SIP_AUTH_MODE_TLS) {
belle_sip_certificates_chain_t* cert = belle_sip_certificates_chain_parse(client_cert,strlen(client_cert),BELLE_SIP_CERTIFICATE_RAW_FORMAT_PEM);
belle_sip_signing_key_t* key = belle_sip_signing_key_parse(private_key,strlen(private_key),private_key_passwd);
belle_sip_certificates_chain_t* cert = belle_sip_certificates_chain_parse(belle_sip_tester_client_cert,strlen(belle_sip_tester_client_cert),BELLE_SIP_CERTIFICATE_RAW_FORMAT_PEM);
belle_sip_signing_key_t* key = belle_sip_signing_key_parse(belle_sip_tester_private_key,strlen(belle_sip_tester_private_key),belle_sip_tester_private_key_passwd);
belle_sip_auth_event_set_client_certificates_chain(event,cert);
belle_sip_auth_event_set_signing_key(event,key);
belle_sip_message("process_auth_requested requested for DN[%s]"
......@@ -300,8 +300,8 @@ belle_sip_request_t* register_user_at_domain(belle_sip_stack_t * stack
,int use_transaction
,const char* username
,const char* domain
,const char* outband) {
return try_register_user_at_domain(stack,prov,transport,use_transaction,username,domain,outband,1);
,const char* outbound) {
return try_register_user_at_domain(stack,prov,transport,use_transaction,username,domain,outbound,1);
}
......@@ -464,7 +464,7 @@ static void test_register_client_authenticated(void) {
/*we don't care to check sercer cert*/
belle_sip_tls_listening_point_set_verify_exceptions( (belle_sip_tls_listening_point_t*)belle_sip_provider_get_listening_point(prov,"tls")
,BELLE_SIP_TLS_LISTENING_POINT_BADCERT_ANY_REASON);
reg=register_user_at_domain(stack, prov, "tls",1,"tester",client_auth_domain,client_auth_outband_proxy);
reg=register_user_at_domain(stack, prov, "tls",1,"tester",client_auth_domain,client_auth_outbound_proxy);
if (authorized_request) {
unregister_user(stack,prov,authorized_request,1);
belle_sip_object_unref(authorized_request);
......
......@@ -67,6 +67,9 @@ extern void belle_sip_tester_init(void);
extern void belle_sip_tester_uninit(void);
extern int belle_sip_tester_run_tests(const char *suite_name, const char *test_name);
extern const char* belle_sip_tester_client_cert;
extern const char* belle_sip_tester_private_key;
extern const char* belle_sip_tester_private_key_passwd;
#ifdef __cplusplus
};
......
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