Exemplo n.º 1
0
Arquivo: info.c Projeto: C4rt/FreeRDP
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
/**
 * 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;
}
Exemplo n.º 4
0
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);

}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
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);
}
Exemplo n.º 9
0
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;
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
/**
 * 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;
}
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
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;
}
Exemplo n.º 18
0
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;
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
static err_t DummyReadOneOrMore(void* p,void* Data,size_t Size,size_t* Readed)
{ 
	return Stream_Read(p,Data,Size,Readed);
}
Exemplo n.º 22
0
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));
}
Exemplo n.º 23
0
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;
}