/*****************************************************************************/ staticvoid
hex_str_to_bin(char *in, char *out, int out_len)
{ int in_index; int in_len; int out_index; int val; char hex[16];
file_read_sections(fd, names); for (index = 0; index < names->count; index++)
{
q = (char *)list_get_item(names, index); if (g_strncasecmp("default", q, 8) != 0)
{ int i;
xrdp_channel_delete(self->chan_layer);
xrdp_mcs_delete(self->mcs_layer);
xrdp_fastpath_delete(self->fastpath_layer);
ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */
ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */
ssl_des3_info_delete(self->decrypt_fips_info);
ssl_des3_info_delete(self->encrypt_fips_info);
ssl_hmac_info_delete(self->sign_fips_info);
g_free(self->client_mcs_data.data);
g_free(self->server_mcs_data.data); /* Crypto information must always be cleared */
g_memset(self, 0, sizeof(struct xrdp_sec));
g_free(self);
}
/* this is the first test that the decrypt is working */ if ((flags & RDP_LOGON_NORMAL) != RDP_LOGON_NORMAL) /* 0x33 */
{ /* must be or error */
LOG(LOG_LEVEL_ERROR, "received wrong flags, likely decrypt not working"); return1;
}
if (flags & RDP_LOGON_LEAVE_AUDIO)
{
self->rdp_layer->client_info.sound_code = 1;
LOG_DEVEL(LOG_LEVEL_DEBUG, "[MS-RDPBCGR] TS_INFO_PACKET flag INFO_REMOTECONSOLEAUDIO found");
LOG(LOG_LEVEL_DEBUG, "Client requested that audio on the server be played on the server.");
}
if (flags & RDP_LOGON_AUTO)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "[MS-RDPBCGR] TS_INFO_PACKET flag INFO_AUTOLOGON found"); /* todo, for now not allowing autologon and mce both */ if (!self->rdp_layer->client_info.is_mce)
{
self->rdp_layer->client_info.rdp_autologin = 1;
LOG(LOG_LEVEL_DEBUG, "Client requested auto logon.");
} else
{
LOG(LOG_LEVEL_WARNING, "Auto logon is not supported with MCE");
}
}
if (flags & RDP_COMPRESSION)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "[MS-RDPBCGR] TS_INFO_PACKET flag INFO_COMPRESSION found, " "CompressionType 0x%1.1x", (flags & 0x00001E00) >> 9); /* TODO: check the client's supported compression type vs the server
compression used */ if (self->rdp_layer->client_info.use_bulk_comp)
{
self->rdp_layer->client_info.rdp_compression = 1;
LOG(LOG_LEVEL_DEBUG, "Client requested compression enabled.");
} else
{
LOG(LOG_LEVEL_DEBUG, "Client requested compression, but server " "compression is disabled.");
}
}
/* *Microsoft'sitapclientrunningonMacOS/Android *alwayssendsautologoncredentials,evenwhenuserhasnot *configuredany
*/ if (len_user == 0 && self->rdp_layer->client_info.rdp_autologin)
{
LOG(LOG_LEVEL_DEBUG, "Client supplied user name is empty, disabling autologin");
self->rdp_layer->client_info.rdp_autologin = 0;
}
if (len_user >= INFO_CLIENT_MAX_CB_LEN)
{
LOG(LOG_LEVEL_ERROR, "Client supplied user name is too long. Max length %d, user name length %d",
INFO_CLIENT_MAX_CB_LEN, len_user); return1;
}
if (len_program >= INFO_CLIENT_MAX_CB_LEN)
{
LOG(LOG_LEVEL_ERROR, "Client supplied program name is too long. Max length %d, program name length %d",
INFO_CLIENT_MAX_CB_LEN, len_program); return1;
}
if (len_directory >= INFO_CLIENT_MAX_CB_LEN)
{
LOG(LOG_LEVEL_ERROR, "Client supplied directory name is too long. Max length %d, directory name length %d",
INFO_CLIENT_MAX_CB_LEN, len_directory); return1;
}
if (ts_info_utf16_in(s, len_user, self->rdp_layer->client_info.username, sizeof(self->rdp_layer->client_info.username)) != 0)
{
LOG(LOG_LEVEL_ERROR, "ERROR reading user name"); return1;
}
// If we require credentials, don't continue if they're not provided if (self->rdp_layer->client_info.require_credentials)
{ if ((flags & RDP_LOGON_AUTO) == 0)
{
LOG(LOG_LEVEL_ERROR, "Server is configured to require that the " "client enable auto logon with credentials, but the client did " "not request auto logon."); return1;
} if (len_user == 0 || len_password == 0)
{
LOG(LOG_LEVEL_ERROR, "Server is configured to require that the " "client enable auto logon with credentials, but the client did " "not supply both a username and password."); return1;
}
}
if (flags & RDP_LOGON_AUTO)
{ if (ts_info_utf16_in(s, len_password, self->rdp_layer->client_info.password, sizeof(self->rdp_layer->client_info.password)) != 0)
{
LOG(LOG_LEVEL_ERROR, "ERROR reading password"); return1;
}
} elseif (self->rdp_layer->client_info.enable_token_login
&& len_user > 0
&& len_password == 0
&& (sep = g_strchr(self->rdp_layer->client_info.username, '\x1f')) != NULL)
{
LOG(LOG_LEVEL_DEBUG, "Client supplied a Logon token. Overwriting password with logon token.");
g_strncpy(self->rdp_layer->client_info.password, sep + 1, sizeof(self->rdp_layer->client_info.password) - 1);
self->rdp_layer->client_info.username[sep - self->rdp_layer->client_info.username] = '\0';
self->rdp_layer->client_info.rdp_autologin = 1;
} else
{ // Skip the password if (!s_check_rem_and_log(s, len_password + 2, "Parsing [MS-RDPBCGR] TS_INFO_PACKET Password"))
{ return1;
}
in_uint8s(s, len_password + 2);
} if (self->rdp_layer->client_info.domain_user_separator[0] != '\0'
&& self->rdp_layer->client_info.domain[0] != '\0')
{ // Check the composite string is not too long unsignedint size =
g_strlen(self->rdp_layer->client_info.username) +
g_strlen(self->rdp_layer->client_info.domain_user_separator) +
g_strlen(self->rdp_layer->client_info.domain);
if (size >= sizeof(self->rdp_layer->client_info.username))
{
LOG(LOG_LEVEL_ERROR, "Username/domain is too long"); return1;
}
LOG(LOG_LEVEL_DEBUG, "Client supplied domain with user name." " Overwriting user name with user name parsed from domain.");
g_strcat(self->rdp_layer->client_info.username,
self->rdp_layer->client_info.domain_user_separator);
g_strcat(self->rdp_layer->client_info.username,
self->rdp_layer->client_info.domain);
}
/* TODO: explain why the windows key flag is used to determine if the
TS_EXTENDED_INFO_PACKET should be parsed */ if (flags & RDP_LOGON_BLOB) /* INFO_ENABLEWINDOWSKEY */
{ if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPBCGR] TS_EXTENDED_INFO_PACKET " "clientAddressFamily and cbClientAddress"))
{ return1;
} /* TS_EXTENDED_INFO_PACKET required fields */
in_uint8s(s, 2); /* clientAddressFamily */
in_uint16_le(s, len_clnt_addr); if (len_clnt_addr > EXTENDED_INFO_MAX_CLIENT_ADDR_LENGTH ||
!s_check_rem(s, len_clnt_addr))
{
LOG(LOG_LEVEL_ERROR, "clientAddress is too long (%u bytes)",
len_clnt_addr); return1;
} // The clientAddress is currently unused. [MS-RDPBCGR] requires // a mandatory null terminator, but some clients set // len_clnt_addr == 0 if this field is missing. Allow for this // in any future implementation.
in_uint8s(s, len_clnt_addr); // Skip Unicode clientAddress
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_EXTENDED_INFO_PACKET clientDir"))
{ return1;
}
in_uint16_le(s, len_clnt_dir); if (len_clnt_dir > INFO_CLIENT_MAX_CB_LEN ||
!s_check_rem(s, len_clnt_dir))
{
LOG(LOG_LEVEL_ERROR, "clientDir is too long (%u bytes)", len_clnt_dir); return1;
}
in_uint8s(s, len_clnt_dir); // Skip Unicode clientDir
/*****************************************************************************/ /* Generate a MAC hash (5.2.3.1), using SHA1 for outgoing data */ staticvoid
xrdp_sec_fips_sign(struct xrdp_sec *self, char *out, int out_len, char *data, int data_len)
{ char buf[20]; char lenhdr[4];
/*****************************************************************************/ /* Check a FIPS hash is valid * *Resultisboolean(i.e.!=0isOK)
* */ staticint
xrdp_sec_fips_check_sig(struct xrdp_sec *self, constchar *sig, int sig_len, char *data, int data_len)
{ char buf[20]; char lenhdr[4];
// Account for the decrypt operation which has just happened when // creating the HMAC
buf_out_uint32(lenhdr, self->decrypt_use_count - 1);
ssl_hmac_sha1_init(self->sign_fips_info, self->fips_sign_key, 20);
ssl_hmac_transform(self->sign_fips_info, data, data_len);
ssl_hmac_transform(self->sign_fips_info, lenhdr, 4);
ssl_hmac_complete(self->sign_fips_info, buf, 20);
return memcmp(buf, sig, sig_len) == 0;
}
/*****************************************************************************/ /* Generate a MAC hash (5.3.6.1), using a combination of SHA1 and MD5 *
* Salted MAC is not currently supported */ staticvoid
xrdp_sec_sign(struct xrdp_sec *self, char *out, int out_len, char *data, int data_len)
{ char shasig[20]; char md5sig[16]; char lenhdr[4]; void *sha1_info; void *md5_info;
/*****************************************************************************/ staticvoid
fips_expand_key_bits(constchar *in, char *out)
{
tui8 buf[32];
tui8 c; int i; int b; int p; int r;
/* reverse every byte in the key */ for (i = 0; i < 21; i++)
{
c = in[i];
buf[i] = g_fips_reverse_table[c];
} /* insert a zero-bit after every 7th bit */ for (i = 0, b = 0; i < 24; i++, b += 7)
{
p = b / 8;
r = b % 8; if (r == 0)
{
out[i] = buf[p] & 0xfe;
} else
{ /* c is accumulator */
c = buf[p] << r;
c |= buf[p + 1] >> (8 - r);
out[i] = c & 0xfe;
}
} /* reverse every byte */ /* alter lsb so the byte has odd parity */ for (i = 0; i < 24; i++)
{
c = out[i];
c = g_fips_reverse_table[c];
out[i] = g_fips_oddparity_table[c];
}
}
return0;
} /*****************************************************************************/ /* returns error */ int
xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan)
{ int flags; int len; int ver; int pad;
/* TODO: check if moving this check until after the is_security_header_present causesanyissues. thesecurityheaderisoptional(eg.TLSconnections),sothis checkshouldreallybeafterthecheckifthesecurityheaderispresent,
this currently seems to be working by coincidence at the moment. */ if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPBCGR] TS_SECURITY_HEADER"))
{ return1;
}
if (!(self->is_security_header_present))
{ /* noisy log statement with no real info since this is an expectedstateforTLSconnections
*/
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_sec_recv: security header NOT present"); return0;
}
if (self->crypt_level == CRYPT_LEVEL_NONE
&& self->crypt_method == CRYPT_METHOD_NONE)
{ /* in tls mode, no more security header from now on */
self->is_security_header_present = 0;
}
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv: out 'send demand active'"); return -1; /* special error that means send demand active */
}
return0;
}
/*****************************************************************************/ /* returns error */ int
xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan)
{ int datalen; int pad;
/*****************************************************************************/ /* returns error */ /* 2.2.9.1.2 Server Fast-Path Update PDU (TS_FP_UPDATE_PDU)
* http://msdn.microsoft.com/en-us/library/cc240621.aspx */ int
xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s)
{ int secFlags; int fpOutputHeader; int datalen; int pdulen; int pad; int error; char save[8];
int version; int colorDepth; int postBeta2ColorDepth; int highColorDepth; int supportedColorDepths; int earlyCapabilityFlags;
UNUSED_VAR(version); struct xrdp_client_info *client_info = &self->rdp_layer->client_info; /* Clear physical sizes. These are optional and may not be read later */
client_info->session_physical_width = 0;
client_info->session_physical_height = 0;
/*****************************************************************************/ /* Process a [MS-RDPBCGR] TS_UD_CS_SEC message */ staticint
xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream *s)
{ int crypt_method; int found;
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPBCGR] CS_SECURITY"))
{ return1;
}
in_uint32_le(s, crypt_method);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_SEC " "encryptionMethods 0x%8.8x, extEncryptionMethods (ignored)",
crypt_method); if (crypt_method & CRYPT_METHOD_40BIT)
{
LOG(LOG_LEVEL_DEBUG, "Client supports 40 bit encryption");
} if (crypt_method & CRYPT_METHOD_128BIT)
{
LOG(LOG_LEVEL_DEBUG, "Client supports 128 bit encryption");
} if (crypt_method & CRYPT_METHOD_56BIT)
{
LOG(LOG_LEVEL_DEBUG, "Client supports 56 bit encryption");
} if (crypt_method & CRYPT_METHOD_FIPS)
{
LOG(LOG_LEVEL_DEBUG, "Client supports fips encryption");
}
found = 0; if ((found == 0) &&
(self->mcs_layer->iso_layer->selectedProtocol == PROTOCOL_SSL))
{
LOG(LOG_LEVEL_DEBUG, "The connection is using TLS, skipping RDP crypto negotiation");
found = 1;
} if ((found == 0) &&
(self->crypt_method & CRYPT_METHOD_FIPS) &&
(self->crypt_level == CRYPT_LEVEL_FIPS))
{ if (crypt_method & CRYPT_METHOD_FIPS)
{
LOG(LOG_LEVEL_DEBUG, "Client and server both support fips encryption, " "using RDP fips encryption.");
self->crypt_method = CRYPT_METHOD_FIPS;
self->crypt_level = CRYPT_LEVEL_FIPS;
found = 1;
}
} if ((found == 0) &&
(self->crypt_method & CRYPT_METHOD_128BIT) &&
(self->crypt_level == CRYPT_LEVEL_HIGH))
{ if (crypt_method & CRYPT_METHOD_128BIT)
{
LOG(LOG_LEVEL_DEBUG, "Client and server both support high encryption, " "using RDP 128-bit encryption.");
self->crypt_method = CRYPT_METHOD_128BIT;
self->crypt_level = CRYPT_LEVEL_HIGH;
found = 1;
}
} /* TODO: figure out why both "COMPATIBLE" and "LOW" crypto level both use 40-bitencryption,andwhythereisnocyptomethodfor56-bit encryptioneventhoughthereiscodeforcheckingfor56-bit
encryption */ if ((found == 0) &&
(self->crypt_method & CRYPT_METHOD_40BIT) &&
(self->crypt_level == CRYPT_LEVEL_CLIENT_COMPATIBLE))
{ if (crypt_method & CRYPT_METHOD_40BIT)
{
LOG(LOG_LEVEL_DEBUG, "Client and server both support medium encryption, " "using RDP 40-bit encryption.");
self->crypt_method = CRYPT_METHOD_40BIT;
self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE;
found = 1;
}
} if ((found == 0) &&
(self->crypt_method & CRYPT_METHOD_40BIT) &&
(self->crypt_level == CRYPT_LEVEL_LOW))
{ if (crypt_method & CRYPT_METHOD_40BIT)
{
LOG(LOG_LEVEL_DEBUG, "Client and server both support low encryption, " "using RDP 40-bit encryption.");
self->crypt_method = CRYPT_METHOD_40BIT;
self->crypt_level = CRYPT_LEVEL_LOW;
found = 1;
}
} if ((found == 0) &&
(self->crypt_level == CRYPT_LEVEL_NONE))
{ if (crypt_method == CRYPT_METHOD_NONE)
{
LOG(LOG_LEVEL_DEBUG, "Client and server both support no encryption, " "RDP encryption is disabled.");
self->crypt_method = CRYPT_METHOD_NONE;
self->crypt_level = CRYPT_LEVEL_NONE;
found = 1;
}
} if (found == 0)
{ /* TODO: figure out why failing to find a shared encryption level
does not return an error? */ /* TODO: does the connection fail now or is the default server
encryption used? */
LOG(LOG_LEVEL_WARNING, "Client and server do not both support the same encryption."); // return 1;
} return0;
}
/*****************************************************************************/ /* Process a [MS-RDPBCGR] TS_UD_CS_NET message. Thisaddsthemcschannelsinthelistofchannelstobeusedwhen
creating the server mcs data */ staticint
xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
{ int num_channels; int index; struct xrdp_client_info *client_info; struct mcs_channel_item *channel_item; int next_mcs_channel_id;
client_info = &(self->rdp_layer->client_info); /* this is an option set in xrdp.ini */ if (client_info->channels_allowed == 0) /* are channels on? */
{
LOG(LOG_LEVEL_DEBUG, "All channels are disabled by configuration"); return0;
} if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPBCGR] TS_UD_CS_NET"))
{ return1;
}
in_uint32_le(s, num_channels);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_NET " "channelCount %d", num_channels); if (num_channels > MAX_STATIC_CHANNELS)
{
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Protocol error: too many channels requested. " "max %d, received %d", MAX_STATIC_CHANNELS, num_channels); return1;
}
/* GOTCHA: When adding a channel the MCS channel ID is set to *MCS_GLOBAL_CHANNEL+(index+1).Thisisassumedby *xrdp_channel_process(),whenmappinganincomingPDUintoan
* entry in this array */
next_mcs_channel_id = MCS_GLOBAL_CHANNEL + 1;
for (index = 0; index < num_channels; index++)
{
channel_item = g_new0(struct mcs_channel_item, 1); if (!s_check_rem_and_log(s, 12, "Parsing [MS-RDPBCGR] TS_UD_CS_NET.CHANNEL_DEF"))
{
g_free(channel_item); return1;
}
in_uint8a(s, channel_item->name, CHANNEL_NAME_LEN + 1); // The channel name *should* be null-terminated. Add a back-stop // terminator in case it isn't.
channel_item->name[CHANNEL_NAME_LEN] = '\0';
in_uint32_le(s, channel_item->flags);
channel_item->chanid = next_mcs_channel_id++;
list_add_item(self->mcs_layer->channel_list,
(intptr_t) channel_item);
LOG(LOG_LEVEL_DEBUG, "Adding channel: name %s, channel id %d, flags 0x%8.8x",
channel_item->name, channel_item->chanid, channel_item->flags);
}
/* Set the user channel as well */
self->mcs_layer->chanid = next_mcs_channel_id++;
self->mcs_layer->userid = self->mcs_layer->chanid - MCS_USERCHANNEL_BASE;
LOG_DEVEL(LOG_LEVEL_DEBUG, "MCS user is %d, channel id is %d",
self->mcs_layer->userid, self->mcs_layer->chanid);
return0;
}
/*****************************************************************************/ /* Process a [MS-RDPBCGR] TS_UD_CS_MONITOR message.
reads the client monitors data */ int
xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s)
{ int flags; int error = 0; struct xrdp_client_info *client_info = &(self->rdp_layer->client_info);
/* this is an option set in xrdp.ini */ if (client_info->multimon != 1) /* are multi-monitors allowed ? */
{
LOG(LOG_LEVEL_INFO, "xrdp_sec_process_mcs_data_monitors:" " Multi-monitor is disabled by server config"); return0;
} if (!s_check_rem_and_log(s, 4, "xrdp_sec_process_mcs_data_monitors:" " Parsing [MS-RDPBCGR] TS_UD_CS_MONITOR"))
{ return SEC_PROCESS_MONITORS_ERR;
}
in_uint32_le(s, flags); /* flags */
//verify flags - must be 0x0 if (flags != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_sec_process_mcs_data_monitors: [MS-RDPBCGR]" " Protocol error: TS_UD_CS_MONITOR flags MUST be zero," " received: 0x%8.8x", flags); return SEC_PROCESS_MONITORS_ERR;
}
/*****************************************************************************/ /* Process a [MS-RDPBCGR] TS_UD_CS_MONITOR_EX message.
reads the client monitor's extended data */ int
xrdp_sec_process_mcs_data_monitors_ex(struct xrdp_sec *self, struct stream *s)
{ int flags; struct xrdp_client_info *client_info = &(self->rdp_layer->client_info);
/* this is an option set in xrdp.ini */ if (client_info->multimon != 1) /* are multi-monitors allowed ? */
{ /* This should already be logged in
xrdp_sec_process_mcs_data_monitors() */ return0;
} if (!s_check_rem_and_log(s, 4, "xrdp_sec_process_mcs_data_monitors_ex:" " Parsing [MS-RDPBCGR] TS_UD_CS_MONITOR_EX"))
{ return SEC_PROCESS_MONITORS_ERR;
}
in_uint32_le(s, flags); /* flags */
//verify flags - must be 0x0 if (flags != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_sec_process_mcs_data_monitors_ex: [MS-RDPBCGR]" " Protocol error: TS_UD_CS_MONITOR_EX flags MUST be zero," " received: 0x%8.8x", flags); return SEC_PROCESS_MONITORS_ERR;
}
if (client_info->max_bpp > 0)
{ if (client_info->bpp > client_info->max_bpp)
{
LOG(LOG_LEVEL_WARNING, "Client requested %d bpp color depth, " "but the server configuration is limited to %d bpp. " "Downgrading the color depth to %d bits-per-pixel.",
client_info->bpp,
client_info->max_bpp,
client_info->max_bpp);
client_info->bpp = client_info->max_bpp;
}
}
/* set p to beginning */
s->p = s->data; return0;
}
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.57Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-07-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.