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; }
BOOL license_read_license_request_packet(rdpLicense* license, wStream* s) { /* ServerRandom (32 bytes) */ if (Stream_GetRemainingLength(s) < 32) return FALSE; Stream_Read(s, license->ServerRandom, 32); /* ProductInfo */ if (!license_read_product_info(s, license->ProductInfo)) return FALSE; /* KeyExchangeList */ if (!license_read_binary_blob(s, license->KeyExchangeList)) return FALSE; /* ServerCertificate */ if (!license_read_binary_blob(s, license->ServerCertificate)) return FALSE; /* ScopeList */ if (!license_read_scope_list(s, license->ScopeList)) return FALSE; /* Parse Server Certificate */ if (!certificate_read_server_certificate(license->certificate, license->ServerCertificate->data, license->ServerCertificate->length)) return FALSE; license_generate_keys(license); license_generate_hwid(license); license_encrypt_premaster_secret(license); #ifdef WITH_DEBUG_LICENSE WLog_DBG(TAG, "ServerRandom:"); winpr_HexDump(TAG, WLOG_DEBUG, license->ServerRandom, 32); license_print_product_info(license->ProductInfo); license_print_scope_list(license->ScopeList); #endif return TRUE; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) { CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataResponse"); if (!context->custom) { WLog_ERR(TAG, "context->custom not set!"); return ERROR_INTERNAL_ERROR; } formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE; formatDataResponse.msgFlags = msgFlags; formatDataResponse.dataLen = dataLen; formatDataResponse.requestedFormatData = NULL; if (dataLen) { formatDataResponse.requestedFormatData = (BYTE*) malloc(dataLen); if (!formatDataResponse.requestedFormatData) { WLog_ERR(TAG, "malloc failed!"); return CHANNEL_RC_NO_MEMORY; } Stream_Read(s, formatDataResponse.requestedFormatData, dataLen); } IFCALLRET(context->ServerFormatDataResponse, error, context, &formatDataResponse); if (error) WLog_ERR(TAG, "ServerFormatDataResponse failed with error %lu!", error); free(formatDataResponse.requestedFormatData); return error; }
void guac_rdpsnd_wave_info_handler(guac_rdpsndPlugin* rdpsnd, wStream* input_stream, guac_rdpsnd_pdu_header* header) { int format; /* Get associated client data */ guac_client* client = rdpsnd->client; guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; /* Get audio stream from client data */ guac_audio_stream* audio = rdp_client->audio; /* Read wave information */ Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp); Stream_Read_UINT16(input_stream, format); Stream_Read_UINT8(input_stream, rdpsnd->waveinfo_block_number); Stream_Seek(input_stream, 3); Stream_Read(input_stream, rdpsnd->initial_wave_data, 4); /* * Size of incoming wave data is equal to the body size field of this * header, less the size of a WaveInfo PDU (not including the header), * thus body_size - 12. */ rdpsnd->incoming_wave_size = header->body_size - 12; /* Read wave in next iteration */ rdpsnd->next_pdu_is_wave = TRUE; /* Reset audio stream if format has changed */ if (audio != NULL) guac_audio_stream_reset(audio, NULL, rdpsnd->formats[format].rate, rdpsnd->formats[format].channels, rdpsnd->formats[format].bps); }
BOOL gcc_read_client_network_data(wStream* s, rdpSettings* settings, UINT16 blockLength) { int i; if (blockLength < 4) return FALSE; Stream_Read_UINT32(s, settings->ChannelCount); /* channelCount */ if (blockLength < 4 + settings->ChannelCount * 12) return FALSE; if (settings->ChannelCount > 16) return FALSE; /* channelDefArray */ for (i = 0; i < settings->ChannelCount; i++) { /* CHANNEL_DEF */ Stream_Read(s, settings->ChannelDefArray[i].Name, 8); /* name (8 bytes) */ Stream_Read_UINT32(s, settings->ChannelDefArray[i].options); /* options (4 bytes) */ settings->ChannelDefArray[i].ChannelId = MCS_GLOBAL_CHANNEL_ID + 1 + i; } return TRUE; }
BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info) { wStream* s; int length; BYTE padding; UINT32 version; int modulus_length; int exponent_length; int error = 0; if (!cert || !info) return FALSE; memset(info, 0, sizeof(rdpCertInfo)); s = Stream_New(cert->data, cert->length); if (!s) return FALSE; info->Modulus = 0; if (!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */ goto error1; error++; if (!ber_read_sequence_tag(s, &length)) /* TBSCertificate (SEQUENCE) */ goto error1; error++; if (!ber_read_contextual_tag(s, 0, &length, TRUE)) /* Explicit Contextual Tag [0] */ goto error1; error++; if (!ber_read_integer(s, &version)) /* version (INTEGER) */ goto error1; error++; version++; /* serialNumber */ if (!ber_read_integer(s, NULL)) /* CertificateSerialNumber (INTEGER) */ goto error1; error++; /* signature */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; /* issuer */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */ goto error1; error++; /* validity */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Validity (SEQUENCE) */ goto error1; error++; /* subject */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* Name (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo */ if (!ber_read_sequence_tag(s, &length)) /* SubjectPublicKeyInfo (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo::AlgorithmIdentifier */ if (!ber_read_sequence_tag(s, &length) || !Stream_SafeSeek(s, length)) /* AlgorithmIdentifier (SEQUENCE) */ goto error1; error++; /* subjectPublicKeyInfo::subjectPublicKey */ if (!ber_read_bit_string(s, &length, &padding)) /* BIT_STRING */ goto error1; error++; /* RSAPublicKey (SEQUENCE) */ if (!ber_read_sequence_tag(s, &length)) /* SEQUENCE */ goto error1; error++; if (!ber_read_integer_length(s, &modulus_length)) /* modulus (INTEGER) */ goto error1; error++; /* skip zero padding, if any */ do { if (Stream_GetRemainingLength(s) < 1) goto error1; Stream_Peek_UINT8(s, padding); if (padding == 0) { if (!Stream_SafeSeek(s, 1)) goto error1; modulus_length--; } } while (padding == 0); error++; if (((int) Stream_GetRemainingLength(s)) < modulus_length) goto error1; info->ModulusLength = modulus_length; info->Modulus = (BYTE*) malloc(info->ModulusLength); if (!info->Modulus) goto error1; Stream_Read(s, info->Modulus, info->ModulusLength); error++; if (!ber_read_integer_length(s, &exponent_length)) /* publicExponent (INTEGER) */ goto error2; error++; if ((((int) Stream_GetRemainingLength(s)) < exponent_length) || (exponent_length > 4)) goto error2; Stream_Read(s, &info->exponent[4 - exponent_length], exponent_length); crypto_reverse(info->Modulus, info->ModulusLength); crypto_reverse(info->exponent, 4); Stream_Free(s, FALSE); return TRUE; error2: free(info->Modulus); info->Modulus = 0; error1: WLog_ERR(TAG, "error reading when reading certificate: part=%s error=%d", certificate_read_errors[error], error); Stream_Free(s, FALSE); return FALSE; }
BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) { UINT16 flags; UINT16 length; rdpRedirection* redirection = rdp->redirection; if (Stream_GetRemainingLength(s) < 12) return -1; Stream_Read_UINT16(s, flags); /* flags (2 bytes) */ Stream_Read_UINT16(s, length); /* length (2 bytes) */ Stream_Read_UINT32(s, redirection->sessionID); /* sessionID (4 bytes) */ Stream_Read_UINT32(s, redirection->flags); /* redirFlags (4 bytes) */ WLog_Print(redirection->log, WLOG_DEBUG, "flags: 0x%04X, redirFlags: 0x%04X length: %d, sessionID: 0x%08X", flags, redirection->flags, length, redirection->sessionID); #ifdef WITH_DEBUG_REDIR rdp_print_redirection_flags(redirection->flags); #endif if (redirection->flags & LB_TARGET_NET_ADDRESS) { if (!rdp_redirection_read_string(s, &(redirection->TargetNetAddress))) return -1; } if (redirection->flags & LB_LOAD_BALANCE_INFO) { if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, redirection->LoadBalanceInfoLength); if (Stream_GetRemainingLength(s) < redirection->LoadBalanceInfoLength) return -1; redirection->LoadBalanceInfo = (BYTE*) malloc(redirection->LoadBalanceInfoLength); Stream_Read(s, redirection->LoadBalanceInfo, redirection->LoadBalanceInfoLength); #ifdef WITH_DEBUG_REDIR DEBUG_REDIR("loadBalanceInfo:"); winpr_HexDump(redirection->LoadBalanceInfo, redirection->LoadBalanceInfoLength); #endif } if (redirection->flags & LB_USERNAME) { if (!rdp_redirection_read_string(s, &(redirection->Username))) return -1; WLog_Print(redirection->log, WLOG_DEBUG, "Username: %s", redirection->Username); } if (redirection->flags & LB_DOMAIN) { if (!rdp_redirection_read_string(s, &(redirection->Domain))) return FALSE; WLog_Print(redirection->log, WLOG_DEBUG, "Domain: %s", redirection->Domain); } if (redirection->flags & LB_PASSWORD) { /* Note: length (hopefully) includes double zero termination */ if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, redirection->PasswordLength); redirection->Password = (BYTE*) malloc(redirection->PasswordLength); Stream_Read(s, redirection->Password, redirection->PasswordLength); #ifdef WITH_DEBUG_REDIR DEBUG_REDIR("PasswordCookie:"); winpr_HexDump(redirection->Password, redirection->PasswordLength); #endif } if (redirection->flags & LB_TARGET_FQDN) { if (!rdp_redirection_read_string(s, &(redirection->TargetFQDN))) return -1; WLog_Print(redirection->log, WLOG_DEBUG, "TargetFQDN: %s", redirection->TargetFQDN); } if (redirection->flags & LB_TARGET_NETBIOS_NAME) { if (!rdp_redirection_read_string(s, &(redirection->TargetNetBiosName))) return -1; WLog_Print(redirection->log, WLOG_DEBUG, "TargetNetBiosName: %s", redirection->TargetNetBiosName); } if (redirection->flags & LB_CLIENT_TSV_URL) { if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, redirection->TsvUrlLength); if (Stream_GetRemainingLength(s) < redirection->TsvUrlLength) return -1; redirection->TsvUrl = (BYTE*) malloc(redirection->TsvUrlLength); Stream_Read(s, redirection->TsvUrl, redirection->TsvUrlLength); #ifdef WITH_DEBUG_REDIR DEBUG_REDIR("TsvUrl:"); winpr_HexDump(redirection->TsvUrl, redirection->TsvUrlLength); #endif } if (redirection->flags & LB_TARGET_NET_ADDRESSES) { int i; UINT32 count; UINT32 targetNetAddressesLength; if (Stream_GetRemainingLength(s) < 8) return -1; Stream_Read_UINT32(s, targetNetAddressesLength); Stream_Read_UINT32(s, redirection->TargetNetAddressesCount); count = redirection->TargetNetAddressesCount; redirection->TargetNetAddresses = (char**) malloc(count * sizeof(char*)); ZeroMemory(redirection->TargetNetAddresses, count * sizeof(char*)); WLog_Print(redirection->log, WLOG_DEBUG, "TargetNetAddressesCount: %d", redirection->TargetNetAddressesCount); for (i = 0; i < (int) count; i++) { if (!rdp_redirection_read_string(s, &(redirection->TargetNetAddresses[i]))) return FALSE; WLog_Print(redirection->log, WLOG_DEBUG, "TargetNetAddresses[%d]: %s", i, redirection->TargetNetAddresses[i]); } } if (!Stream_SafeSeek(s, 8)) /* pad (8 bytes) */ return -1; if (redirection->flags & LB_NOREDIRECT) return 0; return 1; }
BOOL gcc_read_server_security_data(wStream* s, rdpMcs* mcs) { BYTE* data; UINT32 length; rdpSettings* settings = mcs->settings; BOOL validCryptoConfig = FALSE; UINT32 serverEncryptionMethod; if (Stream_GetRemainingLength(s) < 8) return FALSE; Stream_Read_UINT32(s, serverEncryptionMethod); /* encryptionMethod */ Stream_Read_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */ /* Only accept valid/known encryption methods */ switch (serverEncryptionMethod) { case ENCRYPTION_METHOD_NONE: WLog_DBG(TAG, "Server rdp encryption method: NONE"); break; case ENCRYPTION_METHOD_40BIT: WLog_DBG(TAG, "Server rdp encryption method: 40BIT"); break; case ENCRYPTION_METHOD_56BIT: WLog_DBG(TAG, "Server rdp encryption method: 56BIT"); break; case ENCRYPTION_METHOD_128BIT: WLog_DBG(TAG, "Server rdp encryption method: 128BIT"); break; case ENCRYPTION_METHOD_FIPS: WLog_DBG(TAG, "Server rdp encryption method: FIPS"); break; default: WLog_ERR(TAG, "Received unknown encryption method %08X", serverEncryptionMethod); return FALSE; } if (settings->UseRdpSecurityLayer && !(settings->EncryptionMethods & serverEncryptionMethod)) { WLog_WARN(TAG, "Server uses non-advertised encryption method 0x%08X", serverEncryptionMethod); /* FIXME: Should we return FALSE; in this case ?? */ } settings->EncryptionMethods = serverEncryptionMethod; /* Verify encryption level/method combinations according to MS-RDPBCGR Section 5.3.2 */ switch (settings->EncryptionLevel) { case ENCRYPTION_LEVEL_NONE: if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE) { validCryptoConfig = TRUE; } break; case ENCRYPTION_LEVEL_FIPS: if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { validCryptoConfig = TRUE; } break; case ENCRYPTION_LEVEL_LOW: case ENCRYPTION_LEVEL_HIGH: case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE: if (settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT || settings->EncryptionMethods == ENCRYPTION_METHOD_56BIT || settings->EncryptionMethods == ENCRYPTION_METHOD_128BIT || settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { validCryptoConfig = TRUE; } break; default: WLog_ERR(TAG, "Received unknown encryption level %08X", settings->EncryptionLevel); } if (!validCryptoConfig) { WLog_ERR(TAG, "Received invalid cryptographic configuration (level=0x%08X method=0x%08X)", settings->EncryptionLevel, settings->EncryptionMethods); return FALSE; } if (settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE) { /* serverRandomLen and serverCertLen must not be present */ settings->UseRdpSecurityLayer = FALSE; return TRUE; } if (Stream_GetRemainingLength(s) < 8) return FALSE; Stream_Read_UINT32(s, settings->ServerRandomLength); /* serverRandomLen */ Stream_Read_UINT32(s, settings->ServerCertificateLength); /* serverCertLen */ if (Stream_GetRemainingLength(s) < settings->ServerRandomLength + settings->ServerCertificateLength) return FALSE; if ((settings->ServerRandomLength <= 0) || (settings->ServerCertificateLength <= 0)) return FALSE; /* serverRandom */ settings->ServerRandom = (BYTE*) malloc(settings->ServerRandomLength); if (!settings->ServerRandom) return FALSE; Stream_Read(s, settings->ServerRandom, settings->ServerRandomLength); /* serverCertificate */ settings->ServerCertificate = (BYTE*) malloc(settings->ServerCertificateLength); if (!settings->ServerCertificate) return FALSE; Stream_Read(s, settings->ServerCertificate, settings->ServerCertificateLength); certificate_free(settings->RdpServerCertificate); settings->RdpServerCertificate = certificate_new(); if (!settings->RdpServerCertificate) return FALSE; data = settings->ServerCertificate; length = settings->ServerCertificateLength; return certificate_read_server_certificate(settings->RdpServerCertificate, data, length); }
int nla_decode_ts_request(rdpNla* nla, wStream* s) { int length; /* TSRequest */ if (!ber_read_sequence_tag(s, &length) || !ber_read_contextual_tag(s, 0, &length, TRUE) || !ber_read_integer(s, &nla->version)) { return -1; } /* [1] negoTokens (NegoData) */ if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE) { if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */ !ber_read_sequence_tag(s, &length) || /* NegoDataItem */ !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */ !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ ((int) Stream_GetRemainingLength(s)) < length) { return -1; } if (!sspi_SecBufferAlloc(&nla->negoToken, length)) return -1; Stream_Read(s, nla->negoToken.pvBuffer, length); nla->negoToken.cbBuffer = length; } /* [2] authInfo (OCTET STRING) */ if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE) { if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ ((int) Stream_GetRemainingLength(s)) < length) return -1; if (!sspi_SecBufferAlloc(&nla->authInfo, length)) return -1; Stream_Read(s, nla->authInfo.pvBuffer, length); nla->authInfo.cbBuffer = length; } /* [3] pubKeyAuth (OCTET STRING) */ if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE) { if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ ((int) Stream_GetRemainingLength(s)) < length) return -1; if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length)) return -1; Stream_Read(s, nla->pubKeyAuth.pvBuffer, length); nla->pubKeyAuth.cbBuffer = length; } /* [4] errorCode (INTEGER) */ if (nla->version >= 3) { if (ber_read_contextual_tag(s, 4, &length, TRUE) != FALSE) { if (!ber_read_integer(s, &nla->errorCode)) return -1; } } return 1; }
BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) { BYTE* client_random = NULL; BYTE* crypt_client_random = NULL; UINT32 rand_len, key_len; UINT16 channel_id, length, sec_flags; BYTE* mod; BYTE* priv_exp; BOOL ret = FALSE; if (!rdp->settings->DisableEncryption) { /* No RDP Security. */ return TRUE; } if (!rdp_read_header(rdp, s, &length, &channel_id)) { WLog_ERR(TAG, "invalid RDP header"); return FALSE; } if (!rdp_read_security_header(s, &sec_flags)) { WLog_ERR(TAG, "invalid security header"); return FALSE; } if ((sec_flags & SEC_EXCHANGE_PKT) == 0) { WLog_ERR(TAG, "missing SEC_EXCHANGE_PKT in security header"); return FALSE; } rdp->do_crypt_license = (sec_flags & SEC_LICENSE_ENCRYPT_SC) != 0 ? TRUE : FALSE; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, rand_len); /* rand_len already includes 8 bytes of padding */ if (Stream_GetRemainingLength(s) < rand_len) return FALSE; key_len = rdp->settings->RdpServerRsaKey->ModulusLength; client_random = malloc(key_len); if (!client_random) return FALSE; if (rand_len != key_len + 8) { WLog_ERR(TAG, "invalid encrypted client random length"); goto end2; } crypt_client_random = calloc(1, rand_len); if (!crypt_client_random) goto end2; Stream_Read(s, crypt_client_random, rand_len); mod = rdp->settings->RdpServerRsaKey->Modulus; priv_exp = rdp->settings->RdpServerRsaKey->PrivateExponent; crypto_rsa_private_decrypt(crypt_client_random, rand_len - 8, key_len, mod, priv_exp, client_random); /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(client_random, rdp)) { goto end; } rdp->do_crypt = TRUE; if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); if (!rdp->fips_encrypt) { WLog_ERR(TAG, "unable to allocate des3 encrypt key"); goto end; } rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); if (!rdp->fips_decrypt) { WLog_ERR(TAG, "unable to allocate des3 decrypt key"); goto end; } rdp->fips_hmac = crypto_hmac_new(); if (!rdp->fips_hmac) { WLog_ERR(TAG, "unable to allocate fips hmac"); goto end; } ret = TRUE; goto end; } rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); if (!rdp->rc4_decrypt_key) { WLog_ERR(TAG, "unable to allocate rc4 decrypt key"); goto end; } rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); if (!rdp->rc4_encrypt_key) { WLog_ERR(TAG, "unable to allocate rc4 encrypt key"); goto end; } ret = TRUE; end: if (crypt_client_random) free(crypt_client_random); end2: if (client_random) free(client_random); return ret; }
BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags) { BYTE cmac[8]; BYTE wmac[8]; if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { UINT16 len; BYTE version, pad; BYTE* sig; if (Stream_GetRemainingLength(s) < 12) return FALSE; Stream_Read_UINT16(s, len); /* 0x10 */ Stream_Read_UINT8(s, version); /* 0x1 */ Stream_Read_UINT8(s, pad); sig = Stream_Pointer(s); Stream_Seek(s, 8); /* signature */ length -= 12; if (!security_fips_decrypt(Stream_Pointer(s), length, rdp)) { DEBUG_WARN( "FATAL: cannot decrypt\n"); return FALSE; /* TODO */ } if (!security_fips_check_signature(Stream_Pointer(s), length - pad, sig, rdp)) { DEBUG_WARN( "FATAL: invalid packet signature\n"); return FALSE; /* TODO */ } Stream_Length(s) -= pad; return TRUE; } if (Stream_GetRemainingLength(s) < 8) return FALSE; Stream_Read(s, wmac, sizeof(wmac)); length -= sizeof(wmac); if (!security_decrypt(Stream_Pointer(s), length, rdp)) return FALSE; if (securityFlags & SEC_SECURE_CHECKSUM) security_salted_mac_signature(rdp, Stream_Pointer(s), length, FALSE, cmac); else security_mac_signature(rdp, Stream_Pointer(s), length, cmac); if (memcmp(wmac, cmac, sizeof(wmac)) != 0) { DEBUG_WARN( "WARNING: invalid packet signature\n"); /* * Because Standard RDP Security is totally broken, * and cannot protect against MITM, don't treat signature * verification failure as critical. This at least enables * us to work with broken RDP clients and servers that * generate invalid signatures. */ //return FALSE; } return TRUE; }
BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) { BYTE* client_random = NULL; BYTE* crypt_client_random = NULL; UINT32 rand_len, key_len; UINT16 channel_id, length, sec_flags; BYTE* mod; BYTE* priv_exp; BOOL ret = FALSE; if (!rdp->settings->UseRdpSecurityLayer) { /* No RDP Security. */ return TRUE; } if (!rdp_read_header(rdp, s, &length, &channel_id)) { WLog_ERR(TAG, "invalid RDP header"); return FALSE; } if (!rdp_read_security_header(s, &sec_flags, NULL)) { WLog_ERR(TAG, "invalid security header"); return FALSE; } if ((sec_flags & SEC_EXCHANGE_PKT) == 0) { WLog_ERR(TAG, "missing SEC_EXCHANGE_PKT in security header"); return FALSE; } rdp->do_crypt_license = (sec_flags & SEC_LICENSE_ENCRYPT_SC) != 0 ? TRUE : FALSE; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, rand_len); /* rand_len already includes 8 bytes of padding */ if (Stream_GetRemainingLength(s) < rand_len) return FALSE; key_len = rdp->settings->RdpServerRsaKey->ModulusLength; client_random = malloc(key_len); if (!client_random) return FALSE; if (rand_len != key_len + 8) { WLog_ERR(TAG, "invalid encrypted client random length"); free(client_random); goto end; } crypt_client_random = calloc(1, rand_len); if (!crypt_client_random) { free(client_random); goto end; } Stream_Read(s, crypt_client_random, rand_len); mod = rdp->settings->RdpServerRsaKey->Modulus; priv_exp = rdp->settings->RdpServerRsaKey->PrivateExponent; if (crypto_rsa_private_decrypt(crypt_client_random, rand_len - 8, key_len, mod, priv_exp, client_random) <= 0) { free(client_random); goto end; } rdp->settings->ClientRandom = client_random; rdp->settings->ClientRandomLength = 32; /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(client_random, rdp)) goto end; rdp->do_crypt = TRUE; if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { rdp->fips_encrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC, WINPR_ENCRYPT, rdp->fips_encrypt_key, fips_ivec); if (!rdp->fips_encrypt) { WLog_ERR(TAG, "unable to allocate des3 encrypt key"); goto end; } rdp->fips_decrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC, WINPR_DECRYPT, rdp->fips_decrypt_key, fips_ivec); if (!rdp->fips_decrypt) { WLog_ERR(TAG, "unable to allocate des3 decrypt key"); goto end; } ret = TRUE; goto end; } rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len); rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len); if (!rdp->rc4_decrypt_key || !rdp->rc4_encrypt_key) goto end; ret = TRUE; end: free(crypt_client_random); if (!ret) { winpr_Cipher_Free(rdp->fips_encrypt); winpr_Cipher_Free(rdp->fips_decrypt); winpr_RC4_Free(rdp->rc4_encrypt_key); winpr_RC4_Free(rdp->rc4_decrypt_key); rdp->fips_encrypt = NULL; rdp->fips_decrypt = NULL; rdp->rc4_encrypt_key = NULL; rdp->rc4_decrypt_key = NULL; } return ret; }
BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) { BYTE client_random[64]; /* Should be only 32 after successful decryption, but on failure might take up to 64 bytes. */ BYTE crypt_client_random[256 + 8]; UINT32 rand_len, key_len; UINT16 channel_id, length, sec_flags; BYTE* mod; BYTE* priv_exp; if (!rdp->settings->DisableEncryption) { /* No RDP Security. */ return TRUE; } if (!rdp_read_header(rdp, s, &length, &channel_id)) { fprintf(stderr, "rdp_server_establish_keys: invalid RDP header\n"); return FALSE; } if (!rdp_read_security_header(s, &sec_flags)) return FALSE; if ((sec_flags & SEC_EXCHANGE_PKT) == 0) { fprintf(stderr, "rdp_server_establish_keys: missing SEC_EXCHANGE_PKT in security header\n"); return FALSE; } if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, rand_len); if (Stream_GetRemainingLength(s) < rand_len + 8) /* include 8 bytes of padding */ return FALSE; key_len = rdp->settings->RdpServerRsaKey->ModulusLength; if (rand_len != key_len + 8) { fprintf(stderr, "rdp_server_establish_keys: invalid encrypted client random length\n"); return FALSE; } ZeroMemory(crypt_client_random, sizeof(crypt_client_random)); Stream_Read(s, crypt_client_random, rand_len); /* 8 zero bytes of padding */ Stream_Seek(s, 8); mod = rdp->settings->RdpServerRsaKey->Modulus; priv_exp = rdp->settings->RdpServerRsaKey->PrivateExponent; crypto_rsa_private_decrypt(crypt_client_random, rand_len - 8, key_len, mod, priv_exp, client_random); /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(client_random, rdp)) { return FALSE; } rdp->do_crypt = TRUE; if (rdp->settings->SaltedChecksum) rdp->do_secure_checksum = TRUE; if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); rdp->fips_hmac = crypto_hmac_new(); return TRUE; } rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); return TRUE; }
BOOL update_read_icon_info(wStream* s, ICON_INFO* iconInfo) { BYTE* newBitMask; if (Stream_GetRemainingLength(s) < 8) return FALSE; Stream_Read_UINT16(s, iconInfo->cacheEntry); /* cacheEntry (2 bytes) */ Stream_Read_UINT8(s, iconInfo->cacheId); /* cacheId (1 byte) */ Stream_Read_UINT8(s, iconInfo->bpp); /* bpp (1 byte) */ if ((iconInfo->bpp < 1) || (iconInfo->bpp > 32)) { WLog_ERR(TAG, "invalid bpp value %d", iconInfo->bpp); return FALSE; } Stream_Read_UINT16(s, iconInfo->width); /* width (2 bytes) */ Stream_Read_UINT16(s, iconInfo->height); /* height (2 bytes) */ /* cbColorTable is only present when bpp is 1, 2 or 4 */ if (iconInfo->bpp == 1 || iconInfo->bpp == 2 || iconInfo->bpp == 4) { if (Stream_GetRemainingLength(s) < 2) return FALSE; Stream_Read_UINT16(s, iconInfo->cbColorTable); /* cbColorTable (2 bytes) */ } else { iconInfo->cbColorTable = 0; } if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT16(s, iconInfo->cbBitsMask); /* cbBitsMask (2 bytes) */ Stream_Read_UINT16(s, iconInfo->cbBitsColor); /* cbBitsColor (2 bytes) */ if (Stream_GetRemainingLength(s) < iconInfo->cbBitsMask + iconInfo->cbBitsColor) return FALSE; /* bitsMask */ newBitMask = (BYTE*) realloc(iconInfo->bitsMask, iconInfo->cbBitsMask); if (!newBitMask) { free (iconInfo->bitsMask); iconInfo->bitsMask = NULL; return FALSE; } iconInfo->bitsMask = newBitMask; Stream_Read(s, iconInfo->bitsMask, iconInfo->cbBitsMask); /* colorTable */ if (iconInfo->colorTable == NULL) { if (iconInfo->cbColorTable) iconInfo->colorTable = (BYTE*) malloc(iconInfo->cbColorTable); } else if (iconInfo->cbColorTable) { BYTE *new_tab; new_tab = (BYTE*) realloc(iconInfo->colorTable, iconInfo->cbColorTable); if (!new_tab) { free (iconInfo->colorTable); iconInfo->colorTable = NULL; return FALSE; } iconInfo->colorTable = new_tab; } else { free(iconInfo->colorTable); iconInfo->colorTable = NULL; } if (iconInfo->colorTable) Stream_Read(s, iconInfo->colorTable, iconInfo->cbColorTable); /* bitsColor */ newBitMask = (BYTE *)realloc(iconInfo->bitsColor, iconInfo->cbBitsColor); if (!newBitMask) { free (iconInfo->bitsColor); iconInfo->bitsColor = NULL; return FALSE; } iconInfo->bitsColor = newBitMask; Stream_Read(s, iconInfo->bitsColor, iconInfo->cbBitsColor); return TRUE; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ static UINT serial_process_irp_device_control(SERIAL_DEVICE* serial, IRP* irp) { UINT32 IoControlCode; UINT32 InputBufferLength; BYTE* InputBuffer = NULL; UINT32 OutputBufferLength; BYTE* OutputBuffer = NULL; DWORD BytesReturned = 0; if (Stream_GetRemainingLength(irp->input) < 32) return ERROR_INVALID_DATA; Stream_Read_UINT32(irp->input, OutputBufferLength); /* OutputBufferLength (4 bytes) */ Stream_Read_UINT32(irp->input, InputBufferLength); /* InputBufferLength (4 bytes) */ Stream_Read_UINT32(irp->input, IoControlCode); /* IoControlCode (4 bytes) */ Stream_Seek(irp->input, 20); /* Padding (20 bytes) */ if (Stream_GetRemainingLength(irp->input) < InputBufferLength) return ERROR_INVALID_DATA; OutputBuffer = (BYTE*)calloc(OutputBufferLength, sizeof(BYTE)); if (OutputBuffer == NULL) { irp->IoStatus = STATUS_NO_MEMORY; goto error_handle; } InputBuffer = (BYTE*)calloc(InputBufferLength, sizeof(BYTE)); if (InputBuffer == NULL) { irp->IoStatus = STATUS_NO_MEMORY; goto error_handle; } Stream_Read(irp->input, InputBuffer, InputBufferLength); WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl: CompletionId=%"PRIu32", IoControlCode=[0x%"PRIX32"] %s", irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode)); /* FIXME: CommDeviceIoControl to be replaced by DeviceIoControl() */ if (CommDeviceIoControl(serial->hComm, IoControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, &BytesReturned, NULL)) { /* WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl: CompletionId=%"PRIu32", IoControlCode=[0x%"PRIX32"] %s done", irp->CompletionId, IoControlCode, _comm_serial_ioctl_name(IoControlCode)); */ irp->IoStatus = STATUS_SUCCESS; } else { WLog_Print(serial->log, WLOG_DEBUG, "CommDeviceIoControl failure: IoControlCode=[0x%"PRIX32"] %s, last-error: 0x%08"PRIX32"", IoControlCode, _comm_serial_ioctl_name(IoControlCode), GetLastError()); irp->IoStatus = _GetLastErrorToIoStatus(serial); } error_handle: /* FIXME: find out whether it's required or not to get * BytesReturned == OutputBufferLength when * CommDeviceIoControl returns FALSE */ assert(OutputBufferLength == BytesReturned); Stream_Write_UINT32(irp->output, BytesReturned); /* OutputBufferLength (4 bytes) */ if (BytesReturned > 0) { if (!Stream_EnsureRemainingCapacity(irp->output, BytesReturned)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); free(InputBuffer); free(OutputBuffer); return CHANNEL_RC_NO_MEMORY; } Stream_Write(irp->output, OutputBuffer, BytesReturned); /* OutputBuffer */ } /* FIXME: Why at least Windows 2008R2 gets lost with this * extra byte and likely on a IOCTL_SERIAL_SET_BAUD_RATE? The * extra byte is well required according MS-RDPEFS * 2.2.1.5.5 */ /* else */ /* { */ /* Stream_Write_UINT8(irp->output, 0); /\* Padding (1 byte) *\/ */ /* } */ free(InputBuffer); free(OutputBuffer); return CHANNEL_RC_OK; }
int credssp_recv(rdpCredssp* credssp) { wStream* s; int length; int status; UINT32 version; s = Stream_New(NULL, 4096); status = transport_read(credssp->transport, s); Stream_Length(s) = status; if (status < 0) { fprintf(stderr, "credssp_recv() error: %d\n", status); Stream_Free(s, TRUE); return -1; } /* TSRequest */ if(!ber_read_sequence_tag(s, &length) || !ber_read_contextual_tag(s, 0, &length, TRUE) || !ber_read_integer(s, &version)) { Stream_Free(s, TRUE); return -1; } /* [1] negoTokens (NegoData) */ if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE) { if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */ !ber_read_sequence_tag(s, &length) || /* NegoDataItem */ !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */ !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ Stream_GetRemainingLength(s) < length) { Stream_Free(s, TRUE); return -1; } sspi_SecBufferAlloc(&credssp->negoToken, length); Stream_Read(s, credssp->negoToken.pvBuffer, length); credssp->negoToken.cbBuffer = length; } /* [2] authInfo (OCTET STRING) */ if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE) { if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ Stream_GetRemainingLength(s) < length) { Stream_Free(s, TRUE); return -1; } sspi_SecBufferAlloc(&credssp->authInfo, length); Stream_Read(s, credssp->authInfo.pvBuffer, length); credssp->authInfo.cbBuffer = length; } /* [3] pubKeyAuth (OCTET STRING) */ if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE) { if(!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ Stream_GetRemainingLength(s) < length) { Stream_Free(s, TRUE); return -1; } sspi_SecBufferAlloc(&credssp->pubKeyAuth, length); Stream_Read(s, credssp->pubKeyAuth.pvBuffer, length); credssp->pubKeyAuth.cbBuffer = length; } Stream_Free(s, TRUE); return 0; }
UINT32 serial_tty_control(SERIAL_TTY* tty, UINT32 IoControlCode, wStream* input, wStream* output, UINT32* abort_io) { int purge_mask; UINT32 result; UINT32 modemstate; BYTE immediate; UINT32 ret = STATUS_SUCCESS; UINT32 length = 0; UINT32 pos; DEBUG_SVC("in"); Stream_Seek(output, sizeof(UINT32)); switch (IoControlCode) { case IOCTL_SERIAL_SET_BAUD_RATE: Stream_Read_UINT32(input, tty->baud_rate); tty_set_termios(tty); DEBUG_SVC("SERIAL_SET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_GET_BAUD_RATE: length = 4; Stream_Write_UINT32(output, tty->baud_rate); DEBUG_SVC("SERIAL_GET_BAUD_RATE %d", tty->baud_rate); break; case IOCTL_SERIAL_SET_QUEUE_SIZE: Stream_Read_UINT32(input, tty->queue_in_size); Stream_Read_UINT32(input, tty->queue_out_size); DEBUG_SVC("SERIAL_SET_QUEUE_SIZE in %d out %d", tty->queue_in_size, tty->queue_out_size); break; case IOCTL_SERIAL_SET_LINE_CONTROL: Stream_Read_UINT8(input, tty->stop_bits); Stream_Read_UINT8(input, tty->parity); Stream_Read_UINT8(input, tty->word_length); tty_set_termios(tty); DEBUG_SVC("SERIAL_SET_LINE_CONTROL stop %d parity %d word %d", tty->stop_bits, tty->parity, tty->word_length); break; case IOCTL_SERIAL_GET_LINE_CONTROL: DEBUG_SVC("SERIAL_GET_LINE_CONTROL"); length = 3; Stream_Write_UINT8(output, tty->stop_bits); Stream_Write_UINT8(output, tty->parity); Stream_Write_UINT8(output, tty->word_length); break; case IOCTL_SERIAL_IMMEDIATE_CHAR: DEBUG_SVC("SERIAL_IMMEDIATE_CHAR"); Stream_Read_UINT8(input, immediate); tty_write_data(tty, &immediate, 1); break; case IOCTL_SERIAL_CONFIG_SIZE: DEBUG_SVC("SERIAL_CONFIG_SIZE"); length = 4; Stream_Write_UINT32(output, 0); break; case IOCTL_SERIAL_GET_CHARS: DEBUG_SVC("SERIAL_GET_CHARS"); length = 6; Stream_Write(output, tty->chars, 6); break; case IOCTL_SERIAL_SET_CHARS: DEBUG_SVC("SERIAL_SET_CHARS"); Stream_Read(input, tty->chars, 6); tty_set_termios(tty); break; case IOCTL_SERIAL_GET_HANDFLOW: length = 16; tty_get_termios(tty); Stream_Write_UINT32(output, tty->control); Stream_Write_UINT32(output, tty->xonoff); Stream_Write_UINT32(output, tty->onlimit); Stream_Write_UINT32(output, tty->offlimit); DEBUG_SVC("IOCTL_SERIAL_GET_HANDFLOW %X %X %X %X", tty->control, tty->xonoff, tty->onlimit, tty->offlimit); break; case IOCTL_SERIAL_SET_HANDFLOW: Stream_Read_UINT32(input, tty->control); Stream_Read_UINT32(input, tty->xonoff); Stream_Read_UINT32(input, tty->onlimit); Stream_Read_UINT32(input, tty->offlimit); DEBUG_SVC("IOCTL_SERIAL_SET_HANDFLOW %X %X %X %X", tty->control, tty->xonoff, tty->onlimit, tty->offlimit); tty_set_termios(tty); break; case IOCTL_SERIAL_SET_TIMEOUTS: Stream_Read_UINT32(input, tty->read_interval_timeout); Stream_Read_UINT32(input, tty->read_total_timeout_multiplier); Stream_Read_UINT32(input, tty->read_total_timeout_constant); Stream_Read_UINT32(input, tty->write_total_timeout_multiplier); Stream_Read_UINT32(input, tty->write_total_timeout_constant); /* http://www.codeproject.com/KB/system/chaiyasit_t.aspx, see 'ReadIntervalTimeout' section http://msdn.microsoft.com/en-us/library/ms885171.aspx */ if (tty->read_interval_timeout == SERIAL_TIMEOUT_MAX) { tty->read_interval_timeout = 0; tty->read_total_timeout_multiplier = 0; } DEBUG_SVC("SERIAL_SET_TIMEOUTS read timeout %d %d %d", tty->read_interval_timeout, tty->read_total_timeout_multiplier, tty->read_total_timeout_constant); break; case IOCTL_SERIAL_GET_TIMEOUTS: DEBUG_SVC("SERIAL_GET_TIMEOUTS read timeout %d %d %d", tty->read_interval_timeout, tty->read_total_timeout_multiplier, tty->read_total_timeout_constant); length = 20; Stream_Write_UINT32(output, tty->read_interval_timeout); Stream_Write_UINT32(output, tty->read_total_timeout_multiplier); Stream_Write_UINT32(output, tty->read_total_timeout_constant); Stream_Write_UINT32(output, tty->write_total_timeout_multiplier); Stream_Write_UINT32(output, tty->write_total_timeout_constant); break; case IOCTL_SERIAL_GET_WAIT_MASK: DEBUG_SVC("SERIAL_GET_WAIT_MASK %X", tty->wait_mask); length = 4; Stream_Write_UINT32(output, tty->wait_mask); break; case IOCTL_SERIAL_SET_WAIT_MASK: Stream_Read_UINT32(input, tty->wait_mask); DEBUG_SVC("SERIAL_SET_WAIT_MASK %X", tty->wait_mask); break; case IOCTL_SERIAL_SET_DTR: DEBUG_SVC("SERIAL_SET_DTR"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); tty->dtr = 1; break; case IOCTL_SERIAL_CLR_DTR: DEBUG_SVC("SERIAL_CLR_DTR"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_DTR; ioctl(tty->fd, TIOCMSET, &result); tty->dtr = 0; break; case IOCTL_SERIAL_SET_RTS: DEBUG_SVC("SERIAL_SET_RTS"); ioctl(tty->fd, TIOCMGET, &result); result |= TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); tty->rts = 1; break; case IOCTL_SERIAL_CLR_RTS: DEBUG_SVC("SERIAL_CLR_RTS"); ioctl(tty->fd, TIOCMGET, &result); result &= ~TIOCM_RTS; ioctl(tty->fd, TIOCMSET, &result); tty->rts = 0; break; case IOCTL_SERIAL_GET_MODEMSTATUS: modemstate = 0; #ifdef TIOCMGET ioctl(tty->fd, TIOCMGET, &result); if (result & TIOCM_CTS) modemstate |= SERIAL_MS_CTS; if (result & TIOCM_DSR) modemstate |= SERIAL_MS_DSR; if (result & TIOCM_RNG) modemstate |= SERIAL_MS_RNG; if (result & TIOCM_CAR) modemstate |= SERIAL_MS_CAR; if (result & TIOCM_DTR) modemstate |= SERIAL_MS_DTR; if (result & TIOCM_RTS) modemstate |= SERIAL_MS_RTS; #endif DEBUG_SVC("SERIAL_GET_MODEMSTATUS %X", modemstate); length = 4; Stream_Write_UINT32(output, modemstate); break; case IOCTL_SERIAL_GET_COMMSTATUS: length = 18; Stream_Write_UINT32(output, 0); /* Errors */ Stream_Write_UINT32(output, 0); /* Hold reasons */ result = 0; #ifdef TIOCINQ ioctl(tty->fd, TIOCINQ, &result); #endif Stream_Write_UINT32(output, result); /* Amount in in queue */ if (result) DEBUG_SVC("SERIAL_GET_COMMSTATUS in queue %d", result); result = 0; #ifdef TIOCOUTQ ioctl(tty->fd, TIOCOUTQ, &result); #endif Stream_Write_UINT32(output, result); /* Amount in out queue */ DEBUG_SVC("SERIAL_GET_COMMSTATUS out queue %d", result); Stream_Write_UINT8(output, 0); /* EofReceived */ Stream_Write_UINT8(output, 0); /* WaitForImmediate */ break; case IOCTL_SERIAL_PURGE: Stream_Read_UINT32(input, purge_mask); DEBUG_SVC("SERIAL_PURGE purge_mask %X", purge_mask); /* See http://msdn.microsoft.com/en-us/library/ms901431.aspx PURGE_TXCLEAR Clears the output buffer, if the driver has one. PURGE_RXCLEAR Clears the input buffer, if the driver has one. It clearly states to clear the *driver* buffer, not the port buffer */ #ifdef DEBUG_SVC if (purge_mask & SERIAL_PURGE_TXCLEAR) DEBUG_SVC("Ignoring SERIAL_PURGE_TXCLEAR"); if (purge_mask & SERIAL_PURGE_RXCLEAR) DEBUG_SVC("Ignoring SERIAL_PURGE_RXCLEAR"); #endif if (purge_mask & SERIAL_PURGE_TXABORT) *abort_io |= SERIAL_ABORT_IO_WRITE; if (purge_mask & SERIAL_PURGE_RXABORT) *abort_io |= SERIAL_ABORT_IO_READ; break; case IOCTL_SERIAL_WAIT_ON_MASK: DEBUG_SVC("SERIAL_WAIT_ON_MASK %X", tty->wait_mask); tty->event_pending = 1; length = 4; if (serial_tty_get_event(tty, &result)) { DEBUG_SVC("WAIT end event = %X", result); Stream_Write_UINT32(output, result); break; } ret = STATUS_PENDING; break; case IOCTL_SERIAL_SET_BREAK_ON: DEBUG_SVC("SERIAL_SET_BREAK_ON"); tcsendbreak(tty->fd, 0); break; case IOCTL_SERIAL_RESET_DEVICE: DEBUG_SVC("SERIAL_RESET_DEVICE"); break; case IOCTL_SERIAL_SET_BREAK_OFF: DEBUG_SVC("SERIAL_SET_BREAK_OFF"); break; case IOCTL_SERIAL_SET_XOFF: DEBUG_SVC("SERIAL_SET_XOFF"); break; case IOCTL_SERIAL_SET_XON: DEBUG_SVC("SERIAL_SET_XON"); tcflow(tty->fd, TCION); break; default: DEBUG_SVC("NOT FOUND IoControlCode SERIAL IOCTL %d", IoControlCode); return STATUS_INVALID_PARAMETER; } /* Write OutputBufferLength */ pos = Stream_GetPosition(output); Stream_SetPosition(output, 16); Stream_Write_UINT32(output, length); Stream_SetPosition(output, pos); return ret; }
static BOOL certificate_process_server_public_signature(rdpCertificate* certificate, const BYTE* sigdata, size_t sigdatalen, wStream* s, UINT32 siglen) { #if defined(CERT_VALIDATE_PADDING) || defined(CERT_VALIDATE_RSA) size_t i, sum; #endif #if defined(CERT_VALIDATE_RSA) BYTE sig[TSSK_KEY_LENGTH]; #endif BYTE encsig[TSSK_KEY_LENGTH + 8]; #if defined(CERT_VALIDATE_MD5) && defined(CERT_VALIDATE_RSA) BYTE md5hash[WINPR_MD5_DIGEST_LENGTH]; #endif #if !defined(CERT_VALIDATE_MD5) || !defined(CERT_VALIDATE_RSA) (void)sigdata; (void)sigdatalen; #endif (void)certificate; /* Do not bother with validation of server proprietary certificate. The use of MD5 here is not allowed under FIPS. * Since the validation is not protecting against anything since the private/public keys are well known and documented in * MS-RDPBCGR section 5.3.3.1, we are not gaining any security by using MD5 for signature comparison. Rather then use MD5 * here we just dont do the validation to avoid its use. Historically, freerdp has been ignoring a failed validation anyways. */ #if defined(CERT_VALIDATE_MD5) if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash, sizeof(md5hash))) return FALSE; #endif Stream_Read(s, encsig, siglen); /* Last 8 bytes shall be all zero. */ #if defined(CERT_VALIDATE_PADDING) for (sum = 0, i = sizeof(encsig) - 8; i < sizeof(encsig); i++) sum += encsig[i]; if (sum != 0) { WLog_ERR(TAG, "invalid signature"); return FALSE; } #endif siglen -= 8; #if defined(CERT_VALIDATE_RSA) if (crypto_rsa_public_decrypt(encsig, siglen, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig) <= 0) { WLog_ERR(TAG, "invalid RSA decrypt"); return FALSE; } /* Verify signature. */ /* Do not bother with validation of server proprietary certificate as described above. */ #if defined(CERT_VALIDATE_MD5) if (memcmp(md5hash, sig, sizeof(md5hash)) != 0) { WLog_ERR(TAG, "invalid signature"); return FALSE; } #endif /* * Verify rest of decrypted data: * The 17th byte is 0x00. * The 18th through 62nd bytes are each 0xFF. * The 63rd byte is 0x01. */ for (sum = 0, i = 17; i < 62; i++) sum += sig[i]; if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01) { WLog_ERR(TAG, "invalid signature"); return FALSE; } #endif return TRUE; }
static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) { UINT16 flags; UINT16 length; rdpRedirection* redirection = rdp->redirection; if (Stream_GetRemainingLength(s) < 12) return -1; Stream_Read_UINT16(s, flags); /* flags (2 bytes) */ Stream_Read_UINT16(s, length); /* length (2 bytes) */ Stream_Read_UINT32(s, redirection->sessionID); /* sessionID (4 bytes) */ Stream_Read_UINT32(s, redirection->flags); /* redirFlags (4 bytes) */ WLog_DBG(TAG, "flags: 0x%04"PRIX16", redirFlags: 0x%08"PRIX32" length: %"PRIu16", sessionID: 0x%08"PRIX32"", flags, redirection->flags, length, redirection->sessionID); rdp_print_redirection_flags(redirection->flags); /* Although MS-RDPBCGR does not mention any length constraints limits for the * variable length null-terminated unicode strings in the RDP_SERVER_REDIRECTION_PACKET * structure we will use the following limits in bytes including the null terminator: * * TargetNetAddress: 80 bytes * UserName: 512 bytes * Domain: 52 bytes * Password(Cookie): 512 bytes * TargetFQDN: 512 bytes * TargetNetBiosName: 32 bytes */ if (redirection->flags & LB_TARGET_NET_ADDRESS) { if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetAddress), 80)) return -1; } if (redirection->flags & LB_LOAD_BALANCE_INFO) { /* See [MSFT-SDLBTS] (a.k.a. TS_Session_Directory.doc) * load balance info example data: * 0000 43 6f 6f 6b 69 65 3a 20 6d 73 74 73 3d 32 31 33 Cookie: msts=213 * 0010 34 30 32 36 34 33 32 2e 31 35 36 32 39 2e 30 30 4026432.15629.00 * 0020 30 30 0d 0a 00.. */ if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, redirection->LoadBalanceInfoLength); if (Stream_GetRemainingLength(s) < redirection->LoadBalanceInfoLength) return -1; redirection->LoadBalanceInfo = (BYTE*) malloc(redirection->LoadBalanceInfoLength); if (!redirection->LoadBalanceInfo) return -1; Stream_Read(s, redirection->LoadBalanceInfo, redirection->LoadBalanceInfoLength); WLog_DBG(TAG, "loadBalanceInfo:"); winpr_HexDump(TAG, WLOG_DEBUG, redirection->LoadBalanceInfo, redirection->LoadBalanceInfoLength); } if (redirection->flags & LB_USERNAME) { if (!rdp_redirection_read_unicode_string(s, &(redirection->Username), 512)) return -1; WLog_DBG(TAG, "Username: %s", redirection->Username); } if (redirection->flags & LB_DOMAIN) { if (!rdp_redirection_read_unicode_string(s, &(redirection->Domain), 52)) return FALSE; WLog_DBG(TAG, "Domain: %s", redirection->Domain); } if (redirection->flags & LB_PASSWORD) { /* Note: Password is a variable-length array of bytes containing the * password used by the user in Unicode format, including a null-terminator * or (!) or a cookie value that MUST be passed to the target server on * successful connection. * Since the format of the password cookie (probably some salted hash) is * currently unknown we'll treat it as opaque data. All cookies seen so far * are 120 bytes including \0\0 termination. * Here is an observed example of a redirection password cookie: * * 0000 02 00 00 80 44 53 48 4c 60 ab 69 2f 07 d6 9e 2d ....DSHL`.i/...- * 0010 f0 3a 97 3b a9 c5 ec 7e 66 bd b3 84 6c b1 ef b9 .:.;...~f...l... * 0020 b6 82 4e cc 3a df 64 b7 7b 25 04 54 c2 58 98 f8 ..N.:.d.{%.T.X.. * 0030 97 87 d4 93 c7 c1 e1 5b c2 85 f8 22 49 1f 81 88 .......[..."I... * 0040 43 44 83 f6 9a 72 40 24 dc 4d 43 cb d9 92 3c 8f CD...r@$.MC...<. * 0050 3a 37 5c 77 13 a0 72 3c 72 08 64 2a 29 fb dc eb :7\w..r<r.d*)... * 0060 0d 2b 06 b4 c6 08 b4 73 34 16 93 62 6d 24 e9 93 .+.....s4..bm$.. * 0070 97 27 7b dd 9a 72 00 00 .'{..r.. * * Notwithstanding the above, we'll allocated an additional zero WCHAR at the * end of the buffer which won't get counted in PasswordLength. */ if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, redirection->PasswordLength); /* [MS-RDPBCGR] specifies 512 bytes as the upper limit for the password length * including the null terminatior(s). This should also be enough for the unknown * password cookie format (see previous comment). */ if (Stream_GetRemainingLength(s) < redirection->PasswordLength) return -1; if (redirection->PasswordLength > 512) return -1; redirection->Password = (BYTE*) calloc(1, redirection->PasswordLength + sizeof(WCHAR)); if (!redirection->Password) return -1; Stream_Read(s, redirection->Password, redirection->PasswordLength); WLog_DBG(TAG, "PasswordCookie:"); winpr_HexDump(TAG, WLOG_DEBUG, redirection->Password, redirection->PasswordLength); } if (redirection->flags & LB_TARGET_FQDN) { if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetFQDN), 512)) return -1; WLog_DBG(TAG, "TargetFQDN: %s", redirection->TargetFQDN); } if (redirection->flags & LB_TARGET_NETBIOS_NAME) { if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetBiosName), 32)) return -1; WLog_DBG(TAG, "TargetNetBiosName: %s", redirection->TargetNetBiosName); } if (redirection->flags & LB_CLIENT_TSV_URL) { if (Stream_GetRemainingLength(s) < 4) return -1; Stream_Read_UINT32(s, redirection->TsvUrlLength); if (Stream_GetRemainingLength(s) < redirection->TsvUrlLength) return -1; redirection->TsvUrl = (BYTE*) malloc(redirection->TsvUrlLength); if (!redirection->TsvUrl) return -1; Stream_Read(s, redirection->TsvUrl, redirection->TsvUrlLength); WLog_DBG(TAG, "TsvUrl:"); winpr_HexDump(TAG, WLOG_DEBUG, redirection->TsvUrl, redirection->TsvUrlLength); } if (redirection->flags & LB_TARGET_NET_ADDRESSES) { int i; UINT32 count; UINT32 targetNetAddressesLength; if (Stream_GetRemainingLength(s) < 8) return -1; Stream_Read_UINT32(s, targetNetAddressesLength); Stream_Read_UINT32(s, redirection->TargetNetAddressesCount); count = redirection->TargetNetAddressesCount; redirection->TargetNetAddresses = (char**) calloc(count, sizeof(char*)); if (!redirection->TargetNetAddresses) return FALSE; WLog_DBG(TAG, "TargetNetAddressesCount: %"PRIu32"", redirection->TargetNetAddressesCount); for (i = 0; i < (int) count; i++) { if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetAddresses[i]), 80)) return FALSE; WLog_DBG(TAG, "TargetNetAddresses[%d]: %s", i, redirection->TargetNetAddresses[i]); } } if (Stream_GetRemainingLength(s) >= 8) { /* some versions of windows don't included this padding before closing the connection */ Stream_Seek(s, 8); /* pad (8 bytes) */ } if (redirection->flags & LB_NOREDIRECT) return 0; return 1; }
BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, wStream* s) { UINT32 i; BOOL ret; UINT32 certLength; UINT32 numCertBlobs; DEBUG_CERTIFICATE("Server X.509 Certificate Chain"); if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, numCertBlobs); /* numCertBlobs */ certificate->x509_cert_chain = certificate_new_x509_certificate_chain(numCertBlobs); if (!certificate->x509_cert_chain) return FALSE; for (i = 0; i < numCertBlobs; i++) { if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, certLength); if (Stream_GetRemainingLength(s) < certLength) return FALSE; DEBUG_CERTIFICATE("X.509 Certificate #%d, length:%"PRIu32"", i + 1, certLength); certificate->x509_cert_chain->array[i].data = (BYTE*) malloc(certLength); if (!certificate->x509_cert_chain->array[i].data) return FALSE; Stream_Read(s, certificate->x509_cert_chain->array[i].data, certLength); certificate->x509_cert_chain->array[i].length = certLength; if ((numCertBlobs - i) == 2) { rdpCertInfo cert_info = { 0 }; DEBUG_CERTIFICATE("License Server Certificate"); ret = certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &cert_info); DEBUG_LICENSE("modulus length:%"PRIu32"", cert_info.ModulusLength); free(cert_info.Modulus); if (!ret) { WLog_ERR(TAG, "failed to read License Server, content follows:"); winpr_HexDump(TAG, WLOG_ERROR, certificate->x509_cert_chain->array[i].data, certificate->x509_cert_chain->array[i].length); return FALSE; } } else if (numCertBlobs - i == 1) { DEBUG_CERTIFICATE("Terminal Server Certificate"); if (!certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &certificate->cert_info)) return FALSE; DEBUG_CERTIFICATE("modulus length:%"PRIu32"", certificate->cert_info.ModulusLength); } } return TRUE; }
static err_t DummyReadOneOrMore(void* p,void* Data,size_t Size,size_t* Readed) { return Stream_Read(p,Data,Size,Readed); }
int ntlm_read_ntlm_v2_response(wStream* s, NTLMv2_RESPONSE* response) { Stream_Read(s, response->Response, 16); return ntlm_read_ntlm_v2_client_challenge(s, &(response->Challenge)); }
BOOL gcc_read_server_security_data(wStream* s, rdpMcs* mcs) { BYTE* data; UINT32 length; rdpSettings* settings = mcs->settings; if (Stream_GetRemainingLength(s) < 8) return FALSE; Stream_Read_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */ Stream_Read_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */ if (settings->EncryptionMethods == 0 && settings->EncryptionLevel == 0) { /* serverRandom and serverRandom must not be present */ settings->DisableEncryption = FALSE; settings->EncryptionMethods = ENCRYPTION_METHOD_NONE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; return TRUE; } if (Stream_GetRemainingLength(s) < 8) return FALSE; Stream_Read_UINT32(s, settings->ServerRandomLength); /* serverRandomLen */ Stream_Read_UINT32(s, settings->ServerCertificateLength); /* serverCertLen */ if (Stream_GetRemainingLength(s) < settings->ServerRandomLength + settings->ServerCertificateLength) return FALSE; if (settings->ServerRandomLength > 0) { /* serverRandom */ settings->ServerRandom = (BYTE*) malloc(settings->ServerRandomLength); Stream_Read(s, settings->ServerRandom, settings->ServerRandomLength); } else { return FALSE; } if (settings->ServerCertificateLength > 0) { /* serverCertificate */ settings->ServerCertificate = (BYTE*) malloc(settings->ServerCertificateLength); Stream_Read(s, settings->ServerCertificate, settings->ServerCertificateLength); certificate_free(settings->RdpServerCertificate); settings->RdpServerCertificate = certificate_new(); data = settings->ServerCertificate; length = settings->ServerCertificateLength; if (certificate_read_server_certificate(settings->RdpServerCertificate, data, length) < 1) return FALSE; } else { return FALSE; } return TRUE; }