From a1c17a29422aafeaf6748de32c6d65b91f65a2ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com> Date: Fri, 27 Feb 2015 17:07:44 -0500 Subject: [PATCH] tls: transmit certificate and cipher to client Refs #66534 Change-Id: I1ae97785690f37ae6a11e1632d25347ddd4115d0 --- .../dbus/configurationmanager-introspec.xml | 31 ++++++++++++++ daemon/bin/dbus/dbusconfigurationmanager.cpp | 12 ++++++ daemon/bin/dbus/dbusconfigurationmanager.h | 3 +- daemon/contrib/src/opendht/rules.mak | 2 +- daemon/contrib/src/pjproject/gnutls.patch | 40 ++++++++++--------- daemon/contrib/src/pjproject/rules.mak | 1 + daemon/contrib/src/pjproject/tls_cert.patch | 10 +++++ daemon/src/call.cpp | 8 ++-- daemon/src/call.h | 8 ++-- daemon/src/client/configurationmanager.cpp | 34 +++++++++++++++- .../dring/configurationmanager_interface.h | 3 ++ daemon/src/ringdht/sips_transport_ice.cpp | 4 ++ daemon/src/sip/sipcall.cpp | 14 +++++++ daemon/src/sip/sipcall.h | 2 + daemon/src/sip/siptransport.cpp | 20 ++++++++++ daemon/src/sip/siptransport.h | 15 +++++++ daemon/src/sip/tlsvalidator.cpp | 32 +++++++++++---- daemon/src/sip/tlsvalidator.h | 8 ++-- 18 files changed, 208 insertions(+), 39 deletions(-) create mode 100644 daemon/contrib/src/pjproject/tls_cert.patch diff --git a/daemon/bin/dbus/configurationmanager-introspec.xml b/daemon/bin/dbus/configurationmanager-introspec.xml index 3c219b4809..1bebf00e83 100644 --- a/daemon/bin/dbus/configurationmanager-introspec.xml +++ b/daemon/bin/dbus/configurationmanager-introspec.xml @@ -649,6 +649,22 @@ </arg> </method> + <method name="validateCertificateRaw" tp:name-for-bindings="validateCertificateRaw"> + <arg type="s" name="accountId" direction="in"></arg> + <arg type="ay" name="certificateRaw" direction="in"> + <tp:docstring> + <p>A certificate path</p> + </tp:docstring> + </arg> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="details" direction="out"> + <tp:docstring> + <p>A key-value list of all certificate validation</p> + The constants used as keys are defined in the "security.h" constants header file + </tp:docstring> + </arg> + </method> + <method name="getCertificateDetails" tp:name-for-bindings="getCertificateDetails"> <arg type="s" name="certificatePath" direction="in"> <tp:docstring> @@ -664,6 +680,21 @@ </arg> </method> + <method name="getCertificateDetailsRaw" tp:name-for-bindings="getCertificateDetailsRaw"> + <arg type="ay" name="certificateRaw" direction="in"> + <tp:docstring> + <p>A raw certificate</p> + </tp:docstring> + </arg> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/> + <arg type="a{ss}" name="details" direction="out"> + <tp:docstring> + <p>A key-value list of all certificate details</p> + The constants used as keys are defined in the "security.h" constants header file + </tp:docstring> + </arg> + </method> + <method name="getAddrFromInterfaceName" tp:name-for-bindings="getAddrFromInterfaceName"> <arg type="s" name="interface" direction="in"> </arg> diff --git a/daemon/bin/dbus/dbusconfigurationmanager.cpp b/daemon/bin/dbus/dbusconfigurationmanager.cpp index 856a0be490..5099912e05 100644 --- a/daemon/bin/dbus/dbusconfigurationmanager.cpp +++ b/daemon/bin/dbus/dbusconfigurationmanager.cpp @@ -360,12 +360,24 @@ DBusConfigurationManager::validateCertificate(const std::string& accountId, cons return DRing::validateCertificate(accountId, certificate, privateKey); } +std::map<std::string, std::string> +DBusConfigurationManager::validateCertificateRaw(const std::string& accountId, const std::vector<uint8_t>& certificate) +{ + return DRing::validateCertificateRaw(accountId, certificate); +} + auto DBusConfigurationManager::getCertificateDetails(const std::string& certificate) -> decltype(DRing::getCertificateDetails(certificate)) { return DRing::getCertificateDetails(certificate); } +auto +DBusConfigurationManager::getCertificateDetailsRaw(const std::vector<uint8_t>& certificate) -> decltype(DRing::getCertificateDetailsRaw(certificate)) +{ + return DRing::getCertificateDetailsRaw(certificate); +} + void DBusConfigurationManager::setTlsSettings(const std::map<std::string, std::string>& details) { diff --git a/daemon/bin/dbus/dbusconfigurationmanager.h b/daemon/bin/dbus/dbusconfigurationmanager.h index 18447aa96c..4ebba7a264 100644 --- a/daemon/bin/dbus/dbusconfigurationmanager.h +++ b/daemon/bin/dbus/dbusconfigurationmanager.h @@ -128,8 +128,9 @@ class DBusConfigurationManager : void setVolume(const std::string& device, const double& value); double getVolume(const std::string& device); std::map<std::string, std::string> validateCertificate(const std::string& accountId, const std::string& certificate, const std::string& privateKey); + std::map<std::string, std::string> validateCertificateRaw(const std::string& accountId, const std::vector<uint8_t>& certificate); std::map<std::string, std::string> getCertificateDetails(const std::string& certificate); - + std::map<std::string, std::string> getCertificateDetailsRaw(const std::vector<uint8_t>& certificate); }; #endif // __RING_DBUSCONFIGURATIONMANAGER_H__ diff --git a/daemon/contrib/src/opendht/rules.mak b/daemon/contrib/src/opendht/rules.mak index d3859c0a8c..309d906917 100644 --- a/daemon/contrib/src/opendht/rules.mak +++ b/daemon/contrib/src/opendht/rules.mak @@ -1,5 +1,5 @@ # OPENDHT -OPENDHT_VERSION := 13902b0f19f702c43bc34e24a8d42db6a8d81a31 +OPENDHT_VERSION := 6e01255bc00da5ea75c6ee48526743ba56d1f8df OPENDHT_URL := https://github.com/savoirfairelinux/opendht/archive/$(OPENDHT_VERSION).tar.gz PKGS += opendht diff --git a/daemon/contrib/src/pjproject/gnutls.patch b/daemon/contrib/src/pjproject/gnutls.patch index 62f5ef4b61..2b2903fd6e 100644 --- a/daemon/contrib/src/pjproject/gnutls.patch +++ b/daemon/contrib/src/pjproject/gnutls.patch @@ -24,13 +24,13 @@ ssl_sock_gtls: avoid NULL dereference pjlib/include/pj/compat/os_auto.h.in | 3 + pjlib/include/pj/config.h | 4 +- pjlib/src/pj/ssl_sock_common.c | 5 + - pjlib/src/pj/ssl_sock_gtls.c | 2778 ++++++++++++++++++++++++++++++++++ + pjlib/src/pj/ssl_sock_gtls.c | 2782 ++++++++++++++++++++++++++++++++++ pjlib/src/pj/ssl_sock_ossl.c | 6 +- - 8 files changed, 3019 insertions(+), 62 deletions(-) + 8 files changed, 3023 insertions(+), 62 deletions(-) create mode 100644 pjlib/src/pj/ssl_sock_gtls.c diff --git a/aconfigure b/aconfigure -index 24de91d..37e0914 100755 +index a296266..03f727f 100755 --- a/aconfigure +++ b/aconfigure @@ -637,6 +637,8 @@ ac_no_opencore_amrnb @@ -40,9 +40,9 @@ index 24de91d..37e0914 100755 +libgnutls_present +gnutls_h_present ac_no_ssl - ac_openh264_ldflags - ac_openh264_cflags -@@ -1462,8 +1464,8 @@ Optional Features: + ac_v4l2_ldflags + ac_v4l2_cflags +@@ -1457,8 +1459,8 @@ Optional Features: package and samples location using IPPROOT and IPPSAMPLES env var or with --with-ipp and --with-ipp-samples options @@ -53,7 +53,7 @@ index 24de91d..37e0914 100755 --disable-opencore-amr Exclude OpenCORE AMR support from the build (default: autodetect) -@@ -7482,33 +7484,159 @@ fi +@@ -7380,33 +7382,159 @@ fi # Check whether --enable-ssl was given. if test "${enable_ssl+set}" = set; then : @@ -227,7 +227,7 @@ index 24de91d..37e0914 100755 $as_echo_n "checking for ERR_load_BIO_strings in -lcrypto... " >&6; } if ${ac_cv_lib_crypto_ERR_load_BIO_strings+:} false; then : $as_echo_n "(cached) " >&6 -@@ -7548,7 +7676,7 @@ if test "x$ac_cv_lib_crypto_ERR_load_BIO_strings" = xyes; then : +@@ -7446,7 +7574,7 @@ if test "x$ac_cv_lib_crypto_ERR_load_BIO_strings" = xyes; then : libcrypto_present=1 && LIBS="$LIBS -lcrypto" fi @@ -236,7 +236,7 @@ index 24de91d..37e0914 100755 $as_echo_n "checking for SSL_library_init in -lssl... " >&6; } if ${ac_cv_lib_ssl_SSL_library_init+:} false; then : $as_echo_n "(cached) " >&6 -@@ -7588,22 +7716,23 @@ if test "x$ac_cv_lib_ssl_SSL_library_init" = xyes; then : +@@ -7486,22 +7614,23 @@ if test "x$ac_cv_lib_ssl_SSL_library_init" = xyes; then : libssl_present=1 && LIBS="$LIBS -lssl" fi @@ -271,10 +271,10 @@ index 24de91d..37e0914 100755 if test "${with_opencore_amrnb+set}" = set; then : withval=$with_opencore_amrnb; as_fn_error $? "This option is obsolete and replaced by --with-opencore-amr=DIR" "$LINENO" 5 diff --git a/aconfigure.ac b/aconfigure.ac -index 6c35836..3be55c5 100644 +index cd71a7a..465285e 100644 --- a/aconfigure.ac +++ b/aconfigure.ac -@@ -1418,38 +1418,76 @@ fi +@@ -1346,38 +1346,76 @@ fi dnl # Include SSL support AC_SUBST(ac_no_ssl) @@ -383,7 +383,7 @@ index 6c35836..3be55c5 100644 dnl # Obsolete option --with-opencore-amrnb AC_ARG_WITH(opencore-amrnb, diff --git a/pjlib/build/Makefile b/pjlib/build/Makefile -index 1e64950..e650a31 100644 +index a75fa65..529e0ff 100644 --- a/pjlib/build/Makefile +++ b/pjlib/build/Makefile @@ -35,7 +35,7 @@ export PJLIB_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \ @@ -396,7 +396,7 @@ index 1e64950..e650a31 100644 export PJLIB_CFLAGS += $(_CFLAGS) export PJLIB_CXXFLAGS += $(_CXXFLAGS) diff --git a/pjlib/include/pj/compat/os_auto.h.in b/pjlib/include/pj/compat/os_auto.h.in -index 77980d3..6d6a625 100644 +index 18df2bf..9295740 100644 --- a/pjlib/include/pj/compat/os_auto.h.in +++ b/pjlib/include/pj/compat/os_auto.h.in @@ -206,6 +206,9 @@ @@ -410,7 +410,7 @@ index 77980d3..6d6a625 100644 #endif /* __PJ_COMPAT_OS_AUTO_H__ */ diff --git a/pjlib/include/pj/config.h b/pjlib/include/pj/config.h -index c191ef1..4ace1bc 100644 +index 31020a3..90aefe2 100644 --- a/pjlib/include/pj/config.h +++ b/pjlib/include/pj/config.h @@ -854,13 +854,15 @@ @@ -431,7 +431,7 @@ index c191ef1..4ace1bc 100644 diff --git a/pjlib/src/pj/ssl_sock_common.c b/pjlib/src/pj/ssl_sock_common.c -index 67a8d63..602a1af 100644 +index 768a640..b116f1b 100644 --- a/pjlib/src/pj/ssl_sock_common.c +++ b/pjlib/src/pj/ssl_sock_common.c @@ -34,7 +34,12 @@ PJ_DEF(void) pj_ssl_sock_param_default(pj_ssl_sock_param *param) @@ -449,10 +449,10 @@ index 67a8d63..602a1af 100644 #endif diff --git a/pjlib/src/pj/ssl_sock_gtls.c b/pjlib/src/pj/ssl_sock_gtls.c new file mode 100644 -index 0000000..c2a4349 +index 0000000..7b4b941 --- /dev/null +++ b/pjlib/src/pj/ssl_sock_gtls.c -@@ -0,0 +1,2778 @@ +@@ -0,0 +1,2782 @@ +/* $Id$ */ +/* + * Copyright (C) 2014 Savoir-Faire Linux. (http://www.savoirfairelinux.com) @@ -1594,6 +1594,8 @@ index 0000000..c2a4349 + goto us_out; + + tls_cert_get_info(ssock->pool, &ssock->local_cert_info, cert); ++ const pj_str_t local_crt_raw = {(char*)us->data, (pj_ssize_t)us->size}; ++ pj_strdup(ssock->pool, &ssock->local_cert_info.cert_raw, &local_crt_raw); + +us_out: + tls_last_error = ret; @@ -1620,6 +1622,8 @@ index 0000000..c2a4349 + goto peer_out; + + tls_cert_get_info(ssock->pool, &ssock->remote_cert_info, cert); ++ const pj_str_t remote_crt_raw = {(char*)certs->data, (pj_ssize_t)certs->size}; ++ pj_strdup(ssock->pool, &ssock->remote_cert_info.cert_raw, &remote_crt_raw); + +peer_out: + tls_last_error = ret; @@ -3232,7 +3236,7 @@ index 0000000..c2a4349 + +#endif /* PJ_HAS_SSL_SOCK */ diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c -index 7c7b6d0..e466bb7 100644 +index ba4ae0b..98bbfee 100644 --- a/pjlib/src/pj/ssl_sock_ossl.c +++ b/pjlib/src/pj/ssl_sock_ossl.c @@ -31,8 +31,10 @@ diff --git a/daemon/contrib/src/pjproject/rules.mak b/daemon/contrib/src/pjproject/rules.mak index 829bf3fac3..ce28d89aad 100644 --- a/daemon/contrib/src/pjproject/rules.mak +++ b/daemon/contrib/src/pjproject/rules.mak @@ -53,6 +53,7 @@ endif $(APPLY) $(SRC)/pjproject/aconfigureupdate.patch $(APPLY) $(SRC)/pjproject/endianness.patch $(APPLY) $(SRC)/pjproject/unknowncipher.patch + $(APPLY) $(SRC)/pjproject/tls_cert.patch $(APPLY) $(SRC)/pjproject/gnutls.patch $(APPLY) $(SRC)/pjproject/notestsapps.patch $(APPLY) $(SRC)/pjproject/ipv6.patch diff --git a/daemon/contrib/src/pjproject/tls_cert.patch b/daemon/contrib/src/pjproject/tls_cert.patch new file mode 100644 index 0000000000..f030b42319 --- /dev/null +++ b/daemon/contrib/src/pjproject/tls_cert.patch @@ -0,0 +1,10 @@ +--- a/pjlib/include/pj/ssl_sock.h ++++ b/pjlib/include/pj/ssl_sock.h +@@ -181,6 +181,8 @@ typedef struct pj_ssl_cert_info { + } subj_alt_name; /**< Subject alternative + name extension */ + ++ pj_str_t cert_raw; ++ + } pj_ssl_cert_info; + diff --git a/daemon/src/call.cpp b/daemon/src/call.cpp index 769fc662d2..0873fe8ef4 100644 --- a/daemon/src/call.cpp +++ b/daemon/src/call.cpp @@ -80,7 +80,7 @@ Call::setConnectionState(ConnectionState state) } Call::ConnectionState -Call::getConnectionState() +Call::getConnectionState() const { std::lock_guard<std::mutex> lock(callMutex_); return connectionState_; @@ -137,14 +137,14 @@ Call::setState(CallState state) } Call::CallState -Call::getState() +Call::getState() const { std::lock_guard<std::mutex> lock(callMutex_); return callState_; } std::string -Call::getStateStr() +Call::getStateStr() const { switch (getState()) { case ACTIVE: @@ -238,7 +238,7 @@ std::string Call::getTypeStr() const } std::map<std::string, std::string> -Call::getDetails() +Call::getDetails() const { return { {DRing::Call::Details::CALL_TYPE, ring::to_string(type_)}, diff --git a/daemon/src/call.h b/daemon/src/call.h index faa3a68886..31963a5cd3 100644 --- a/daemon/src/call.h +++ b/daemon/src/call.h @@ -167,7 +167,7 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> { * Get the connection state of the call (protected by mutex) * @return ConnectionState The connection state */ - ConnectionState getConnectionState(); + ConnectionState getConnectionState() const; /** * Set the state of the call (protected by mutex) @@ -180,9 +180,9 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> { * Get the call state of the call (protected by mutex) * @return CallState The call state */ - CallState getState(); + CallState getState() const; - std::string getStateStr(); + std::string getStateStr() const; void setIPToIP(bool IPToIP) { isIPToIP_ = IPToIP; @@ -231,7 +231,7 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> { unsigned int getLocalVideoPort() const; void time_stop(); - virtual std::map<std::string, std::string> getDetails(); + virtual std::map<std::string, std::string> getDetails() const; static std::map<std::string, std::string> getNullDetails(); virtual bool toggleRecording(); diff --git a/daemon/src/client/configurationmanager.cpp b/daemon/src/client/configurationmanager.cpp index 2126bb3f4a..beb916b888 100644 --- a/daemon/src/client/configurationmanager.cpp +++ b/daemon/src/client/configurationmanager.cpp @@ -168,6 +168,23 @@ validateCertificate(const std::string&, #endif } +std::map<std::string, std::string> +validateCertificateRaw(const std::string&, + const std::vector<uint8_t>& certificate_raw) +{ +#if HAVE_TLS && HAVE_DHT + try { + return TlsValidator{certificate_raw}.getSerializedChecks(); + } catch(const std::runtime_error& e) { + RING_WARN("Certificate loading failed"); + return {{Certificate::ChecksNames::EXIST, Certificate::CheckValuesNames::FAILED}}; + } +#else + RING_WARN("TLS not supported"); + return {}; +#endif +} + std::map<std::string, std::string> getCertificateDetails(const std::string& certificate) { @@ -180,7 +197,22 @@ getCertificateDetails(const std::string& certificate) #else RING_WARN("TLS not supported"); #endif - return std::map<std::string, std::string>(); + return {}; +} + +std::map<std::string, std::string> +getCertificateDetailsRaw(const std::vector<uint8_t>& certificate_raw) +{ +#if HAVE_TLS && HAVE_DHT + try { + return TlsValidator{certificate_raw}.getSerializedDetails(); + } catch(const std::runtime_error& e) { + RING_WARN("Certificate loading failed"); + } +#else + RING_WARN("TLS not supported"); +#endif + return {}; } void diff --git a/daemon/src/dring/configurationmanager_interface.h b/daemon/src/dring/configurationmanager_interface.h index 9ef4a02625..280a473082 100644 --- a/daemon/src/dring/configurationmanager_interface.h +++ b/daemon/src/dring/configurationmanager_interface.h @@ -169,7 +169,10 @@ double getVolume(const std::string& device); */ std::map<std::string, std::string> validateCertificate(const std::string& accountId, const std::string& certificate, const std::string& privateKey); +std::map<std::string, std::string> validateCertificateRaw(const std::string& accountId, + const std::vector<uint8_t>& certificate); std::map<std::string, std::string> getCertificateDetails(const std::string& certificate); +std::map<std::string, std::string> getCertificateDetailsRaw(const std::vector<uint8_t>& certificate); } // namespace DRing diff --git a/daemon/src/ringdht/sips_transport_ice.cpp b/daemon/src/ringdht/sips_transport_ice.cpp index ba66dc5fb0..4de5b2f868 100644 --- a/daemon/src/ringdht/sips_transport_ice.cpp +++ b/daemon/src/ringdht/sips_transport_ice.cpp @@ -389,6 +389,10 @@ SipsIceTransport::certGetInfo(pj_pool_t *pool, pj_ssl_cert_info *ci, const gnutl /* Update cert info */ pj_bzero(ci, sizeof(pj_ssl_cert_info)); + /* Full raw certificate */ + const pj_str_t raw_crt_pjstr {(char*)crt_raw.data, crt_raw.size}; + pj_strdup(pool, &ci->cert_raw, &raw_crt_pjstr); + /* Version */ ci->version = gnutls_x509_crt_get_version(crt.cert); diff --git a/daemon/src/sip/sipcall.cpp b/daemon/src/sip/sipcall.cpp index 1a55a5e4b8..5c98c74bc3 100644 --- a/daemon/src/sip/sipcall.cpp +++ b/daemon/src/sip/sipcall.cpp @@ -52,6 +52,8 @@ #include "im/instant_messaging.h" #endif +#include "dring/call_const.h" + #ifdef RING_VIDEO #include "client/videomanager.h" #include "video/video_rtp_session.h" @@ -869,6 +871,18 @@ SIPCall::openPortsUPnP() } } +std::map<std::string, std::string> +SIPCall::getDetails() const +{ + auto details = Call::getDetails(); + if (transport_ and transport_->isSecure()) { + const auto& tlsInfos = transport_->getTlsInfos(); + details.emplace(DRing::Call::Details::TLS_PEER_CERT, tlsInfos.peerCert.toString()); + details.emplace(DRing::Call::Details::TLS_CIPHER, pj_ssl_cipher_name(tlsInfos.cipher)); + } + return details; +} + void SIPCall::setSecure(bool sec) { diff --git a/daemon/src/sip/sipcall.h b/daemon/src/sip/sipcall.h index a3499dd243..92fb964aaf 100644 --- a/daemon/src/sip/sipcall.h +++ b/daemon/src/sip/sipcall.h @@ -193,6 +193,8 @@ class SIPCall : public Call void openPortsUPnP(); + virtual std::map<std::string, std::string> getDetails() const; + private: NON_COPYABLE(SIPCall); diff --git a/daemon/src/sip/siptransport.cpp b/daemon/src/sip/siptransport.cpp index 36aa772fe5..7b0fe75a70 100644 --- a/daemon/src/sip/siptransport.cpp +++ b/daemon/src/sip/siptransport.cpp @@ -45,6 +45,7 @@ #include <pjsip/sip_types.h> #if HAVE_TLS #include <pjsip/sip_transport_tls.h> +#include <pj/ssl_sock.h> #endif #include <pjnath.h> #include <pjnath/stun_config.h> @@ -131,6 +132,25 @@ void SipTransport::stateCallback(pjsip_transport_state state, const pjsip_transport_state_info *info) { +#if HAVE_TLS + auto extInfo = static_cast<const pjsip_tls_state_info*>(info->ext_info); + if (isSecure() && extInfo && extInfo->ssl_sock_info && extInfo->ssl_sock_info->established) { + auto tlsInfo = extInfo->ssl_sock_info; + tlsInfos_.proto = tlsInfo->proto; + tlsInfos_.cipher = tlsInfo->cipher; + tlsInfos_.verifyStatus = (pj_ssl_cert_verify_flag_t)tlsInfo->verify_status; + const auto& peer_crt = tlsInfo->remote_cert_info->cert_raw; + if (peer_crt.ptr && peer_crt.slen) + tlsInfos_.peerCert = {std::vector<uint8_t>(peer_crt.ptr, peer_crt.ptr + peer_crt.slen)}; + else + tlsInfos_.peerCert = {}; + } else { + tlsInfos_.proto = PJ_SSL_SOCK_PROTO_DEFAULT; + tlsInfos_.cipher = PJ_TLS_UNKNOWN_CIPHER; + tlsInfos_.peerCert = {}; + } +#endif + std::vector<SipTransportStateCallback> cbs; { std::lock_guard<std::mutex> lock(stateListenersMutex_); diff --git a/daemon/src/sip/siptransport.h b/daemon/src/sip/siptransport.h index 64232882c1..e79c6f706d 100644 --- a/daemon/src/sip/siptransport.h +++ b/daemon/src/sip/siptransport.h @@ -39,6 +39,8 @@ #include "noncopyable.h" #include "logger.h" +#include <opendht/crypto.h> + #include <pjsip.h> #include <pjnath/stun_config.h> @@ -103,6 +105,13 @@ private: pjsip_tpfactory* listener {nullptr}; }; +struct TlsInfos { + pj_ssl_cipher cipher; + pj_ssl_sock_proto proto; + pj_ssl_cert_verify_flag_t verifyStatus; + dht::crypto::Certificate peerCert; +}; + using SipTransportStateCallback = std::function<void(pjsip_transport_state, const pjsip_transport_state_info*)>; /** @@ -131,6 +140,10 @@ class SipTransport return PJSIP_TRANSPORT_IS_SECURE(transport_); } + const TlsInfos& getTlsInfos() const { + return tlsInfos_; + } + static bool isAlive(const std::shared_ptr<SipTransport>&, pjsip_transport_state state); private: @@ -142,6 +155,8 @@ class SipTransport std::shared_ptr<TlsListener> tlsListener_; std::map<uintptr_t, SipTransportStateCallback> stateListeners_; std::mutex stateListenersMutex_; + + TlsInfos tlsInfos_; }; class IpAddr; diff --git a/daemon/src/sip/tlsvalidator.cpp b/daemon/src/sip/tlsvalidator.cpp index de0adce39c..5bfda9e7a3 100644 --- a/daemon/src/sip/tlsvalidator.cpp +++ b/daemon/src/sip/tlsvalidator.cpp @@ -212,8 +212,9 @@ const Matrix2D<TlsValidator::CheckValuesType , TlsValidator::CheckValues , bool> TlsValidator::TlsValidator(const std::string& certificate, const std::string& privatekey) : -certificatePath_(certificate), privateKeyPath_(privatekey), certificateFound_(false), caCert_(nullptr), -caChecked_(false) + certificatePath_(certificate), + privateKeyPath_(privatekey), + certificateFound_(false) { int err = gnutls_global_init(); if (err != GNUTLS_E_SUCCESS) @@ -236,6 +237,22 @@ caChecked_(false) } } +TlsValidator::TlsValidator(const std::vector<uint8_t>& certificate_raw) : + certificateFound_(true) +{ + int err = gnutls_global_init(); + if (err != GNUTLS_E_SUCCESS) + throw TlsValidatorException(gnutls_strerror(err)); + + try { + x509crt_ = {certificate_raw}; + certificateContent_ = x509crt_.getPacked(); + certificateFound_ = true; + } catch (const std::exception& e) { + throw TlsValidatorException("Can't load certificate"); + } +} + TlsValidator::~TlsValidator() { gnutls_global_deinit(); @@ -367,11 +384,12 @@ static TlsValidator::CheckResult checkError(int err, char* copy_buffer, size_t s * ASCII-hexadecimal representation before being sent to DBus as it will cause the * process to assert */ -static std::string binaryToHex(const char* input, size_t input_sz) +static std::string binaryToHex(const uint8_t* input, size_t input_sz) { std::ostringstream ret; + ret << std::hex; for (size_t i=0; i<input_sz; i++) - ret << std::hex << std::setfill('0') << std::setw(2) << std::uppercase << (unsigned)input[i]; + ret << std::setfill('0') << std::setw(2) << (unsigned)input[i]; return ret.str(); } @@ -394,7 +412,7 @@ static TlsValidator::CheckResult formatDate(const time_t time) static TlsValidator::CheckResult checkBinaryError(int err, char* copy_buffer, size_t resultSize) { if (err == GNUTLS_E_SUCCESS) - return TlsValidator::CheckResult(TlsValidator::CheckValues::CUSTOM, binaryToHex(copy_buffer, resultSize)); + return TlsValidator::CheckResult(TlsValidator::CheckValues::CUSTOM, binaryToHex(reinterpret_cast<uint8_t*>(copy_buffer), resultSize)); else return TlsValidator::CheckResult(TlsValidator::CheckValues::UNSUPPORTED, ""); } @@ -970,7 +988,7 @@ TlsValidator::CheckResult TlsValidator::getSerialNumber() // gnutls_x509_crt_get_authority_key_gn_serial size_t resultSize = sizeof(copy_buffer); int err = gnutls_x509_crt_get_serial(x509crt_.cert, copy_buffer, &resultSize); - return checkError(err, copy_buffer, resultSize); + return checkBinaryError(err, copy_buffer, resultSize); } /** @@ -1080,8 +1098,8 @@ TlsValidator::CheckResult TlsValidator::getSha1Fingerprint() */ TlsValidator::CheckResult TlsValidator::getPublicKeyId() { - size_t resultSize = sizeof(copy_buffer); static unsigned char unsigned_copy_buffer[4096]; + size_t resultSize = sizeof(unsigned_copy_buffer); int err = gnutls_x509_crt_get_key_id(x509crt_.cert,0,unsigned_copy_buffer,&resultSize); // TODO check for GNUTLS_E_SHORT_MEMORY_BUFFER and increase the buffer size diff --git a/daemon/src/sip/tlsvalidator.h b/daemon/src/sip/tlsvalidator.h index dca99d0caa..123be98479 100644 --- a/daemon/src/sip/tlsvalidator.h +++ b/daemon/src/sip/tlsvalidator.h @@ -143,6 +143,8 @@ public: TlsValidator(const std::string& certificate, const std::string& privatekey = ""); + TlsValidator(const std::vector<uint8_t>& certificate_raw); + ~TlsValidator(); bool hasCa() const; @@ -233,9 +235,9 @@ private: dht::crypto::Certificate x509crt_; bool certificateFound_; - bool privateKeyFound_; - TlsValidator* caCert_; - bool caChecked_; + bool privateKeyFound_ {false}; + TlsValidator* caCert_ {nullptr}; + bool caChecked_ {false}; unsigned int caValidationOutput_; mutable char copy_buffer[4096]; -- GitLab