Esempio n. 1
0
int CTlsSocket::ContinueHandshake()
{
	m_pOwner->LogMessage(Debug_Verbose, _T("CTlsSocket::ContinueHandshake()"));
	wxASSERT(m_session);
	wxASSERT(m_tlsState == handshake);

	int res = gnutls_handshake(m_session);
	while (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED)
	{
		if ( gnutls_record_get_direction(m_session) != 1 || !m_canWriteToSocket )
			break;

		res = gnutls_handshake(m_session);
	}
	if (!res)
	{
		m_pOwner->LogMessage(Debug_Info, _T("TLS Handshake successful"));

		if (ResumedSession())
			m_pOwner->LogMessage(Debug_Info, _T("TLS Session resumed"));

		const wxString protocol = GetProtocolName();
		const wxString keyExchange = GetKeyExchange();
		const wxString cipherName = GetCipherName();
		const wxString macName = GetMacName();

		m_pOwner->LogMessage(Debug_Info, _T("Protocol: %s, Key exchange: %s, Cipher: %s, MAC: %s"), protocol.c_str(), keyExchange.c_str(), cipherName.c_str(), macName.c_str());

		res = VerifyCertificate();
		if (res != FZ_REPLY_OK)
			return res;

		if (m_shutdown_requested)
		{
			int error = Shutdown();
			if (!error || error != EAGAIN)
			{
				CSocketEvent *evt = new CSocketEvent(m_pEvtHandler, this, CSocketEvent::close);
				CSocketEventDispatcher::Get().SendEvent(evt);
			}
		}

		return FZ_REPLY_OK;
	}
	else if (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED)
		return FZ_REPLY_WOULDBLOCK;

	Failure(res, ECONNABORTED);

	return FZ_REPLY_ERROR;
}
Esempio n. 2
0
int CTlsSocket::ContinueHandshake()
{
	m_pOwner->LogMessage(MessageType::Debug_Verbose, _T("CTlsSocket::ContinueHandshake()"));
	wxASSERT(m_session);
	wxASSERT(m_tlsState == TlsState::handshake);

	int res = gnutls_handshake(m_session);
	while (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) {
		if (!(gnutls_record_get_direction(m_session) ? m_canWriteToSocket : m_canReadFromSocket)) {
			break;
		}
		res = gnutls_handshake(m_session);
	}
	if (!res) {
		m_pOwner->LogMessage(MessageType::Debug_Info, _T("TLS Handshake successful"));

		if (ResumedSession())
			m_pOwner->LogMessage(MessageType::Debug_Info, _T("TLS Session resumed"));

		const wxString protocol = GetProtocolName();
		const wxString keyExchange = GetKeyExchange();
		const wxString cipherName = GetCipherName();
		const wxString macName = GetMacName();

		m_pOwner->LogMessage(MessageType::Debug_Info, _T("Protocol: %s, Key exchange: %s, Cipher: %s, MAC: %s"), protocol, keyExchange, cipherName, macName);

		res = VerifyCertificate();
		if (res != FZ_REPLY_OK)
			return res;

		if (m_shutdown_requested) {
			int error = Shutdown();
			if (!error || error != EAGAIN) {
				m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, 0);
			}
		}

		return FZ_REPLY_OK;
	}
	else if (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED)
		return FZ_REPLY_WOULDBLOCK;

	Failure(res, true);

	return FZ_REPLY_ERROR;
}
Esempio n. 3
0
int CTlsSocket::ContinueHandshake()
{
	m_pOwner->LogMessage(Debug_Verbose, _T("CTlsSocket::ContinueHandshake()"));
	wxASSERT(m_session);
	wxASSERT(m_tlsState == handshake);

	int res = gnutls_handshake(m_session);
	if (!res)
	{
		m_pOwner->LogMessage(Debug_Info, _T("Handshake successful"));

		if (ResumedSession())
			m_pOwner->LogMessage(Debug_Info, _T("Session resumed"));

		const wxString& cipherName = GetCipherName();
		const wxString& macName = GetMacName();

		m_pOwner->LogMessage(Debug_Info, _T("Cipher: %s, MAC: %s"), cipherName.c_str(), macName.c_str());

		res = VerifyCertificate();
		if (res != FZ_REPLY_OK)
			return res;

		if (m_shutdown_requested)
		{
			int error = Shutdown();
			if (!error || error != EAGAIN)
			{
				CSocketEvent *evt = new CSocketEvent(m_pEvtHandler, this, CSocketEvent::close);
				CSocketEventDispatcher::Get().SendEvent(evt);
			}
		}

		return FZ_REPLY_OK;
	}
	else if (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED)
		return FZ_REPLY_WOULDBLOCK;

	Failure(res, ECONNABORTED);

	return FZ_REPLY_ERROR;
}
Esempio n. 4
0
int CTlsSocket::VerifyCertificate()
{
	if (m_tlsState != handshake)
	{
		m_pOwner->LogMessage(::Debug_Warning, _T("VerifyCertificate called at wrong time"));
		return FZ_REPLY_ERROR;
	}

	m_tlsState = verifycert;

	if (gnutls_certificate_type_get(m_session) != GNUTLS_CRT_X509)
	{
		m_pOwner->LogMessage(::Error, _("Unsupported certificate type"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	unsigned int status = 0;
	if (gnutls_certificate_verify_peers2(m_session, &status) < 0)
	{
		m_pOwner->LogMessage(::Error, _("Failed to verify peer certificate"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	if (status & GNUTLS_CERT_REVOKED)
	{
		m_pOwner->LogMessage(::Error, _("Beware! Certificate has been revoked"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	if (status & GNUTLS_CERT_SIGNER_NOT_CA)
	{
		m_pOwner->LogMessage(::Error, _("Incomplete chain, top certificate is not self-signed certificate authority certificate"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	if (m_require_root_trust && status & GNUTLS_CERT_SIGNER_NOT_FOUND)
	{
		m_pOwner->LogMessage(::Error, _("Root certificate is not trusted"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	unsigned int cert_list_size;
	const gnutls_datum_t* cert_list = gnutls_certificate_get_peers(m_session, &cert_list_size);
	if (!cert_list || !cert_list_size)
	{
		m_pOwner->LogMessage(::Error, _("gnutls_certificate_get_peers returned no certificates"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	if (m_implicitTrustedCert.data)
	{
		if (m_implicitTrustedCert.size != cert_list[0].size ||
			memcmp(m_implicitTrustedCert.data, cert_list[0].data, cert_list[0].size))
		{
			m_pOwner->LogMessage(::Error, _("Primary connection and data connection certificates don't match."));
			Failure(0, ECONNABORTED);
			return FZ_REPLY_ERROR;
		}

		TrustCurrentCert(true);

		if (m_tlsState != conn)
			return FZ_REPLY_ERROR;
		return FZ_REPLY_OK;
	}

	std::vector<CCertificate> certificates;
	for (unsigned int i = 0; i < cert_list_size; i++)
	{
		CCertificate cert;
		if (ExtractCert(cert_list, cert))
			certificates.push_back(cert);
		else
		{
			Failure(0, ECONNABORTED);
			return FZ_REPLY_ERROR;
		}

		++cert_list;
	}

	CCertificateNotification *pNotification = new CCertificateNotification(
		m_pOwner->GetCurrentServer()->GetHost(),
		m_pOwner->GetCurrentServer()->GetPort(),
		GetProtocolName(),
		GetKeyExchange(),
		GetCipherName(),
		GetMacName(),
		certificates);

	m_pOwner->SendAsyncRequest(pNotification);

	m_pOwner->LogMessage(Status, _("Verifying certificate..."));

	return FZ_REPLY_WOULDBLOCK;
}
Esempio n. 5
0
int CTlsSocket::VerifyCertificate()
{
	if (m_tlsState != handshake)
	{
		m_pOwner->LogMessage(::Debug_Warning, _T("VerifyCertificate called at wrong time"));
		return FZ_REPLY_ERROR;
	}

	m_tlsState = verifycert;

	if (gnutls_certificate_type_get(m_session) != GNUTLS_CRT_X509)
	{
		m_pOwner->LogMessage(::Error, _("Unsupported certificate type"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	unsigned int status = 0;
	if (gnutls_certificate_verify_peers2(m_session, &status) < 0)
	{
		m_pOwner->LogMessage(::Error, _("Failed to verify peer certificate"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	if (status & GNUTLS_CERT_REVOKED)
	{
		m_pOwner->LogMessage(::Error, _("Beware! Certificate has been revoked"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	if (status & GNUTLS_CERT_SIGNER_NOT_CA)
	{
		m_pOwner->LogMessage(::Error, _("Incomplete chain, top certificate is not self-signed certificate authority certificate"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	if (m_require_root_trust && status & GNUTLS_CERT_SIGNER_NOT_FOUND)
	{
		m_pOwner->LogMessage(::Error, _("Root certificate is not trusted"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	unsigned int cert_list_size;
	const gnutls_datum_t* cert_list = gnutls_certificate_get_peers(m_session, &cert_list_size);
	if (!cert_list || !cert_list_size)
	{
		m_pOwner->LogMessage(::Error, _("gnutls_certificate_get_peers returned no certificates"));
		Failure(0, ECONNABORTED);
		return FZ_REPLY_ERROR;
	}

	if (m_implicitTrustedCert.data)
	{
		if (m_implicitTrustedCert.size != cert_list[0].size ||
			memcmp(m_implicitTrustedCert.data, cert_list[0].data, cert_list[0].size))
		{
			m_pOwner->LogMessage(::Error, _("Primary connection and data connection certificates don't match."));
			Failure(0, ECONNABORTED);
			return FZ_REPLY_ERROR;
		}

		TrustCurrentCert(true);

		if (m_tlsState != conn)
			return FZ_REPLY_ERROR;
		return FZ_REPLY_OK;
	}

	std::vector<CCertificate> certificates;
	for (unsigned int i = 0; i < cert_list_size; i++)
	{
		gnutls_x509_crt_t cert;
		if (gnutls_x509_crt_init(&cert))
		{
			m_pOwner->LogMessage(::Error, _("Could not initialize structure for peer certificates, gnutls_x509_crt_init failed"));
			Failure(0, ECONNABORTED);
			return FZ_REPLY_ERROR;
		}

		if (gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER))
		{
			m_pOwner->LogMessage(::Error, _("Could not import peer certificates, gnutls_x509_crt_import failed"));
			Failure(0, ECONNABORTED);
			gnutls_x509_crt_deinit(cert);
			return FZ_REPLY_ERROR;
		}

		wxDateTime expirationTime = gnutls_x509_crt_get_expiration_time(cert);
		wxDateTime activationTime = gnutls_x509_crt_get_activation_time(cert);

		// Get the serial number of the certificate
		unsigned char buffer[40];
		size_t size = sizeof(buffer);
		int res = gnutls_x509_crt_get_serial(cert, buffer, &size);

		wxString serial = bin2hex(buffer, size);

		unsigned int bits;
		int algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits);

		wxString algoName;
		const char* pAlgo = gnutls_pk_algorithm_get_name((gnutls_pk_algorithm_t)algo);
		if (pAlgo)
			algoName = wxString(pAlgo, wxConvUTF8);

		//int version = gnutls_x509_crt_get_version(cert);

		wxString subject, issuer;

		size = 0;
		res = gnutls_x509_crt_get_dn(cert, 0, &size);
		if (size)
		{
			char* dn = new char[size + 1];
			dn[size] = 0;
			if (!(res = gnutls_x509_crt_get_dn(cert, dn, &size)))
			{
				dn[size] = 0;
				subject = wxString(dn, wxConvUTF8);
			}
			else
				LogError(res);
			delete [] dn;
		}
		else
			LogError(res);
		if (subject == _T(""))
		{
			m_pOwner->LogMessage(::Error, _("Could not get distinguished name of certificate subject, gnutls_x509_get_dn failed"));
			Failure(0, ECONNABORTED);
			gnutls_x509_crt_deinit(cert);
			return FZ_REPLY_ERROR;
		}

		size = 0;
		res = gnutls_x509_crt_get_issuer_dn(cert, 0, &size);
		if (size)
		{
			char* dn = new char[++size + 1];
			dn[size] = 0;
			if (!(res = gnutls_x509_crt_get_issuer_dn(cert, dn, &size)))
			{
				dn[size] = 0;
				issuer = wxString(dn, wxConvUTF8);
			}
			else
				LogError(res);
			delete [] dn;
		}
		else
			LogError(res);
		if (issuer == _T(""))
		{
			m_pOwner->LogMessage(::Error, _("Could not get distinguished name of certificate issuer, gnutls_x509_get_issuer_dn failed"));
			Failure(0, ECONNABORTED);
			gnutls_x509_crt_deinit(cert);
			return FZ_REPLY_ERROR;
		}

		wxString fingerprint_md5;
		wxString fingerprint_sha1;

		unsigned char digest[100];
		size = sizeof(digest) - 1;
		if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, digest, &size))
		{
			digest[size] = 0;
			fingerprint_md5 = bin2hex(digest, size);
		}
		size = sizeof(digest) - 1;
		if (!gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, digest, &size))
		{
			digest[size] = 0;
			fingerprint_sha1 = bin2hex(digest, size);
		}

		certificates.push_back(CCertificate(
			cert_list->data, cert_list->size,
			activationTime, expirationTime,
			serial,
			algoName, bits,
			fingerprint_md5,
			fingerprint_sha1,
			subject,
			issuer));

		cert_list++;
	}

	CCertificateNotification *pNotification = new CCertificateNotification(
		m_pOwner->GetCurrentServer()->GetHost(),
		m_pOwner->GetCurrentServer()->GetPort(),
		GetCipherName(),
		GetMacName(),
		certificates);

	m_pOwner->SendAsyncRequest(pNotification);

	m_pOwner->LogMessage(Status, _("Verifying certificate..."));

	return FZ_REPLY_WOULDBLOCK;
}