Commit d6a16581 authored by jehan's avatar jehan

add client certificate auth

parent 49e0dcb7
......@@ -60,7 +60,7 @@
<folderInfo id="cdt.managedbuild.toolchain.gnu.macosx.base.557244179.959032290." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.macosx.base.1209613831" name="cdt.managedbuild.toolchain.gnu.macosx.base" superClass="cdt.managedbuild.toolchain.gnu.macosx.base">
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.MachO64" id="cdt.managedbuild.target.gnu.platform.macosx.base.973927327" name="Debug Platform" osList="macosx" superClass="cdt.managedbuild.target.gnu.platform.macosx.base"/>
<builder arguments="CFLAGS=&quot;-g -Wall &quot;" command="make" id="cdt.managedbuild.target.gnu.builder.macosx.base.190701400" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.target.gnu.builder.macosx.base"/>
<builder arguments="CFLAGS=&quot;-g -Wall&quot;" command="make" id="cdt.managedbuild.target.gnu.builder.macosx.base.190701400" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.target.gnu.builder.macosx.base"/>
<tool id="cdt.managedbuild.tool.macosx.c.linker.macosx.base.419159753" name="MacOS X C Linker" superClass="cdt.managedbuild.tool.macosx.c.linker.macosx.base">
<inputType id="cdt.managedbuild.tool.macosx.c.linker.input.1079464415" superClass="cdt.managedbuild.tool.macosx.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
......
......@@ -90,4 +90,33 @@ BELLESIP_EXPORT int belle_sip_auth_helper_compute_response_qop_auth( const char*
, const char* ha2
, char response[33]);
/*TLS client certificate auth*/
/**
* Format of certificate buffer
* */
typedef enum belle_sip_certificate_raw_format {
BELLE_SIP_CERTIFICATE_RAW_FORMAT_PEM, /** PEM format*/
BELLE_SIP_CERTIFICATE_RAW_FORMAT_DER /** ASN.1 raw format*/
}belle_sip_certificate_raw_format_t;
/**
* Parse a buffer containing either a certificate chain order in PEM format or a single DER cert
* @param buff raw buffer
* @param size buffer size
* @param format either PEM or DER
* @return belle_sip_certificates_chain_t or NUL if cannot be decoded
*/
BELLESIP_EXPORT belle_sip_certificates_chain_t* belle_sip_certificates_chain_parse(const char* buff, size_t size,belle_sip_certificate_raw_format_t format);
/**
* Parse a buffer containing either a private or public rsa key
* @param buff raw buffer
* @param size buffer size
* @param passwd password (optionnal)
* @return list of belle_sip_signing_key_t or NUL iff cannot be decoded
*/
BELLESIP_EXPORT belle_sip_signing_key_t* belle_sip_signing_key_parse(const char* buff, size_t size,const char* passwd);
#endif /* AUTHENTICATION_HELPER_H_ */
......@@ -108,7 +108,9 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(belle_sip,1)
BELLE_SIP_TYPE_ID(belle_sip_header_replaces_t),
BELLE_SIP_TYPE_ID(belle_sip_header_date_t),
BELLE_SIP_TYPE_ID(belle_sip_header_p_preferred_identity_t),
BELLE_SIP_TYPE_ID(belle_sip_header_privacy_t)
BELLE_SIP_TYPE_ID(belle_sip_header_privacy_t),
BELLE_SIP_TYPE_ID(belle_sip_certificates_chain_t),
BELLE_SIP_TYPE_ID(belle_sip_signing_key_t)
BELLE_SIP_DECLARE_TYPES_END
......
......@@ -29,6 +29,8 @@ 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;
typedef struct belle_sip_certificates_chain belle_sip_certificates_chain_t;
typedef struct belle_sip_signing_key belle_sip_signing_key_t;
BELLE_SIP_DECLARE_INTERFACE_BEGIN(belle_sip_listener_t)
......@@ -69,23 +71,68 @@ BELLESIP_EXPORT belle_sip_client_transaction_t *belle_sip_transaction_terminated
BELLESIP_EXPORT belle_sip_server_transaction_t *belle_sip_transaction_terminated_event_get_server_transaction(const belle_sip_transaction_terminated_event_t* event);
/*auth event*/
/**
* auth event mode
* */
typedef enum belle_sip_auth_mode {
BELLE_SIP_AUTH_MODE_HTTP_DISGEST, /** Disgest authentication has been requested by the server*/
BELLE_SIP_AUTH_MODE_TLS /** Client certificates has bee requested by the server*/
} belle_sip_auth_mode_t;
BELLESIP_EXPORT void belle_sip_auth_event_destroy(belle_sip_auth_event_t* event);
BELLESIP_EXPORT 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);
BELLESIP_EXPORT 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);
BELLESIP_EXPORT const char* belle_sip_auth_event_get_userid(const belle_sip_auth_event_t* event);
BELLESIP_EXPORT void belle_sip_auth_event_set_userid(belle_sip_auth_event_t* event, const char* value);
BELLESIP_EXPORT 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);
BELLESIP_EXPORT 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);
BELLESIP_EXPORT const char* belle_sip_auth_event_get_passwd(const belle_sip_auth_event_t* event);
BELLESIP_EXPORT 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);
BELLESIP_EXPORT const char* belle_sip_auth_event_get_ha1(const belle_sip_auth_event_t* event);
BELLESIP_EXPORT void belle_sip_auth_event_set_ha1(belle_sip_auth_event_t* event, const char* value);
/**
* get the authentication mode requested by the server, can be either TLS client certificates of http digest
* @param event
* @return belle_sip_auth_mode_t
* */
BELLESIP_EXPORT belle_sip_auth_mode_t belle_sip_auth_event_get_mode(const belle_sip_auth_event_t* event);
/**
* In case of TLS auth, get value of the distinguished name sent by the server
* @param event
* @return DN has sent by the server
*
*/
BELLESIP_EXPORT const char* belle_sip_auth_event_get_distinguished_name(const belle_sip_auth_event_t* event);
/**
* get client certificate
* @return belle_sip_certificate_t*
* */
BELLESIP_EXPORT belle_sip_certificates_chain_t* belle_sip_auth_event_get_client_certificates_chain(const belle_sip_auth_event_t* event);
/**
* set client certificate to be sent in answer to the certificate request issued by the server for the DN belle_sip_auth_event_get_distinguished_name() name
* @return belle_sip_certificate_t*
* */
BELLESIP_EXPORT void belle_sip_auth_event_set_client_certificates_chain(belle_sip_auth_event_t* event, belle_sip_certificates_chain_t* value);
/**
* get client certificate private key
* @return belle_sip_signing_key_t*
* */
BELLESIP_EXPORT belle_sip_signing_key_t* belle_sip_auth_event_get_signing_key(const belle_sip_auth_event_t* event);
/**
* set the private key attached to the client certificate.
* @param event belle_sip_auth_event_t
* @param value belle_sip_signing_key_t signing key
* */
BELLESIP_EXPORT void belle_sip_auth_event_set_signing_key(belle_sip_auth_event_t* event, belle_sip_signing_key_t* value);
/*Io error event*/
/*
* Give access to the remote host
......
......@@ -18,12 +18,15 @@ $(generated_src) : $(builddir)/generated_src_stamp
BUILT_SOURCES=$(generated_src)
noinst_LTLIBRARIES=libbellesip_generated.la
noinst_LTLIBRARIES=libbellesip_generated.la libbellesip_tls.la
nodist_libbellesip_generated_la_SOURCES=$(generated_src)
libbellesip_generated_la_CFLAGS=$(LESS_STRICT_OPTIONS) $(ANTLR_CFLAGS)
#to disbale warning introduced by compatibility between polar 1.2 and 1.3
nodist_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)
lib_LTLIBRARIES=libbellesip.la
......@@ -58,8 +61,6 @@ libbellesip_la_SOURCES= \
transports/stream_channel.c \
transports/stream_channel.h \
transports/stream_listeningpoint.c \
transports/tls_listeningpoint_polarssl.c \
transports/tls_channel_polarssl.c \
refresher.c \
dns.c dns.h
......@@ -73,7 +74,7 @@ endif
libbellesip_la_CFLAGS=$(STRICT_OPTIONS) $(ANTLR_CFLAGS) $(TLS_CFLAGS) $(TUNNEL_CFLAGS) $(LIBBELLESIP_CFLAGS)
libbellesip_la_CXXFLAGS=$(STRICT_OPTIONS) $(TLS_CFLAGS) $(TUNNEL_CFLAGS) $(LIBBELLESIP_CFLAGS)
libbellesip_la_LIBADD=libbellesip_generated.la $(ANTLR_LIBS) $(TLS_LIBS) $(TUNNEL_LIBS)
libbellesip_la_LIBADD=libbellesip_generated.la libbellesip_tls.la $(ANTLR_LIBS) $(TLS_LIBS) $(TUNNEL_LIBS)
libbellesip_la_LDFLAGS=-no-undefined $(LDFLAGS)
......
......@@ -27,9 +27,11 @@ 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)
GET_SET_STRING(belle_sip_auth_event,distinguished_name)
belle_sip_auth_event_t* belle_sip_auth_event_create(const char* realm,const char* username) {
belle_sip_auth_event_t* result = belle_sip_new(belle_sip_auth_event_t);
memset(result,0,sizeof(belle_sip_auth_event_t));
belle_sip_auth_event_t* result = belle_sip_new0(belle_sip_auth_event_t);
belle_sip_auth_event_set_realm(result,realm);
belle_sip_auth_event_set_username(result,username);
return result;
......@@ -40,5 +42,33 @@ void belle_sip_auth_event_destroy(belle_sip_auth_event_t* event) {
DESTROY_STRING(event,realm);
DESTROY_STRING(event,passwd);
DESTROY_STRING(event,ha1);
DESTROY_STRING(event,distinguished_name);
if (event->cert) belle_sip_object_unref(event->cert);
if (event->key) belle_sip_object_unref(event->key);
belle_sip_free(event);
}
belle_sip_certificates_chain_t* belle_sip_auth_event_get_client_certificates_chain(const belle_sip_auth_event_t* event) {
return event->cert;
}
void belle_sip_auth_event_set_client_certificates_chain(belle_sip_auth_event_t* event, belle_sip_certificates_chain_t* value) {
if (event->cert) belle_sip_object_unref(event->cert);
event->cert=value;
if (event->cert) belle_sip_object_ref(event->cert);
}
belle_sip_signing_key_t* belle_sip_auth_event_get_signing_key(const belle_sip_auth_event_t* event) {
return event->key;
}
void belle_sip_auth_event_set_signing_key(belle_sip_auth_event_t* event, belle_sip_signing_key_t* value) {
if (event->key) belle_sip_object_unref(event->key);
event->key=value;
if (event->key) belle_sip_object_ref(event->key);
}
belle_sip_auth_mode_t belle_sip_auth_event_get_mode(const belle_sip_auth_event_t* event) {
return event->mode;
}
......@@ -226,3 +226,7 @@ int belle_sip_auth_helper_fill_proxy_authorization(belle_sip_header_proxy_author
}
......@@ -190,6 +190,8 @@ BELLE_SIP_DECLARE_VPTR(belle_sip_hop_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_object_pool_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_p_preferred_identity_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_header_privacy_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_certificates_chain_t);
BELLE_SIP_DECLARE_VPTR(belle_sip_signing_key_t);
typedef void (*belle_sip_source_remove_callback_t)(belle_sip_source_t *);
......@@ -854,14 +856,24 @@ struct belle_sip_transaction_terminated_event{
};
struct belle_sip_auth_event {
belle_sip_auth_mode_t mode;
char* username;
char* userid;
char* realm;
char* passwd;
char* ha1;
const char* distinguished_name;
belle_sip_certificates_chain_t * cert;
belle_sip_signing_key_t* key;
};
belle_sip_auth_event_t* belle_sip_auth_event_create(const char* realm,const char* username);
void belle_sip_auth_event_set_distinguished_name(belle_sip_auth_event_t* event,const char* value);
/*
* refresher
* */
......
......@@ -159,8 +159,11 @@ const belle_sip_list_t* belle_sip_uri_get_header_names(const belle_sip_uri_t* ur
int belle_sip_uri_get_listening_port(const belle_sip_uri_t *uri){
int port=belle_sip_uri_get_port(uri);
const char *transport=belle_sip_uri_get_transport_param(uri);
if (!transport) {
transport=belle_sip_uri_is_secure(uri)?"tls":"udp";
}
if (port==0)
port=belle_sip_listening_point_get_well_known_port(transport ? transport : "UDP");
port=belle_sip_listening_point_get_well_known_port(transport);
return port;
}
......
......@@ -51,6 +51,7 @@ BELLE_SIP_DECLARE_INTERFACE_BEGIN(belle_sip_channel_listener_t)
void (*on_state_changed)(belle_sip_channel_listener_t *l, belle_sip_channel_t *, belle_sip_channel_state_t state);
int (*on_event)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, unsigned revents);
void (*on_sending)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, belle_sip_message_t *msg);
int (*on_auth_requested)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, const char* distinghised_name);
BELLE_SIP_DECLARE_INTERFACE_END
#define BELLE_SIP_CHANNEL_LISTENER(obj) BELLE_SIP_INTERFACE_CAST(obj,belle_sip_channel_listener_t)
......@@ -175,8 +176,10 @@ BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_channel_t,belle_sip_source_t)
void (*close)(belle_sip_channel_t *obj);
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
/**
* tls client certificate authentication. might be relevant for both tls and dtls channels.Only implemented in tls channel for now
* **/
void belle_sip_channel_set_client_certificates_chain(belle_sip_channel_t *obj, belle_sip_certificates_chain_t* cert_chain);
void belle_sip_channel_set_client_certificate_key(belle_sip_channel_t *obj, belle_sip_signing_key_t* key);
#endif
......@@ -20,6 +20,7 @@
#define LISTENINGPOINT_INTERNAL_H_
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_listening_point_t,belle_sip_object_t)
const char *transport;
belle_sip_channel_t * (*create_channel)(belle_sip_listening_point_t *, const belle_sip_hop_t *hop);
......
......@@ -285,6 +285,19 @@ static int channel_on_event(belle_sip_channel_listener_t *obj, belle_sip_channel
}
return 0;
}
static int channel_on_auth_requested(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, const char* distinguished_name){
if (BELLE_SIP_IS_INSTANCE_OF(chan,belle_sip_tls_channel_t)) {
belle_sip_provider_t *prov=BELLE_SIP_PROVIDER(obj);
belle_sip_auth_event_t* auth_event = belle_sip_auth_event_create(NULL,NULL);
auth_event->mode=BELLE_SIP_AUTH_MODE_TLS;
belle_sip_auth_event_set_distinguished_name(auth_event,distinguished_name);
BELLE_SIP_PROVIDER_INVOKE_LISTENERS(prov->listeners,process_auth_requested,auth_event);
belle_sip_channel_set_client_certificates_chain(chan,auth_event->cert);
belle_sip_channel_set_client_certificate_key(chan,auth_event->key);
belle_sip_auth_event_destroy(auth_event);
}
return 0;
}
static void channel_on_sending(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
belle_sip_header_contact_t* contact;
......@@ -349,7 +362,8 @@ static void channel_on_sending(belle_sip_channel_listener_t *obj, belle_sip_chan
BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(belle_sip_provider_t,belle_sip_channel_listener_t)
channel_state_changed,
channel_on_event,
channel_on_sending
channel_on_sending,
channel_on_auth_requested
BELLE_SIP_IMPLEMENT_INTERFACE_END
BELLE_SIP_DECLARE_IMPLEMENTED_INTERFACES_1(belle_sip_provider_t,belle_sip_channel_listener_t);
......@@ -565,24 +579,23 @@ belle_sip_channel_t * belle_sip_provider_get_channel(belle_sip_provider_t *p, co
belle_sip_list_t *l;
belle_sip_listening_point_t *candidate=NULL,*lp;
belle_sip_channel_t *chan;
const char *transport=hop->transport;
if (transport==NULL) transport="UDP";
for(l=p->lps;l!=NULL;l=l->next){
lp=(belle_sip_listening_point_t*)l->data;
if (strcasecmp(belle_sip_listening_point_get_transport(lp),transport)==0){
chan=belle_sip_listening_point_get_channel(lp,hop);
if (chan) return chan;
candidate=lp;
if (hop->transport!=NULL) {
for(l=p->lps;l!=NULL;l=l->next){
lp=(belle_sip_listening_point_t*)l->data;
if (strcasecmp(belle_sip_listening_point_get_transport(lp),hop->transport)==0){
chan=belle_sip_listening_point_get_channel(lp,hop);
if (chan) return chan;
candidate=lp;
}
}
if (candidate){
chan=belle_sip_listening_point_create_channel(candidate,hop);
if (!chan) belle_sip_error("Could not create channel to [%s://%s:%i]",hop->transport,hop->host,hop->port);
return chan;
}
}
if (candidate){
chan=belle_sip_listening_point_create_channel(candidate,hop);
if (!chan) belle_sip_error("Could not create channel to %s://%s:%i",transport,hop->host,hop->port);
return chan;
}
belle_sip_error("No listening point matching for transport %s",transport);
belle_sip_error("No listening point matching for [%s://%s:%i]",hop->transport,hop->host,hop->port);
return NULL;
}
......
......@@ -32,13 +32,18 @@ belle_sip_hop_t* belle_sip_hop_new(const char* transport, const char *cname, con
belle_sip_hop_t* belle_sip_hop_new_from_uri(const belle_sip_uri_t *uri){
const char *host;
const char *cname=NULL;
const char * transport=belle_sip_uri_get_transport_param(uri);
if (!transport) {
transport=belle_sip_uri_is_secure(uri)?"tls":"udp";
}
host=belle_sip_uri_get_maddr_param(uri);
if (!host) host=belle_sip_uri_get_host(uri);
else cname=belle_sip_uri_get_host(uri);
return belle_sip_hop_new(belle_sip_uri_get_transport_param(uri),
cname,
host,
belle_sip_uri_get_listening_port(uri));
return belle_sip_hop_new( transport,
cname,
host,
belle_sip_uri_get_listening_port(uri));
}
static void belle_sip_hop_destroy(belle_sip_hop_t *hop){
......
......@@ -20,14 +20,34 @@
#include "stream_channel.h"
#ifdef HAVE_POLARSSL
#include <polarssl/ssl.h>
/* Uncomment to get very verbose polarssl logs*/
//#define ENABLE_POLARSSL_LOGS
#include <polarssl/ssl.h>
#include <polarssl/version.h>
#include <polarssl/error.h>
#if POLARSSL_VERSION_NUMBER >= 0x01030000
#include <polarssl/compat-1.2.h>
#endif
#endif
struct belle_sip_certificates_chain {
belle_sip_object_t objet;
#ifdef HAVE_POLARSSL
x509_cert cert;
#endif
};
struct belle_sip_signing_key {
belle_sip_object_t objet;
#ifdef HAVE_POLARSSL
rsa_context key;
#endif
};
#ifdef HAVE_POLARSSL
/*************tls********/
static int tls_process_data(belle_sip_channel_t *obj,unsigned int revents);
......@@ -40,6 +60,8 @@ struct belle_sip_tls_channel{
socklen_t socklen;
int socket_connected;
char *cur_debug_msg;
belle_sip_certificates_chain_t* client_cert_chain;
belle_sip_signing_key_t* client_cert_key;
};
static void tls_channel_close(belle_sip_tls_channel_t *obj){
......@@ -114,6 +136,45 @@ BELLE_SIP_INSTANCIATE_CUSTOM_VPTR(belle_sip_tls_channel_t)=
}
};
static int tls_channel_handshake(belle_sip_tls_channel_t *channel) {
int ret;
while( channel->sslctx.state != SSL_HANDSHAKE_OVER ) {
if ((ret = ssl_handshake_step( &channel->sslctx ))) {
break;
}
if (channel->sslctx.state == SSL_CERTIFICATE_REQUEST) {
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2( channel->base.base.listeners
,belle_sip_channel_listener_t
,on_auth_requested
,&channel->base.base
,NULL/*not set yet*/);
if (channel->client_cert_chain) {
#if POLARSSL_VERSION_NUMBER >= 0x01030000
int err;
#endif
char tmp[512];
x509parse_cert_info(tmp,sizeof(tmp),"",&channel->client_cert_chain->cert);
belle_sip_message("Channel [%p] found client certificate:\n%s",channel,tmp);
#if POLARSSL_VERSION_NUMBER < 0x01030000
ssl_set_own_cert(&channel->sslctx,&channel->client_cert_chain->cert,&channel->client_cert_key->key);
#else
if ((err=ssl_set_own_cert_rsa(&channel->sslctx,&channel->client_cert_chain->cert,&channel->client_cert_key->key))) {
char tmp[128];
error_strerror(err,tmp,sizeof(tmp));
belle_sip_error("Channel [%p] cannot ssl_set_own_cert_rsa [%s]",channel,tmp);
}
/*update own cert see ssl_handshake frompolarssl*/
channel->sslctx.handshake->key_cert = channel->sslctx.key_cert;
#endif
}
}
}
return ret;
}
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;
int err;
......@@ -128,7 +189,7 @@ static int tls_process_data(belle_sip_channel_t *obj,unsigned int revents){
channel->socket_connected=1;
belle_sip_message("Channel [%p]: Connected at TCP level, now doing TLS handshake",obj);
}
err=ssl_handshake(&channel->sslctx);
err=tls_channel_handshake(channel) /*ssl_handshake(&channel->sslctx)*/;
if (err==0){
belle_sip_message("Channel [%p]: SSL handshake finished.",obj);
belle_sip_channel_set_ready(obj,(struct sockaddr*)&channel->ss,channel->socklen);
......@@ -299,6 +360,109 @@ belle_sip_channel_t * belle_sip_channel_new_tls(belle_sip_tls_listening_point_t
return (belle_sip_channel_t*)obj;
}
void belle_sip_channel_set_client_certificates_chain(belle_sip_channel_t *obj, belle_sip_certificates_chain_t* cert_chain) {
belle_sip_tls_channel_t* channel = (belle_sip_tls_channel_t*)obj;
if (channel->client_cert_chain) belle_sip_object_unref(channel->client_cert_chain);
channel->client_cert_chain=cert_chain;
if (channel->client_cert_chain) belle_sip_object_ref(channel->client_cert_chain);
}
void belle_sip_channel_set_client_certificate_key(belle_sip_channel_t *obj, belle_sip_signing_key_t* key) {
belle_sip_tls_channel_t* channel = (belle_sip_tls_channel_t*)obj;
if (channel->client_cert_key) belle_sip_object_unref(channel->client_cert_key);
channel->client_cert_key=key;
if (channel->client_cert_key) belle_sip_object_ref(channel->client_cert_key);
}
#else /*HAVE_POLLAR_SSL*/
void belle_sip_channel_set_client_certificates_chain(belle_sip_channel_t *obj, belle_sip_certificates_chain_t* cert_chain) {
belle_sip_error("belle_sip_channel_set_client_certificate_chain requires TLS");
}
void belle_sip_channel_set_client_certificate_key(belle_sip_channel_t *obj, belle_sip_signing_key_t* key) {
belle_sip_error("belle_sip_channel_set_client_certificate_key requires TLS");
}
#endif
/**************************** belle_sip_certificates_chain_t **/
static int belle_sip_certificate_fill(belle_sip_certificates_chain_t* certificate,const char* buff, size_t size,belle_sip_certificate_raw_format_t format) {
#ifdef HAVE_POLARSSL
int err;
if ((err=x509parse_crt(&certificate->cert,(const unsigned char *)buff,size)) <0) {
char tmp[128];
error_strerror(err,tmp,sizeof(tmp));
belle_sip_error("cannot parse x509 cert because [%s]",tmp);
return -1;
}
return 0;
#else /*HAVE_POLARSSL*/
return -1;
#endif
}
/*belle_sip_certificate */
belle_sip_certificates_chain_t* belle_sip_certificates_chain_parse(const char* buff, size_t size,belle_sip_certificate_raw_format_t format) {
belle_sip_certificates_chain_t* certificate = belle_sip_object_new(belle_sip_certificates_chain_t);
if (belle_sip_certificate_fill(certificate,buff, size,format)) {
belle_sip_object_unref(certificate);
certificate=NULL;
}
return certificate;
}
static void belle_sip_certificates_chain_destroy(belle_sip_certificates_chain_t *certificate){
#ifdef HAVE_POLARSSL
x509_free(&certificate->cert);
#endif
}
static void belle_sip_certificates_chain_clone(belle_sip_certificates_chain_t *certificate, const belle_sip_certificates_chain_t *orig){
belle_sip_error("belle_sip_certificate_clone not supported");
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_certificates_chain_t);
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_certificates_chain_t,belle_sip_object_t,belle_sip_certificates_chain_destroy,belle_sip_certificates_chain_clone,NULL,TRUE);
belle_sip_signing_key_t* belle_sip_signing_key_parse(const char* buff, size_t size,const char* passwd) {
#ifdef HAVE_POLARSSL
belle_sip_signing_key_t* signing_key = belle_sip_object_new(belle_sip_signing_key_t);
int err;
if ((err=x509parse_key(&signing_key->key,(const unsigned char *)buff,size,(const unsigned char*)passwd,passwd?strlen(passwd):0)) <0) {
char tmp[128];
error_strerror(err,tmp,sizeof(tmp));
belle_sip_error("cannot parse x509 cert because [%s]",tmp);
belle_sip_object_unref(signing_key);
return NULL;
}
return signing_key;
#else /*HAVE_POLARSSL*/
return NULL;
#endif
}
static void belle_sip_signing_key_destroy(belle_sip_signing_key_t *signing_key){
#ifdef HAVE_POLARSSL
rsa_free(&signing_key->key);
#endif
}
static void belle_sip_signing_key_clone(belle_sip_signing_key_t *signing_key, const belle_sip_signing_key_t *orig){
belle_sip_error("belle_sip_signing_key_clone not supported");
}
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);
......@@ -27,6 +27,9 @@
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";
static int is_register_ok;
static int number_of_challenge;
static int using_transaction;
......@@ -100,12 +103,70 @@ 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*/
"-----BEGIN CERTIFICATE-----\n"
"MIIDYzCCAsygAwIBAgIBCDANBgkqhkiG9w0BAQUFADCBuzELMAkGA1UEBhMCRlIx\n"
"EzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAcMCEdyZW5vYmxlMSIwIAYDVQQK\n"
"DBlCZWxsZWRvbm5lIENvbW11bmljYXRpb25zMQwwCgYDVQQLDANMQUIxFjAUBgNV\n"
"BAMMDUplaGFuIE1vbm5pZXIxOjA4BgkqhkiG9w0BCQEWK2plaGFuLm1vbm5pZXJA\n"
"YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTMxMDAzMTQ0MTEwWhcN\n"
"MjMxMDAxMTQ0MTEwWjCBtTELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkZyYW5jZTER\n"
"MA8GA1UEBwwIR3Jlbm9ibGUxIjAgBgNVBAoMGUJlbGxlZG9ubmUgQ29tbXVuaWNh\n"
"dGlvbnMxDDAKBgNVBAsMA0xBQjEUMBIGA1UEAwwLY2xpZW50IGNlcnQxOjA4Bgkq\n"
"hkiG9w0BCQEWK2plaGFuLm1vbm5pZXJAYmVsbGVkb25uZS1jb21tdW5pY2F0aW9u\n"
"cy5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALZxC/qBi/zB/4lgI7V7\n"
"I5TsmMmOp0+R/TCyVnYvKQuaJXh9i+CobVM7wj/pQg8RgsY1x+4mVwH1QbhOdIN0\n"
"ExYHKgLTPlo9FaN6oHPOcHxU/wt552aZhCHC+ushwUUyjy8+T09UOP+xK9V7y5uD\n"
"ZY+vIOvi6QNwc5cqyy8TREwNAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4\n"
"QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTL\n"
"eWEg7jewRbQbKXSdBvsyygGIFzAfBgNVHSMEGDAWgBQGX13HFq9i+C1ucQOIoNYd\n"
"KwR/ujANBgkqhkiG9w0BAQUFAAOBgQBTbEoi94pVfevbK22Oj8PJFsuy+el1pJG+\n"
"h0XGM9SQGfbcS7PsV/MhFXtmpnmj3vQB3u5QtMGtWcLA2uxXi79i82gw+oEpBKHR\n"
"sLqsNCzWNCL9n1pjpNSdqqBFGUdB9pSpnYalujAbuzkqq1ZLyzsElvK7pCaLQcSs\n"
"oEncRDdPOA==\n"
"-----END CERTIFICATE-----";
static const char* private_key =
"-----BEGIN ENCRYPTED PRIVATE KEY-----\n"
"MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIbEHnQwhgRwoCAggA\n"
"MBQGCCqGSIb3DQMHBAgmrtCEBCP9kASCAoCq9EKInROalaBSLWY44U4RVAC+CKdx\n"
"Q8ooT7Bz/grgZuCiaGf0UKINJeV4LYHoP+AWjCH8EeebIA8dldNy5rGcBTt7sXd1\n"
"QOGmnkBplXTW/NTsb9maYRK56kNJhLE4DR5X5keziV1Tdy2KBmTlpllsCXWsSOBq\n"
"iI63PTaakIvZxA0TEmie5QQWpH777e/LmW3vVHdH8hhp2zeDDjfSW2E290+ce4Yj\n"
"SDW9oFXvauzhzhSYRkUdfoJSbpu5MYwyzhjAXQpmBJDauu7+jAU/rQw6TLmYjDNZ\n"
"3PYHzyD4N7tCG9u4mPBo33dhUirP+8E1BftHB+i/VIn6pI3ypMyiFZ1ZCHqi4vhW\n"
"z7aChRrUY/8XWCpln3azcfj4SW+Mz62sAChY8rn+yyxFgIno8d9rrx67jyAnYJ6Q\n"
"sfIMwKp3Sz5oI7IDk8If5SuBVkpqlRV+eZFT6zRRFk65beYpq70BN2mYaKzSV8A7\n"
"rnciho/dfa9wvyWmkqXciBgWh18UTACOM9HPLmQef3FGaUDLiTAGS1osyypGUEPt\n"
"Ox3u51qpYkibwyQZo1+ujQkh9PiKfevIAXmty0nTFWMEED15G2SJKjunw5N1rEAh\n"
"M9jlYpLnATcfigPfGo19QrIPQ1c0LB4BqdwAWN3ZLe0QqYdgwzdcwIoLQRp9iDcw\n"
"Omc31+38cTc2yGQ2Y2XHZkL8GY/rkqkbhVt9Rnh+VJxFeB6FlsL66EycApe07ngx\n"
"QimGP57yp4aBzpJyW+6GPf8A/Ogsv3ay1QBLUiGEJtUglRHnl9F6nm5Nxm7wubVx\n"
"WEuSefVM4xgB+mfQauAJu2N9yKhzXOytslZflpa06qJedlLYFk9njvcv\n"
"-----END ENCRYPTED PRIVATE KEY-----\n";
static const char* private_key_passwd="secret";
static void process_auth_requested(void *user_ctx, belle_sip_auth_event_t *event){
BELLESIP_UNUSED(user_ctx);
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");
if (belle_sip_auth_event_get_mode(event) == BELLE_SIP_AUTH_MODE_HTTP_DISGEST) {
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");
} 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_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));
} else {
belle_sip_error("Unexpected auth mode");
}
}
int register_init(void) {
......@@ -198,7 +259,7 @@ belle_sip_request_t* try_register_user_at_domain(belle_sip_stack_t * stack
}
if (outbound_proxy){
if (strstr(outbound_proxy,"sip:")==NULL){
if (strstr(outbound_proxy,"sip:")==NULL && strstr(outbound_proxy,"sips:")==NULL){
outbound=belle_sip_strdup_printf("sip:%s",outbound_proxy);
}else outbound=belle_sip_strdup(outbound_proxy);
}
......@@ -390,6 +451,23 @@ static void test_register_channel_inactive(void){
belle_sip_stack_set_inactive_transport_timeout(stack,3600);
}
static void test_register_client_authenticated(void) {
belle_sip_request_t *reg;
authorized_request=NULL;
/*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")