From f8258757ab9952ccb58ee9ccad2af155831e5f77 Mon Sep 17 00:00:00 2001 From: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> Date: Thu, 5 Feb 2015 17:46:05 -0500 Subject: [PATCH] dring: remove dead/deprecated API (TLS validation) Refs #65511 Change-Id: Ic9026eea08456f6d94e93edbbc6ea13b3aea3735 --- .../dbus/configurationmanager-introspec.xml | 26 - daemon/bin/dbus/dbusconfigurationmanager.cpp | 15 - daemon/bin/dbus/dbusconfigurationmanager.h | 3 - daemon/src/client/configurationmanager.cpp | 36 - daemon/src/client/configurationmanager.h | 5 - daemon/src/dring/dring.h | 3 - daemon/src/ring_api.cpp | 15 - daemon/src/sip/Makefile.am | 2 - daemon/src/sip/tlsvalidation.c | 673 ------------------ daemon/src/sip/tlsvalidation.h | 60 -- daemon/src/sip/tlsvalidator.cpp | 2 + daemon/src/sip/tlsvalidator.h | 8 +- daemon/test/tlstest.cpp | 17 +- .../dbus/configurationmanager-introspec.xml | 26 - gnome/src/dbus/dbus.c | 16 +- 15 files changed, 12 insertions(+), 895 deletions(-) delete mode 100644 daemon/src/sip/tlsvalidation.c delete mode 100644 daemon/src/sip/tlsvalidation.h diff --git a/daemon/bin/dbus/configurationmanager-introspec.xml b/daemon/bin/dbus/configurationmanager-introspec.xml index 229743620c..ad56b08290 100644 --- a/daemon/bin/dbus/configurationmanager-introspec.xml +++ b/daemon/bin/dbus/configurationmanager-introspec.xml @@ -716,31 +716,5 @@ <arg type="a{ss}" name="shortcutsMap" direction="in"> </arg> </method> - - <!-- Security Methods --> - <method name="checkForPrivateKey" tp:name-for-bindings="checkForPrivateKey"> - <arg type="s" name="pemPath" direction="in"> - </arg> - <arg type="b" name="containPrivateKey" direction="out"> - </arg> - </method> - - <method name="checkCertificateValidity" tp:name-for-bindings="checkCertificateValidity"> - <arg type="s" name="caPath" direction="in"> - </arg> - <arg type="s" name="pemPath" direction="in"> - </arg> - <arg type="b" name="isValid" direction="out"> - </arg> - </method> - - <method name="checkHostnameCertificate" tp:name-for-bindings="checkHostnameCertificate"> - <arg type="s" name="host" direction="in"> - </arg> - <arg type="s" name="port" direction="in"> - </arg> - <arg type="b" name="isValid" direction="out"> - </arg> - </method> </interface> </node> diff --git a/daemon/bin/dbus/dbusconfigurationmanager.cpp b/daemon/bin/dbus/dbusconfigurationmanager.cpp index 9c6f7a9a7f..d2830b2156 100644 --- a/daemon/bin/dbus/dbusconfigurationmanager.cpp +++ b/daemon/bin/dbus/dbusconfigurationmanager.cpp @@ -371,18 +371,3 @@ double DBusConfigurationManager::getVolume(const std::string& device) { return ring_config_get_volume(device); } - -bool DBusConfigurationManager::checkForPrivateKey(const std::string& pemPath) -{ - return ring_config_check_for_private_key(pemPath); -} - -bool DBusConfigurationManager::checkCertificateValidity(const std::string& caPath, const std::string& pemPath) -{ - return ring_config_check_certificate_validity(caPath, pemPath); -} - -bool DBusConfigurationManager::checkHostnameCertificate(const std::string& host, const std::string& port) -{ - return ring_config_check_hostname_certificate(host, port); -} diff --git a/daemon/bin/dbus/dbusconfigurationmanager.h b/daemon/bin/dbus/dbusconfigurationmanager.h index 106f27cd94..39465eda05 100644 --- a/daemon/bin/dbus/dbusconfigurationmanager.h +++ b/daemon/bin/dbus/dbusconfigurationmanager.h @@ -132,9 +132,6 @@ class DBusConfigurationManager : void setShortcuts(const std::map<std::string, std::string> &shortcutsMap); void setVolume(const std::string& device, const double& value); double getVolume(const std::string& device); - bool checkForPrivateKey(const std::string& pemPath); - bool checkCertificateValidity(const std::string& caPath, const std::string& pemPath); - bool checkHostnameCertificate(const std::string& host, const std::string& port); 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> getCertificateDetails(const std::string& certificate); diff --git a/daemon/src/client/configurationmanager.cpp b/daemon/src/client/configurationmanager.cpp index ca33bb98a3..296209d1ac 100644 --- a/daemon/src/client/configurationmanager.cpp +++ b/daemon/src/client/configurationmanager.cpp @@ -39,7 +39,6 @@ #include "manager.h" #if HAVE_TLS && HAVE_DHT #include "sip/tlsvalidator.h" -#include "sip/tlsvalidation.h" #endif #include "logger.h" #include "fileutils.h" @@ -617,41 +616,6 @@ void ConfigurationManager::setCredentials(const std::string& accountID, sipaccount->setCredentials(details); } -bool ConfigurationManager::checkForPrivateKey(const std::string& pemPath) -{ -#if HAVE_TLS && HAVE_DHT - return containsPrivateKey(pemPath.c_str()) == 0; -#else - RING_WARN("TLS not supported"); - return false; -#endif -} - -bool ConfigurationManager::checkCertificateValidity(const std::string& caPath, - const std::string& pemPath) -{ -#if HAVE_TLS && HAVE_DHT - return certificateIsValid(caPath.size() > 0 ? caPath.c_str() : NULL, - pemPath.c_str()) == 0; -#else - RING_WARN("TLS not supported"); - return false; -#endif -} - -bool ConfigurationManager::checkHostnameCertificate(const std::string& host, - const std::string& port) -{ -#if HAVE_TLS && HAVE_DHT - return verifyHostnameCertificate(host.c_str(), - strtol(port.c_str(), NULL, 10)) == 0; -#else - RING_WARN("TLS not supported"); - return false; -#endif -} - - void ConfigurationManager::volumeChanged(const std::string& device, double value) { if (evHandlers_.on_volume_change) { diff --git a/daemon/src/client/configurationmanager.h b/daemon/src/client/configurationmanager.h index ae3cceffee..1d384603f5 100644 --- a/daemon/src/client/configurationmanager.h +++ b/daemon/src/client/configurationmanager.h @@ -141,11 +141,6 @@ class ConfigurationManager /* * Security */ - bool checkForPrivateKey(const std::string& pemPath); - bool checkCertificateValidity(const std::string& caPath, - const std::string& pemPath); - bool checkHostnameCertificate(const std::string& host, - const std::string& port); 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> getCertificateDetails(const std::string& certificate); diff --git a/daemon/src/dring/dring.h b/daemon/src/dring/dring.h index 1e72cac3eb..6579b55279 100644 --- a/daemon/src/dring/dring.h +++ b/daemon/src/dring/dring.h @@ -261,9 +261,6 @@ std::map<std::string, std::string> ring_config_get_shortcuts(); void ring_config_set_shortcuts(const std::map<std::string, std::string>& shortcuts); void ring_config_set_volume(const std::string& device, double value); double ring_config_get_volume(const std::string& device); -bool ring_config_check_for_private_key(const std::string& pem_path); -bool ring_config_check_certificate_validity(const std::string& ca_path, const std::string& pem_path); -bool ring_config_check_hostname_certificate(const std::string& host, const std::string& port); /* presence API */ void ring_pres_publish(const std::string& account_id, int status, const std::string& note); diff --git a/daemon/src/ring_api.cpp b/daemon/src/ring_api.cpp index 04f2ac2b7b..dd6175b1fe 100644 --- a/daemon/src/ring_api.cpp +++ b/daemon/src/ring_api.cpp @@ -670,21 +670,6 @@ double ring_config_get_volume(const std::string& device) return getConfigurationManager()->getVolume(device); } -bool ring_config_check_for_private_key(const std::string& pem_path) -{ - return getConfigurationManager()->checkForPrivateKey(pem_path); -} - -bool ring_config_check_certificate_validity(const std::string& ca_path, const std::string& pem_path) -{ - return getConfigurationManager()->checkCertificateValidity(ca_path, pem_path); -} - -bool ring_config_check_hostname_certificate(const std::string& host, const std::string& port) -{ - return getConfigurationManager()->checkHostnameCertificate(host, port); -} - std::map<std::string, std::string> ring_config_validate_certificate(const std::string& accountId, const std::string& certificate, const std::string& private_key) { return getConfigurationManager()->validateCertificate(accountId,certificate,private_key); diff --git a/daemon/src/sip/Makefile.am b/daemon/src/sip/Makefile.am index c23a33b532..ce6d0be934 100644 --- a/daemon/src/sip/Makefile.am +++ b/daemon/src/sip/Makefile.am @@ -20,8 +20,6 @@ libsiplink_la_SOURCES = \ sip_utils.h if BUILD_TLS -libsiplink_la_SOURCES += tlsvalidation.c \ - tlsvalidation.h # These files depend on opendht if USE_DHT libsiplink_la_SOURCES += tlsvalidator.cpp \ diff --git a/daemon/src/sip/tlsvalidation.c b/daemon/src/sip/tlsvalidation.c deleted file mode 100644 index 8e25028535..0000000000 --- a/daemon/src/sip/tlsvalidation.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - * Copyright (C) 2004-2015 Savoir-Faire Linux Inc. - * - * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> - * Vittorio Giovara <vittorio.giovara@savoirfairelinux.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Additional permission under GNU GPL version 3 section 7: - * - * If you modify this program, or any covered work, by linking or - * combining it with the OpenSSL project's OpenSSL library (or a - * modified version of that library), containing parts covered by the - * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc. - * grants you additional permission to convey the resulting work. - * Corresponding Source for a non-source form of such a combination - * shall include the source code for the parts of OpenSSL used as well - * as that of the covered work. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <netinet/tcp.h> -#include <netinet/in.h> -#include <netdb.h> -#include <unistd.h> -#include <fcntl.h> -#include <limits.h> -#include <errno.h> -#include <dirent.h> - -#include <gnutls/gnutls.h> -#include <gnutls/x509.h> -#include <gnutls/abstract.h> - -#include "logger.h" -#include "tlsvalidation.h" - -/** - * Load the content of a file and return the data pointer to it. - */ -static unsigned char *crypto_file_read(const char *path, size_t *out_len) -{ - struct stat st; - int fd; - ssize_t bytes_read; - size_t file_size; - unsigned char *data = NULL; - - *out_len = 0; - - fd = open(path, O_RDONLY); - if (fd < 0) { - RING_ERR("Failed to open file '%s'.", path); - return NULL; - } - - if (fstat(fd, &st) < 0) { - RING_ERR("Failed to stat file '%s'.", path); - goto out; - } - - if (st.st_size <= 0 || st.st_size > INT_MAX) { - RING_ERR("Invalid file '%s' length %ld.", path, st.st_size); - goto out; - } - - file_size = st.st_size; - data = (unsigned char *)malloc(file_size); - if (!data) { - RING_ERR("Not enough memory to read file '%s'.", path); - goto out; - } - - do { - bytes_read = read(fd, &(data[*out_len]), (st.st_size - *out_len)); - if (bytes_read < 0) { - free(data); - data = NULL; - *out_len = 0; - RING_ERR("Failed to read file '%s'.", path); - goto out; - } - *out_len += bytes_read; - } while ((bytes_read > 0) && (*out_len < file_size)); - -out: - close(fd); - return data; -} - -/** - * Check the validity date of a given certificate. - */ -static int crypto_cert_check_date(gnutls_x509_crt_t cert) -{ - time_t now = time(0); - time_t activationTime, expirationTime; - - activationTime = gnutls_x509_crt_get_activation_time(cert); - if (activationTime == -1) { - RING_ERR("Could not retrieve activation time."); - return -1; - } - if (now < activationTime) { - RING_ERR("Certificate not yet activated."); - return -1; - } - - expirationTime = gnutls_x509_crt_get_expiration_time(cert); - if (expirationTime == -1) { - RING_ERR("Could not errrieve expiration time."); - return -2; - } - if (now > expirationTime) { - RING_ERR("Certificate expired."); - return -2; - } - - return 0; -} - -/** - * Load the content of a certificate file and return the data pointer to it. - */ -static unsigned char *crypto_cert_read(const char *path, size_t *out_len) -{ - gnutls_x509_crt_t cert; - unsigned char *data = NULL; - gnutls_datum_t dt; - size_t fsize = 0; - int err; - - dt.data = crypto_file_read(path, &fsize); - if (!dt.data) - return NULL; - - dt.size = (unsigned int) fsize; - if (gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS) { - RING_ERR("Not enough memory for certificate."); - goto out; - } - - err = gnutls_x509_crt_import(cert, &dt, GNUTLS_X509_FMT_PEM); - if (err != GNUTLS_E_SUCCESS) - err = gnutls_x509_crt_import(cert, &dt, GNUTLS_X509_FMT_DER); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not import certificate %s - %s", path, gnutls_strerror(err)); - goto out; - } - - /* check if cert date is valid */ - err = crypto_cert_check_date(cert); - if (err < 0) - goto out; - - *out_len = 10000; - data = (unsigned char *)malloc(*out_len); - if (!data) - goto out; - err = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, data, out_len); - if (err != GNUTLS_E_SUCCESS) { - free(data); - data = NULL; - *out_len = 0; - RING_ERR("Certificate %s could not be exported - %s.\n", - path, gnutls_strerror(err)); - } - -out: - if (dt.data) - gnutls_free(dt.data); - gnutls_x509_crt_deinit(cert); - return data; -} - -/** - * Load all root CAs present in the system. - * Normally we should use gnutls_certificate_set_x509_system_trust(), but it requires - * GnuTLS 3.0 or later. As a workaround we iterate on the system trusted store folder - * and load every certificate available there. - */ -static int crypto_cert_load_trusted(gnutls_certificate_credentials_t cred) -{ - DIR *trust_store; - struct dirent *trust_ca; - struct stat statbuf; - int err, res = -1; - char ca_file[512]; - - trust_store = opendir("/etc/ssl/certs/"); - if (!trust_store) { - RING_ERR("Failed to open system trusted store."); - goto out; - } - while ((trust_ca = readdir(trust_store)) != NULL) { - /* Prepare the string and check it is a regular file. */ - err = snprintf(ca_file, sizeof(ca_file), "/etc/ssl/certs/%s", trust_ca->d_name); - if (err < 0) { - RING_ERR("snprintf() error"); - goto out; - } else if (err >= sizeof(ca_file)) { - RING_ERR("File name too long '%s'.", trust_ca->d_name); - goto out; - } - err = stat(ca_file, &statbuf); - if (err < 0) { - RING_ERR("Failed to stat file '%s'.", ca_file); - goto out; - } - if (!S_ISREG(statbuf.st_mode)) - continue; - - /* Load the root CA. */ - err = gnutls_certificate_set_x509_trust_file(cred, ca_file, GNUTLS_X509_FMT_PEM); - if (err == 0) { - RING_WARN("No trusted certificates found - %s", gnutls_strerror(err)); - } else if (err < 0) { - RING_ERR("Could not load trusted certificates - %s", gnutls_strerror(err)); - goto out; - } - } - - res = 0; -out: - closedir(trust_store); - return res; -} - -/** - * Print the Subject, the Issuer and the Verification status of a given certificate. - */ -static int crypto_cert_print_issuer(gnutls_x509_crt_t cert, - gnutls_x509_crt_t issuer) -{ - char name[512]; - char issuer_name[512]; - size_t name_size; - size_t issuer_name_size; - - issuer_name_size = sizeof(issuer_name); - gnutls_x509_crt_get_issuer_dn(cert, issuer_name, - &issuer_name_size); - - name_size = sizeof(name); - gnutls_x509_crt_get_dn(cert, name, &name_size); - - RING_DBG("Subject: %s", name); - RING_DBG("Issuer: %s", issuer_name); - - if (issuer != NULL) { - issuer_name_size = sizeof(issuer_name); - gnutls_x509_crt_get_dn(issuer, issuer_name, &issuer_name_size); - - RING_DBG("Verified against: %s", issuer_name); - } - - return 0; -} - -int containsPrivateKey(const char *pemPath) -{ - gnutls_datum_t dt; - gnutls_x509_privkey_t key; - size_t bufsize; - int err, res = -1; - - dt.data = crypto_file_read(pemPath, &bufsize); - if (!dt.data) - return res; - dt.size = bufsize; - - err = gnutls_global_init(); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not init GnuTLS - %s", gnutls_strerror(err)); - free(dt.data); - return res; - } - - err = gnutls_x509_privkey_init(&key); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not init key - %s", gnutls_strerror(err)); - free(dt.data); - gnutls_global_deinit(); - return res; - } - - err = gnutls_x509_privkey_import(key, &dt, GNUTLS_X509_FMT_PEM); - if (err != GNUTLS_E_SUCCESS) - err = gnutls_x509_privkey_import(key, &dt, GNUTLS_X509_FMT_DER); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not read key - %s", gnutls_strerror(err)); - goto out; - } - - res = 0; - RING_DBG("Key from %s seems valid.", pemPath); -out: - free(dt.data); - gnutls_x509_privkey_deinit(key); - gnutls_global_deinit(); - return res; -} - -int certificateIsValid(const char *caPath, const char *certPath) -{ - gnutls_x509_crt_t ca = NULL; - gnutls_x509_crt_t cert = NULL; - gnutls_datum_t ca_dt = {}, cert_dt = {}; - size_t bufsize; - unsigned int output; - int err, self_signed; - int res = -1; - - err = gnutls_global_init(); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not init GnuTLS - %s", gnutls_strerror(err)); - goto out; - } - - cert_dt.data = crypto_cert_read(certPath, &bufsize); - cert_dt.size = bufsize; - if (!cert_dt.data) - goto out; - - err = gnutls_x509_crt_init(&cert); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not init certificate - %s", gnutls_strerror(err)); - goto out; - } - - err = gnutls_x509_crt_import(cert, &cert_dt, GNUTLS_X509_FMT_PEM); - if (err != GNUTLS_E_SUCCESS) - err = gnutls_x509_crt_import(cert, &cert_dt, GNUTLS_X509_FMT_DER); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not read certificate - %s", gnutls_strerror(err)); - goto out; - } - free(cert_dt.data); - cert_dt.data = NULL; - - /* check if cert is self signed */ - self_signed = gnutls_x509_crt_check_issuer(cert, cert); - if (!self_signed && !caPath) { - RING_ERR("Certificate is not self-signed, and CA is not provided."); - goto out; - } - if (caPath) { - ca_dt.data = crypto_cert_read(caPath, &bufsize); - ca_dt.size = bufsize; - if (!ca_dt.data) - goto out; - - err = gnutls_x509_crt_init(&ca); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not init CA - %s", gnutls_strerror(err)); - goto out; - } - - err = gnutls_x509_crt_import(ca, &ca_dt, GNUTLS_X509_FMT_PEM); - if (err != GNUTLS_E_SUCCESS) - err = gnutls_x509_crt_import(ca, &ca_dt, GNUTLS_X509_FMT_DER); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not read CA - %s", gnutls_strerror(err)); - goto out; - } - free(ca_dt.data); - ca_dt.data = NULL; - - /* Check if the CA is the issuer of certificate. */ - self_signed = gnutls_x509_crt_check_issuer(cert, ca); - if (!self_signed) { - RING_ERR("Certificate is not issued by the provided CA."); - goto out; - } - - /* Verify the certificate with its issuer. */ - err = gnutls_x509_crt_verify(cert, &ca, 1, 0, &output); - if (err < 0) { - RING_ERR("Could not verify cert: %s", gnutls_strerror(err)); - goto out; - } - if (output & GNUTLS_CERT_INVALID) { - RING_ERR("Verification failed."); - if (output & GNUTLS_CERT_SIGNER_NOT_FOUND) - RING_ERR("The certificate hasn't got a known issuer."); - if (output & GNUTLS_CERT_SIGNER_NOT_CA) - RING_ERR("The certificate issuer is not a CA."); - if (output & GNUTLS_CERT_REVOKED) - RING_ERR("The certificate has been revoked."); - if (output & GNUTLS_CERT_EXPIRED) - RING_ERR("The certificate has expired."); - if (output & GNUTLS_CERT_NOT_ACTIVATED) - RING_ERR("The certificate is not yet activated."); - goto out; - } - } - - RING_DBG("Certificate from %s seems valid.", certPath); - crypto_cert_print_issuer(cert, ca); - res = 0; -out: - if (ca_dt.data) - free(ca_dt.data); - if (cert_dt.data) - free(cert_dt.data); - if (ca) - gnutls_x509_crt_deinit(ca); - gnutls_x509_crt_deinit(cert); - gnutls_global_deinit(); - return res; -} - -/* mainly based on Fedora Defensive Coding tutorial - * https://docs.fedoraproject.org/en-US/Fedora_Security_Team/html/Defensive_Coding/sect-Defensive_Coding-TLS-Client-GNUTLS.html - */ -int verifyHostnameCertificate(const char *host, const uint16_t port) -{ - int err, arg, res = -1; - unsigned int status = (unsigned) -1; - const char *errptr = NULL; - gnutls_session_t session = NULL; - gnutls_certificate_credentials_t cred = NULL; - unsigned int certslen = 0; - const gnutls_datum_t *certs = NULL; - gnutls_x509_crt_t cert = NULL; - - char buf[4096]; - int sockfd; - struct sockaddr_in name; - struct hostent *hostinfo; - const int one = 1; - fd_set fdset; - struct timeval tv; - - if (!host || !port) { - RING_ERR("Wrong parameters used - host %s, port %d.", host, port); - return res; - } - - /* Create the socket. */ - sockfd = socket (PF_INET, SOCK_STREAM, 0); - if (sockfd < 0) { - RING_ERR("Could not create socket."); - return res; - } - /* Set non-blocking so we can dected timeouts. */ - arg = fcntl(sockfd, F_GETFL, NULL); - if (arg < 0) - goto out; - arg |= O_NONBLOCK; - if (fcntl(sockfd, F_SETFL, arg) < 0) - goto out; - - /* Give the socket a name. */ - memset(&name, 0, sizeof(name)); - name.sin_family = AF_INET; - name.sin_port = htons(port); - hostinfo = gethostbyname(host); - if (hostinfo == NULL) { - RING_ERR("Unknown host %s.", host); - goto out; - } - name.sin_addr = *(struct in_addr *)hostinfo->h_addr; - /* Connect to the address specified in name struct. */ - err = connect(sockfd, (struct sockaddr *)&name, sizeof(name)); - if (err < 0) { - /* Connection in progress, use select to see if timeout is reached. */ - if (errno == EINPROGRESS) { - do { - FD_ZERO(&fdset); - FD_SET(sockfd, &fdset); - tv.tv_sec = 10; // 10 second timeout - tv.tv_usec = 0; - err = select(sockfd + 1, NULL, &fdset, NULL, &tv); - if (err < 0 && errno != EINTR) { - RING_ERR("Could not connect to hostname %s at port %d", - host, port); - goto out; - } else if (err > 0) { - /* Select returned, if so_error is clean we are ready. */ - int so_error; - socklen_t len = sizeof(so_error); - getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &so_error, &len); - - if (so_error) { - RING_ERR("Connection delayed."); - goto out; - } - break; // exit do-while loop - } else { - RING_ERR("Connection timeout."); - goto out; - } - } while(1); - } else { - RING_ERR("Could not connect to hostname %s at port %d", host, port); - goto out; - } - } - /* Set the socked blocking again. */ - arg = fcntl(sockfd, F_GETFL, NULL); - if (arg < 0) - goto out; - arg &= ~O_NONBLOCK; - if (fcntl(sockfd, F_SETFL, arg) < 0) - goto out; - - /* Disable Nagle algorithm that slows down the SSL handshake. */ - err = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); - if (err < 0) { - RING_ERR("Could not set TCP_NODELAY."); - goto out; - } - - err = gnutls_global_init(); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not init GnuTLS - %s", gnutls_strerror(err)); - goto out; - } - /* Load the trusted CA certificates. */ - err = gnutls_certificate_allocate_credentials(&cred); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not allocate credentials - %s", gnutls_strerror(err)); - goto out; - } - err = crypto_cert_load_trusted(cred); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not load credentials."); - goto out; - } - - /* Create the session object. */ - err = gnutls_init(&session, GNUTLS_CLIENT); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not init session -%s\n", gnutls_strerror(err)); - goto out; - } - - /* Configure the cipher preferences. The default set should be good enough. */ - err = gnutls_priority_set_direct(session, "NORMAL", &errptr); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not set up ciphers - %s (%s)", gnutls_strerror(err), errptr); - goto out; - } - - /* Install the trusted certificates. */ - err = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not set up credentials - %s", gnutls_strerror(err)); - goto out; - } - - /* Associate the socket with the session object and set the server name. */ - gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) (uintptr_t) sockfd); - err = gnutls_server_name_set(session, GNUTLS_NAME_DNS, host, strlen(host)); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not set server name - %s", gnutls_strerror(err)); - goto out; - } - - /* Establish the connection. */ - err = gnutls_handshake(session); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Handshake failed - %s", gnutls_strerror(err)); - goto out; - } - /* Obtain the server certificate chain. The server certificate - * itself is stored in the first element of the array. */ - certs = gnutls_certificate_get_peers(session, &certslen); - if (certs == NULL || certslen == 0) { - RING_ERR("Could not obtain peer certificate - %s", gnutls_strerror(err)); - goto out; - } - - /* Validate the certificate chain. */ - err = gnutls_certificate_verify_peers2(session, &status); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not verify the certificate chain - %s", gnutls_strerror(err)); - goto out; - } - if (status != 0) { - gnutls_datum_t msg; -#if GNUTLS_VERSION_AT_LEAST_3_1_4 - int type = gnutls_certificate_type_get(session); - err = gnutls_certificate_verification_status_print(status, type, &out, 0); -#else - err = -1; -#endif - if (err == 0) { - RING_ERR("Certificate validation failed - %s\n", msg.data); - gnutls_free(msg.data); - goto out; - } else { - RING_ERR("Certificate validation failed with code 0x%x.", status); - goto out; - } - } - - /* Match the peer certificate against the hostname. - * We can only obtain a set of DER-encoded certificates from the - * session object, so we have to re-parse the peer certificate into - * a certificate object. */ - - err = gnutls_x509_crt_init(&cert); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not init certificate - %s", gnutls_strerror(err)); - goto out; - } - - /* The peer certificate is the first certificate in the list. */ - err = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_PEM); - if (err != GNUTLS_E_SUCCESS) - err = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER); - if (err != GNUTLS_E_SUCCESS) { - RING_ERR("Could not read peer certificate - %s", gnutls_strerror(err)); - goto out; - } - /* Finally check if the hostnames match. */ - err = gnutls_x509_crt_check_hostname(cert, host); - if (err == 0) { - RING_ERR("Hostname %s does not match certificate.", host); - goto out; - } - - /* Try sending and receiving some data through. */ - snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host); - err = gnutls_record_send(session, buf, strlen(buf)); - if (err < 0) { - RING_ERR("Send failed - %s", gnutls_strerror(err)); - goto out; - } - err = gnutls_record_recv(session, buf, sizeof(buf)); - if (err < 0) { - RING_ERR("Recv failed - %s", gnutls_strerror(err)); - goto out; - } - - RING_DBG("Hostname %s seems to point to a valid server.", host); - res = 0; -out: - if (session) { - gnutls_bye(session, GNUTLS_SHUT_RDWR); - gnutls_deinit(session); - } - if (cert) - gnutls_x509_crt_deinit(cert); - if (cred) - gnutls_certificate_free_credentials(cred); - gnutls_global_deinit(); - close(sockfd); - return res; -} diff --git a/daemon/src/sip/tlsvalidation.h b/daemon/src/sip/tlsvalidation.h deleted file mode 100644 index 2549733f63..0000000000 --- a/daemon/src/sip/tlsvalidation.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2004-2015 Savoir-Faire Linux Inc. - * - * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> - * Vittorio Giovara <vittorio.giovara@savoirfairelinux.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef SECURITY_EVALUATOR_H -#define SECURITY_EVALUATOR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdint.h> - - /** - * Check if the given .pem contains a valid private key. - * - * @return 0 if success, -1 otherwise - */ - int containsPrivateKey(const char *pemPath); - - /** - * Check if the given .pem contains a valid certificate. - * - * @return 0 if success, -1 otherwise - */ - int certificateIsValid(const char *caPath, - const char *pemPath); - - /** - * Verify that the local hostname points to a valid SSL server by - * establishing a connection to it and by validating its certificate. - * - * @param host the DNS domain address that the certificate should feature - * @return 0 if success, -1 otherwise - */ - int verifyHostnameCertificate(const char *host, - const uint16_t port); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/daemon/src/sip/tlsvalidator.cpp b/daemon/src/sip/tlsvalidator.cpp index b17d73bd69..de0adce39c 100644 --- a/daemon/src/sip/tlsvalidator.cpp +++ b/daemon/src/sip/tlsvalidator.cpp @@ -421,6 +421,7 @@ unsigned int TlsValidator::compareToCa() return caValidationOutput_; } +#if 0 // disabled, see .h for reason /** * Verify if a hostname is valid * @@ -661,6 +662,7 @@ out: close(sockfd); return res; } +#endif /** * Check if the Validator have access to a private key diff --git a/daemon/src/sip/tlsvalidator.h b/daemon/src/sip/tlsvalidator.h index 94c70b32c8..dca99d0caa 100644 --- a/daemon/src/sip/tlsvalidator.h +++ b/daemon/src/sip/tlsvalidator.h @@ -140,7 +140,8 @@ public: * @param certificate The certificate path * @param privatekey An optional private key file path */ - TlsValidator(const std::string& certificate, const std::string& privatekey); + TlsValidator(const std::string& certificate, + const std::string& privatekey = ""); ~TlsValidator(); @@ -247,8 +248,8 @@ private: // Helper unsigned int compareToCa(); - // TODO remove public: +#if 0 // TODO reimplement this method. do not use it as it /** * Verify that the local hostname points to a valid SSL server by * establishing a connection to it and by validating its certificate. @@ -257,7 +258,8 @@ public: * @return 0 if success, -1 otherwise */ static int verifyHostnameCertificate(const std::string& host, - const uint16_t port); + const uint16_t port); +#endif }; // TlsValidator diff --git a/daemon/test/tlstest.cpp b/daemon/test/tlstest.cpp index 555d2a7956..a06e9c77b4 100644 --- a/daemon/test/tlstest.cpp +++ b/daemon/test/tlstest.cpp @@ -36,7 +36,7 @@ #include "test_utils.h" #include "logger.h" -#include "sip/tlsvalidation.h" +#include "sip/tlsvalidator.h" namespace ring { namespace test { @@ -81,19 +81,4 @@ void TlsTest::testCertificate() CPPUNIT_ASSERT(certificateIsValid(NULL, expiredCertificate) != 0); } -void TlsTest::testHostname() -{ - TITLE(); - - const char *correctUrl = "casecurity.org"; - const char *wrongUrl = "www..com"; - - CPPUNIT_ASSERT(verifyHostnameCertificate(correctUrl, 443) == 0); - - CPPUNIT_ASSERT(verifyHostnameCertificate(correctUrl, 80) != 0); - CPPUNIT_ASSERT(verifyHostnameCertificate(correctUrl, 0) != 0); - CPPUNIT_ASSERT(verifyHostnameCertificate(wrongUrl, 443) != 0); - CPPUNIT_ASSERT(verifyHostnameCertificate(NULL, 443) != 0); -} - }} // namespace ring::test diff --git a/gnome/src/dbus/configurationmanager-introspec.xml b/gnome/src/dbus/configurationmanager-introspec.xml index 66ff98163a..019edd3b43 100644 --- a/gnome/src/dbus/configurationmanager-introspec.xml +++ b/gnome/src/dbus/configurationmanager-introspec.xml @@ -622,31 +622,5 @@ <arg type="a{ss}" name="shortcutsMap" direction="in"> </arg> </method> - - <!-- Security Methods --> - <method name="checkForPrivateKey" tp:name-for-bindings="checkForPrivateKey"> - <arg type="s" name="pemPath" direction="in"> - </arg> - <arg type="b" name="containPrivateKey" direction="out"> - </arg> - </method> - - <method name="checkCertificateValidity" tp:name-for-bindings="checkCertificateValidity"> - <arg type="s" name="caPath" direction="in"> - </arg> - <arg type="s" name="pemPath" direction="in"> - </arg> - <arg type="b" name="isValid" direction="out"> - </arg> - </method> - - <method name="checkHostnameCertificate" tp:name-for-bindings="checkHostnameCertificate"> - <arg type="s" name="host" direction="in"> - </arg> - <arg type="s" name="port" direction="in"> - </arg> - <arg type="b" name="isValid" direction="out"> - </arg> - </method> </interface> </node> diff --git a/gnome/src/dbus/dbus.c b/gnome/src/dbus/dbus.c index e5408c8f8a..342c580598 100644 --- a/gnome/src/dbus/dbus.c +++ b/gnome/src/dbus/dbus.c @@ -2129,23 +2129,15 @@ dbus_get_tls_settings_default(void) gboolean dbus_check_certificate(const gchar *capath, const gchar *certpath) { - GError *error = NULL; - gboolean result; - cx_ring_Ring_ConfigurationManager_check_certificate_validity(config_proxy, capath, certpath, &result, &error); - check_error(error); - - return result; + /* deprecated */ + return FALSE; } gboolean dbus_certificate_contains_private_key(const gchar *filepath) { - GError *error = NULL; - gboolean result; - cx_ring_Ring_ConfigurationManager_check_for_private_key(config_proxy, filepath, &result, &error); - check_error(error); - - return result; + /* deprecated */ + return FALSE; } gchar * -- GitLab