From f45856be68efba1ab08e8ff37b2db0dde8da3635 Mon Sep 17 00:00:00 2001 From: Johan Pascal Date: Mon, 21 Mar 2016 20:29:17 +0100 Subject: [PATCH] Tunnel client can verify server certificate --- coreapi/TunnelManager.cc | 17 ++++++ coreapi/TunnelManager.hh | 13 +++++ coreapi/linphone_tunnel.cc | 11 ++++ ...auline_tunnel_verify_server_certificate_rc | 54 +++++++++++++++++++ tester/tunnel_tester.c | 14 +++-- 5 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 tester/rcfiles/pauline_tunnel_verify_server_certificate_rc diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc index b74baedb2..362816674 100644 --- a/coreapi/TunnelManager.cc +++ b/coreapi/TunnelManager.cc @@ -100,6 +100,15 @@ void TunnelManager::startClient() { ms_message("TunnelManager: Starting tunnel client"); mTunnelClient = new TunnelClient(TRUE); mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this); + if (mVerifyServerCertificate) { + const char *rootCertificatePath = linphone_core_get_root_ca(mCore); + if (rootCertificatePath != NULL) { + ms_message("TunnelManager: Load root certificate from %s", rootCertificatePath); + mTunnelClient->setRootCertificate(rootCertificatePath); /* give the path to root certificate to the tunnel client in order to be able to verify the server certificate */ + } else { + ms_warning("TunnelManager is set to verify server certificate but no root certificate is available in linphoneCore"); + } + } list::iterator it; for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){ const ServerAddr &addr=*it; @@ -427,6 +436,14 @@ bool TunnelManager::tunnelizeSipPacketsEnabled() const { return mTunnelizeSipPackets; } +void TunnelManager::verifyServerCertificate(bool enable){ + mVerifyServerCertificate = enable; +} + +bool TunnelManager::verifyServerCertificateEnabled() const { + return mVerifyServerCertificate; +} + void TunnelManager::setHttpProxy(const char *host,int port, const char *username, const char *passwd){ mHttpUserName=username?username:""; mHttpPasswd=passwd?passwd:""; diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh index 764c8efda..dccaf8756 100644 --- a/coreapi/TunnelManager.hh +++ b/coreapi/TunnelManager.hh @@ -110,6 +110,18 @@ namespace belledonnecomm { * @return True, SIP packets pass through the tunnel */ bool tunnelizeSipPacketsEnabled() const; + /** + * Indicate to the tunnel manager wether server certificate + * must be verified during TLS handshake. Default: disabled + * @param enable If set to TRUE, SIP packets will pass through the tunnel. + * If set to FALSE, SIP packets will pass by the configured proxies. + */ + void verifyServerCertificate(bool enable); + /** + * Check wether the tunnel manager is set to verify server certificate during TLS handshake + * @return True, server certificate is verified(using the linphonecore root certificate) + */ + bool verifyServerCertificateEnabled() const; /** * @brief Constructor * @param lc The LinphoneCore instance of which the TunnelManager will be associated to. @@ -188,6 +200,7 @@ namespace belledonnecomm { LinphoneTunnelMode mMode; State mState; bool mTunnelizeSipPackets; + bool mVerifyServerCertificate; TunnelClient* mTunnelClient; std::string mHttpUserName; std::string mHttpPasswd; diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc index a751bc948..76b320f06 100644 --- a/coreapi/linphone_tunnel.cc +++ b/coreapi/linphone_tunnel.cc @@ -330,6 +330,15 @@ bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel) { return bcTunnel(tunnel)->tunnelizeSipPacketsEnabled() ? TRUE : FALSE; } +void linphone_tunnel_verify_server_certificate(LinphoneTunnel *tunnel, bool_t enable) { + bcTunnel(tunnel)->verifyServerCertificate(enable); + lp_config_set_int(config(tunnel), "tunnel", "verifyCert", (enable ? TRUE : FALSE)); +} + +bool_t linphone_tunnel_verify_server_certificate_enabled(const LinphoneTunnel *tunnel) { + return bcTunnel(tunnel)->verifyServerCertificateEnabled() ? TRUE : FALSE; +} + static void my_ortp_logv(const char *domain, OrtpLogLevel level, const char *fmt, va_list args){ ortp_logv(domain, level,fmt,args); } @@ -342,10 +351,12 @@ static void my_ortp_logv(const char *domain, OrtpLogLevel level, const char *fmt void linphone_tunnel_configure(LinphoneTunnel *tunnel){ LinphoneTunnelMode mode = linphone_tunnel_mode_from_string(lp_config_get_string(config(tunnel), "tunnel", "mode", NULL)); bool_t tunnelizeSIPPackets = (bool_t)lp_config_get_int(config(tunnel), "tunnel", "sip", TRUE); + bool_t tunnelVerifyServerCertificate = (bool_t)lp_config_get_int(config(tunnel), "tunnel", "verifyCert", FALSE); linphone_tunnel_enable_logs_with_handler(tunnel,TRUE,my_ortp_logv); linphone_tunnel_load_config(tunnel); linphone_tunnel_enable_sip(tunnel, tunnelizeSIPPackets); linphone_tunnel_set_mode(tunnel, mode); + linphone_tunnel_verify_server_certificate(tunnel, tunnelVerifyServerCertificate); } /* Deprecated functions */ diff --git a/tester/rcfiles/pauline_tunnel_verify_server_certificate_rc b/tester/rcfiles/pauline_tunnel_verify_server_certificate_rc new file mode 100644 index 000000000..ca9d1eeac --- /dev/null +++ b/tester/rcfiles/pauline_tunnel_verify_server_certificate_rc @@ -0,0 +1,54 @@ +[sip] +sip_port=-1 +sip_tcp_port=-1 +sip_tls_port=-1 +default_proxy=0 +ping_with_options=0 + +composing_idle_timeout=1 + +[auth_info_0] +username=pauline +userid=pauline +passwd=secret +realm=sip.example.org + + +[proxy_0] +reg_proxy=sip2.linphone.org;transport=tls +reg_route=sip2.linphone.org;transport=tls +reg_identity=sip:pauline@sip.example.org +reg_expires=3600 +reg_sendregister=1 +publish=0 +dial_escape_plus=0 + +#[friend_0] +#url="Mariette" +#pol=accept +#subscribe=0 + +[rtp] +audio_rtp_port=18070-28000 +video_rtp_port=39072-49000 + +[video] +display=0 +capture=0 +show_local=0 +size=qcif +enabled=0 +self_view=0 +automatically_initiate=0 +automatically_accept=0 +device=StaticImage: Static picture + +[sound] +echocancellation=0 #to not overload cpu in case of VG + +[net] +dns_srv_enabled=0 #no srv needed in general +stun_server=stun.linphone.org + +[tunnel] +verifyCert=1 diff --git a/tester/tunnel_tester.c b/tester/tunnel_tester.c index 85db979ba..4b1555bdc 100644 --- a/tester/tunnel_tester.c +++ b/tester/tunnel_tester.c @@ -30,10 +30,10 @@ static char* get_public_contact_ip(LinphoneCore* lc) { } -static void call_with_tunnel_base(LinphoneTunnelMode tunnel_mode, bool_t with_sip, LinphoneMediaEncryption encryption, bool_t with_video_and_ice) { +static void call_with_tunnel_base_with_config_files(LinphoneTunnelMode tunnel_mode, bool_t with_sip, LinphoneMediaEncryption encryption, bool_t with_video_and_ice, const char *marie_rc, const char *pauline_rc) { if (linphone_core_tunnel_available()){ - LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_rc"); - LinphoneCoreManager *marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new( pauline_rc); + LinphoneCoreManager *marie = linphone_core_manager_new( marie_rc); LinphoneCall *pauline_call, *marie_call; LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(pauline->lc); LinphoneAddress *server_addr = linphone_address_new(linphone_proxy_config_get_server_addr(proxy)); @@ -155,6 +155,9 @@ static void call_with_tunnel_base(LinphoneTunnelMode tunnel_mode, bool_t with_si } } +static void call_with_tunnel_base(LinphoneTunnelMode tunnel_mode, bool_t with_sip, LinphoneMediaEncryption encryption, bool_t with_video_and_ice) { + call_with_tunnel_base_with_config_files(tunnel_mode, with_sip, encryption, with_video_and_ice, "marie_rc", "pauline_rc"); +} static void call_with_tunnel(void) { call_with_tunnel_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionNone, FALSE); @@ -168,6 +171,10 @@ static void call_with_tunnel_without_sip(void) { call_with_tunnel_base(LinphoneTunnelModeEnable, FALSE, LinphoneMediaEncryptionNone, FALSE); } +static void call_with_tunnel_verify_server_certificate(void) { + call_with_tunnel_base_with_config_files(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionNone, FALSE, "marie_rc", "pauline_tunnel_verify_server_certificate_rc"); +} + static void call_with_tunnel_auto(void) { call_with_tunnel_base(LinphoneTunnelModeAuto, TRUE, LinphoneMediaEncryptionNone, FALSE); } @@ -237,6 +244,7 @@ test_t tunnel_tests[] = { TEST_NO_TAG("Simple", call_with_tunnel), TEST_NO_TAG("With SRTP", call_with_tunnel_srtp), TEST_NO_TAG("Without SIP", call_with_tunnel_without_sip), + TEST_NO_TAG("Verify Server Certificate", call_with_tunnel_verify_server_certificate), TEST_NO_TAG("In automatic mode", call_with_tunnel_auto), TEST_NO_TAG("In automatic mode with SRTP without SIP", call_with_tunnel_auto_without_sip_with_srtp), TEST_NO_TAG("Ice call", tunnel_ice_call),