From 62de84315e5226b805d6ae238a15c6e1aeb55fe2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 2 Apr 2014 17:56:04 -0700 Subject: [PATCH] detect handshake completion in DS and client --- domain-server/src/DomainServer.cpp | 22 +++++++++++++++++----- libraries/shared/src/DTLSClientSession.cpp | 10 +--------- libraries/shared/src/DTLSSession.cpp | 3 ++- libraries/shared/src/DTLSSession.h | 4 ++++ libraries/shared/src/NodeList.cpp | 22 ++++++++++++++-------- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 5550c2741d..efecd5d322 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -628,9 +628,22 @@ void DomainServer::readAvailableDTLSDatagrams() { DTLSServerSession* existingSession = _dtlsSessions.value(senderHifiSockAddr); if (existingSession) { - // check if we have completed handshake with this user - int handshakeReturn = gnutls_handshake(*existingSession->getGnuTLSSession()); - qDebug() << "Handshake return for user is" << handshakeReturn; + if (!existingSession->completedHandshake()) { + // check if we have completed handshake with this user + int handshakeReturn = gnutls_handshake(*existingSession->getGnuTLSSession()); + + if (handshakeReturn == 0) { + existingSession->setCompletedHandshake(true); + } 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" + << senderHifiSockAddr; + _dtlsSessions.remove(senderHifiSockAddr); + } + } else { + // pull the data from this user off the stack and process it + dtlsSocket.readDatagram(peekDatagram.data(), peekDatagram.size()); + } } else { // first we verify the cookie // see http://gnutls.org/manual/html_node/DTLS-sessions.html for why this is required @@ -659,8 +672,7 @@ void DomainServer::readAvailableDTLSDatagrams() { gnutls_dtls_prestate_set(*gnutlsSession, &prestate); // handshake to begin the session - int handshakeReturn = gnutls_handshake(*gnutlsSession); - qDebug() << "initial handshake return" << handshakeReturn; + gnutls_handshake(*gnutlsSession); qDebug() << "Beginning DTLS session with node at" << senderHifiSockAddr; _dtlsSessions[senderHifiSockAddr] = newServerSession; diff --git a/libraries/shared/src/DTLSClientSession.cpp b/libraries/shared/src/DTLSClientSession.cpp index 109172487f..73daa4e03a 100644 --- a/libraries/shared/src/DTLSClientSession.cpp +++ b/libraries/shared/src/DTLSClientSession.cpp @@ -14,22 +14,14 @@ gnutls_certificate_credentials_t* DTLSClientSession::x509CACredentials() { if (!credentialsInitialized) { gnutls_certificate_allocate_credentials(&x509Credentials); - qDebug() << "processed" << gnutls_certificate_set_x509_trust_file(x509Credentials, "/Users/birarda/code/hifi/certs/root-ca.crt", GNUTLS_X509_FMT_PEM); } return &x509Credentials; } -int verifyX509Certificate(gnutls_session_t session) { - int certificateType = gnutls_certificate_type_get(session); - qDebug() << "Verifying a certificate of type" << certificateType; - - return 0; -} - DTLSClientSession::DTLSClientSession(QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) : DTLSSession(GNUTLS_CLIENT, dtlsSocket, destinationSocket) { gnutls_priority_set_direct(_gnutlsSession, "PERFORMANCE", NULL); - gnutls_credentials_set(_gnutlsSession, GNUTLS_CRD_CERTIFICATE, x509CACredentials()); + gnutls_credentials_set(_gnutlsSession, GNUTLS_CRD_CERTIFICATE, *x509CACredentials()); } \ No newline at end of file diff --git a/libraries/shared/src/DTLSSession.cpp b/libraries/shared/src/DTLSSession.cpp index 52c55bec23..9d30ab8148 100644 --- a/libraries/shared/src/DTLSSession.cpp +++ b/libraries/shared/src/DTLSSession.cpp @@ -77,7 +77,8 @@ ssize_t DTLSSession::socketPush(gnutls_transport_ptr_t ptr, const void* buffer, DTLSSession::DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinationSocket) : _dtlsSocket(dtlsSocket), - _destinationSocket(destinationSocket) + _destinationSocket(destinationSocket), + _completedHandshake(false) { gnutls_init(&_gnutlsSession, end | GNUTLS_DATAGRAM | GNUTLS_NONBLOCK); diff --git a/libraries/shared/src/DTLSSession.h b/libraries/shared/src/DTLSSession.h index ce190e11c0..01e0e187e8 100644 --- a/libraries/shared/src/DTLSSession.h +++ b/libraries/shared/src/DTLSSession.h @@ -26,10 +26,14 @@ public: gnutls_session_t* getGnuTLSSession() { return &_gnutlsSession; } + bool completedHandshake() const { return _completedHandshake; } + void setCompletedHandshake(bool completedHandshake) { _completedHandshake = completedHandshake; } + protected: QUdpSocket& _dtlsSocket; gnutls_session_t _gnutlsSession; HifiSockAddr _destinationSocket; + bool _completedHandshake; }; #endif /* defined(__hifi__DTLSSession__) */ diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 1740525ef1..792215ea68 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -324,15 +324,21 @@ void NodeList::sendDomainServerCheckIn() { DTLSClientSession* dtlsSession = _domainHandler.getDTLSSession(); if (dtlsSession) { - int handshakeReturn = gnutls_handshake(*dtlsSession->getGnuTLSSession()); + if (dtlsSession->completedHandshake()) { + qDebug() << "we can send a DTLS check in!"; + } else { + int handshakeReturn = gnutls_handshake(*dtlsSession->getGnuTLSSession()); + if (handshakeReturn == 0) { + dtlsSession->setCompletedHandshake(true); + } 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" << _domainHandler.getHostname(); + + _domainHandler.clearConnectionInfo(); + } + } - gnutls_handshake_description_t inType = gnutls_handshake_get_last_in(*dtlsSession->getGnuTLSSession()); - gnutls_handshake_description_t outType = gnutls_handshake_get_last_out(*dtlsSession->getGnuTLSSession()); - qDebug() << "in" << gnutls_handshake_description_get_name(inType); - qDebug() << "out" << gnutls_handshake_description_get_name(outType); - - // make sure DTLS handshake with the domain-server is complete - qDebug() << "GnuTLS handshake return is" << handshakeReturn; } else { // construct the DS check in packet QUuid packetUUID = (!_sessionUUID.isNull() ? _sessionUUID : _domainHandler.getAssignmentUUID());