예제 #1
0
void CTlsSocket::OnRead()
{
	m_pOwner->LogMessage(MessageType::Debug_Debug, _T("CTlsSocket::OnRead()"));

	m_canReadFromSocket = true;

	if (!m_session)
		return;

	const int direction = gnutls_record_get_direction(m_session);
	if (direction && !m_lastReadFailed) {
		m_pOwner->LogMessage(MessageType::Debug_Debug, _T("CTlsSocket::Postponing read"));
		return;
	}

	if (m_tlsState == TlsState::handshake)
		ContinueHandshake();
	if (m_tlsState == TlsState::closing)
		ContinueShutdown();
	else if (m_tlsState == TlsState::conn)
	{
		CheckResumeFailedReadWrite();
		TriggerEvents();
	}
}
예제 #2
0
파일: tlssocket.cpp 프로젝트: jplee/MILF
void CTlsSocket::TrustCurrentCert(bool trusted)
{
	if (m_tlsState != verifycert)
	{
		m_pOwner->LogMessage(Debug_Warning, _T("TrustCurrentCert called at wrong time."));
		return;
	}

	if (trusted)
	{
		m_tlsState = conn;

		if (m_lastWriteFailed)
			m_lastWriteFailed = false;
		CheckResumeFailedReadWrite();

		if (m_tlsState == conn)
		{
			CSocketEvent *evt = new CSocketEvent(m_pEvtHandler, this, CSocketEvent::connection);
			CSocketEventDispatcher::Get().SendEvent(evt);
		}

		TriggerEvents();

		return;
	}

	m_pOwner->LogMessage(::Error, _("Remote certificate not trusted."));
	Failure(0, ECONNABORTED);
}
예제 #3
0
void CTlsSocket::TrustCurrentCert(bool trusted)
{
	if (m_tlsState != TlsState::verifycert) {
		m_pOwner->LogMessage(MessageType::Debug_Warning, _T("TrustCurrentCert called at wrong time."));
		return;
	}

	if (trusted) {
		m_tlsState = TlsState::conn;

		if (m_lastWriteFailed)
			m_lastWriteFailed = false;
		CheckResumeFailedReadWrite();

		if (m_tlsState == TlsState::conn) {
			m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::connection, 0);
		}

		TriggerEvents();

		return;
	}

	m_pOwner->LogMessage(MessageType::Error, _("Remote certificate not trusted."));
	Failure(0, true);
}
예제 #4
0
int CTlsSocket::Write(const void *buffer, unsigned int len, int& error)
{
	if (m_tlsState == TlsState::handshake || m_tlsState == TlsState::verifycert) {
		error = EAGAIN;
		return -1;
	}
	else if (m_tlsState != TlsState::conn) {
		error = ENOTCONN;
		return -1;
	}

	if (m_lastWriteFailed) {
		error = EAGAIN;
		return -1;
	}

	if (m_writeSkip >= len) {
		m_writeSkip -= len;
		return len;
	}

	len -= m_writeSkip;
	buffer = (char*)buffer + m_writeSkip;

	int res = gnutls_record_send(m_session, buffer, len);

	while ((res == GNUTLS_E_INTERRUPTED || res == GNUTLS_E_AGAIN) && m_canWriteToSocket)
		res = gnutls_record_send(m_session, 0, 0);

	if (res >= 0) {
		error = 0;
		int written = res + m_writeSkip;
		m_writeSkip = 0;

		TriggerEvents();
		return written;
	}

	if (res == GNUTLS_E_INTERRUPTED || res == GNUTLS_E_AGAIN) {
		if (m_writeSkip) {
			error = 0;
			int written = m_writeSkip;
			m_writeSkip = 0;
			return written;
		}
		else {
			error = EAGAIN;
			m_lastWriteFailed = true;
			return -1;
		}
	}
	else {
		Failure(res, false, _T("gnutls_record_send"));
		error = m_socket_error;
		return -1;
	}
}
bool EventDispatcher::DispatchEvent(Element* target_element, const String& name, const Dictionary& parameters, bool interruptible)
{
	//Event event(target_element, name, parameters, interruptible);
	Event* event = Factory::InstanceEvent(target_element, name, parameters, interruptible);
	if (event == NULL)
		return false;

	// Build the element traversal from the tree
	typedef std::vector<Element*> Elements;
	Elements elements;

	Element* walk_element = target_element->GetParentNode();
	while (walk_element) 
	{
		elements.push_back(walk_element);
		walk_element = walk_element->GetParentNode();
	}

	event->SetPhase(Event::PHASE_CAPTURE);
	// Capture phase - root, to target (only events that have registered as capture events)
	// Note: We walk elements in REVERSE as they're placed in the list from the elements parent to the root
	for (int i = elements.size() - 1; i >= 0 && event->IsPropagating(); i--) 
	{
		EventDispatcher* dispatcher = elements[i]->GetEventDispatcher();
		event->SetCurrentElement(elements[i]);
		dispatcher->TriggerEvents(event);
	}

	// Target phase - direct at the target
	if (event->IsPropagating()) 
	{
		event->SetPhase(Event::PHASE_TARGET);
		event->SetCurrentElement(target_element);
		TriggerEvents(event);
	}

	if (event->IsPropagating()) 
	{
		event->SetPhase(Event::PHASE_BUBBLE);
		// Bubble phase - target to root (normal event bindings)
		for (size_t i = 0; i < elements.size() && event->IsPropagating(); i++) 
		{
			EventDispatcher* dispatcher = elements[i]->GetEventDispatcher();
			event->SetCurrentElement(elements[i]);
			dispatcher->TriggerEvents(event);
		}
	}

	bool propagating = event->IsPropagating();
	event->RemoveReference();
	return propagating;
}
예제 #6
0
void CTlsSocket::TrustCurrentCert(bool trusted)
{
	if (m_tlsState != verifycert)
	{
		m_pOwner->LogMessage(Debug_Warning, _T("TrustCurrentCert called at wrong time."));
		return;
	}

	if (trusted)
	{
		m_tlsState = conn;

		wxSocketEvent evt(GetId());
		evt.m_event = wxSOCKET_CONNECTION;
		wxPostEvent(m_pEvtHandler, evt);
		TriggerEvents();
		return;
	}

	m_pOwner->LogMessage(::Error, _("Remote certificate not trusted."));
	Failure(0);
}
예제 #7
0
void CTlsSocket::OnSend()
{
	m_pOwner->LogMessage(Debug_Debug, _T("CTlsSocket::OnSend()"));

	m_canWriteToSocket = true;

	if (!m_session)
		return;

	if (!gnutls_record_get_direction(m_session))
		return;

	if (m_tlsState == handshake)
		Handshake();
	else if (m_tlsState == closing)
		ContinueShutdown();
	else if (m_tlsState == conn)
	{
		CheckResumeFailedWrite();
		TriggerEvents();
	}
}
예제 #8
0
파일: tlssocket.cpp 프로젝트: jplee/MILF
int CTlsSocket::Read(void *buffer, unsigned int len, int& error)
{
	if (m_tlsState == handshake || m_tlsState == verifycert)
	{
		error = EAGAIN;
		return -1;
	}
	else if (m_tlsState != conn)
	{
		error = ENOTCONN;
		return -1;
	}
	else if (m_lastReadFailed)
	{
		error = EAGAIN;
		return -1;
	}

	if (m_peekDataLen)
	{
		unsigned int min = wxMin(len, m_peekDataLen);
		memcpy(buffer, m_peekData, min);

		if (min == m_peekDataLen)
		{
			m_peekDataLen = 0;
			delete [] m_peekData;
			m_peekData = 0;
		}
		else
		{
			memmove(m_peekData, m_peekData + min, m_peekDataLen - min);
			m_peekDataLen -= min;
		}

		TriggerEvents();

		error = 0;
		return min;
	}

	int res = gnutls_record_recv(m_session, buffer, len);
	if (res >= 0)
	{
		if (res > 0)
			TriggerEvents();
		else
		{
			// Peer did already initiate a shutdown, reply to it
			gnutls_bye(m_session, GNUTLS_SHUT_WR);
			// Note: Theoretically this could return a write error.
			// But we ignore it, since it is perfectly valid for peer
			// to close the connection after sending its shutdown
			// notification.
		}

		error = 0;
		return res;
	}

	if (res == GNUTLS_E_INTERRUPTED || res == GNUTLS_E_AGAIN)
	{
		error = EAGAIN;
		m_lastReadFailed = true;
	}
	else
	{
		Failure(res, 0, _T("gnutls_record_recv"));
		error = ECONNABORTED;
	}

	return -1;
}
예제 #9
0
void CTlsSocket::Write(const void *buffer, unsigned int len)
{
	if (m_tlsState == handshake)
	{
		m_lastError = wxSOCKET_WOULDBLOCK;
		m_lastSuccessful = false;
		return;
	}
	else if (m_tlsState != conn)
	{
		m_lastError = wxSOCKET_IOERR;
		m_lastSuccessful = false;
		return;
	}

	if (m_lastWriteFailed)
	{
		m_lastError = wxSOCKET_WOULDBLOCK;
		m_lastSuccessful = false;
		return;
	}

	if (m_writeSkip >= len)
	{
		m_writeSkip -= len;
		m_lastCount = len;
		m_lastSuccessful = true;
		return;
	}

	len -= m_writeSkip;
	buffer = (char*)buffer + m_writeSkip;

	int res = gnutls_record_send(m_session, buffer, len);
	if (res >= 0)
	{
		m_lastSuccessful = true;
		m_lastCount = res + m_writeSkip;
		m_writeSkip = 0;

		TriggerEvents();
		return;
	}

	if (res == GNUTLS_E_INTERRUPTED || res == GNUTLS_E_AGAIN)
	{
		if (m_writeSkip)
		{
			m_lastSuccessful = true;
			m_lastCount = m_writeSkip;
			m_writeSkip = 0;
		}
		else
		{
			m_lastSuccessful = false;
			m_lastError = wxSOCKET_WOULDBLOCK;
			m_lastWriteFailed = true;
		}
	}
	else
	{
		m_lastSuccessful = false;
		Failure(res);
		m_lastError = wxSOCKET_IOERR;
	}
}
예제 #10
0
void CTlsSocket::Read(void *buffer, unsigned int len)
{
	if (m_tlsState == handshake)
	{
		m_lastError = wxSOCKET_WOULDBLOCK;
		m_lastSuccessful = false;
		return;
	}
	else if (m_tlsState != conn)
	{
		m_lastError = wxSOCKET_IOERR;
		m_lastSuccessful = false;
		return;
	}

	m_canTriggerRead = true;

	if (m_peekDataLen)
	{
		unsigned int min = wxMin(len, m_peekDataLen);
		memcpy(buffer, m_peekData, min);
		
		if (min == m_peekDataLen)
		{
			m_peekDataLen = 0;
			delete [] m_peekData;
			m_peekData = 0;
		}
		else
		{
			memmove(m_peekData, m_peekData + min, m_peekDataLen - min);
			m_peekDataLen -= min;
		}

		TriggerEvents();

		m_lastSuccessful = true;
		m_lastCount = min;
		return;
	}
	
	int res = gnutls_record_recv(m_session, buffer, len);
	if (res >= 0)
	{
		m_lastSuccessful = true;
		m_lastCount = res;

		if (res > 0)
			TriggerEvents();

		return;
	}

	if (res == GNUTLS_E_INTERRUPTED || res == GNUTLS_E_AGAIN)
		m_lastError = wxSOCKET_WOULDBLOCK;
	else
	{
		Failure(res);
		m_lastError = wxSOCKET_IOERR;
	}

	m_lastSuccessful = false;
	return;
}
예제 #11
0
int CTlsSocket::Handshake(const CTlsSocket* pPrimarySocket /*=0*/)
{
	m_pOwner->LogMessage(Debug_Verbose, _T("CTlsSocket::Handshake()"));
	wxASSERT(m_session);

	m_tlsState = handshake;

	if (pPrimarySocket)
	{
		// Implicitly trust certificate of primary socket
		unsigned int cert_list_size;
		const gnutls_datum_t* const cert_list = gnutls_certificate_get_peers(pPrimarySocket->m_session, &cert_list_size);
		if (cert_list && cert_list_size)
		{
			m_implicitTrustedCert.data = new unsigned char[cert_list[0].size];
			memcpy(m_implicitTrustedCert.data, cert_list[0].data, cert_list[0].size);
			m_implicitTrustedCert.size = cert_list[0].size;
		}
	}

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

		wxString cipherName;
		const char* cipher = gnutls_cipher_get_name(gnutls_cipher_get(m_session));
		if (cipher)
			cipherName = wxString(cipher, wxConvUTF8);
		else
			cipherName = _T("unknown");

		wxString macName;
		const char* mac = gnutls_mac_get_name(gnutls_mac_get(m_session));
		if (mac)
			macName = wxString(mac, wxConvUTF8);
		else
			macName = _T("unknown");

		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;

		m_tlsState = conn;

		wxSocketEvent evt(GetId());
		evt.m_event = wxSOCKET_CONNECTION;
		wxPostEvent(m_pEvtHandler, evt);
		TriggerEvents();

		if (m_shutdown_requested)
		{
			Shutdown();
			if (!Error() || LastError() != wxSOCKET_WOULDBLOCK)
			{
				wxSocketEvent evt(GetId());
				evt.m_event = wxSOCKET_LOST;
				wxPostEvent(m_pEvtHandler, evt);
			}
		}

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

	Failure(res);

	return FZ_REPLY_ERROR;
}