libfreerdp-crypto: make distinction between TLS connection error and user cancellation
This commit is contained in:
parent
046a33ba9f
commit
feea87b42f
@ -84,7 +84,7 @@ struct rdp_tls
|
|||||||
int alertDescription;
|
int alertDescription;
|
||||||
};
|
};
|
||||||
|
|
||||||
FREERDP_API BOOL tls_connect(rdpTls* tls);
|
FREERDP_API int tls_connect(rdpTls* tls);
|
||||||
FREERDP_API BOOL tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file);
|
FREERDP_API BOOL tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file);
|
||||||
FREERDP_API BOOL tls_disconnect(rdpTls* tls);
|
FREERDP_API BOOL tls_disconnect(rdpTls* tls);
|
||||||
|
|
||||||
|
@ -224,6 +224,7 @@ BIO_METHOD* BIO_s_tsg(void)
|
|||||||
|
|
||||||
BOOL transport_connect_tls(rdpTransport* transport)
|
BOOL transport_connect_tls(rdpTransport* transport)
|
||||||
{
|
{
|
||||||
|
int tls_status;
|
||||||
freerdp* instance;
|
freerdp* instance;
|
||||||
rdpContext* context;
|
rdpContext* context;
|
||||||
|
|
||||||
@ -245,13 +246,23 @@ BOOL transport_connect_tls(rdpTransport* transport)
|
|||||||
if (transport->TsgTls->port == 0)
|
if (transport->TsgTls->port == 0)
|
||||||
transport->TsgTls->port = 3389;
|
transport->TsgTls->port = 3389;
|
||||||
|
|
||||||
if (!tls_connect(transport->TsgTls))
|
tls_status = tls_connect(transport->TsgTls);
|
||||||
|
|
||||||
|
if (tls_status < 1)
|
||||||
|
{
|
||||||
|
if (tls_status < 0)
|
||||||
{
|
{
|
||||||
if (!connectErrorCode)
|
if (!connectErrorCode)
|
||||||
connectErrorCode = TLSCONNECTERROR;
|
connectErrorCode = TLSCONNECTERROR;
|
||||||
|
|
||||||
if (!freerdp_get_last_error(context))
|
if (!freerdp_get_last_error(context))
|
||||||
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!freerdp_get_last_error(context))
|
||||||
|
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||||
|
}
|
||||||
|
|
||||||
tls_free(transport->TsgTls);
|
tls_free(transport->TsgTls);
|
||||||
transport->TsgTls = NULL;
|
transport->TsgTls = NULL;
|
||||||
@ -277,13 +288,23 @@ BOOL transport_connect_tls(rdpTransport* transport)
|
|||||||
if (transport->TlsIn->port == 0)
|
if (transport->TlsIn->port == 0)
|
||||||
transport->TlsIn->port = 3389;
|
transport->TlsIn->port = 3389;
|
||||||
|
|
||||||
if (!tls_connect(transport->TlsIn))
|
tls_status = tls_connect(transport->TlsIn);
|
||||||
|
|
||||||
|
if (tls_status < 1)
|
||||||
|
{
|
||||||
|
if (tls_status < 0)
|
||||||
{
|
{
|
||||||
if (!connectErrorCode)
|
if (!connectErrorCode)
|
||||||
connectErrorCode = TLSCONNECTERROR;
|
connectErrorCode = TLSCONNECTERROR;
|
||||||
|
|
||||||
if (!freerdp_get_last_error(context))
|
if (!freerdp_get_last_error(context))
|
||||||
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!freerdp_get_last_error(context))
|
||||||
|
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||||
|
}
|
||||||
|
|
||||||
tls_free(transport->TlsIn);
|
tls_free(transport->TlsIn);
|
||||||
|
|
||||||
@ -355,6 +376,13 @@ BOOL transport_connect_nla(rdpTransport* transport)
|
|||||||
|
|
||||||
BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16 port)
|
BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16 port)
|
||||||
{
|
{
|
||||||
|
int tls_status;
|
||||||
|
freerdp* instance;
|
||||||
|
rdpContext* context;
|
||||||
|
|
||||||
|
instance = (freerdp*) transport->settings->instance;
|
||||||
|
context = instance->context;
|
||||||
|
|
||||||
rdpTsg* tsg = tsg_new(transport);
|
rdpTsg* tsg = tsg_new(transport);
|
||||||
|
|
||||||
tsg->transport = transport;
|
tsg->transport = transport;
|
||||||
@ -381,11 +409,41 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
|
|||||||
if (transport->TlsOut->port == 0)
|
if (transport->TlsOut->port == 0)
|
||||||
transport->TlsOut->port = 443;
|
transport->TlsOut->port = 443;
|
||||||
|
|
||||||
if (!tls_connect(transport->TlsIn))
|
tls_status = tls_connect(transport->TlsIn);
|
||||||
return FALSE;
|
|
||||||
|
if (tls_status < 1)
|
||||||
|
{
|
||||||
|
if (tls_status < 0)
|
||||||
|
{
|
||||||
|
if (!freerdp_get_last_error(context))
|
||||||
|
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!freerdp_get_last_error(context))
|
||||||
|
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||||
|
}
|
||||||
|
|
||||||
if (!tls_connect(transport->TlsOut))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tls_status = tls_connect(transport->TlsOut);
|
||||||
|
|
||||||
|
if (tls_status < 1)
|
||||||
|
{
|
||||||
|
if (tls_status < 0)
|
||||||
|
{
|
||||||
|
if (!freerdp_get_last_error(context))
|
||||||
|
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!freerdp_get_last_error(context))
|
||||||
|
freerdp_set_last_error(context, FREERDP_ERROR_CONNECT_CANCELLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!tsg_connect(tsg, hostname, port))
|
if (!tsg_connect(tsg, hostname, port))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -105,10 +105,11 @@ static void tls_ssl_info_callback(const SSL* ssl, int type, int val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL tls_connect(rdpTls* tls)
|
int tls_connect(rdpTls* tls)
|
||||||
{
|
{
|
||||||
CryptoCert cert;
|
CryptoCert cert;
|
||||||
long options = 0;
|
long options = 0;
|
||||||
|
int verify_status;
|
||||||
int connection_status;
|
int connection_status;
|
||||||
|
|
||||||
tls->ctx = SSL_CTX_new(TLSv1_client_method());
|
tls->ctx = SSL_CTX_new(TLSv1_client_method());
|
||||||
@ -116,7 +117,7 @@ BOOL tls_connect(rdpTls* tls)
|
|||||||
if (!tls->ctx)
|
if (!tls->ctx)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "SSL_CTX_new failed\n");
|
fprintf(stderr, "SSL_CTX_new failed\n");
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
|
//SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE);
|
||||||
@ -157,7 +158,7 @@ BOOL tls_connect(rdpTls* tls)
|
|||||||
if (!tls->ssl)
|
if (!tls->ssl)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "SSL_new failed\n");
|
fprintf(stderr, "SSL_new failed\n");
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tls->tsg)
|
if (tls->tsg)
|
||||||
@ -167,7 +168,7 @@ BOOL tls_connect(rdpTls* tls)
|
|||||||
if (!tls->bio)
|
if (!tls->bio)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "BIO_new failed\n");
|
fprintf(stderr, "BIO_new failed\n");
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls->bio->ptr = tls->tsg;
|
tls->bio->ptr = tls->tsg;
|
||||||
@ -181,7 +182,7 @@ BOOL tls_connect(rdpTls* tls)
|
|||||||
if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
|
if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "SSL_set_fd failed\n");
|
fprintf(stderr, "SSL_set_fd failed\n");
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +192,7 @@ BOOL tls_connect(rdpTls* tls)
|
|||||||
{
|
{
|
||||||
if (tls_print_error("SSL_connect", tls->ssl, connection_status))
|
if (tls_print_error("SSL_connect", tls->ssl, connection_status))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +201,7 @@ BOOL tls_connect(rdpTls* tls)
|
|||||||
if (!cert)
|
if (!cert)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "tls_connect: tls_get_certificate failed to return the server certificate.\n");
|
fprintf(stderr, "tls_connect: tls_get_certificate failed to return the server certificate.\n");
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls->Bindings = tls_get_channel_bindings(cert->px509);
|
tls->Bindings = tls_get_channel_bindings(cert->px509);
|
||||||
@ -209,20 +210,22 @@ BOOL tls_connect(rdpTls* tls)
|
|||||||
{
|
{
|
||||||
fprintf(stderr, "tls_connect: crypto_cert_get_public_key failed to return the server public key.\n");
|
fprintf(stderr, "tls_connect: crypto_cert_get_public_key failed to return the server public key.\n");
|
||||||
tls_free_certificate(cert);
|
tls_free_certificate(cert);
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tls_verify_certificate(tls, cert, tls->hostname, tls->port))
|
verify_status = tls_verify_certificate(tls, cert, tls->hostname, tls->port);
|
||||||
|
|
||||||
|
if (verify_status < 1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n");
|
fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n");
|
||||||
tls_disconnect(tls);
|
tls_disconnect(tls);
|
||||||
tls_free_certificate(cert);
|
tls_free_certificate(cert);
|
||||||
return FALSE;
|
return verify_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
tls_free_certificate(cert);
|
tls_free_certificate(cert);
|
||||||
|
|
||||||
return TRUE;
|
return (verify_status == 0) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file)
|
BOOL tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file)
|
||||||
@ -612,7 +615,7 @@ BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port)
|
int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port)
|
||||||
{
|
{
|
||||||
int match;
|
int match;
|
||||||
int index;
|
int index;
|
||||||
@ -644,7 +647,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
|||||||
if (!bio)
|
if (!bio)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "tls_verify_certificate: BIO_new() failure\n");
|
fprintf(stderr, "tls_verify_certificate: BIO_new() failure\n");
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = PEM_write_bio_X509(bio, cert->px509);
|
status = PEM_write_bio_X509(bio, cert->px509);
|
||||||
@ -652,7 +655,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
|||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "tls_verify_certificate: PEM_write_bio_X509 failure: %d\n", status);
|
fprintf(stderr, "tls_verify_certificate: PEM_write_bio_X509 failure: %d\n", status);
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
@ -664,7 +667,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
|||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "tls_verify_certificate: failed to read certificate\n");
|
fprintf(stderr, "tls_verify_certificate: failed to read certificate\n");
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += status;
|
offset += status;
|
||||||
@ -685,7 +688,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
|||||||
if (status < 0)
|
if (status < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "tls_verify_certificate: failed to read certificate\n");
|
fprintf(stderr, "tls_verify_certificate: failed to read certificate\n");
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
length = offset;
|
length = offset;
|
||||||
@ -704,12 +707,15 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
|||||||
free(pemCert);
|
free(pemCert);
|
||||||
BIO_free(bio);
|
BIO_free(bio);
|
||||||
|
|
||||||
return (status < 0) ? FALSE : TRUE;
|
if (status < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return (status == 0) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ignore certificate verification if user explicitly required it (discouraged) */
|
/* ignore certificate verification if user explicitly required it (discouraged) */
|
||||||
if (tls->settings->IgnoreCertificate)
|
if (tls->settings->IgnoreCertificate)
|
||||||
return TRUE; /* success! */
|
return 1; /* success! */
|
||||||
|
|
||||||
/* if user explicitly specified a certificate name, use it instead of the hostname */
|
/* if user explicitly specified a certificate name, use it instead of the hostname */
|
||||||
if (tls->settings->CertificateName)
|
if (tls->settings->CertificateName)
|
||||||
@ -727,7 +733,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
|||||||
|
|
||||||
/* compare against common name */
|
/* compare against common name */
|
||||||
|
|
||||||
if (common_name != NULL)
|
if (common_name)
|
||||||
{
|
{
|
||||||
if (tls_match_hostname(common_name, common_name_length, hostname))
|
if (tls_match_hostname(common_name, common_name_length, hostname))
|
||||||
hostname_match = TRUE;
|
hostname_match = TRUE;
|
||||||
@ -735,7 +741,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
|||||||
|
|
||||||
/* compare against alternative names */
|
/* compare against alternative names */
|
||||||
|
|
||||||
if (alt_names != NULL)
|
if (alt_names)
|
||||||
{
|
{
|
||||||
for (index = 0; index < alt_names_count; index++)
|
for (index = 0; index < alt_names_count; index++)
|
||||||
{
|
{
|
||||||
@ -851,7 +857,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
|||||||
crypto_cert_subject_alt_name_free(alt_names_count, alt_names_lengths,
|
crypto_cert_subject_alt_name_free(alt_names_count, alt_names_lengths,
|
||||||
alt_names);
|
alt_names);
|
||||||
|
|
||||||
return verification_status;
|
return (verification_status == 0) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tls_print_certificate_error(char* hostname, char* fingerprint, char *hosts_file)
|
void tls_print_certificate_error(char* hostname, char* fingerprint, char *hosts_file)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user