int tls_read(rdpTls* tls, BYTE* data, int length) { int error; int status; if (!tls) return -1; if (!tls->ssl) return -1; status = SSL_read(tls->ssl, data, length); if (status == 0) { return -1; /* peer disconnected */ } if (status <= 0) { error = SSL_get_error(tls->ssl, status); //fprintf(stderr, "tls_read: length: %d status: %d error: 0x%08X\n", // length, status, error); switch (error) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: status = 0; break; case SSL_ERROR_SYSCALL: if ((errno == EAGAIN) || (errno == 0)) { status = 0; } else { tls_print_error("SSL_read", tls->ssl, status); status = -1; } break; default: tls_print_error("SSL_read", tls->ssl, status); status = -1; break; } } return status; }
int tls_write(rdpTls* tls, BYTE* data, int length) { int error; int status; status = SSL_write(tls->ssl, data, length); if (status <= 0) { error = SSL_get_error(tls->ssl, status); //fprintf(stderr, "tls_write: length: %d status: %d error: 0x%08X\n", length, status, error); switch (error) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: status = 0; break; default: tls_print_error("SSL_write", tls->ssl, status); status = -1; break; } } return status; }
int tls_read(rdpTls* tls, BYTE* data, int length) { int status; int ret; status = SSL_read(tls->ssl, data, length); ret = SSL_get_error(tls->ssl, status); switch (ret) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: status = 0; break; default: printf("ssl read error:%d\n", ret); tls_print_error("SSL_read", tls->ssl, status); status = -1; break; } return status; }
boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file) { int connection_status; tls->ctx = SSL_CTX_new(SSLv23_server_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } /* * We only want SSLv3 and TLSv1, so disable SSLv2. * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. */ SSL_CTX_set_options(tls->ctx, SSL_OP_NO_SSLv2); if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); return false; } tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_use_certificate_file failed\n"); return false; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return false; } connection_status = SSL_accept(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_accept", tls->ssl, connection_status)) return false; } printf("TLS connection accepted\n"); return true; }
tbool tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file) { int connection_status; tls->ctx = SSL_CTX_new(TLSv1_server_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); return false; } tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_use_certificate_file failed\n"); return false; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return false; } connection_status = SSL_accept(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_accept", tls->ssl, connection_status)) return false; } printf("TLS connection accepted\n"); return true; }
tbool tls_connect(rdpTls* tls) { int connection_status; LLOGLN(10, ("tls_connect:")); tls->ctx = SSL_CTX_new(TLSv1_client_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } /* * This is necessary, because the Microsoft TLS implementation is not perfect. * SSL_OP_ALL enables a couple of workarounds for buggy TLS implementations, * but the most important workaround being SSL_OP_TLS_BLOCK_PADDING_BUG. * As the size of the encrypted payload may give hints about its contents, * block padding is normally used, but the Microsoft TLS implementation * won't recognize it and will disconnect you after sending a TLS alert. */ SSL_CTX_set_options(tls->ctx, SSL_OP_ALL); tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return false; } connection_status = SSL_connect(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_connect", tls->ssl, connection_status)) return false; } return true; }
int tls_write(rdpTls* tls, uint8* data, int length) { int status; status = SSL_write(tls->ssl, data, length); switch (SSL_get_error(tls->ssl, status)) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: status = 0; break; default: tls_print_error("SSL_write", tls->ssl, status); status = -1; break; } return status; }
int tls_write(rdpTls* tls, uint8* data, int length) { int status; LLOGLN(10, ("tls_write: int length %d", length)); status = SSL_write(tls->ssl, data, length); LLOGLN(10, ("tls_write: ssl %p SSL_write rv %d", tls->ssl, status)); if (status > 0) { LHEXDUMP(10, (data, status)); return status; } if (status == 0) { return -1; /* disconnected */ } switch (SSL_get_error(tls->ssl, status)) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: status = 0; break; default: tls_print_error("SSL_write", tls->ssl, status); status = -1; break; } LLOGLN(10, ("tls_write: out status %d", status)); return status; }
boolean tls_connect(rdpTls* tls) { CryptoCert cert; int connection_status; tls->ctx = SSL_CTX_new(TLSv1_client_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } /* * This is necessary, because the Microsoft TLS implementation is not perfect. * SSL_OP_ALL enables a couple of workarounds for buggy TLS implementations, * but the most important workaround being SSL_OP_TLS_BLOCK_PADDING_BUG. * As the size of the encrypted payload may give hints about its contents, * block padding is normally used, but the Microsoft TLS implementation * won't recognize it and will disconnect you after sending a TLS alert. */ SSL_CTX_set_options(tls->ctx, SSL_OP_ALL); tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { SSL_CTX_free(tls->ctx); printf("SSL_new failed\n"); return false; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { SSL_free(tls->ssl); SSL_CTX_free(tls->ctx); printf("SSL_set_fd failed\n"); return false; } connection_status = SSL_connect(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_connect", tls->ssl, connection_status)) { SSL_free(tls->ssl); SSL_CTX_free(tls->ctx); return false; } } cert = tls_get_certificate(tls); if (cert == NULL) { printf("tls_connect: tls_get_certificate failed to return the server certificate.\n"); return false; } if (!crypto_cert_get_public_key(cert, &tls->public_key)) { printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n"); return false; } if (!tls_verify_certificate(tls, cert, tls->settings->hostname)) tls_disconnect(tls); tls_free_certificate(cert); return true; }
boolean tls_connect(rdpTls* tls) { CryptoCert cert; long options = 0; int connection_status; tls->ctx = SSL_CTX_new(TLSv1_client_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } /** * 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; SSL_CTX_set_options(tls->ctx, options); tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return false; } connection_status = SSL_connect(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_connect", tls->ssl, connection_status)) { return false; } } cert = tls_get_certificate(tls, true); if (cert == NULL) { printf("tls_connect: tls_get_certificate failed to return the server certificate.\n"); return false; } if (!crypto_cert_get_public_key(cert, &tls->public_key)) { printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n"); tls_free_certificate(cert) ; return false; } if (!tls_verify_certificate(tls, cert, tls->settings->hostname)) { printf("tls_connect: certificate not trusted, aborting.\n"); tls_disconnect(tls); tls_free_certificate(cert); return false; } tls_free_certificate(cert); return true; }
boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file) { CryptoCert cert; long options = 0; int connection_status; tls->ctx = SSL_CTX_new(SSLv23_server_method()); if (tls->ctx == NULL) { printf("SSL_CTX_new failed\n"); return false; } /* * 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; SSL_CTX_set_options(tls->ctx, options); if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_CTX_use_RSAPrivateKey_file failed\n"); return false; } tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { printf("SSL_new failed\n"); return false; } if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0) { printf("SSL_use_certificate_file failed\n"); return false; } cert = tls_get_certificate(tls, false); if (cert == NULL) { printf("tls_connect: tls_get_certificate failed to return the server certificate.\n"); return false; } if (!crypto_cert_get_public_key(cert, &tls->public_key)) { printf("tls_connect: crypto_cert_get_public_key failed to return the server public key.\n"); tls_free_certificate(cert); return false; } xfree(cert); if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { printf("SSL_set_fd failed\n"); return false; } while (1) { connection_status = SSL_accept(tls->ssl); if (connection_status <= 0) { switch (SSL_get_error(tls->ssl, connection_status)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: break; default: if (tls_print_error("SSL_accept", tls->ssl, connection_status)) return false; break; } } else { break; } } printf("TLS connection accepted\n"); return true; }
BOOL tls_connect(rdpTls* tls) { CryptoCert cert; long options = 0; int connection_status; char *hostname; tls->ctx = SSL_CTX_new(TLSv1_client_method()); if (tls->ctx == NULL) { fprintf(stderr, "SSL_CTX_new failed\n"); return FALSE; } //SSL_CTX_set_mode(tls->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_ENABLE_PARTIAL_WRITE); /** * 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; SSL_CTX_set_options(tls->ctx, options); tls->ssl = SSL_new(tls->ctx); if (tls->ssl == NULL) { fprintf(stderr, "SSL_new failed\n"); return FALSE; } if (SSL_set_fd(tls->ssl, tls->sockfd) < 1) { fprintf(stderr, "SSL_set_fd failed\n"); return FALSE; } connection_status = SSL_connect(tls->ssl); if (connection_status <= 0) { if (tls_print_error("SSL_connect", tls->ssl, connection_status)) { return FALSE; } } cert = tls_get_certificate(tls, TRUE); if (cert == NULL) { fprintf(stderr, "tls_connect: tls_get_certificate failed to return the server certificate.\n"); return FALSE; } tls->Bindings = tls_get_channel_bindings(cert->px509); if (!crypto_cert_get_public_key(cert, &tls->PublicKey, &tls->PublicKeyLength)) { fprintf(stderr, "tls_connect: crypto_cert_get_public_key failed to return the server public key.\n"); tls_free_certificate(cert); return FALSE; } if (tls->settings->GatewayUsageMethod) hostname = tls->settings->GatewayHostname; else hostname = tls->settings->ServerHostname; if (!tls_verify_certificate(tls, cert, hostname)) { fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n"); tls_disconnect(tls); tls_free_certificate(cert); return FALSE; } tls_free_certificate(cert); return TRUE; }
/* try to read length bytes * returns the number of bytes read or -1 on error * returns zero on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE * returns zero if length < 1 */ int tls_read(rdpTls* tls, uint8* data, int length) { int status; int left; LLOGLN(10, ("tls_read: in length %d", length)); if (length < 1) { return 0; } if (tls->read_extra != NULL) { LLOGLN(10, ("tls_read: got left over, using first")); left = stream_get_left(tls->read_extra); if (length < left) { memcpy(data, tls->read_extra->p, length); tls->read_extra->p += length; LHEXDUMP(10, (data, length)); return length; } memcpy(data, tls->read_extra->p, left); LLOGLN(10, ("tls_read: freeing read_extra")); stream_free(tls->read_extra); tls->read_extra = NULL; status = tls_read(tls, data + left, length - left); if (status < 0) { return -1; } LHEXDUMP(10, (data, left + status)); return left + status; } status = SSL_read(tls->ssl, data, length); LLOGLN(10, ("tls_read: ssl %p SSL_read rv %d", tls->ssl, status)); if (status > 0) { g_total_read += status; LLOGLN(10, ("tls_read: g_total_read %d", g_total_read)); LHEXDUMP(10, (data, status)); return status; } if (status == 0) { return -1; /* disconnected */ } /* status must be < 0 */ switch (SSL_get_error(tls->ssl, status)) { case SSL_ERROR_NONE: break; case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: status = 0; break; default: tls_print_error("SSL_read", tls->ssl, status); status = -1; break; } LLOGLN(10, ("tls_read: out status %d", status)); return status; }