DWORD rdg_get_event_handles(rdpRdg* rdg, HANDLE* events, DWORD count) { DWORD nCount = 0; assert(rdg != NULL); if (rdg->tlsOut && rdg->tlsOut->bio) { if (events && (nCount < count)) { BIO_get_event(rdg->tlsOut->bio, &events[nCount]); nCount++; } else return 0; } if (rdg->tlsIn && rdg->tlsIn->bio) { if (events && (nCount < count)) { BIO_get_event(rdg->tlsIn->bio, &events[nCount]); nCount++; } else return 0; } return nCount; }
static HANDLE freerdp_peer_get_event_handle(freerdp_peer* client) { HANDLE hEvent = NULL; rdpTransport* transport = client->context->rdp->transport; BIO_get_event(transport->frontBio, &hEvent); return hEvent; }
BOOL rdg_check_event_handles(rdpRdg* rdg) { HANDLE event = NULL; assert(rdg != NULL); BIO_get_event(rdg->tlsOut->bio, &event); if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0) { return rdg_out_channel_recv(rdg); } BIO_get_event(rdg->tlsIn->bio, &event); if (WaitForSingleObject(event, 0) == WAIT_OBJECT_0) { return rdg_in_channel_recv(rdg); } return TRUE; }
static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2) { int status = 0; rdpRdg* rdg = (rdpRdg*)bio->ptr; rdpTls* tlsOut = rdg->tlsOut; rdpTls* tlsIn = rdg->tlsIn; if (cmd == BIO_CTRL_FLUSH) { (void)BIO_flush(tlsOut->bio); (void)BIO_flush(tlsIn->bio); status = 1; } else if (cmd == BIO_C_GET_EVENT) { if (arg2) { BIO_get_event(rdg->tlsOut->bio, arg2); status = 1; } } else if (cmd == BIO_C_SET_NONBLOCK) { rdg->nonBlocking = arg1; status = 1; } else if (cmd == BIO_C_READ_BLOCKED) { status = 0; } else if (cmd == BIO_C_WRITE_BLOCKED) { status = 0; } else if (cmd == BIO_C_WAIT_READ) { int timeout = (int)arg1; return BIO_wait_read(tlsOut->bio, timeout); } else if (cmd == BIO_C_WAIT_WRITE) { status = 0; } return status; }
DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events, DWORD count) { DWORD nCount = 0; DWORD tmp; if (!transport->GatewayEnabled) { if (events && (nCount < count)) { if (BIO_get_event(transport->frontBio, &events[nCount]) != 1) return 0; nCount++; } } else { if (transport->rdg) { tmp = rdg_get_event_handles(transport->rdg, events, nCount - count); if (tmp == 0) return 0; nCount = tmp; } else if (transport->tsg) { tmp = tsg_get_event_handles(transport->tsg, events, nCount - count); if (tmp == 0) return 0; nCount = tmp; } } return nCount; }
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; }
static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2) { int status = 0; rdpRdg* rdg = (rdpRdg*) BIO_get_data(bio); rdpTls* tlsOut = rdg->tlsOut; rdpTls* tlsIn = rdg->tlsIn; if (cmd == BIO_CTRL_FLUSH) { (void)BIO_flush(tlsOut->bio); (void)BIO_flush(tlsIn->bio); status = 1; } else if (cmd == BIO_C_GET_EVENT) { if (arg2) { BIO_get_event(rdg->tlsOut->bio, arg2); status = 1; } } else if (cmd == BIO_C_SET_NONBLOCK) { status = 1; } else if (cmd == BIO_C_READ_BLOCKED) { BIO* bio = tlsOut->bio; status = BIO_read_blocked(bio); } else if (cmd == BIO_C_WRITE_BLOCKED) { BIO* bio = tlsIn->bio; status = BIO_write_blocked(bio); } else if (cmd == BIO_C_WAIT_READ) { int timeout = (int) arg1; BIO* bio = tlsOut->bio; if (BIO_read_blocked(bio)) return BIO_wait_read(bio, timeout); else if (BIO_write_blocked(bio)) return BIO_wait_write(bio, timeout); else status = 1; } else if (cmd == BIO_C_WAIT_WRITE) { int timeout = (int) arg1; BIO* bio = tlsIn->bio; if (BIO_write_blocked(bio)) status = BIO_wait_write(bio, timeout); else if (BIO_read_blocked(bio)) status = BIO_wait_read(bio, timeout); else status = 1; } return status; }
DWORD transport_get_event_handles(rdpTransport* transport, HANDLE* events, DWORD count) { DWORD nCount = 1; /* always the reread Event */ DWORD tmp; if (events) { if (count < 1) { WLog_Print(transport->log, WLOG_ERROR, "%s: provided handles array is too small", __FUNCTION__); return 0; } events[0] = transport->rereadEvent; } if (!transport->GatewayEnabled) { nCount++; if (events) { if (nCount > count) { WLog_Print(transport->log, WLOG_ERROR, "%s: provided handles array is too small (count=%"PRIu32" nCount=%"PRIu32")", __FUNCTION__, count, nCount); return 0; } if (BIO_get_event(transport->frontBio, &events[1]) != 1) { WLog_Print(transport->log, WLOG_ERROR, "%s: error getting the frontBio handle", __FUNCTION__); return 0; } } } else { if (transport->rdg) { tmp = rdg_get_event_handles(transport->rdg, &events[1], count - 1); if (tmp == 0) return 0; nCount += tmp; } else if (transport->tsg) { tmp = tsg_get_event_handles(transport->tsg, &events[1], count - 1); if (tmp == 0) return 0; nCount += tmp; } } return nCount; }