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;
|
||||
};
|
||||
|
||||
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_disconnect(rdpTls* tls);
|
||||
|
||||
|
@ -224,6 +224,7 @@ BIO_METHOD* BIO_s_tsg(void)
|
||||
|
||||
BOOL transport_connect_tls(rdpTransport* transport)
|
||||
{
|
||||
int tls_status;
|
||||
freerdp* instance;
|
||||
rdpContext* context;
|
||||
|
||||
@ -245,13 +246,23 @@ BOOL transport_connect_tls(rdpTransport* transport)
|
||||
if (transport->TsgTls->port == 0)
|
||||
transport->TsgTls->port = 3389;
|
||||
|
||||
if (!tls_connect(transport->TsgTls))
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = TLSCONNECTERROR;
|
||||
tls_status = tls_connect(transport->TsgTls);
|
||||
|
||||
if (!freerdp_get_last_error(context))
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||
if (tls_status < 1)
|
||||
{
|
||||
if (tls_status < 0)
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = TLSCONNECTERROR;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
tls_free(transport->TsgTls);
|
||||
transport->TsgTls = NULL;
|
||||
@ -277,13 +288,23 @@ BOOL transport_connect_tls(rdpTransport* transport)
|
||||
if (transport->TlsIn->port == 0)
|
||||
transport->TlsIn->port = 3389;
|
||||
|
||||
if (!tls_connect(transport->TlsIn))
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = TLSCONNECTERROR;
|
||||
tls_status = tls_connect(transport->TlsIn);
|
||||
|
||||
if (!freerdp_get_last_error(context))
|
||||
freerdp_set_last_error(context, FREERDP_ERROR_TLS_CONNECT_FAILED);
|
||||
if (tls_status < 1)
|
||||
{
|
||||
if (tls_status < 0)
|
||||
{
|
||||
if (!connectErrorCode)
|
||||
connectErrorCode = TLSCONNECTERROR;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int tls_status;
|
||||
freerdp* instance;
|
||||
rdpContext* context;
|
||||
|
||||
instance = (freerdp*) transport->settings->instance;
|
||||
context = instance->context;
|
||||
|
||||
rdpTsg* tsg = tsg_new(transport);
|
||||
|
||||
tsg->transport = transport;
|
||||
@ -381,11 +409,41 @@ BOOL transport_tsg_connect(rdpTransport* transport, const char* hostname, UINT16
|
||||
if (transport->TlsOut->port == 0)
|
||||
transport->TlsOut->port = 443;
|
||||
|
||||
if (!tls_connect(transport->TlsIn))
|
||||
return FALSE;
|
||||
tls_status = tls_connect(transport->TlsIn);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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))
|
||||
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;
|
||||
long options = 0;
|
||||
int verify_status;
|
||||
int connection_status;
|
||||
|
||||
tls->ctx = SSL_CTX_new(TLSv1_client_method());
|
||||
@ -116,7 +117,7 @@ BOOL tls_connect(rdpTls* tls)
|
||||
if (!tls->ctx)
|
||||
{
|
||||
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);
|
||||
@ -157,7 +158,7 @@ BOOL tls_connect(rdpTls* tls)
|
||||
if (!tls->ssl)
|
||||
{
|
||||
fprintf(stderr, "SSL_new failed\n");
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tls->tsg)
|
||||
@ -167,7 +168,7 @@ BOOL tls_connect(rdpTls* tls)
|
||||
if (!tls->bio)
|
||||
{
|
||||
fprintf(stderr, "BIO_new failed\n");
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tls->bio->ptr = tls->tsg;
|
||||
@ -181,7 +182,7 @@ BOOL tls_connect(rdpTls* tls)
|
||||
if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
|
||||
{
|
||||
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))
|
||||
{
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,7 +201,7 @@ BOOL tls_connect(rdpTls* tls)
|
||||
if (!cert)
|
||||
{
|
||||
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);
|
||||
@ -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");
|
||||
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");
|
||||
tls_disconnect(tls);
|
||||
tls_free_certificate(cert);
|
||||
return FALSE;
|
||||
return verify_status;
|
||||
}
|
||||
|
||||
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)
|
||||
@ -612,7 +615,7 @@ BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname)
|
||||
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 index;
|
||||
@ -644,7 +647,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
||||
if (!bio)
|
||||
{
|
||||
fprintf(stderr, "tls_verify_certificate: BIO_new() failure\n");
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
fprintf(stderr, "tls_verify_certificate: PEM_write_bio_X509 failure: %d\n", status);
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
@ -664,7 +667,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
||||
if (status < 0)
|
||||
{
|
||||
fprintf(stderr, "tls_verify_certificate: failed to read certificate\n");
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
offset += status;
|
||||
@ -685,7 +688,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
||||
if (status < 0)
|
||||
{
|
||||
fprintf(stderr, "tls_verify_certificate: failed to read certificate\n");
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
length = offset;
|
||||
@ -704,12 +707,15 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
||||
free(pemCert);
|
||||
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) */
|
||||
if (tls->settings->IgnoreCertificate)
|
||||
return TRUE; /* success! */
|
||||
return 1; /* success! */
|
||||
|
||||
/* if user explicitly specified a certificate name, use it instead of the hostname */
|
||||
if (tls->settings->CertificateName)
|
||||
@ -727,7 +733,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
||||
|
||||
/* compare against common name */
|
||||
|
||||
if (common_name != NULL)
|
||||
if (common_name)
|
||||
{
|
||||
if (tls_match_hostname(common_name, common_name_length, hostname))
|
||||
hostname_match = TRUE;
|
||||
@ -735,7 +741,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int po
|
||||
|
||||
/* compare against alternative names */
|
||||
|
||||
if (alt_names != NULL)
|
||||
if (alt_names)
|
||||
{
|
||||
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,
|
||||
alt_names);
|
||||
|
||||
return verification_status;
|
||||
return (verification_status == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
void tls_print_certificate_error(char* hostname, char* fingerprint, char *hosts_file)
|
||||
|
Loading…
Reference in New Issue
Block a user