Commit c23e2d10 authored by jehan's avatar jehan

add http proxy support for TLS listening point

parent c93a0161
......@@ -69,6 +69,12 @@ BELLESIP_EXPORT int belle_sip_tls_listening_point_set_verify_exceptions(belle_si
BELLESIP_EXPORT int belle_sip_tls_listening_point_set_verify_policy(belle_sip_tls_listening_point_t *s, belle_tls_verify_policy_t *pol);
BELLESIP_EXPORT void belle_sip_tls_listening_point_set_http_proxy_addr(belle_sip_tls_listening_point_t *s, const char* proxy_addr);
BELLESIP_EXPORT void belle_sip_tls_listening_point_set_http_proxy_port(belle_sip_tls_listening_point_t *s, int port);
BELLESIP_EXPORT const char *belle_sip_tls_listening_point_get_http_proxy_addr(const belle_sip_tls_listening_point_t *s);
BELLESIP_EXPORT int belle_sip_tls_listening_point_get_http_proxy_port(const belle_sip_tls_listening_point_t *s);
BELLESIP_EXPORT belle_sip_listening_point_t * belle_sip_tunnel_listening_point_new(belle_sip_stack_t *s, void *tunnelclient);
......
......@@ -1253,13 +1253,18 @@ static void channel_res_done(void *data, const char *name, struct addrinfo *ai_l
channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
}
}
belle_sip_resolver_context_t * belle_sip_channel_resolve_base(belle_sip_channel_t *obj,belle_sip_resolver_callback_t res_done, const char * peer_name,int peer_port, int ai_family){
belle_sip_resolver_context_t *resolver = NULL;
if (belle_sip_stack_dns_srv_enabled(obj->stack) && obj->lp!=NULL)
resolver=belle_sip_stack_resolve(obj->stack, belle_sip_channel_get_transport_name_lower_case(obj), peer_name, peer_port, ai_family, res_done, obj);
else
obj->resolver_ctx=belle_sip_stack_resolve_a(obj->stack, peer_name, peer_port, ai_family, res_done, obj);
return resolver;
}
void belle_sip_channel_resolve(belle_sip_channel_t *obj){
channel_set_state(obj,BELLE_SIP_CHANNEL_RES_IN_PROGRESS);
if (belle_sip_stack_dns_srv_enabled(obj->stack) && obj->lp!=NULL)
obj->resolver_ctx=belle_sip_stack_resolve(obj->stack, belle_sip_channel_get_transport_name_lower_case(obj), obj->peer_name, obj->peer_port, obj->ai_family, channel_res_done, obj);
else
obj->resolver_ctx=belle_sip_stack_resolve_a(obj->stack, obj->peer_name, obj->peer_port, obj->ai_family, channel_res_done, obj);
obj->resolver_ctx = belle_sip_channel_resolve_base(obj,channel_res_done, obj->peer_name, obj->peer_port, obj->ai_family);
if (obj->resolver_ctx){
belle_sip_object_ref(obj->resolver_ctx);
}
......
......@@ -137,6 +137,9 @@ int belle_sip_channel_matches(const belle_sip_channel_t *obj, const belle_sip_ho
void belle_sip_channel_resolve(belle_sip_channel_t *obj);
belle_sip_resolver_context_t * belle_sip_channel_resolve_base(belle_sip_channel_t *obj,belle_sip_resolver_callback_t res_done, const char * peer_name,int peer_port, int ai_family);
void belle_sip_channel_connect(belle_sip_channel_t *obj);
void belle_sip_channel_prepare(belle_sip_channel_t *obj);
......
......@@ -92,6 +92,10 @@ belle_sip_listening_point_t * belle_sip_stream_listening_point_new(belle_sip_sta
struct belle_sip_tls_listening_point{
belle_sip_stream_listening_point_t base;
belle_tls_verify_policy_t *verify_ctx;
char *http_proxy_addr;
int http_proxy_port;
char *http_proxy_username; /*for futur use*/
char *http_proxy_passwd; /*for futur use*/
};
int belle_sip_tls_listening_point_available(void);
......@@ -102,6 +106,7 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_END
belle_sip_listening_point_t * belle_sip_tls_listening_point_new(belle_sip_stack_t *s, const char *ipaddress, int port);
belle_sip_channel_t * belle_sip_channel_new_tls(belle_sip_stack_t *s, belle_tls_verify_policy_t* verify_ctx, const char *bindip, int localport,const char *cname, const char *name, int port);
/*tunnel*/
#ifdef HAVE_TUNNEL
typedef struct belle_sip_tunnel_listening_point belle_sip_tunnel_listening_point_t;
......
......@@ -33,6 +33,7 @@
#include <polarssl/sha1.h>
#include <polarssl/sha256.h>
#include <polarssl/sha512.h>
#include "polarssl/base64.h"
#endif
#endif
......@@ -122,6 +123,8 @@ struct belle_sip_tls_channel{
belle_sip_certificates_chain_t* client_cert_chain;
belle_sip_signing_key_t* client_cert_key;
belle_tls_verify_policy_t *verify_ctx;
int http_proxy_connected;
belle_sip_resolver_context_t *http_proxy_resolver_ctx;
};
static void tls_channel_close(belle_sip_tls_channel_t *obj){
......@@ -148,6 +151,7 @@ static void tls_channel_uninit(belle_sip_tls_channel_t *obj){
belle_sip_object_unref(obj->verify_ctx);
if (obj->client_cert_chain) belle_sip_object_unref(obj->client_cert_chain);
if (obj->client_cert_key) belle_sip_object_unref(obj->client_cert_key);
if (obj->http_proxy_resolver_ctx) belle_sip_object_unref(obj->http_proxy_resolver_ctx);
}
static int tls_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen){
......@@ -175,8 +179,9 @@ static int tls_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
return err;
}
static int tls_channel_connect(belle_sip_channel_t *obj, const struct addrinfo *ai){
int err= stream_channel_connect((belle_sip_stream_channel_t*)obj,ai);
static int tls_channel_connect_to(belle_sip_channel_t *obj, const struct addrinfo *ai){
int err;
err= stream_channel_connect((belle_sip_stream_channel_t*)obj,ai);
if (err==0){
belle_sip_source_set_notify((belle_sip_source_t *)obj, (belle_sip_source_func_t)tls_process_data);
return 0;
......@@ -184,6 +189,34 @@ static int tls_channel_connect(belle_sip_channel_t *obj, const struct addrinfo *
return -1;
}
static void http_proxy_res_done(void *data, const char *name, struct addrinfo *ai_list){
belle_sip_tls_channel_t *obj=(belle_sip_tls_channel_t*)data;
if (obj->http_proxy_resolver_ctx){
belle_sip_object_unref(obj->http_proxy_resolver_ctx);
obj->http_proxy_resolver_ctx=NULL;
}
if (ai_list){
tls_channel_connect_to((belle_sip_channel_t *)obj,ai_list);
}else{
belle_sip_error("%s: DNS resolution failed for %s", __FUNCTION__, name);
channel_set_state((belle_sip_channel_t*)obj,BELLE_SIP_CHANNEL_ERROR);
}
}
static int tls_channel_connect(belle_sip_channel_t *obj, const struct addrinfo *ai){
belle_sip_tls_listening_point_t * lp = (belle_sip_tls_listening_point_t * )obj->lp;
belle_sip_tls_channel_t *channel=(belle_sip_tls_channel_t*)obj;
if (lp->http_proxy_addr) {
belle_sip_message("Resolving http proxy addr [%s] for channel [%p]",lp->http_proxy_addr,obj);
/*assume ai family is the same*/
channel->http_proxy_resolver_ctx = belle_sip_stack_resolve_a(obj->stack, lp->http_proxy_addr, lp->http_proxy_port, obj->ai_family, http_proxy_res_done, obj);
if (channel->http_proxy_resolver_ctx) belle_sip_object_ref(channel->http_proxy_resolver_ctx);
return 0;
} else {
return tls_channel_connect_to(obj, ai);
}
}
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_tls_channel_t,belle_sip_stream_channel_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
......@@ -269,21 +302,97 @@ static int tls_process_handshake(belle_sip_channel_t *obj){
return 0;
}
static int tls_process_http_connect(belle_sip_tls_channel_t *obj) {
char* request;
belle_sip_channel_t *channel = (belle_sip_channel_t *)obj;
belle_sip_tls_listening_point_t* lp = (belle_sip_tls_listening_point_t*)(channel->lp);
int err;
char ip[64];
int port;
belle_sip_addrinfo_to_ip(channel->current_peer,ip,sizeof(ip),&port);
request = belle_sip_strdup_printf("CONNECT %s:%i HTTP/1.1\r\nProxy-Connection: keep-alive\r\nConnection: keep-alive\r\nHost: %s\r\nUser-Agent: Mozilla/5.0\r\n"
,ip
,port
,ip);
if (lp->http_proxy_username && lp->http_proxy_passwd) {
char username_passwd = belle_sip_strdup_printf("%s:%s",lp->http_proxy_username,lp->http_proxy_passwd);
size_t username_passwd_length = strlen(username_passwd);
unsigned char *encoded_username_paswd = belle_sip_malloc(2*username_passwd_length);
base64_encode(encoded_username_paswd,2*username_passwd_length,username_passwd,username_passwd_length);
belle_sip_strcat_printf(request, "Proxy-Authorization: Basic %s\r\n",encoded_username_paswd);
belle_sip_free(username_passwd);
belle_sip_free(encoded_username_paswd);
}
belle_sip_strcat_printf(request,"\r\n");
err = send(belle_sip_source_get_socket((belle_sip_source_t*)obj),request,strlen(request),0);
belle_sip_free(request);
if (err <= 0) {
belle_sip_error("tls_process_http_connect: fail to send connect request to http proxy [%s:%i] status [%s]"
,lp->http_proxy_addr
,lp->http_proxy_port
,strerror(errno));
return -1;
}
return 0;
}
static int tls_process_data(belle_sip_channel_t *obj,unsigned int revents){
belle_sip_tls_channel_t* channel=(belle_sip_tls_channel_t*)obj;
belle_sip_tls_listening_point_t* lp = (belle_sip_tls_listening_point_t*)(obj->lp);
int err;
if (obj->state == BELLE_SIP_CHANNEL_CONNECTING ) {
if (!channel->socket_connected) {
channel->socklen=sizeof(channel->ss);
if (finalize_stream_connection((belle_sip_stream_channel_t*)obj,revents,(struct sockaddr*)&channel->ss,&channel->socklen)) {
goto process_error;
}
belle_sip_message("Channel [%p]: Connected at TCP level, now doing TLS handshake",obj);
channel->socket_connected=1;
belle_sip_source_set_events((belle_sip_source_t*)channel,BELLE_SIP_EVENT_READ|BELLE_SIP_EVENT_ERROR);
belle_sip_source_set_timeout((belle_sip_source_t*)obj,belle_sip_stack_get_transport_timeout(obj->stack));
if (tls_process_handshake(obj)==-1) goto process_error;
}else{
if (lp->http_proxy_addr) {
belle_sip_message("Channel [%p]: Connected at TCP level, now doing http proxy connect",obj);
if (tls_process_http_connect(channel)) goto process_error;
} else {
belle_sip_message("Channel [%p]: Connected at TCP level, now doing TLS handshake",obj);
if (tls_process_handshake(obj)==-1) goto process_error;
}
} else if (lp->http_proxy_addr && !channel->http_proxy_connected) {
char response[256];
err = stream_channel_recv((belle_sip_stream_channel_t*)obj,response,sizeof(response));
if (err<0 ){
belle_sip_error("Channel [%p]: connection refused by http proxy [%s:%i] status [%s]"
,channel
,lp->http_proxy_addr
,lp->http_proxy_port
,strerror(errno));
goto process_error;
} else if (strstr(response,"407")) {
belle_sip_error("Channel [%p]: auth requested, provide user/passwd by http proxy [%s:%i]"
,channel
,lp->http_proxy_addr
,lp->http_proxy_port);
goto process_error;
} else if (strstr(response,"200")) {
belle_sip_message("Channel [%p]: connected to http proxy, doing TLS handshake [%s:%i] "
,channel
,lp->http_proxy_addr
,lp->http_proxy_port);
channel->http_proxy_connected = 1;
if (tls_process_handshake(obj)==-1) goto process_error;
} else {
belle_sip_error("Channel [%p]: connection refused by http proxy [%s:%i]"
,channel
,lp->http_proxy_addr
,lp->http_proxy_port);
goto process_error;
}
} else {
if (revents & BELLE_SIP_EVENT_READ){
if (tls_process_handshake(obj)==-1) goto process_error;
}else if (revents==BELLE_SIP_EVENT_TIMEOUT){
......@@ -988,5 +1097,10 @@ static void belle_sip_signing_key_clone(belle_sip_signing_key_t *signing_key, co
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_signing_key_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_signing_key_t,belle_sip_object_t,belle_sip_signing_key_destroy,belle_sip_signing_key_clone,NULL,TRUE);
GET_SET_STRING(belle_sip_tls_listening_point,http_proxy_addr)
GET_SET_INT(belle_sip_tls_listening_point,http_proxy_port, int)
......@@ -24,6 +24,9 @@
static void belle_sip_tls_listening_point_uninit(belle_sip_tls_listening_point_t *lp){
belle_sip_object_unref(lp->verify_ctx);
if (lp->http_proxy_addr) belle_sip_object_unref(lp->http_proxy_addr);
if (lp->http_proxy_passwd) belle_sip_object_unref(lp->http_proxy_passwd);
if (lp->http_proxy_username) belle_sip_object_unref(lp->http_proxy_username);
}
static belle_sip_channel_t *tls_create_channel(belle_sip_listening_point_t *lp, const belle_sip_hop_t *hop){
......
......@@ -30,6 +30,8 @@ const char *client_auth_outbound_proxy="sips:sip2.linphone.org:5063";
const char *no_server_running_here="sip:test.linphone.org:3;transport=tcp";
const char *no_response_here="sip:78.220.48.77:3;transport=%s";
const char *test_domain_tls_to_tcp="sip:sip2.linphone.org:5060;transport=tls";
const char *test_http_proxy_addr="sip.linphone.org";
int test_http_proxy_port = 3128 ;
static int is_register_ok;
static int number_of_challenge;
......@@ -413,6 +415,36 @@ static void stateful_register_tls(void){
register_test("tls",1);
}
static void stateful_register_tls_with_http_proxy(void) {
belle_sip_tls_listening_point_t * lp = (belle_sip_tls_listening_point_t*)belle_sip_provider_get_listening_point(prov, "tls");
if (!lp) {
belle_sip_error("No TLS support, test skipped.");
return;
}
belle_sip_tls_listening_point_set_http_proxy_addr(lp, test_http_proxy_addr);
belle_sip_tls_listening_point_set_http_proxy_port(lp, test_http_proxy_port);
register_test("tls",1);
belle_sip_tls_listening_point_set_http_proxy_addr(lp, NULL);
belle_sip_tls_listening_point_set_http_proxy_port(lp, 0);
}
static void stateful_register_tls_with_wrong_http_proxy(void){
belle_sip_tls_listening_point_t * lp = (belle_sip_tls_listening_point_t*)belle_sip_provider_get_listening_point(prov, "tls");
if (!lp) {
belle_sip_error("No TLS support, test skipped.");
return;
}
belle_sip_tls_listening_point_set_http_proxy_addr(lp, "mauvaisproxy.linphone.org");
belle_sip_tls_listening_point_set_http_proxy_port(lp, test_http_proxy_port);
try_register_user_at_domain(stack,prov,"tls",1,"tester",test_domain,NULL,0);
belle_sip_tls_listening_point_set_http_proxy_addr(lp, NULL);
belle_sip_tls_listening_point_set_http_proxy_port(lp, 0);
}
static void bad_req_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
BELLESIP_UNUSED(user_ctx);
BELLESIP_UNUSED(event);
......@@ -575,6 +607,23 @@ static void register_dns_srv_tls(void){
if (req) belle_sip_object_unref(req);
}
static void register_dns_srv_tls_with_http_proxy(void){
belle_sip_request_t *req;
belle_sip_tls_listening_point_t * lp = (belle_sip_tls_listening_point_t*)belle_sip_provider_get_listening_point(prov, "tls");
if (!lp) {
belle_sip_error("No TLS support, test skipped.");
return;
}
io_error_count=0;
belle_sip_tls_listening_point_set_http_proxy_addr(lp, test_http_proxy_addr);
belle_sip_tls_listening_point_set_http_proxy_port(lp, test_http_proxy_port);
req=try_register_user_at_domain(stack, prov, "TLS",1,"tester",client_auth_domain,"sip:linphone.net;transport=tls",1);
belle_sip_tls_listening_point_set_http_proxy_addr(lp, NULL);
belle_sip_tls_listening_point_set_http_proxy_port(lp, 0);
BC_ASSERT_EQUAL(io_error_count, 0, int, "%d");
if (req) belle_sip_object_unref(req);
}
static void register_dns_load_balancing(void) {
belle_sip_request_t *req;
io_error_count = 0;
......@@ -711,6 +760,8 @@ test_t register_tests[] = {
{ "Stateful UDP with outbound proxy", stateful_register_udp_with_outbound_proxy },
{ "Stateful TCP", stateful_register_tcp },
{ "Stateful TLS", stateful_register_tls },
{ "Stateful TLS with http proxy", stateful_register_tls_with_http_proxy },
{ "Stateful TLS with wong http proxy", stateful_register_tls_with_wrong_http_proxy },
{ "Stateless UDP", stateless_register_udp },
{ "Stateless TCP", stateless_register_tcp },
{ "Stateless TLS", stateless_register_tls },
......@@ -724,6 +775,7 @@ test_t register_tests[] = {
{ "TLS connection to TCP server", test_tls_to_tcp },
{ "Register with DNS SRV failover TCP", register_dns_srv_tcp },
{ "Register with DNS SRV failover TLS", register_dns_srv_tls },
{ "Register with DNS SRV failover TLS with http proxy", register_dns_srv_tls_with_http_proxy },
{ "Register with DNS load-balancing", register_dns_load_balancing },
{ "Nonce reutilization", reuse_nonce }
};
......
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