From 86a0b715f3185eefba0163190037af041256b0ce Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 7 Apr 2014 11:36:32 -0700 Subject: [PATCH] verify DTLS certificate to ensure trust before handshaking --- domain-server/src/DomainServer.cpp | 2 +- libraries/shared/src/DTLSClientSession.cpp | 36 ++++++++++++++++++++-- libraries/shared/src/DTLSClientSession.h | 2 ++ libraries/shared/src/DTLSSession.cpp | 1 - libraries/shared/src/DomainHandler.cpp | 3 +- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 2f4179e56b..d0ac369700 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -689,7 +689,7 @@ void DomainServer::readAvailableDTLSDatagrams() { // the cookie sent by the client was not valid // send a valid one DummyDTLSSession tempServerSession(LimitedNodeList::getInstance()->getDTLSSocket(), senderHifiSockAddr); - qDebug() << "sending back a fresh cookie!"; + gnutls_dtls_cookie_send(_cookieKey, &senderSockAddr, sizeof(senderSockAddr), &prestate, &tempServerSession, DTLSSession::socketPush); diff --git a/libraries/shared/src/DTLSClientSession.cpp b/libraries/shared/src/DTLSClientSession.cpp index 40b2b87b66..0ebb282f29 100644 --- a/libraries/shared/src/DTLSClientSession.cpp +++ b/libraries/shared/src/DTLSClientSession.cpp @@ -16,8 +16,9 @@ void DTLSClientSession::globalInit() { if (!initialized) { gnutls_global_init(); gnutls_certificate_allocate_credentials(&_x509CACredentials); - int certsProcessed = gnutls_certificate_set_x509_trust_mem(_x509CACredentials, DTLSSession::highFidelityCADatum(), GNUTLS_X509_FMT_PEM); - qDebug() << "There were" << certsProcessed; + + gnutls_certificate_set_x509_trust_mem(_x509CACredentials, DTLSSession::highFidelityCADatum(), GNUTLS_X509_FMT_PEM); + gnutls_certificate_set_verify_function(_x509CACredentials, DTLSClientSession::verifyServerCertificate); } } @@ -27,6 +28,37 @@ void DTLSClientSession::globalDeinit() { gnutls_global_deinit(); } +int DTLSClientSession::verifyServerCertificate(gnutls_session_t session) { + unsigned int verifyStatus = 0; + int certReturn = gnutls_certificate_verify_peers3(session, NULL, &verifyStatus); + + if (certReturn < 0) { + return GNUTLS_E_CERTIFICATE_ERROR; + } + + gnutls_certificate_type_t typeReturn = gnutls_certificate_type_get(session); + + gnutls_datum_t printOut; + + + certReturn = gnutls_certificate_verification_status_print(verifyStatus, typeReturn, &printOut, 0); + + if (certReturn < 0) { + return GNUTLS_E_CERTIFICATE_ERROR; + } + + qDebug() << "Gnutls certificate verification status:" << reinterpret_cast(printOut.data); + gnutls_free(printOut.data); + + if (verifyStatus != 0) { + qDebug() << "Server provided certificate for DTLS is not trusted. Can not complete handshake."; + return GNUTLS_E_CERTIFICATE_ERROR; + } else { + // certificate is valid, continue handshaking as normal + return 0; + } +} + DTLSClientSession::DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) : DTLSSession(GNUTLS_CLIENT, dtlsSocket, destinationSocket) { diff --git a/libraries/shared/src/DTLSClientSession.h b/libraries/shared/src/DTLSClientSession.h index ad5b0cd55b..fe8dec49b9 100644 --- a/libraries/shared/src/DTLSClientSession.h +++ b/libraries/shared/src/DTLSClientSession.h @@ -18,6 +18,8 @@ public: static void globalInit(); static void globalDeinit(); + static int verifyServerCertificate(gnutls_session_t session); + static gnutls_certificate_credentials_t _x509CACredentials; static bool _wasGloballyInitialized; }; diff --git a/libraries/shared/src/DTLSSession.cpp b/libraries/shared/src/DTLSSession.cpp index f76119fd1f..4685a05970 100644 --- a/libraries/shared/src/DTLSSession.cpp +++ b/libraries/shared/src/DTLSSession.cpp @@ -128,7 +128,6 @@ DTLSSession::DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinat } DTLSSession::~DTLSSession() { - qDebug() << "cleaning up current session"; gnutls_deinit(_gnutlsSession); } diff --git a/libraries/shared/src/DomainHandler.cpp b/libraries/shared/src/DomainHandler.cpp index e1aedc4d11..380a9a4b7b 100644 --- a/libraries/shared/src/DomainHandler.cpp +++ b/libraries/shared/src/DomainHandler.cpp @@ -129,7 +129,8 @@ void DomainHandler::completeDTLSHandshake() { } else if (gnutls_error_is_fatal(handshakeReturn)) { // this was a fatal error handshaking, so remove this session qDebug() << "Fatal error -" << gnutls_strerror(handshakeReturn) - << "- during DTLS handshake with DS at" << getHostname(); + << "- during DTLS handshake with DS at" + << qPrintable((_hostname.isEmpty() ? _sockAddr.getAddress().toString() : _hostname)); clearConnectionInfo(); }