Beispiel #1
0
BOOL transport_accept_nla(rdpTransport* transport)
{
	rdpSettings* settings = transport->settings;
	freerdp* instance = (freerdp*) settings->instance;

	if (!transport->tls)
		transport->tls = tls_new(transport->settings);

	transport->layer = TRANSPORT_LAYER_TLS;

	if (!tls_accept(transport->tls, transport->frontBio, settings))
		return FALSE;

	transport->frontBio = transport->tls->bio;

	/* Network Level Authentication */

	if (!settings->Authentication)
		return TRUE;

	if (!transport->nla)
	{
		transport->nla = nla_new(instance, transport, settings);
		transport_set_nla_mode(transport, TRUE);
	}

	if (nla_authenticate(transport->nla) < 0)
	{
		WLog_Print(transport->log, WLOG_ERROR, "client authentication failure");
		transport_set_nla_mode(transport, FALSE);
		nla_free(transport->nla);
		transport->nla = NULL;
		tls_set_alert_code(transport->tls, TLS_ALERT_LEVEL_FATAL,
		                   TLS_ALERT_DESCRIPTION_ACCESS_DENIED);
		tls_send_alert(transport->tls);
		return FALSE;
	}

	/* don't free nla module yet, we need to copy the credentials from it first */
	transport_set_nla_mode(transport, FALSE);
	return TRUE;
}
Beispiel #2
0
int tls_do_handshake(rdpTls* tls, BOOL clientMode)
{
	CryptoCert cert;
	int verify_status;

	do
	{
#ifdef HAVE_POLL_H
		int fd;
		int status;
		struct pollfd pollfds;
#elif !defined(_WIN32)
		int fd;
		int status;
		fd_set rset;
		struct timeval tv;
#else
		HANDLE event;
		DWORD status;
#endif
		status = BIO_do_handshake(tls->bio);

		if (status == 1)
			break;

		if (!BIO_should_retry(tls->bio))
			return -1;

#ifndef _WIN32
		/* we select() only for read even if we should test both read and write
		 * depending of what have blocked */
		fd = BIO_get_fd(tls->bio, NULL);

		if (fd < 0)
		{
			WLog_ERR(TAG, "unable to retrieve BIO fd");
			return -1;
		}

#else
		BIO_get_event(tls->bio, &event);

		if (!event)
		{
			WLog_ERR(TAG, "unable to retrieve BIO event");
			return -1;
		}

#endif
#ifdef HAVE_POLL_H
		pollfds.fd = fd;
		pollfds.events = POLLIN;
		pollfds.revents = 0;

		do
		{
			status = poll(&pollfds, 1, 10 * 1000);
		}
		while ((status < 0) && (errno == EINTR));

#elif !defined(_WIN32)
		FD_ZERO(&rset);
		FD_SET(fd, &rset);
		tv.tv_sec = 0;
		tv.tv_usec = 10 * 1000; /* 10ms */
		status = _select(fd + 1, &rset, NULL, NULL, &tv);
#else
		status = WaitForSingleObject(event, 10);
#endif
#ifndef _WIN32

		if (status < 0)
		{
			WLog_ERR(TAG, "error during select()");
			return -1;
		}

#else

		if ((status != WAIT_OBJECT_0) && (status != WAIT_TIMEOUT))
		{
			WLog_ERR(TAG, "error during WaitForSingleObject(): 0x%04X", status);
			return -1;
		}

#endif
	}
	while (TRUE);

	cert = tls_get_certificate(tls, clientMode);

	if (!cert)
	{
		WLog_ERR(TAG, "tls_get_certificate failed to return the server certificate.");
		return -1;
	}

	tls->Bindings = tls_get_channel_bindings(cert->px509);

	if (!tls->Bindings)
	{
		WLog_ERR(TAG, "unable to retrieve bindings");
		verify_status = -1;
		goto out;
	}

	if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength))
	{
		WLog_ERR(TAG,
		         "crypto_cert_get_public_key failed to return the server public key.");
		verify_status = -1;
		goto out;
	}

	/* server-side NLA needs public keys (keys from us, the server) but no certificate verify */
	verify_status = 1;

	if (clientMode)
	{
		verify_status = tls_verify_certificate(tls, cert, tls->hostname, tls->port);

		if (verify_status < 1)
		{
			WLog_ERR(TAG, "certificate not trusted, aborting.");
			tls_send_alert(tls);
			verify_status = 0;
		}
	}

out:
	tls_free_certificate(cert);
	return verify_status;
}