verify DTLS certificate to ensure trust before handshaking

This commit is contained in:
Stephen Birarda 2014-04-07 11:36:32 -07:00
parent 0f92e02da7
commit 86a0b715f3
5 changed files with 39 additions and 5 deletions

View file

@ -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);

View file

@ -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<char *>(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)
{

View file

@ -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;
};

View file

@ -128,7 +128,6 @@ DTLSSession::DTLSSession(int end, QUdpSocket& dtlsSocket, HifiSockAddr& destinat
}
DTLSSession::~DTLSSession() {
qDebug() << "cleaning up current session";
gnutls_deinit(_gnutlsSession);
}

View file

@ -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();
}