Merge pull request #3514 from gpotter2/hyperv-modes

vmconnect mode: support all security modes when used in a Hyper-V environment
This commit is contained in:
matt335672
2025-05-08 15:17:11 +01:00
committed by GitHub
8 changed files with 96 additions and 14 deletions
+6 -1
View File
@@ -35,7 +35,12 @@
#define PROTOCOL_RDSTLS 0x00000004
#define PROTOCOL_HYBRID_EX 0x00000008
/* Negotiation packet flags (2.2.1.2.1) */
/* Negotiation request packet flags (2.2.1.1.1) */
#define RESTRICTED_ADMIN_MODE_REQUIRED 0x00000001
#define REDIRECTED_AUTHENTICATION_MODE_REQUIRED 0x00000002
#define CORRELATION_INFO_PRESENT 0x00000008
/* Negotiation response packet flags (2.2.1.2.1) */
#define EXTENDED_CLIENT_DATA_SUPPORTED 0x01
#define DYNVC_GFX_PROTOCOL_SUPPORTED 0x02
#define NEGRSP_RESERVED 0x04
+2
View File
@@ -181,6 +181,8 @@ struct xrdp_client_info
int require_credentials; /* when true, credentials *must* be passed on cmd line */
int security_layer; /* SECURITY_LAYER_* */
int vmconnect; /* Used when used from inside Hyper-V */
int multimon; /* 0 = deny , 1 = allow */
struct display_size_description display_sizes;
+19
View File
@@ -23,6 +23,25 @@ All options and values (except for file names and paths) are case insensitive, a
.SH "GLOBALS"
The options to be specified in the \fB[Globals]\fR section are the following:
.TP
\fBport\fR=\fIport_specification [ port_specification ... ]\fR
Specify the port(s) that xrdp should listen on. More instructions and
examples can be found within xrdp.ini itself.
.TP
\fBvmconnect\fR=\fI[true|false]\fR
(Hyper-V VMs only). Enables a wider support of security protocols when a
virtual machine running xrdp is hosted on Hyper-V, and the user connects
to it via the vmms service on TCP port 2179. In this configuration,
RDP security is handled by the vmms service, and security features which
are not yet added to xrdp itself can be supported.
This parameter is required in environments which do not support 'classic'
RDP encryption.
The parameter is ignored for connections which are not made to the
virtual machine over the vsock transport.
.TP
\fBautorun\fP=\fIsession_name\fP
Section name for automatic login. If set and the client supplies valid
+54 -8
View File
@@ -72,6 +72,17 @@ xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans)
self = (struct xrdp_iso *) g_malloc(sizeof(struct xrdp_iso), 1);
self->mcs_layer = owner;
self->trans = trans;
// See if we're running in vmconnect mode on this connection
struct xrdp_client_info *client_info = &(self->mcs_layer->sec_layer->rdp_layer->client_info);
if (client_info->vmconnect && trans->mode != TRANS_MODE_VSOCK)
{
char desc[MAX_PEER_DESCSTRLEN];
g_sck_get_peer_description(trans->sck, desc, sizeof(desc));
LOG(LOG_LEVEL_INFO, "Disabling vmconnect mode for connection from %s",
desc);
client_info->vmconnect = 0;
}
return self;
}
@@ -116,6 +127,11 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
{
security_type_mask = PROTOCOL_SSL;
}
/* But VMConnect mode supports everything. */
if (client_info->vmconnect)
{
security_type_mask |= PROTOCOL_HYBRID | PROTOCOL_HYBRID_EX;
}
/* Logically 'and' this value with the mask requested by the client, and
* see what's left */
@@ -124,12 +140,25 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
protostr);
security_type_mask &= self->requestedProtocol;
/* Is there a match on SSL/TLS? */
if ((security_type_mask & PROTOCOL_SSL) != 0)
if (security_type_mask & PROTOCOL_HYBRID_EX)
{
/* Can we do TLS? (basic check) */
if (g_file_readable(client_info->certificate) &&
g_file_readable(client_info->key_file))
/* Currently supported by VMConnect mode only */
LOG(LOG_LEVEL_INFO, "Selected HYBRID_EX security");
self->selectedProtocol = PROTOCOL_HYBRID_EX;
got_protocol = 1;
}
else if (security_type_mask & PROTOCOL_HYBRID)
{
/* Currently supported by VMConnect mode only */
LOG(LOG_LEVEL_INFO, "Selected HYBRID security");
self->selectedProtocol = PROTOCOL_HYBRID;
got_protocol = 1;
}
else if ((security_type_mask & PROTOCOL_SSL) != 0)
{
/* Can we do TLS? (basic check). VMConnect is exempt. */
if ((g_file_readable(client_info->certificate) &&
g_file_readable(client_info->key_file)) || client_info->vmconnect)
{
LOG(LOG_LEVEL_INFO, "Selected TLS security");
self->selectedProtocol = PROTOCOL_SSL;
@@ -205,13 +234,20 @@ xrdp_iso_process_rdp_neg_req(struct xrdp_iso *self, struct stream *s)
/* The type field has already been read to determine that this function
should be called */
in_uint8(s, flags); /* flags */
if (flags != 0x0 && flags != 0x8 && flags != 0x1)
if ((flags & 0x0000000b) != flags)
{
LOG(LOG_LEVEL_ERROR,
"Unsupported [MS-RDPBCGR] RDP_NEG_REQ flags: 0x%2.2x", flags);
return 1;
}
/* If both flags are set, it means 'OR', so fail only if only the one is set. */
if ((flags & REDIRECTED_AUTHENTICATION_MODE_REQUIRED) && !(flags & RESTRICTED_ADMIN_MODE_REQUIRED))
{
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] RDP_NEG_REQ: RemoteGuard isn't supported !");
return 1;
}
in_uint16_le(s, len); /* length */
if (len != 8)
{
@@ -374,9 +410,12 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
char *holdp;
char *len_ptr;
char *len_indicator_ptr;
char flags;
int len;
int len_indicator;
struct xrdp_client_info *client_info = &(self->mcs_layer->sec_layer->rdp_layer->client_info);
make_stream(s);
init_stream(s, 8192);
@@ -410,10 +449,17 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
}
else
{
flags = EXTENDED_CLIENT_DATA_SUPPORTED;
if (client_info->vmconnect)
{
/* NLA is handled by the host and not us. */
flags |= RESTRICTED_ADMIN_MODE_SUPPORTED;
}
/* [MS-RDPBCGR] RDP_NEG_RSP */
out_uint8(s, RDP_NEG_RSP); /* type*/
//TODO: hardcoded flags
out_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */
out_uint8(s, flags); /* flags */
out_uint16_le(s, 8); /* length (must be 8) */
out_uint32_le(s, self->selectedProtocol); /* selectedProtocol */
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding structure [MS-RDPBCGR] RDP_NEG_RSP "
+4
View File
@@ -211,6 +211,10 @@ xrdp_rdp_read_config(const char *xrdp_ini, struct xrdp_client_info *client_info)
client_info->security_layer = SECURITY_LAYER_NEGOTIATE;
}
}
else if (g_strcasecmp(item, "vmconnect") == 0)
{
client_info->vmconnect = g_text2bool(value);
}
else if (g_strcasecmp(item, "certificate") == 0)
{
g_memset(client_info->certificate, 0, sizeof(char) * 1024);
+5 -1
View File
@@ -2252,7 +2252,11 @@ xrdp_sec_incoming(struct xrdp_sec *self)
}
/* initialize selected security layer */
if (iso->selectedProtocol > PROTOCOL_RDP)
if (self->rdp_layer->client_info.vmconnect && iso->selectedProtocol > PROTOCOL_RDP)
{
/* Security handled by host: do nothing. */
}
else if (iso->selectedProtocol > PROTOCOL_RDP)
{
/* init tls security */
+3
View File
@@ -332,6 +332,9 @@ read_xrdp_ini_startup_params(struct xrdp_startup_params *startup_params)
else if (g_strcasecmp(name, "use_vsock") == 0)
{
LOG(LOG_LEVEL_WARNING,
"Config parameter 'use_vsock' is obsolete. "
"Use 'port=vsock://...' instead");
startup_params->use_vsock = g_text2bool(val);
}
+3 -4
View File
@@ -22,10 +22,9 @@ fork=true
; port=vsock://<cid>:<port>
port=3389
; 'port' above should be connected to with vsock instead of tcp
; use this only with number alone in port above
; prefer use vsock://<cid>:<port> above
use_vsock=false
; if used inside a Hyper-V VM through vmconnect and bound on vsock,
; turn this on to enable wider security protocol support.
#vmconnect=true
; Unprivileged User name and group to run the xrdp daemon.
; It is HIGHLY RECOMMENDED you set these values. See the xrdp.ini(5)