/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT encomsp_server_receive_pdu(EncomspServerContext* context, wStream* s) { UINT error = CHANNEL_RC_OK; ENCOMSP_ORDER_HEADER header; while (Stream_GetRemainingLength(s) > 0) { if ((error = encomsp_read_header(s, &header))) { WLog_ERR(TAG, "encomsp_read_header failed with error %u!", error); return error; } WLog_INFO(TAG, "EncomspReceive: Type: %d Length: %d", header.Type, header.Length); switch (header.Type) { case ODTYPE_PARTICIPANT_CTRL_CHANGED: if ((error = encomsp_recv_change_participant_control_level_pdu(context, s, &header))) { WLog_ERR(TAG, "encomsp_recv_change_participant_control_level_pdu failed with error %u!", error); return error; } break; default: WLog_ERR(TAG, "header.Type unknown %d!", header.Type); return ERROR_INVALID_DATA; break; } } return error; }
BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s) { BYTE* p; ARC_SC_PRIVATE_PACKET* autoReconnectCookie; rdpSettings* settings = rdp->settings; autoReconnectCookie = settings->ServerAutoReconnectCookie; if (Stream_GetRemainingLength(s) < 28) return FALSE; Stream_Read_UINT32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */ Stream_Read_UINT32(s, autoReconnectCookie->version); /* Version (4 bytes) */ Stream_Read_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */ Stream_Read(s, autoReconnectCookie->arcRandomBits, 16); /* ArcRandomBits (16 bytes) */ if (autoReconnectCookie->cbLen != 28) { WLog_ERR(TAG, "ServerAutoReconnectCookie.cbLen != 28"); return FALSE; } p = autoReconnectCookie->arcRandomBits; WLog_DBG(TAG, "ServerAutoReconnectCookie: Version: %d LogonId: %d SecurityVerifier: " "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", autoReconnectCookie->version, autoReconnectCookie->logonId, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); if ((settings->PrintReconnectCookie) && (autoReconnectCookie->cbLen > 0)) { char* base64; base64 = crypto_base64_encode((BYTE*) autoReconnectCookie, sizeof(ARC_SC_PRIVATE_PACKET)); WLog_INFO(TAG, "Reconnect-cookie: %s", base64); free(base64); } return TRUE; }
void wf_info_peer_unregister(wfInfo* wfi, wfPeerContext* context) { if (wf_info_lock(wfi) > 0) { int peerId; peerId = ((rdpContext*) context)->peer->pId; wfi->peers[peerId] = NULL; wfi->peerCount--; CloseHandle(context->updateEvent); WLog_INFO(TAG, "Unregistering Peer: id=%d, #=%d", peerId, wfi->peerCount); #ifdef WITH_DXGI_1_2 if (wfi->peerCount == 0) wf_dxgi_cleanup(wfi); #endif wf_info_unlock(wfi); wfreerdp_server_peer_callback_event(peerId, WF_SRV_CALLBACK_EVENT_DISCONNECT); } }
void cliprdr_print_general_capability_flags(UINT32 flags) { WLog_INFO(TAG, "generalFlags (0x%08X) {", flags); if (flags & CB_USE_LONG_FORMAT_NAMES) WLog_INFO(TAG, "\tCB_USE_LONG_FORMAT_NAMES"); if (flags & CB_STREAM_FILECLIP_ENABLED) WLog_INFO(TAG, "\tCB_STREAM_FILECLIP_ENABLED"); if (flags & CB_FILECLIP_NO_FILE_PATHS) WLog_INFO(TAG, "\tCB_FILECLIP_NO_FILE_PATHS"); if (flags & CB_CAN_LOCK_CLIPDATA) WLog_INFO(TAG, "\tCB_CAN_LOCK_CLIPDATA"); WLog_INFO(TAG, "}"); }
static void openh264_trace_callback(H264_CONTEXT* h264, int level, const char* message) { WLog_INFO(TAG, "%d - %s", level, message); }
static void PrintRailIconInfo(WINDOW_ORDER_INFO* orderInfo, ICON_INFO* iconInfo) { WLog_INFO(TAG, "ICON_INFO"); WLog_INFO(TAG, "{"); WLog_INFO(TAG, "\tbigIcon: %s", (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ICON_BIG) ? "true" : "false"); WLog_INFO(TAG, "\tcacheEntry; 0x%04X", iconInfo->cacheEntry); WLog_INFO(TAG, "\tcacheId: 0x%04X", iconInfo->cacheId); WLog_INFO(TAG, "\tbpp: %d", iconInfo->bpp); WLog_INFO(TAG, "\twidth: %d", iconInfo->width); WLog_INFO(TAG, "\theight: %d", iconInfo->height); WLog_INFO(TAG, "\tcbColorTable: %d", iconInfo->cbColorTable); WLog_INFO(TAG, "\tcbBitsMask: %d", iconInfo->cbBitsMask); WLog_INFO(TAG, "\tcbBitsColor: %d", iconInfo->cbBitsColor); WLog_INFO(TAG, "\tcolorTable: %p", iconInfo->colorTable); WLog_INFO(TAG, "\tbitsMask: %p", iconInfo->bitsMask); WLog_INFO(TAG, "\tbitsColor: %p", iconInfo->bitsColor); WLog_INFO(TAG, "}"); }
int shadow_capture_compare(BYTE* pData1, int nStep1, int nWidth, int nHeight, BYTE* pData2, int nStep2, RECTANGLE_16* rect) { BOOL equal; BOOL allEqual; int tw, th; int tx, ty, k; int nrow, ncol; int l, t, r, b; BYTE *p1, *p2; BOOL rows[1024]; #ifdef WITH_DEBUG_SHADOW_CAPTURE BOOL cols[1024]; #endif allEqual = TRUE; ZeroMemory(rect, sizeof(RECTANGLE_16)); FillMemory(rows, sizeof(rows), 0xFF); #ifdef WITH_DEBUG_SHADOW_CAPTURE FillMemory(cols, sizeof(cols), 0xFF); #endif nrow = (nHeight + 15) / 16; ncol = (nWidth + 15) / 16; l = ncol + 1; r = -1; t = nrow + 1; b = -1; for (ty = 0; ty < nrow; ty++) { th = ((ty + 1) == nrow) ? (nHeight % 16) : 16; if (!th) th = 16; for (tx = 0; tx < ncol; tx++) { equal = TRUE; tw = ((tx + 1) == ncol) ? (nWidth % 16) : 16; if (!tw) tw = 16; p1 = &pData1[(ty * 16 * nStep1) + (tx * 16 * 4)]; p2 = &pData2[(ty * 16 * nStep2) + (tx * 16 * 4)]; for (k = 0; k < th; k++) { if (memcmp(p1, p2, tw * 4) != 0) { equal = FALSE; break; } p1 += nStep1; p2 += nStep2; } if (!equal) { rows[ty] = FALSE; #ifdef WITH_DEBUG_SHADOW_CAPTURE cols[tx] = FALSE; #endif if (l > tx) l = tx; if (r < tx) r = tx; } } if (!rows[ty]) { allEqual = FALSE; if (t > ty) t = ty; if (b < ty) b = ty; } } if (allEqual) return 0; rect->left = l * 16; rect->top = t * 16; rect->right = (r + 1) * 16; rect->bottom = (b + 1) * 16; if (rect->right > nWidth) rect->right = nWidth; if (rect->bottom > nHeight) rect->bottom = nHeight; #ifdef WITH_DEBUG_SHADOW_CAPTURE char *col_str = calloc(ncol + 1, sizeof(char)); if (!col_str) { WLog_ERR(TAG, "calloc failed!"); return 1; } for (tx = 0; tx < ncol; tx++) sprintf(&col_str[tx], "-"); WLog_INFO(TAG, "%s", col_str); for (tx = 0; tx < ncol; tx++) sprintf(&col_str[tx], "%c", cols[tx] ? 'O' : 'X'); WLog_INFO(TAG, "%s", col_str); for (tx = 0; tx < ncol; tx++) sprintf(&col_str[tx], "-"); WLog_INFO(TAG, "%s", col_str); for (ty = 0; ty < nrow; ty++) { for (tx = 0; tx < ncol; tx++) sprintf(&col_str[tx], "%c", cols[tx] ? 'O' : 'X'); WLog_INFO(TAG, "%s", col_str); WLog_INFO(TAG, "|%s|", rows[ty] ? "O" : "X"); } WLog_INFO(TAG, "left: %d top: %d right: %d bottom: %d ncol: %d nrow: %d", l, t, r, b, ncol, nrow); free(col_str); #endif return 1; }
void gcc_write_server_security_data(wStream* s, rdpMcs* mcs) { CryptoMd5 md5; BYTE* sigData; int expLen, keyLen, sigDataLen; BYTE encryptedSignature[TSSK_KEY_LENGTH]; BYTE signature[sizeof(initial_signature)]; UINT32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen; rdpSettings* settings = mcs->settings; /** * Re: settings->EncryptionLevel: * This is configured/set by the server implementation and serves the same * purpose as the "Encryption Level" setting in the RDP-Tcp configuration * dialog of Microsoft's Remote Desktop Session Host Configuration. * Re: settings->EncryptionMethods: * at this point this setting contains the client's supported encryption * methods we've received in gcc_read_client_security_data() */ if (!settings->UseRdpSecurityLayer) { /* TLS/NLA is used: disable rdp style encryption */ settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } /* verify server encryption level value */ switch (settings->EncryptionLevel) { case ENCRYPTION_LEVEL_NONE: WLog_INFO(TAG, "Active rdp encryption level: NONE"); break; case ENCRYPTION_LEVEL_FIPS: WLog_INFO(TAG, "Active rdp encryption level: FIPS Compliant"); break; case ENCRYPTION_LEVEL_HIGH: WLog_INFO(TAG, "Active rdp encryption level: HIGH"); break; case ENCRYPTION_LEVEL_LOW: WLog_INFO(TAG, "Active rdp encryption level: LOW"); break; case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE: WLog_INFO(TAG, "Active rdp encryption level: CLIENT-COMPATIBLE"); break; default: WLog_ERR(TAG, "Invalid server encryption level 0x%08X", settings->EncryptionLevel); WLog_ERR(TAG, "Switching to encryption level CLIENT-COMPATIBLE"); settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } /* choose rdp encryption method based on server level and client methods */ switch (settings->EncryptionLevel) { case ENCRYPTION_LEVEL_NONE: /* The only valid method is NONE in this case */ settings->EncryptionMethods = ENCRYPTION_METHOD_NONE; break; case ENCRYPTION_LEVEL_FIPS: /* The only valid method is FIPS in this case */ if (!(settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS)) { WLog_WARN(TAG, "client does not support FIPS as required by server configuration"); } settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS; break; case ENCRYPTION_LEVEL_HIGH: /* Maximum key strength supported by the server must be used (128 bit)*/ if (!(settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT)) { WLog_WARN(TAG, "client does not support 128 bit encryption method as required by server configuration"); } settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT; break; case ENCRYPTION_LEVEL_LOW: case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE: /* Maximum key strength supported by the client must be used */ if (settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT) settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT; else if (settings->EncryptionMethods & ENCRYPTION_METHOD_56BIT) settings->EncryptionMethods = ENCRYPTION_METHOD_56BIT; else if (settings->EncryptionMethods & ENCRYPTION_METHOD_40BIT) settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT; else if (settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS) settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS; else { WLog_WARN(TAG, "client has not announced any supported encryption methods"); settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT; } break; default: WLog_ERR(TAG, "internal error: unknown encryption level"); } /* log selected encryption method */ switch (settings->EncryptionMethods) { case ENCRYPTION_METHOD_NONE: WLog_INFO(TAG, "Selected rdp encryption method: NONE"); break; case ENCRYPTION_METHOD_40BIT: WLog_INFO(TAG, "Selected rdp encryption method: 40BIT"); break; case ENCRYPTION_METHOD_56BIT: WLog_INFO(TAG, "Selected rdp encryption method: 56BIT"); break; case ENCRYPTION_METHOD_128BIT: WLog_INFO(TAG, "Selected rdp encryption method: 128BIT"); break; case ENCRYPTION_METHOD_FIPS: WLog_INFO(TAG, "Selected rdp encryption method: FIPS"); break; default: WLog_ERR(TAG, "internal error: unknown encryption method"); } headerLen = 12; keyLen = 0; wPublicKeyBlobLen = 0; serverRandomLen = 0; serverCertLen = 0; if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE) { serverRandomLen = 32; keyLen = settings->RdpServerRsaKey->ModulusLength; expLen = sizeof(settings->RdpServerRsaKey->exponent); wPublicKeyBlobLen = 4; /* magic (RSA1) */ wPublicKeyBlobLen += 4; /* keylen */ wPublicKeyBlobLen += 4; /* bitlen */ wPublicKeyBlobLen += 4; /* datalen */ wPublicKeyBlobLen += expLen; wPublicKeyBlobLen += keyLen; wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */ serverCertLen = 4; /* dwVersion */ serverCertLen += 4; /* dwSigAlgId */ serverCertLen += 4; /* dwKeyAlgId */ serverCertLen += 2; /* wPublicKeyBlobType */ serverCertLen += 2; /* wPublicKeyBlobLen */ serverCertLen += wPublicKeyBlobLen; serverCertLen += 2; /* wSignatureBlobType */ serverCertLen += 2; /* wSignatureBlobLen */ serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */ serverCertLen += 8; /* 8 bytes of zero padding */ headerLen += sizeof(serverRandomLen); headerLen += sizeof(serverCertLen); headerLen += serverRandomLen; headerLen += serverCertLen; } gcc_write_user_data_header(s, SC_SECURITY, headerLen); Stream_Write_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */ Stream_Write_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */ if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE) { return; } Stream_Write_UINT32(s, serverRandomLen); /* serverRandomLen */ Stream_Write_UINT32(s, serverCertLen); /* serverCertLen */ settings->ServerRandomLength = serverRandomLen; settings->ServerRandom = (BYTE*) malloc(serverRandomLen); crypto_nonce(settings->ServerRandom, serverRandomLen); Stream_Write(s, settings->ServerRandom, serverRandomLen); sigData = Stream_Pointer(s); Stream_Write_UINT32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */ Stream_Write_UINT32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */ Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */ Stream_Write_UINT16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */ Stream_Write_UINT16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */ Stream_Write(s, "RSA1", 4); /* magic */ Stream_Write_UINT32(s, keyLen + 8); /* keylen */ Stream_Write_UINT32(s, keyLen * 8); /* bitlen */ Stream_Write_UINT32(s, keyLen - 1); /* datalen */ Stream_Write(s, settings->RdpServerRsaKey->exponent, expLen); Stream_Write(s, settings->RdpServerRsaKey->Modulus, keyLen); Stream_Zero(s, 8); sigDataLen = Stream_Pointer(s) - sigData; Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */ Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */ memcpy(signature, initial_signature, sizeof(initial_signature)); md5 = crypto_md5_init(); if (!md5) { WLog_ERR(TAG, "unable to allocate a md5"); return; } crypto_md5_update(md5, sigData, sigDataLen); crypto_md5_final(md5, signature); crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH, tssk_modulus, tssk_privateExponent, encryptedSignature); Stream_Write(s, encryptedSignature, sizeof(encryptedSignature)); Stream_Zero(s, 8); }
int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port) { int match; int index; char* common_name = NULL; int common_name_length = 0; char** dns_names = 0; int dns_names_count = 0; int* dns_names_lengths = NULL; BOOL certificate_status; BOOL hostname_match = FALSE; BOOL verification_status = FALSE; rdpCertificateData* certificate_data; freerdp* instance = (freerdp*) tls->settings->instance; DWORD length; BYTE* pemCert; if (!tls_extract_pem(cert, &pemCert, &length)) return -1; /* Check, if we already accepted this key. */ if (is_accepted(tls, pemCert, length)) { free(pemCert); return 1; } if (tls->settings->ExternalCertificateManagement) { int status = -1; if (instance->VerifyX509Certificate) status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, tls->isGatewayTransport | is_redirected(tls) ? 2 : 0); else WLog_ERR(TAG, "No VerifyX509Certificate callback registered!"); if (status > 0) { accept_cert(tls, pemCert, length); } else if (status < 0) { WLog_ERR(TAG, "VerifyX509Certificate failed: (length = %d) status: [%d] %s", length, status, pemCert); free(pemCert); return -1; } else free(pemCert); return (status == 0) ? 0 : 1; } /* ignore certificate verification if user explicitly required it (discouraged) */ if (tls->settings->IgnoreCertificate) { free(pemCert); return 1; /* success! */ } if (!tls->isGatewayTransport && tls->settings->AuthenticationLevel == 0) { free(pemCert); return 1; /* success! */ } /* if user explicitly specified a certificate name, use it instead of the hostname */ if (!tls->isGatewayTransport && tls->settings->CertificateName) hostname = tls->settings->CertificateName; /* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */ certificate_status = x509_verify_certificate(cert, tls->certificate_store->path); /* verify certificate name match */ certificate_data = crypto_get_certificate_data(cert->px509, hostname, port); /* extra common name and alternative names */ common_name = crypto_cert_subject_common_name(cert->px509, &common_name_length); dns_names = crypto_cert_get_dns_names(cert->px509, &dns_names_count, &dns_names_lengths); /* compare against common name */ if (common_name) { if (tls_match_hostname(common_name, common_name_length, hostname)) hostname_match = TRUE; } /* compare against alternative names */ if (dns_names) { for (index = 0; index < dns_names_count; index++) { if (tls_match_hostname(dns_names[index], dns_names_lengths[index], hostname)) { hostname_match = TRUE; break; } } } /* if the certificate is valid and the certificate name matches, verification succeeds */ if (certificate_status && hostname_match) verification_status = TRUE; /* success! */ /* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */ if (!certificate_status || !hostname_match) { char* issuer; char* subject; char* fingerprint; DWORD accept_certificate = 0; issuer = crypto_cert_issuer(cert->px509); subject = crypto_cert_subject(cert->px509); fingerprint = crypto_cert_fingerprint(cert->px509); /* search for matching entry in known_hosts file */ match = certificate_data_match(tls->certificate_store, certificate_data); if (match == 1) { /* no entry was found in known_hosts file, prompt user for manual verification */ if (!hostname_match) tls_print_certificate_name_mismatch_error( hostname, port, common_name, dns_names, dns_names_count); /* Automatically accept certificate on first use */ if (tls->settings->AutoAcceptCertificate) { WLog_INFO(TAG, "No certificate stored, automatically accepting."); accept_certificate = 1; } else if (instance->VerifyCertificate) { accept_certificate = instance->VerifyCertificate( instance, common_name, subject, issuer, fingerprint, !hostname_match); } switch (accept_certificate) { case 1: /* user accepted certificate, add entry in known_hosts file */ verification_status = certificate_data_print(tls->certificate_store, certificate_data); break; case 2: /* user did accept temporaty, do not add to known hosts file */ verification_status = TRUE; break; default: /* user did not accept, abort and do not add entry in known_hosts file */ verification_status = FALSE; /* failure! */ break; } } else if (match == -1) { char* old_subject = NULL; char* old_issuer = NULL; char* old_fingerprint = NULL; /* entry was found in known_hosts file, but fingerprint does not match. ask user to use it */ tls_print_certificate_error(hostname, port, fingerprint, tls->certificate_store->file); if (!certificate_get_stored_data(tls->certificate_store, certificate_data, &old_subject, &old_issuer, &old_fingerprint)) WLog_WARN(TAG, "Failed to get certificate entry for %s:%d", hostname, port); if (instance->VerifyChangedCertificate) { accept_certificate = instance->VerifyChangedCertificate( instance, common_name, subject, issuer, fingerprint, old_subject, old_issuer, old_fingerprint); } free(old_subject); free(old_issuer); free(old_fingerprint); switch (accept_certificate) { case 1: /* user accepted certificate, add entry in known_hosts file */ verification_status = certificate_data_replace(tls->certificate_store, certificate_data); break; case 2: /* user did accept temporaty, do not add to known hosts file */ verification_status = TRUE; break; default: /* user did not accept, abort and do not add entry in known_hosts file */ verification_status = FALSE; /* failure! */ break; } } else if (match == 0) verification_status = TRUE; /* success! */ free(issuer); free(subject); free(fingerprint); } certificate_data_free(certificate_data); free(common_name); if (dns_names) crypto_cert_dns_names_free(dns_names_count, dns_names_lengths, dns_names); if (verification_status > 0) { accept_cert(tls, pemCert, length); } else { free(pemCert); } return (verification_status == 0) ? 0 : 1; }
static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char* method, const char* peerAddress, int timeout, BOOL* rpcFallback) { HttpResponse* response = NULL; int statusCode; int bodyLength; if (!rdg_tls_connect(rdg, tls, peerAddress, timeout)) return FALSE; if (rdg->extAuth == HTTP_EXTENDED_AUTH_NONE) { if (!rdg_ntlm_init(rdg, tls)) return FALSE; if (!rdg_send_http_request(rdg, tls, method, NULL)) return FALSE; response = http_response_recv(tls); if (!response) return FALSE; if (response->StatusCode == HTTP_STATUS_NOT_FOUND) { WLog_INFO(TAG, "RD Gateway does not support HTTP transport."); if (rpcFallback) *rpcFallback = TRUE; http_response_free(response); return FALSE; } if (!rdg_handle_ntlm_challenge(rdg->ntlm, response)) { http_response_free(response); return FALSE; } http_response_free(response); } if (!rdg_send_http_request(rdg, tls, method, NULL)) return FALSE; ntlm_free(rdg->ntlm); rdg->ntlm = NULL; response = http_response_recv(tls); if (!response) return FALSE; statusCode = response->StatusCode; bodyLength = response->BodyLength; http_response_free(response); WLog_DBG(TAG, "%s authorization result: %d", method, statusCode); if (statusCode != HTTP_STATUS_OK) return FALSE; if (strcmp(method, "RDG_OUT_DATA") == 0) { if (!rdg_skip_seed_payload(tls, bodyLength)) return FALSE; } else { if (!rdg_send_http_request(rdg, tls, method, "chunked")) return FALSE; } return TRUE; }
rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* settings) { rdpNla* nla = (rdpNla*) calloc(1, sizeof(rdpNla)); if (!nla) return NULL; nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY)); if (!nla->identity) { free (nla); return NULL; } nla->instance = instance; nla->settings = settings; nla->server = settings->ServerMode; nla->transport = transport; nla->sendSeqNum = 0; nla->recvSeqNum = 0; nla->version = 3; ZeroMemory(&nla->negoToken, sizeof(SecBuffer)); ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer)); ZeroMemory(&nla->authInfo, sizeof(SecBuffer)); SecInvalidateHandle(&nla->context); if (nla->server) { LONG status; HKEY hKey; DWORD dwType; DWORD dwSize; status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, SERVER_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey); if (status != ERROR_SUCCESS) return nla; status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType, NULL, &dwSize); if (status != ERROR_SUCCESS) { RegCloseKey(hKey); return nla; } nla->SspiModule = (LPTSTR) malloc(dwSize + sizeof(TCHAR)); if (!nla->SspiModule) { RegCloseKey(hKey); free(nla); return NULL; } status = RegQueryValueEx(hKey, _T("SspiModule"), NULL, &dwType, (BYTE*) nla->SspiModule, &dwSize); if (status == ERROR_SUCCESS) WLog_INFO(TAG, "Using SSPI Module: %s", nla->SspiModule); RegCloseKey(hKey); } return nla; }
void profiler_print_footer() { WLog_INFO(TAG, "|--------------------------------------------------------------------|"); }
int win_shadow_surface_copy(winShadowSubsystem* subsystem) { int x, y; int width; int height; int count; int status = 1; int nDstStep = 0; BYTE* pDstData = NULL; rdpShadowServer* server; rdpShadowSurface* surface; RECTANGLE_16 surfaceRect; RECTANGLE_16 invalidRect; const RECTANGLE_16* extents; server = subsystem->server; surface = server->surface; if (ArrayList_Count(server->clients) < 1) { region16_clear(&(subsystem->invalidRegion)); return 1; } surfaceRect.left = surface->x; surfaceRect.top = surface->y; surfaceRect.right = surface->x + surface->width; surfaceRect.bottom = surface->y + surface->height; region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect); if (region16_is_empty(&(subsystem->invalidRegion))) return 1; extents = region16_extents(&(subsystem->invalidRegion)); CopyMemory(&invalidRect, extents, sizeof(RECTANGLE_16)); shadow_capture_align_clip_rect(&invalidRect, &surfaceRect); x = invalidRect.left; y = invalidRect.top; width = invalidRect.right - invalidRect.left; height = invalidRect.bottom - invalidRect.top; if (0) { x = 0; y = 0; width = surface->width; height = surface->height; } WLog_INFO(TAG, "SurfaceCopy x: %d y: %d width: %d height: %d right: %d bottom: %d", x, y, width, height, x + width, y + height); #if defined(WITH_WDS_API) { rdpGdi* gdi; shwContext* shw; rdpContext* context; shw = subsystem->shw; context = (rdpContext*) shw; gdi = context->gdi; pDstData = gdi->primary_buffer; nDstStep = gdi->width * 4; } #elif defined(WITH_DXGI_1_2) status = win_shadow_dxgi_fetch_frame_data(subsystem, &pDstData, &nDstStep, x, y, width, height); #endif if (status <= 0) return status; freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, x - surface->x, y - surface->y, width, height, pDstData, PIXEL_FORMAT_XRGB32, nDstStep, 0, 0, NULL); ArrayList_Lock(server->clients); count = ArrayList_Count(server->clients); shadow_multiclient_publish_and_wait(subsystem->updateEvent); ArrayList_Unlock(server->clients); region16_clear(&(subsystem->invalidRegion)); return 1; }
void AioSignalHandler(int signum, siginfo_t* siginfo, void* arg) { WLog_INFO("%d", signum); }
static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_address, UINT16 port) { int status; int sockfd; char addr[64]; void* sin_addr; int option_value; char servname[16]; struct addrinfo* ai; struct addrinfo* res; struct addrinfo hints = { 0 }; rdpListener* listener = (rdpListener*) instance->listener; #ifdef _WIN32 u_long arg; #endif hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (!bind_address) hints.ai_flags = AI_PASSIVE; sprintf_s(servname, sizeof(servname), "%d", port); status = getaddrinfo(bind_address, servname, &hints, &res); if (status != 0) { #ifdef _WIN32 WLog_ERR("getaddrinfo error: %s", gai_strerrorA(status)); #else WLog_ERR(TAG, "getaddrinfo"); #endif return FALSE; } for (ai = res; ai && (listener->num_sockfds < 5); ai = ai->ai_next) { if ((ai->ai_family != AF_INET) && (ai->ai_family != AF_INET6)) continue; if (listener->num_sockfds == MAX_LISTENER_HANDLES) { WLog_ERR(TAG, "too many listening sockets"); continue; } sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfd == -1) { WLog_ERR(TAG, "socket"); continue; } if (ai->ai_family == AF_INET) sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr); else sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr); inet_ntop(ai->ai_family, sin_addr, addr, sizeof(addr)); option_value = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &option_value, sizeof(option_value)) == -1) WLog_ERR(TAG, "setsockopt"); #ifndef _WIN32 fcntl(sockfd, F_SETFL, O_NONBLOCK); #else arg = 1; ioctlsocket(sockfd, FIONBIO, &arg); #endif status = _bind((SOCKET) sockfd, ai->ai_addr, ai->ai_addrlen); if (status != 0) { closesocket((SOCKET) sockfd); continue; } status = _listen((SOCKET) sockfd, 10); if (status != 0) { WLog_ERR(TAG, "listen"); closesocket((SOCKET) sockfd); continue; } /* FIXME: these file descriptors do not work on Windows */ listener->sockfds[listener->num_sockfds] = sockfd; listener->events[listener->num_sockfds] = WSACreateEvent(); if (!listener->events[listener->num_sockfds]) { listener->num_sockfds = 0; break; } WSAEventSelect(sockfd, listener->events[listener->num_sockfds], FD_READ | FD_ACCEPT | FD_CLOSE); listener->num_sockfds++; WLog_INFO(TAG, "Listening on %s:%s", addr, servname); } freeaddrinfo(res); return (listener->num_sockfds > 0 ? TRUE : FALSE); }
static BOOL freerdp_listener_open_local(freerdp_listener* instance, const char* path) { #ifndef _WIN32 int status; int sockfd; struct sockaddr_un addr; rdpListener* listener = (rdpListener*) instance->listener; HANDLE hevent; if (listener->num_sockfds == MAX_LISTENER_HANDLES) { WLog_ERR(TAG, "too many listening sockets"); return FALSE; } sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sockfd == -1) { WLog_ERR(TAG, "socket"); return FALSE; } fcntl(sockfd, F_SETFL, O_NONBLOCK); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, path, sizeof(addr.sun_path)); unlink(path); status = _bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)); if (status != 0) { WLog_ERR(TAG, "bind"); closesocket((SOCKET) sockfd); return FALSE; } status = _listen(sockfd, 10); if (status != 0) { WLog_ERR(TAG, "listen"); closesocket((SOCKET) sockfd); return FALSE; } hevent = CreateFileDescriptorEvent(NULL, FALSE, FALSE, sockfd, WINPR_FD_READ); if (!hevent) { WLog_ERR(TAG, "failed to create sockfd event"); closesocket((SOCKET) sockfd); return FALSE; } listener->sockfds[listener->num_sockfds] = sockfd; listener->events[listener->num_sockfds] = hevent; listener->num_sockfds++; WLog_INFO(TAG, "Listening on socket %s.", addr.sun_path); return TRUE; #else return TRUE; #endif }
void rdp_print_redirection_flags(UINT32 flags) { WLog_INFO(TAG, "redirectionFlags = {"); if (flags & LB_TARGET_NET_ADDRESS) WLog_INFO(TAG, "\tLB_TARGET_NET_ADDRESS"); if (flags & LB_LOAD_BALANCE_INFO) WLog_INFO(TAG, "\tLB_LOAD_BALANCE_INFO"); if (flags & LB_USERNAME) WLog_INFO(TAG, "\tLB_USERNAME"); if (flags & LB_DOMAIN) WLog_INFO(TAG, "\tLB_DOMAIN"); if (flags & LB_PASSWORD) WLog_INFO(TAG, "\tLB_PASSWORD"); if (flags & LB_DONTSTOREUSERNAME) WLog_INFO(TAG, "\tLB_DONTSTOREUSERNAME"); if (flags & LB_SMARTCARD_LOGON) WLog_INFO(TAG, "\tLB_SMARTCARD_LOGON"); if (flags & LB_NOREDIRECT) WLog_INFO(TAG, "\tLB_NOREDIRECT"); if (flags & LB_TARGET_FQDN) WLog_INFO(TAG, "\tLB_TARGET_FQDN"); if (flags & LB_TARGET_NETBIOS_NAME) WLog_INFO(TAG, "\tLB_TARGET_NETBIOS_NAME"); if (flags & LB_TARGET_NET_ADDRESSES) WLog_INFO(TAG, "\tLB_TARGET_NET_ADDRESSES"); if (flags & LB_CLIENT_TSV_URL) WLog_INFO(TAG, "\tLB_CLIENT_TSV_URL"); if (flags & LB_SERVER_TSV_CAPABLE) WLog_INFO(TAG, "\tLB_SERVER_TSV_CAPABLE"); WLog_INFO(TAG, "}"); }
static void shw_OnConnectionResultEventHandler(void* context, ConnectionResultEventArgs* e) { shwContext* shw = (shwContext*) context; WLog_INFO(TAG, "OnConnectionResult: %d", e->result); }
BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s) { BOOL status; rdpSettings* settings = rdp->settings; rdpNego *nego = rdp->nego; transport_set_blocking_mode(rdp->transport, TRUE); if (!nego_read_request(nego, s)) return FALSE; nego->selected_protocol = 0; WLog_INFO(TAG, "Client Security: NLA:%d TLS:%d RDP:%d", (nego->requested_protocols & PROTOCOL_NLA) ? 1 : 0, (nego->requested_protocols & PROTOCOL_TLS) ? 1 : 0, (nego->requested_protocols == PROTOCOL_RDP) ? 1 : 0 ); WLog_INFO(TAG, "Server Security: NLA:%d TLS:%d RDP:%d", settings->NlaSecurity, settings->TlsSecurity, settings->RdpSecurity); if ((settings->NlaSecurity) && (nego->requested_protocols & PROTOCOL_NLA)) { nego->selected_protocol = PROTOCOL_NLA; } else if ((settings->TlsSecurity) && (nego->requested_protocols & PROTOCOL_TLS)) { nego->selected_protocol = PROTOCOL_TLS; } else if ((settings->RdpSecurity) && (nego->selected_protocol == PROTOCOL_RDP)) { nego->selected_protocol = PROTOCOL_RDP; } else { WLog_ERR(TAG, "Protocol security negotiation failure"); } WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d", (nego->selected_protocol & PROTOCOL_NLA) ? 1 : 0, (nego->selected_protocol & PROTOCOL_TLS) ? 1 : 0, (nego->selected_protocol == PROTOCOL_RDP) ? 1: 0 ); if (!nego_send_negotiation_response(nego)) return FALSE; status = FALSE; if (nego->selected_protocol & PROTOCOL_NLA) status = transport_accept_nla(rdp->transport); else if (nego->selected_protocol & PROTOCOL_TLS) status = transport_accept_tls(rdp->transport); else if (nego->selected_protocol == PROTOCOL_RDP) /* 0 */ status = transport_accept_rdp(rdp->transport); if (!status) return FALSE; transport_set_blocking_mode(rdp->transport, FALSE); rdp_server_transition_to_state(rdp, CONNECTION_STATE_NEGO); return TRUE; }
static DWORD WINAPI shw_client_thread(LPVOID arg) { int index; int rcount; int wcount; BOOL bSuccess; void* rfds[32]; void* wfds[32]; int fds_count; HANDLE fds[64]; shwContext* shw; rdpContext* context; rdpChannels* channels; freerdp* instance = (freerdp*) arg; ZeroMemory(rfds, sizeof(rfds)); ZeroMemory(wfds, sizeof(wfds)); context = (rdpContext*) instance->context; shw = (shwContext*) context; bSuccess = freerdp_connect(instance); WLog_INFO(TAG, "freerdp_connect: %d", bSuccess); if (!bSuccess) { ExitThread(0); return 0; } channels = instance->context->channels; while (1) { rcount = 0; wcount = 0; if (!freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get FreeRDP file descriptor"); break; } if (!freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get channels file descriptor"); break; } fds_count = 0; for (index = 0; index < rcount; index++) fds[fds_count++] = rfds[index]; for (index = 0; index < wcount; index++) fds[fds_count++] = wfds[index]; if (MsgWaitForMultipleObjects(fds_count, fds, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED) { WLog_ERR(TAG, "MsgWaitForMultipleObjects failure: 0x%08lX", GetLastError()); break; } if (!freerdp_check_fds(instance)) { WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); break; } if (freerdp_shall_disconnect(instance)) { break; } if (!freerdp_channels_check_fds(channels, instance)) { WLog_ERR(TAG, "Failed to check channels file descriptor"); break; } } freerdp_free(instance); ExitThread(0); return 0; }
BOOL wf_pre_connect(freerdp* instance) { wfContext* wfc; int desktopWidth; int desktopHeight; rdpContext* context; rdpSettings* settings; context = instance->context; wfc = (wfContext*) instance->context; wfc->instance = instance; wfc->codecs = instance->context->codecs; settings = instance->settings; if (settings->ConnectionFile) { if (wfc->connectionRdpFile) { freerdp_client_rdp_file_free(wfc->connectionRdpFile); } wfc->connectionRdpFile = freerdp_client_rdp_file_new(); WLog_INFO(TAG, "Using connection file: %s", settings->ConnectionFile); freerdp_client_parse_rdp_file(wfc->connectionRdpFile, settings->ConnectionFile); freerdp_client_populate_settings_from_rdp_file(wfc->connectionRdpFile, settings); } settings->OsMajorType = OSMAJORTYPE_WINDOWS; settings->OsMinorType = OSMINORTYPE_WINDOWS_NT; settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE; settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE; settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE; settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE; settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE; settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE; settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE; settings->OrderSupport[NEG_LINETO_INDEX] = TRUE; settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE; settings->OrderSupport[NEG_MEMBLT_INDEX] = TRUE; settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE; settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = FALSE; settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE; settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE; settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE; settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; settings->GlyphSupportLevel = GLYPH_SUPPORT_NONE; wfc->fullscreen = settings->Fullscreen; if (wfc->fullscreen) wfc->fs_toggle = 1; wfc->clrconv = (HCLRCONV) malloc(sizeof(CLRCONV)); ZeroMemory(wfc->clrconv, sizeof(CLRCONV)); wfc->clrconv->palette = NULL; wfc->clrconv->alpha = FALSE; instance->context->cache = cache_new(settings); desktopWidth = settings->DesktopWidth; desktopHeight = settings->DesktopHeight; if (wfc->percentscreen > 0) { desktopWidth = (GetSystemMetrics(SM_CXSCREEN) * wfc->percentscreen) / 100; settings->DesktopWidth = desktopWidth; desktopHeight = (GetSystemMetrics(SM_CYSCREEN) * wfc->percentscreen) / 100; settings->DesktopHeight = desktopHeight; } if (wfc->fullscreen) { if (settings->UseMultimon) { desktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN); desktopHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN); } else { desktopWidth = GetSystemMetrics(SM_CXSCREEN); desktopHeight = GetSystemMetrics(SM_CYSCREEN); } } /* FIXME: desktopWidth has a limitation that it should be divisible by 4, * otherwise the screen will crash when connecting to an XP desktop.*/ desktopWidth = (desktopWidth + 3) & (~3); if (desktopWidth != settings->DesktopWidth) { freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, desktopWidth); } if (desktopHeight != settings->DesktopHeight) { freerdp_set_param_uint32(settings, FreeRDP_DesktopHeight, desktopHeight); } if ((settings->DesktopWidth < 64) || (settings->DesktopHeight < 64) || (settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096)) { WLog_ERR(TAG, "invalid dimensions %d %d", settings->DesktopWidth, settings->DesktopHeight); return 1; } freerdp_set_param_uint32(settings, FreeRDP_KeyboardLayout, (int) GetKeyboardLayout(0) & 0x0000FFFF); PubSub_SubscribeChannelConnected(instance->context->pubSub, (pChannelConnectedEventHandler) wf_OnChannelConnectedEventHandler); PubSub_SubscribeChannelDisconnected(instance->context->pubSub, (pChannelDisconnectedEventHandler) wf_OnChannelDisconnectedEventHandler); freerdp_channels_pre_connect(instance->context->channels, instance); return TRUE; }
static void shw_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEventArgs* e) { shwContext* shw = (shwContext*) context; WLog_INFO(TAG, "OnChannelDisconnected: %s", e->name); }
int wf_wasapi_get_device_string(LPWSTR pattern, LPWSTR * deviceStr) { HRESULT hr; IMMDeviceEnumerator *pEnumerator = NULL; IMMDeviceCollection *pCollection = NULL; IMMDevice *pEndpoint = NULL; IPropertyStore *pProps = NULL; LPWSTR pwszID = NULL; unsigned int count, i; CoInitialize(NULL); hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (void **) &pEnumerator); if (FAILED(hr)) { WLog_ERR(TAG, "Failed to cocreate device enumerator"); exit(1); } hr = pEnumerator->lpVtbl->EnumAudioEndpoints(pEnumerator, eCapture, DEVICE_STATE_ACTIVE, &pCollection); if ( FAILED(hr) ) { WLog_ERR(TAG, "Failed to create endpoint collection"); exit(1); } pCollection->lpVtbl->GetCount(pCollection, &count); WLog_INFO(TAG, "Num endpoints: %d", count); if (count == 0) { WLog_ERR(TAG, "No endpoints!"); exit(1); } for (i = 0; i < count; ++i) { PROPVARIANT nameVar; PropVariantInit(&nameVar); hr = pCollection->lpVtbl->Item(pCollection, i, &pEndpoint); if ( FAILED(hr) ) { WLog_ERR(TAG, "Failed to get endpoint %d", i); exit(1); } hr = pEndpoint->lpVtbl->GetId(pEndpoint, &pwszID); if ( FAILED(hr) ) { WLog_ERR(TAG, "Failed to get endpoint ID"); exit(1); } hr = pEndpoint->lpVtbl->OpenPropertyStore(pEndpoint, STGM_READ, &pProps); if ( FAILED(hr) ) { WLog_ERR(TAG, "Failed to open property store"); exit(1); } hr = pProps->lpVtbl->GetValue(pProps, &PKEY_Device_FriendlyName, &nameVar); if ( FAILED(hr) ) { WLog_ERR(TAG, "Failed to get device friendly name"); exit(1); } //do this a more reliable way if (wcscmp(pattern, nameVar.pwszVal) < 0) { unsigned int devStrLen; WLog_INFO(TAG, "Using sound ouput endpoint: [%s] (%s)", nameVar.pwszVal, pwszID); //WLog_INFO(TAG, "matched %d characters", wcscmp(pattern, nameVar.pwszVal); devStrLen = wcslen(pwszID); *deviceStr = (LPWSTR) calloc(1, (devStrLen * 2) + 2); if (!deviceStr) return -1; wcscpy_s(*deviceStr, devStrLen+1, pwszID); } CoTaskMemFree(pwszID); pwszID = NULL; PropVariantClear(&nameVar); pProps->lpVtbl->Release(pProps); pProps = NULL; pEndpoint->lpVtbl->Release(pEndpoint); pEndpoint = NULL; } pCollection->lpVtbl->Release(pCollection); pCollection = NULL; pEnumerator->lpVtbl->Release(pEnumerator); pEnumerator = NULL; CoUninitialize(); return 0; }
int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port) { int match; int index; char* common_name = NULL; int common_name_length = 0; char** alt_names = NULL; int alt_names_count = 0; int* alt_names_lengths = NULL; BOOL certificate_status; BOOL hostname_match = FALSE; BOOL verification_status = FALSE; rdpCertificateData* certificate_data; if (tls->settings->ExternalCertificateManagement) { BIO* bio; int status; int length; int offset; BYTE* pemCert; freerdp* instance = (freerdp*) tls->settings->instance; /** * Don't manage certificates internally, leave it up entirely to the external client implementation */ bio = BIO_new(BIO_s_mem()); if (!bio) { WLog_ERR(TAG, "BIO_new() failure"); return -1; } status = PEM_write_bio_X509(bio, cert->px509); if (status < 0) { WLog_ERR(TAG, "PEM_write_bio_X509 failure: %d", status); return -1; } offset = 0; length = 2048; pemCert = (BYTE*) malloc(length + 1); if (!pemCert) { WLog_ERR(TAG, "error allocating pemCert"); return -1; } status = BIO_read(bio, pemCert, length); if (status < 0) { WLog_ERR(TAG, "failed to read certificate"); return -1; } offset += status; while (offset >= length) { int new_len; BYTE* new_cert; new_len = length * 2; new_cert = (BYTE*) realloc(pemCert, new_len + 1); if (!new_cert) return -1; length = new_len; pemCert = new_cert; status = BIO_read(bio, &pemCert[offset], length); if (status < 0) break; offset += status; } if (status < 0) { WLog_ERR(TAG, "failed to read certificate"); return -1; } length = offset; pemCert[length] = '\0'; status = -1; if (instance->VerifyX509Certificate) status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, tls->isGatewayTransport); else WLog_ERR(TAG, "No VerifyX509Certificate callback registered!"); free(pemCert); BIO_free(bio); if (status < 0) { WLog_ERR(TAG, "VerifyX509Certificate failed: (length = %d) status: [%d] %s", length, status, pemCert); return -1; } return (status == 0) ? 0 : 1; } /* ignore certificate verification if user explicitly required it (discouraged) */ if (tls->settings->IgnoreCertificate) return 1; /* success! */ /* if user explicitly specified a certificate name, use it instead of the hostname */ if (tls->settings->CertificateName) hostname = tls->settings->CertificateName; /* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */ certificate_status = x509_verify_certificate(cert, tls->certificate_store->path); /* verify certificate name match */ certificate_data = crypto_get_certificate_data(cert->px509, hostname, port); /* extra common name and alternative names */ common_name = crypto_cert_subject_common_name(cert->px509, &common_name_length); alt_names = crypto_cert_subject_alt_name(cert->px509, &alt_names_count, &alt_names_lengths); /* compare against common name */ if (common_name) { if (tls_match_hostname(common_name, common_name_length, hostname)) hostname_match = TRUE; } /* compare against alternative names */ if (alt_names) { for (index = 0; index < alt_names_count; index++) { if (tls_match_hostname(alt_names[index], alt_names_lengths[index], hostname)) { hostname_match = TRUE; break; } } } /* if the certificate is valid and the certificate name matches, verification succeeds */ if (certificate_status && hostname_match) verification_status = TRUE; /* success! */ /* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */ if (!certificate_status || !hostname_match) { char* issuer; char* subject; char* fingerprint; freerdp* instance = (freerdp*) tls->settings->instance; DWORD accept_certificate = 0; issuer = crypto_cert_issuer(cert->px509); subject = crypto_cert_subject(cert->px509); fingerprint = crypto_cert_fingerprint(cert->px509); /* search for matching entry in known_hosts file */ match = certificate_data_match(tls->certificate_store, certificate_data); if (match == 1) { /* no entry was found in known_hosts file, prompt user for manual verification */ if (!hostname_match) tls_print_certificate_name_mismatch_error( hostname, port, common_name, alt_names, alt_names_count); /* Automatically accept certificate on first use */ if (tls->settings->AutoAcceptCertificate) { WLog_INFO(TAG, "No certificate stored, automatically accepting."); accept_certificate = 1; } else if (instance->VerifyCertificate) { accept_certificate = instance->VerifyCertificate( instance, common_name, subject, issuer, fingerprint, !hostname_match); } switch (accept_certificate) { case 1: /* user accepted certificate, add entry in known_hosts file */ verification_status = certificate_data_print(tls->certificate_store, certificate_data); break; case 2: /* user did accept temporaty, do not add to known hosts file */ verification_status = TRUE; break; default: /* user did not accept, abort and do not add entry in known_hosts file */ verification_status = FALSE; /* failure! */ break; } } else if (match == -1) { char* old_subject = NULL; char* old_issuer = NULL; char* old_fingerprint = NULL; /* entry was found in known_hosts file, but fingerprint does not match. ask user to use it */ tls_print_certificate_error(hostname, port, fingerprint, tls->certificate_store->file); if (!certificate_get_stored_data(tls->certificate_store, certificate_data, &old_subject, &old_issuer, &old_fingerprint)) WLog_WARN(TAG, "Failed to get certificate entry for %s:%d", hostname, port); if (instance->VerifyChangedCertificate) { accept_certificate = instance->VerifyChangedCertificate( instance, common_name, subject, issuer, fingerprint, old_subject, old_issuer, old_fingerprint); } free(old_subject); free(old_issuer); free(old_fingerprint); switch (accept_certificate) { case 1: /* user accepted certificate, add entry in known_hosts file */ verification_status = certificate_data_replace(tls->certificate_store, certificate_data); break; case 2: /* user did accept temporaty, do not add to known hosts file */ verification_status = TRUE; break; default: /* user did not accept, abort and do not add entry in known_hosts file */ verification_status = FALSE; /* failure! */ break; } } else if (match == 0) verification_status = TRUE; /* success! */ free(issuer); free(subject); free(fingerprint); } certificate_data_free(certificate_data); free(common_name); if (alt_names) crypto_cert_subject_alt_name_free(alt_names_count, alt_names_lengths, alt_names); return (verification_status == 0) ? 0 : 1; }
void PrintRailWindowState(WINDOW_ORDER_INFO* orderInfo, WINDOW_STATE_ORDER* windowState) { if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW) WLog_INFO(TAG, "WindowCreate: WindowId: 0x%04X", orderInfo->windowId); else WLog_INFO(TAG, "WindowUpdate: WindowId: 0x%04X", orderInfo->windowId); WLog_INFO(TAG, "{"); if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_OWNER) { WLog_INFO(TAG, "\tOwnerWindowId: 0x%04X", windowState->ownerWindowId); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_STYLE) { WLog_INFO(TAG, "\tStyle: 0x%04X ExtendedStyle: 0x%04X", windowState->style, windowState->extendedStyle); PrintWindowStyles(windowState->style); PrintExtendedWindowStyles(windowState->extendedStyle); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_SHOW) { WLog_INFO(TAG, "\tShowState: %d", windowState->showState); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_TITLE) { char* title = NULL; ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, windowState->titleInfo.length / 2, &title, 0, NULL, NULL); WLog_INFO(TAG, "\tTitleInfo: %s (length = %d)", title, windowState->titleInfo.length); free(title); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) { WLog_INFO(TAG, "\tClientOffsetX: %d ClientOffsetY: %d", windowState->clientOffsetX, windowState->clientOffsetY); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) { WLog_INFO(TAG, "\tClientAreaWidth: %d ClientAreaHeight: %d", windowState->clientAreaWidth, windowState->clientAreaHeight); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_RP_CONTENT) { WLog_INFO(TAG, "\tRPContent: %d", windowState->RPContent); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_ROOT_PARENT) { WLog_INFO(TAG, "\tRootParentHandle: 0x%04X", windowState->rootParentHandle); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_OFFSET) { WLog_INFO(TAG, "\tWindowOffsetX: %d WindowOffsetY: %d", windowState->windowOffsetX, windowState->windowOffsetY); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) { WLog_INFO(TAG, "\tWindowClientDeltaX: %d WindowClientDeltaY: %d", windowState->windowClientDeltaX, windowState->windowClientDeltaY); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_SIZE) { WLog_INFO(TAG, "\tWindowWidth: %d WindowHeight: %d", windowState->windowWidth, windowState->windowHeight); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_WND_RECTS) { UINT32 index; RECTANGLE_16* rect; WLog_INFO(TAG, "\tnumWindowRects: %d", windowState->numWindowRects); for (index = 0; index < windowState->numWindowRects; index++) { rect = &windowState->windowRects[index]; WLog_INFO(TAG, "\twindowRect[%d]: left: %d top: %d right: %d bottom: %d", index, rect->left, rect->top, rect->right, rect->bottom); } } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VIS_OFFSET) { WLog_INFO(TAG, "\tvisibileOffsetX: %d visibleOffsetY: %d", windowState->visibleOffsetX, windowState->visibleOffsetY); } if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_VISIBILITY) { UINT32 index; RECTANGLE_16* rect; WLog_INFO(TAG, "\tnumVisibilityRects: %d", windowState->numVisibilityRects); for (index = 0; index < windowState->numVisibilityRects; index++) { rect = &windowState->visibilityRects[index]; WLog_INFO(TAG, "\tvisibilityRect[%d]: left: %d top: %d right: %d bottom: %d", index, rect->left, rect->top, rect->right, rect->bottom); } } WLog_INFO(TAG, "}"); }
int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nDstWidth, int nDstHeight, RDPGFX_RECT16* regionRects, int numRegionRects) { int index; int status; int* iStride; BYTE* pDstData; BYTE* pDstPoint; prim_size_t roi; BYTE** pYUVData; int width, height; BYTE* pYUVPoint[3]; RDPGFX_RECT16* rect; primitives_t *prims = primitives_get(); if (!h264) return -1; #if 0 WLog_INFO(TAG, "h264_decompress: pSrcData=%p, SrcSize=%u, pDstData=%p, nDstStep=%d, nDstHeight=%d, numRegionRects=%d", pSrcData, SrcSize, *ppDstData, nDstStep, nDstHeight, numRegionRects); #endif if (!(pDstData = *ppDstData)) return -1; if ((status = h264->subsystem->Decompress(h264, pSrcData, SrcSize)) < 0) return status; pYUVData = h264->pYUVData; iStride = h264->iStride; for (index = 0; index < numRegionRects; index++) { rect = &(regionRects[index]); /* Check, if the ouput rectangle is valid in decoded h264 frame. */ if ((rect->right > h264->width) || (rect->left > h264->width)) return -1; if ((rect->top > h264->height) || (rect->bottom > h264->height)) return -1; /* Check, if the output rectangle is valid in destination buffer. */ if ((rect->right > nDstWidth) || (rect->left > nDstWidth)) return -1; if ((rect->bottom > nDstHeight) || (rect->top > nDstHeight)) return -1; width = rect->right - rect->left; height = rect->bottom - rect->top; pDstPoint = pDstData + rect->top * nDstStep + rect->left * 4; pYUVPoint[0] = pYUVData[0] + rect->top * iStride[0] + rect->left; pYUVPoint[1] = pYUVData[1] + rect->top/2 * iStride[1] + rect->left/2; pYUVPoint[2] = pYUVData[2] + rect->top/2 * iStride[2] + rect->left/2; #if 0 WLog_INFO(TAG, "regionRect: x: %d y: %d width: %d height: %d", rect->left, rect->top, width, height); #endif roi.width = width; roi.height = height; prims->YUV420ToRGB_8u_P3AC4R((const BYTE**) pYUVPoint, iStride, pDstPoint, nDstStep, &roi); } return 1; }
static BOOL tsmf_oss_open(ITSMFAudioDevice* audio, const char* device) { int tmp; TSMFOssAudioDevice* oss = (TSMFOssAudioDevice*)audio; if (oss == NULL || oss->pcm_handle != -1) return FALSE; if (device == NULL) /* Default device. */ { strncpy(oss->dev_name, "/dev/dsp", sizeof(oss->dev_name)); } else { strncpy(oss->dev_name, device, sizeof(oss->dev_name)); } if ((oss->pcm_handle = open(oss->dev_name, O_WRONLY)) < 0) { OSS_LOG_ERR("sound dev open failed", errno); oss->pcm_handle = -1; return FALSE; } #if 0 /* FreeBSD OSS implementation at this moment (2015.03) does not set PCM_CAP_OUTPUT flag. */ tmp = 0; if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETCAPS, &mask) == -1) { OSS_LOG_ERR("SNDCTL_DSP_GETCAPS failed, try ignory", errno); } else if ((mask & PCM_CAP_OUTPUT) == 0) { OSS_LOG_ERR("Device does not supports playback", EOPNOTSUPP); close(oss->pcm_handle); oss->pcm_handle = -1; return FALSE; } #endif tmp = 0; if (ioctl(oss->pcm_handle, SNDCTL_DSP_GETFMTS, &tmp) == -1) { OSS_LOG_ERR("SNDCTL_DSP_GETFMTS failed", errno); close(oss->pcm_handle); oss->pcm_handle = -1; return FALSE; } if ((AFMT_S16_LE & tmp) == 0) { OSS_LOG_ERR("SNDCTL_DSP_GETFMTS - AFMT_S16_LE", EOPNOTSUPP); close(oss->pcm_handle); oss->pcm_handle = -1; return FALSE; } WLog_INFO(TAG, "open: %s", oss->dev_name); return TRUE; }
static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize) { DECODING_STATE state; SBufferInfo sBufferInfo; SSysMEMBuffer* pSystemBuffer; H264_CONTEXT_OPENH264* sys = (H264_CONTEXT_OPENH264*) h264->pSystemData; if (!sys->pDecoder) return -1; /* * Decompress the image. The RDP host only seems to send I420 format. */ h264->pYUVData[0] = NULL; h264->pYUVData[1] = NULL; h264->pYUVData[2] = NULL; ZeroMemory(&sBufferInfo, sizeof(sBufferInfo)); state = (*sys->pDecoder)->DecodeFrame2( sys->pDecoder, pSrcData, SrcSize, h264->pYUVData, &sBufferInfo); /** * Calling DecodeFrame2 twice apparently works around Openh264 issue #1136: * https://github.com/cisco/openh264/issues/1136 * * This is a hack, but it works and it is only necessary for the first frame. */ if (sBufferInfo.iBufferStatus != 1) state = (*sys->pDecoder)->DecodeFrame2(sys->pDecoder, NULL, 0, h264->pYUVData, &sBufferInfo); pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer; #if 0 WLog_INFO(TAG, "h264_decompress: state=%u, pYUVData=[%p,%p,%p], bufferStatus=%d, width=%d, height=%d, format=%d, stride=[%d,%d]", state, h264->pYUVData[0], h264->pYUVData[1], h264->pYUVData[2], sBufferInfo.iBufferStatus, pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iFormat, pSystemBuffer->iStride[0], pSystemBuffer->iStride[1]); #endif if (state != 0) return -1; if (sBufferInfo.iBufferStatus != 1) return -2; if (pSystemBuffer->iFormat != videoFormatI420) return -1; if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2]) return -1; h264->iStride[0] = pSystemBuffer->iStride[0]; h264->iStride[1] = pSystemBuffer->iStride[1]; h264->iStride[2] = pSystemBuffer->iStride[1]; h264->width = pSystemBuffer->iWidth; h264->height = pSystemBuffer->iHeight; return 1; }
BOOL nego_send_negotiation_response(rdpNego* nego) { int length; int bm, em; BOOL status; wStream* s; BYTE flags; rdpSettings* settings; status = TRUE; settings = nego->transport->settings; s = Stream_New(NULL, 512); if (!s) return FALSE; length = TPDU_CONNECTION_CONFIRM_LENGTH; bm = Stream_GetPosition(s); Stream_Seek(s, length); if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO) { UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO); flags = 0; Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE); Stream_Write_UINT8(s, flags); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT32(s, errorCode); length += 8; status = FALSE; } else { flags = EXTENDED_CLIENT_DATA_SUPPORTED; if (settings->SupportGraphicsPipeline) flags |= DYNVC_GFX_PROTOCOL_SUPPORTED; /* RDP_NEG_DATA must be present for TLS, NLA, and RDP */ Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP); Stream_Write_UINT8(s, flags); /* flags */ Stream_Write_UINT16(s, 8); /* RDP_NEG_DATA length (8) */ Stream_Write_UINT32(s, nego->SelectedProtocol); /* selectedProtocol */ length += 8; } em = Stream_GetPosition(s); Stream_SetPosition(s, bm); tpkt_write_header(s, length); tpdu_write_connection_confirm(s, length - 5); Stream_SetPosition(s, em); Stream_SealLength(s); if (transport_write(nego->transport, s) < 0) { Stream_Free(s, TRUE); return FALSE; } Stream_Free(s, TRUE); if (status) { /* update settings with negotiated protocol security */ settings->RequestedProtocols = nego->RequestedProtocols; settings->SelectedProtocol = nego->SelectedProtocol; if (settings->SelectedProtocol == PROTOCOL_RDP) { settings->TlsSecurity = FALSE; settings->NlaSecurity = FALSE; settings->RdpSecurity = TRUE; settings->UseRdpSecurityLayer = TRUE; if (settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE) { /** * If the server implementation did not explicitely set a * encryption level we default to client compatible */ settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } if (settings->LocalConnection) { /** * Note: This hack was firstly introduced in commit 95f5e115 to * disable the unnecessary encryption with peers connecting to * 127.0.0.1 or local unix sockets. * This also affects connections via port tunnels! (e.g. ssh -L) */ WLog_INFO(TAG, "Turning off encryption for local peer with standard rdp security"); settings->UseRdpSecurityLayer = FALSE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } if (!settings->RdpServerRsaKey && !settings->RdpKeyFile) { WLog_ERR(TAG, "Missing server certificate"); return FALSE; } } else if (settings->SelectedProtocol == PROTOCOL_TLS) { settings->TlsSecurity = TRUE; settings->NlaSecurity = FALSE; settings->RdpSecurity = FALSE; settings->UseRdpSecurityLayer = FALSE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } else if (settings->SelectedProtocol == PROTOCOL_NLA) { settings->TlsSecurity = TRUE; settings->NlaSecurity = TRUE; settings->RdpSecurity = FALSE; settings->UseRdpSecurityLayer = FALSE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } } return status; }
BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s) { BOOL status; rdpSettings* settings = rdp->settings; rdpNego *nego = rdp->nego; transport_set_blocking_mode(rdp->transport, TRUE); if (!nego_read_request(nego, s)) return FALSE; nego->SelectedProtocol = 0; WLog_INFO(TAG, "Client Security: NLA:%d TLS:%d RDP:%d", (nego->RequestedProtocols & PROTOCOL_NLA) ? 1 : 0, (nego->RequestedProtocols & PROTOCOL_TLS) ? 1 : 0, (nego->RequestedProtocols == PROTOCOL_RDP) ? 1 : 0 ); WLog_INFO(TAG, "Server Security: NLA:%d TLS:%d RDP:%d", settings->NlaSecurity, settings->TlsSecurity, settings->RdpSecurity); if ((settings->NlaSecurity) && (nego->RequestedProtocols & PROTOCOL_NLA)) { nego->SelectedProtocol = PROTOCOL_NLA; } else if ((settings->TlsSecurity) && (nego->RequestedProtocols & PROTOCOL_TLS)) { nego->SelectedProtocol = PROTOCOL_TLS; } else if ((settings->RdpSecurity) && (nego->RequestedProtocols == PROTOCOL_RDP)) { nego->SelectedProtocol = PROTOCOL_RDP; } else { /* * when here client and server aren't compatible, we select the right * error message to return to the client in the nego failure packet */ nego->SelectedProtocol = PROTOCOL_FAILED_NEGO; if (settings->RdpSecurity) { WLog_ERR(TAG, "server supports only Standard RDP Security"); nego->SelectedProtocol |= SSL_NOT_ALLOWED_BY_SERVER; } else { if (settings->NlaSecurity && !settings->TlsSecurity) { WLog_ERR(TAG, "server supports only NLA Security"); nego->SelectedProtocol |= HYBRID_REQUIRED_BY_SERVER; } else { WLog_ERR(TAG, "server supports only a SSL based Security (TLS or NLA)"); nego->SelectedProtocol |= SSL_REQUIRED_BY_SERVER; } } WLog_ERR(TAG, "Protocol security negotiation failure"); } if (!(nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)) { WLog_INFO(TAG, "Negotiated Security: NLA:%d TLS:%d RDP:%d", (nego->SelectedProtocol & PROTOCOL_NLA) ? 1 : 0, (nego->SelectedProtocol & PROTOCOL_TLS) ? 1 : 0, (nego->SelectedProtocol == PROTOCOL_RDP) ? 1: 0 ); } if (!nego_send_negotiation_response(nego)) return FALSE; status = FALSE; if (nego->SelectedProtocol & PROTOCOL_NLA) status = transport_accept_nla(rdp->transport); else if (nego->SelectedProtocol & PROTOCOL_TLS) status = transport_accept_tls(rdp->transport); else if (nego->SelectedProtocol == PROTOCOL_RDP) /* 0 */ status = transport_accept_rdp(rdp->transport); if (!status) return FALSE; transport_set_blocking_mode(rdp->transport, FALSE); rdp_server_transition_to_state(rdp, CONNECTION_STATE_NEGO); return TRUE; }