BOOL tls_accept(rdpTls* tls, BIO *underlying, const char* cert_file, const char* privatekey_file) { long options = 0; /** * SSL_OP_NO_SSLv2: * * We only want SSLv3 and TLSv1, so disable SSLv2. * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. */ options |= SSL_OP_NO_SSLv2; /** * SSL_OP_NO_COMPRESSION: * * The Microsoft RDP server does not advertise support * for TLS compression, but alternative servers may support it. * This was observed between early versions of the FreeRDP server * and the FreeRDP client, and caused major performance issues, * which is why we're disabling it. */ #ifdef SSL_OP_NO_COMPRESSION options |= SSL_OP_NO_COMPRESSION; #endif /** * SSL_OP_TLS_BLOCK_PADDING_BUG: * * The Microsoft RDP server does *not* support TLS padding. * It absolutely needs to be disabled otherwise it won't work. */ options |= SSL_OP_TLS_BLOCK_PADDING_BUG; /** * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: * * Just like TLS padding, the Microsoft RDP server does not * support empty fragments. This needs to be disabled. */ options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; if (!tls_prepare(tls, underlying, SSLv23_server_method(), options, FALSE)) return FALSE; if (SSL_use_RSAPrivateKey_file(tls->ssl, privatekey_file, SSL_FILETYPE_PEM) <= 0) { DEBUG_WARN( "%s: SSL_CTX_use_RSAPrivateKey_file failed\n", __FUNCTION__); DEBUG_WARN( "PrivateKeyFile: %s\n", privatekey_file); return FALSE; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { DEBUG_WARN( "%s: SSL_use_certificate_file failed\n", __FUNCTION__); return FALSE; } return tls_do_handshake(tls, FALSE) > 0; }
int tls_connect(rdpTls* tls, BIO* underlying) { int options = 0; /** * SSL_OP_NO_COMPRESSION: * * The Microsoft RDP server does not advertise support * for TLS compression, but alternative servers may support it. * This was observed between early versions of the FreeRDP server * and the FreeRDP client, and caused major performance issues, * which is why we're disabling it. */ #ifdef SSL_OP_NO_COMPRESSION options |= SSL_OP_NO_COMPRESSION; #endif /** * SSL_OP_TLS_BLOCK_PADDING_BUG: * * The Microsoft RDP server does *not* support TLS padding. * It absolutely needs to be disabled otherwise it won't work. */ options |= SSL_OP_TLS_BLOCK_PADDING_BUG; /** * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: * * Just like TLS padding, the Microsoft RDP server does not * support empty fragments. This needs to be disabled. */ options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; /** * disable SSLv2 and SSLv3 */ options |= SSL_OP_NO_SSLv2; options |= SSL_OP_NO_SSLv3; if (!tls_prepare(tls, underlying, SSLv23_client_method(), options, TRUE)) return FALSE; #ifndef OPENSSL_NO_TLSEXT SSL_set_tlsext_host_name(tls->ssl, tls->hostname); #endif return tls_do_handshake(tls, TRUE); }
BOOL tls_accept(rdpTls* tls, BIO* underlying, rdpSettings* settings) { long options = 0; BIO* bio; RSA* rsa; X509* x509; /** * SSL_OP_NO_SSLv2: * * We only want SSLv3 and TLSv1, so disable SSLv2. * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. */ options |= SSL_OP_NO_SSLv2; /** * SSL_OP_NO_COMPRESSION: * * The Microsoft RDP server does not advertise support * for TLS compression, but alternative servers may support it. * This was observed between early versions of the FreeRDP server * and the FreeRDP client, and caused major performance issues, * which is why we're disabling it. */ #ifdef SSL_OP_NO_COMPRESSION options |= SSL_OP_NO_COMPRESSION; #endif /** * SSL_OP_TLS_BLOCK_PADDING_BUG: * * The Microsoft RDP server does *not* support TLS padding. * It absolutely needs to be disabled otherwise it won't work. */ options |= SSL_OP_TLS_BLOCK_PADDING_BUG; /** * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: * * Just like TLS padding, the Microsoft RDP server does not * support empty fragments. This needs to be disabled. */ options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; if (!tls_prepare(tls, underlying, SSLv23_server_method(), options, FALSE)) return FALSE; if (settings->PrivateKeyFile) { bio = BIO_new_file(settings->PrivateKeyFile, "rb"); if (!bio) { WLog_ERR(TAG, "BIO_new_file failed for private key %s", settings->PrivateKeyFile); return FALSE; } } else if (settings->PrivateKeyContent) { bio = BIO_new_mem_buf(settings->PrivateKeyContent, strlen(settings->PrivateKeyContent)); if (!bio) { WLog_ERR(TAG, "BIO_new_mem_buf failed for private key"); return FALSE; } } else { WLog_ERR(TAG, "no private key defined"); return FALSE; } rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); BIO_free(bio); if (!rsa) { WLog_ERR(TAG, "invalid private key"); return FALSE; } if (SSL_use_RSAPrivateKey(tls->ssl, rsa) <= 0) { WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed"); RSA_free(rsa); return FALSE; } if (settings->CertificateFile) { bio = BIO_new_file(settings->CertificateFile, "rb"); if (!bio) { WLog_ERR(TAG, "BIO_new_file failed for certificate %s", settings->CertificateFile); return FALSE; } } else if (settings->CertificateContent) { bio = BIO_new_mem_buf(settings->CertificateContent, strlen(settings->CertificateContent)); if (!bio) { WLog_ERR(TAG, "BIO_new_mem_buf failed for certificate"); return FALSE; } } else { WLog_ERR(TAG, "no certificate defined"); return FALSE; } x509 = PEM_read_bio_X509(bio, NULL, NULL, 0); BIO_free(bio); if (!x509) { WLog_ERR(TAG, "invalid certificate"); return FALSE; } if (SSL_use_certificate(tls->ssl, x509) <= 0) { WLog_ERR(TAG, "SSL_use_certificate_file failed"); X509_free(x509); return FALSE; } #if defined(MICROSOFT_IOS_SNI_BUG) && !defined(OPENSSL_NO_TLSEXT) SSL_set_tlsext_debug_callback(tls->ssl, tls_openssl_tlsext_debug_callback); #endif return tls_do_handshake(tls, FALSE) > 0; }
/*-------------------------------------------------------------------------*/ int tls_continue_handshake (interactive_t *ip) /* Continue the TLS initialisation handshake for interactive <ip>. * Return a negative error code if the connection can not be set up. * Return 0 if the connection is still begin set up. * Return 1 if the connection is now active (or if no secure connection * had been requested). * * If a callback is set for <ip> and connection comes out of the handshaking * state, it will be called with the result code. */ { int ret; if (ip->tls_status != TLS_HANDSHAKING) return 1; ret = tls_do_handshake(ip); if (!ret) return 0; if (ret < 0) { ip->tls_status = TLS_INACTIVE; } else { ip->tls_status = TLS_ACTIVE; } /* If the connection is no longer in handshake, execute the callback */ if (ip->tls_cb != NULL) { tls_cb_handler_t * handler; xallocate( handler, sizeof(*handler) , "TLS: Callback handler protector"); handler->cb = ip->tls_cb; ip->tls_cb = NULL; /* Protect the callback during its execution. */ push_error_handler (handle_tls_cb_error, &(handler->head)); push_number(inter_sp, ret < 0 ? ret : 0); push_ref_object(inter_sp, ip->ob, "tls_handshake"); command_giver = ip->ob; current_interactive = ip->ob; /* Set current_interactive as it would be for a normal logon() call. */ (void)apply_callback(handler->cb, 2); if (!(ip->ob->flags & O_DESTRUCTED)) print_prompt(); command_giver = NULL; free_svalue(inter_sp); inter_sp--; /* free the callback */ } return ret; } /* tls_continue_handshake() */
BOOL tls_accept(rdpTls* tls, BIO* underlying, rdpSettings* settings) { long options = 0; BIO* bio; RSA* rsa; X509* x509; /** * SSL_OP_NO_SSLv2: * * We only want SSLv3 and TLSv1, so disable SSLv2. * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. */ options |= SSL_OP_NO_SSLv2; /** * SSL_OP_NO_COMPRESSION: * * The Microsoft RDP server does not advertise support * for TLS compression, but alternative servers may support it. * This was observed between early versions of the FreeRDP server * and the FreeRDP client, and caused major performance issues, * which is why we're disabling it. */ #ifdef SSL_OP_NO_COMPRESSION options |= SSL_OP_NO_COMPRESSION; #endif /** * SSL_OP_TLS_BLOCK_PADDING_BUG: * * The Microsoft RDP server does *not* support TLS padding. * It absolutely needs to be disabled otherwise it won't work. */ options |= SSL_OP_TLS_BLOCK_PADDING_BUG; /** * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: * * Just like TLS padding, the Microsoft RDP server does not * support empty fragments. This needs to be disabled. */ options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; if (!tls_prepare(tls, underlying, SSLv23_server_method(), options, FALSE)) return FALSE; if (settings->PrivateKeyFile) { bio = BIO_new_file(settings->PrivateKeyFile, "rb+"); if (!bio) { WLog_ERR(TAG, "BIO_new_file failed for private key %s", settings->PrivateKeyFile); return FALSE; } } else if (settings->PrivateKeyContent) { bio = BIO_new_mem_buf(settings->PrivateKeyContent, strlen(settings->PrivateKeyContent)); if (!bio) { WLog_ERR(TAG, "BIO_new_mem_buf failed for private key"); return FALSE; } } else { WLog_ERR(TAG, "no private key defined"); return FALSE; } rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); BIO_free(bio); if (!rsa) { WLog_ERR(TAG, "invalid private key"); return FALSE; } if (SSL_use_RSAPrivateKey(tls->ssl, rsa) <= 0) { WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed"); RSA_free(rsa); return FALSE; } if (settings->CertificateFile) { bio = BIO_new_file(settings->CertificateFile, "rb+"); if (!bio) { WLog_ERR(TAG, "BIO_new_file failed for certificate %s", settings->CertificateFile); return FALSE; } } else if (settings->CertificateContent) { bio = BIO_new_mem_buf(settings->CertificateContent, strlen(settings->CertificateContent)); if (!bio) { WLog_ERR(TAG, "BIO_new_mem_buf failed for certificate"); return FALSE; } } else { WLog_ERR(TAG, "no certificate defined"); return FALSE; } x509 = PEM_read_bio_X509(bio, NULL, NULL, 0); BIO_free(bio); if (!x509) { WLog_ERR(TAG, "invalid certificate"); return FALSE; } if (SSL_use_certificate(tls->ssl, x509) <= 0) { WLog_ERR(TAG, "SSL_use_certificate_file failed"); X509_free(x509); return FALSE; } #ifndef OPENSSL_NO_TLSEXT /** * The Microsoft iOS clients eventually send a null or even double null * terminated hostname in the SNI TLS extension! * If the length indicator does not equal the hostname strlen OpenSSL * will abort (see openssl:ssl/t1_lib.c). * Here is a tcpdump segment of Microsoft Remote Desktop Client Version * 8.1.7 running on an iPhone 4 with iOS 7.1.2 showing the transmitted * SNI hostname TLV blob when connection to server "abcd": * 00 name_type 0x00 (host_name) * 00 06 length_in_bytes 0x0006 * 61 62 63 64 00 00 host_name "abcd\0\0" * * Currently the only (runtime) workaround is setting an openssl tls * extension debug callback that sets the SSL context's servername_done * to 1 which effectively disables the parsing of that extension type. */ SSL_set_tlsext_debug_callback(tls->ssl, tls_openssl_tlsext_debug_callback); #endif return tls_do_handshake(tls, FALSE) > 0; }