diff --git a/daemon/bin/dbus/configurationmanager-introspec.xml b/daemon/bin/dbus/configurationmanager-introspec.xml index c19f3229a2f000649ee33b9d3946d7616a960e4f..229743620c78622f54decbf00f751e0ad6942a9b 100644 --- a/daemon/bin/dbus/configurationmanager-introspec.xml +++ b/daemon/bin/dbus/configurationmanager-introspec.xml @@ -612,6 +612,26 @@ </arg> </method> + <method name="getSupportedCiphers" tp:name-for-bindings="getSupportedCiphers"> + <tp:added version="2.0.0"/> + <tp:docstring> + Returns a list of supported encryption ciphers used to encrypt SIP messages. The list depends on the TLS library being used. + Only registered SIP accounts currently support setting custom ciphers. This method returns an empty list if TLS support is disabled in either pjproject or Ring. + </tp:docstring> + <arg type="s" name="accountID" direction="in"> + <tp:docstring> + A SIP account id, other account IDs will be rejected. + </tp:docstring> + </arg> + <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorString"/> + <arg type="as" name="list" direction="out"> + <tp:docstring> + A list of randomly sorted cipher names. The order may or may + not be significant depending on the SSL library being used. + </tp:docstring> + </arg> + </method> + <method name="getTlsSettingsDefault" tp:name-for-bindings="getTlsSettingsDefault"> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/> <arg type="a{ss}" name="details" direction="out"> diff --git a/daemon/bin/dbus/dbusconfigurationmanager.cpp b/daemon/bin/dbus/dbusconfigurationmanager.cpp index a0648294a0c867b58a9223f84e7a6df4bef8c71d..9c6f7a9a7f92a22b9d3feccbdf13556b6c106642 100644 --- a/daemon/bin/dbus/dbusconfigurationmanager.cpp +++ b/daemon/bin/dbus/dbusconfigurationmanager.cpp @@ -97,6 +97,11 @@ std::vector< std::string > DBusConfigurationManager::getSupportedTlsMethod() return ring_config_get_supported_tls_method(); } +std::vector< std::string > DBusConfigurationManager::getSupportedCiphers(const std::string& accountID) +{ + return ring_config_get_supported_ciphers(accountID); +} + std::vector< std::string > DBusConfigurationManager::getAudioCodecDetails(const int32_t& payload) { return ring_config_get_audio_codec_details(payload); diff --git a/daemon/bin/dbus/dbusconfigurationmanager.h b/daemon/bin/dbus/dbusconfigurationmanager.h index e522973c1460b7c8034d7122fb410d32a2d657d9..106f27cd9425439d157be3af131fd761c4f97a6f 100644 --- a/daemon/bin/dbus/dbusconfigurationmanager.h +++ b/daemon/bin/dbus/dbusconfigurationmanager.h @@ -77,6 +77,7 @@ class DBusConfigurationManager : void sendRegister(const std::string& accoundID, const bool& enable); void registerAllAccounts(void); std::map< std::string, std::string > getTlsSettingsDefault(); + std::vector< std::string > getSupportedCiphers(const std::string& accountID); std::vector< int32_t > getAudioCodecList(); std::vector< std::string > getSupportedTlsMethod(); std::vector< std::string > getAudioCodecDetails(const int32_t& payload); diff --git a/daemon/src/client/configurationmanager.cpp b/daemon/src/client/configurationmanager.cpp index ad04d0429d90806bf2481a362c2f93aebf8786e1..662286a9bf1b0b9a0464941c1b49407e2dcc1c7c 100644 --- a/daemon/src/client/configurationmanager.cpp +++ b/daemon/src/client/configurationmanager.cpp @@ -207,9 +207,9 @@ std::string ConfigurationManager::addAccount(const std::map<std::string, std::st return Manager::instance().addAccount(details); } -void ConfigurationManager::removeAccount(const std::string& accoundID) +void ConfigurationManager::removeAccount(const std::string& accountID) { - return Manager::instance().removeAccount(accoundID); + return Manager::instance().removeAccount(accountID); } std::vector<std::string> ConfigurationManager::getAccountList() @@ -241,6 +241,22 @@ std::vector<std::string> ConfigurationManager::getSupportedTlsMethod() return method; } +std::vector<std::string> ConfigurationManager::getSupportedCiphers(const std::string& accountID) const +{ +#if HAVE_TLS + const auto sipaccount = Manager::instance().getAccount<SIPAccount>(accountID); + if (sipaccount) { + return sipaccount->getSupportedCiphers(); + } else { + RING_ERR("SIP account %s doesn't exist", accountID.c_str()); +#else + { +#endif + return {}; + } + +} + std::vector<std::string> ConfigurationManager::getAudioCodecDetails(int32_t payload) { std::vector<std::string> result(Manager::instance().audioCodecFactory.getCodecSpecifications(payload)); diff --git a/daemon/src/client/configurationmanager.h b/daemon/src/client/configurationmanager.h index b62bbc2bbdf34b1c296c5be4f1b5d03a94e753b8..ae3cceffee7e5178ac99ce5939dbfa0ec9ffae8f 100644 --- a/daemon/src/client/configurationmanager.h +++ b/daemon/src/client/configurationmanager.h @@ -67,6 +67,7 @@ class ConfigurationManager std::vector< int32_t > getAudioCodecList(); std::vector< std::string > getSupportedTlsMethod(); + std::vector< std::string > getSupportedCiphers(const std::string& accountID) const; std::vector< std::string > getAudioCodecDetails(int32_t payload); std::vector< int32_t > getActiveAudioCodecList(const std::string& accountID); diff --git a/daemon/src/dring/dring.h b/daemon/src/dring/dring.h index d734d0461976772d26456bb3a1d8f2912f739980..1e72cac3eba31948b5fbfc27019f8fc3d310f62c 100644 --- a/daemon/src/dring/dring.h +++ b/daemon/src/dring/dring.h @@ -205,6 +205,7 @@ void ring_config_register_all_accounts(void); std::map<std::string, std::string> ring_config_get_tls_default_settings(void); std::vector<int> ring_config_get_audio_codec_list(void); std::vector<std::string> ring_config_get_supported_tls_method(void); +std::vector<std::string> ring_config_get_supported_ciphers(const std::string& account_id); std::vector<std::string> ring_config_get_audio_codec_details(int payload); std::vector<int> ring_config_get_active_audio_codec_list(const std::string& account_id); void ring_config_set_active_audio_codec_list(const std::vector<std::string>& list, const std::string& account_id); diff --git a/daemon/src/ring_api.cpp b/daemon/src/ring_api.cpp index f1acf44b40269f4d4741f80bb75a673afcd5a532..04f2ac2b7b9bd37acf8c63fa88fb5b35138c0cdd 100644 --- a/daemon/src/ring_api.cpp +++ b/daemon/src/ring_api.cpp @@ -395,6 +395,11 @@ std::vector<std::string> ring_config_get_supported_tls_method(void) return getConfigurationManager()->getSupportedTlsMethod(); } +std::vector<std::string> ring_config_get_supported_ciphers(const std::string& account_id) +{ + return getConfigurationManager()->getSupportedCiphers(account_id); +} + std::vector<std::string> ring_config_get_audio_codec_details(int payload) { return getConfigurationManager()->getAudioCodecDetails(payload); diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp index 125c2c173414024ce1f15e575ab0a955015b2f24..53949882d6fd7805a98460bab038820ba5e1a50d 100644 --- a/daemon/src/sip/sipaccount.cpp +++ b/daemon/src/sip/sipaccount.cpp @@ -121,6 +121,7 @@ SIPAccount::SIPAccount(const std::string& accountID, bool presenceEnabled) , serviceRoute_() , cred_() , tlsSetting_() + , ciphers_(100) , tlsCaListFile_() , tlsCertificateFile_() , tlsPrivateKeyFile_() @@ -1501,6 +1502,30 @@ SIPAccount::getHostPortFromSTUN(pj_pool_t *pool) return result; } +const std::vector<std::string>& +SIPAccount::getSupportedCiphers() const +{ + //Currently, both OpenSSL and GNUTLS implementations are static + //reloading this for each account is unnecessary + static std::vector<std::string> availCiphers {}; + + // LIMITATION Assume the size might change, if there aren't any ciphers, + // this will cause the cache to be repopulated at each call for nothing. + if (availCiphers.empty()) { + unsigned cipherNum = 256; + CipherArray avail_ciphers(cipherNum); + if (pj_ssl_cipher_get_availables(&avail_ciphers.front(), &cipherNum) != PJ_SUCCESS) + RING_ERR("Could not determine cipher list on this system"); + + // filter-out 0 ciphers + std::copy_if(avail_ciphers.begin(), avail_ciphers.end(), + availCiphers.begin(), + [](pj_ssl_cipher& item){ return item > 0; }); + } + + return availCiphers; +} + void SIPAccount::keepAliveRegistrationCb(UNUSED pj_timer_heap_t *th, pj_timer_entry *te) { SIPAccount *sipAccount = static_cast<SIPAccount *>(te->user_data); diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h index 170b430908dc405b3bdc8ba89c57862cf0b6a9de..9cb3a231ca21996ffde431effacbab602150619b 100644 --- a/daemon/src/sip/sipaccount.h +++ b/daemon/src/sip/sipaccount.h @@ -315,6 +315,8 @@ class SIPAccount : public SIPAccountBase { return stunServerName_; } + const std::vector<std::string>& getSupportedCiphers() const; + /** * @return pj_uint8_t structure, filled from the configuration * file, that can be used directly by PJSIP to initialize @@ -614,7 +616,7 @@ class SIPAccount : public SIPAccountBase { /** * Allocate a vector to be used by pjsip to store the supported ciphers on this system. */ - CipherArray ciphers_ {}; + CipherArray ciphers_; /** * Determine if STUN public address resolution is required to register this account. In this case a