Skip to content

Commit c62167e

Browse files
authored
Merge pull request neutrinolabs#3514 from gpotter2/hyperv-modes
vmconnect mode: support all security modes when used in a Hyper-V environment
2 parents b2d4077 + 8547744 commit c62167e

File tree

8 files changed

+96
-14
lines changed

8 files changed

+96
-14
lines changed

common/ms-rdpbcgr.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@
3535
#define PROTOCOL_RDSTLS 0x00000004
3636
#define PROTOCOL_HYBRID_EX 0x00000008
3737

38-
/* Negotiation packet flags (2.2.1.2.1) */
38+
/* Negotiation request packet flags (2.2.1.1.1) */
39+
#define RESTRICTED_ADMIN_MODE_REQUIRED 0x00000001
40+
#define REDIRECTED_AUTHENTICATION_MODE_REQUIRED 0x00000002
41+
#define CORRELATION_INFO_PRESENT 0x00000008
42+
43+
/* Negotiation response packet flags (2.2.1.2.1) */
3944
#define EXTENDED_CLIENT_DATA_SUPPORTED 0x01
4045
#define DYNVC_GFX_PROTOCOL_SUPPORTED 0x02
4146
#define NEGRSP_RESERVED 0x04

common/xrdp_client_info.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ struct xrdp_client_info
181181
int require_credentials; /* when true, credentials *must* be passed on cmd line */
182182

183183
int security_layer; /* SECURITY_LAYER_* */
184+
int vmconnect; /* Used when used from inside Hyper-V */
185+
184186
int multimon; /* 0 = deny , 1 = allow */
185187
struct display_size_description display_sizes;
186188

docs/man/xrdp.ini.5.in

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,25 @@ All options and values (except for file names and paths) are case insensitive, a
2323
.SH "GLOBALS"
2424
The options to be specified in the \fB[Globals]\fR section are the following:
2525

26+
.TP
27+
\fBport\fR=\fIport_specification [ port_specification ... ]\fR
28+
Specify the port(s) that xrdp should listen on. More instructions and
29+
examples can be found within xrdp.ini itself.
30+
31+
.TP
32+
\fBvmconnect\fR=\fI[true|false]\fR
33+
(Hyper-V VMs only). Enables a wider support of security protocols when a
34+
virtual machine running xrdp is hosted on Hyper-V, and the user connects
35+
to it via the vmms service on TCP port 2179. In this configuration,
36+
RDP security is handled by the vmms service, and security features which
37+
are not yet added to xrdp itself can be supported.
38+
39+
This parameter is required in environments which do not support 'classic'
40+
RDP encryption.
41+
42+
The parameter is ignored for connections which are not made to the
43+
virtual machine over the vsock transport.
44+
2645
.TP
2746
\fBautorun\fP=\fIsession_name\fP
2847
Section name for automatic login. If set and the client supplies valid

libxrdp/xrdp_iso.c

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,17 @@ xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans)
7272
self = (struct xrdp_iso *) g_malloc(sizeof(struct xrdp_iso), 1);
7373
self->mcs_layer = owner;
7474
self->trans = trans;
75+
76+
// See if we're running in vmconnect mode on this connection
77+
struct xrdp_client_info *client_info = &(self->mcs_layer->sec_layer->rdp_layer->client_info);
78+
if (client_info->vmconnect && trans->mode != TRANS_MODE_VSOCK)
79+
{
80+
char desc[MAX_PEER_DESCSTRLEN];
81+
g_sck_get_peer_description(trans->sck, desc, sizeof(desc));
82+
LOG(LOG_LEVEL_INFO, "Disabling vmconnect mode for connection from %s",
83+
desc);
84+
client_info->vmconnect = 0;
85+
}
7586
return self;
7687
}
7788

@@ -116,6 +127,11 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
116127
{
117128
security_type_mask = PROTOCOL_SSL;
118129
}
130+
/* But VMConnect mode supports everything. */
131+
if (client_info->vmconnect)
132+
{
133+
security_type_mask |= PROTOCOL_HYBRID | PROTOCOL_HYBRID_EX;
134+
}
119135

120136
/* Logically 'and' this value with the mask requested by the client, and
121137
* see what's left */
@@ -124,12 +140,25 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
124140
protostr);
125141
security_type_mask &= self->requestedProtocol;
126142

127-
/* Is there a match on SSL/TLS? */
128-
if ((security_type_mask & PROTOCOL_SSL) != 0)
143+
if (security_type_mask & PROTOCOL_HYBRID_EX)
144+
{
145+
/* Currently supported by VMConnect mode only */
146+
LOG(LOG_LEVEL_INFO, "Selected HYBRID_EX security");
147+
self->selectedProtocol = PROTOCOL_HYBRID_EX;
148+
got_protocol = 1;
149+
}
150+
else if (security_type_mask & PROTOCOL_HYBRID)
151+
{
152+
/* Currently supported by VMConnect mode only */
153+
LOG(LOG_LEVEL_INFO, "Selected HYBRID security");
154+
self->selectedProtocol = PROTOCOL_HYBRID;
155+
got_protocol = 1;
156+
}
157+
else if ((security_type_mask & PROTOCOL_SSL) != 0)
129158
{
130-
/* Can we do TLS? (basic check) */
131-
if (g_file_readable(client_info->certificate) &&
132-
g_file_readable(client_info->key_file))
159+
/* Can we do TLS? (basic check). VMConnect is exempt. */
160+
if ((g_file_readable(client_info->certificate) &&
161+
g_file_readable(client_info->key_file)) || client_info->vmconnect)
133162
{
134163
LOG(LOG_LEVEL_INFO, "Selected TLS security");
135164
self->selectedProtocol = PROTOCOL_SSL;
@@ -205,13 +234,20 @@ xrdp_iso_process_rdp_neg_req(struct xrdp_iso *self, struct stream *s)
205234
/* The type field has already been read to determine that this function
206235
should be called */
207236
in_uint8(s, flags); /* flags */
208-
if (flags != 0x0 && flags != 0x8 && flags != 0x1)
237+
if ((flags & 0x0000000b) != flags)
209238
{
210239
LOG(LOG_LEVEL_ERROR,
211240
"Unsupported [MS-RDPBCGR] RDP_NEG_REQ flags: 0x%2.2x", flags);
212241
return 1;
213242
}
214243

244+
/* If both flags are set, it means 'OR', so fail only if only the one is set. */
245+
if ((flags & REDIRECTED_AUTHENTICATION_MODE_REQUIRED) && !(flags & RESTRICTED_ADMIN_MODE_REQUIRED))
246+
{
247+
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] RDP_NEG_REQ: RemoteGuard isn't supported !");
248+
return 1;
249+
}
250+
215251
in_uint16_le(s, len); /* length */
216252
if (len != 8)
217253
{
@@ -374,9 +410,12 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
374410
char *holdp;
375411
char *len_ptr;
376412
char *len_indicator_ptr;
413+
char flags;
377414
int len;
378415
int len_indicator;
379416

417+
struct xrdp_client_info *client_info = &(self->mcs_layer->sec_layer->rdp_layer->client_info);
418+
380419
make_stream(s);
381420
init_stream(s, 8192);
382421

@@ -410,10 +449,17 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
410449
}
411450
else
412451
{
452+
flags = EXTENDED_CLIENT_DATA_SUPPORTED;
453+
454+
if (client_info->vmconnect)
455+
{
456+
/* NLA is handled by the host and not us. */
457+
flags |= RESTRICTED_ADMIN_MODE_SUPPORTED;
458+
}
459+
413460
/* [MS-RDPBCGR] RDP_NEG_RSP */
414461
out_uint8(s, RDP_NEG_RSP); /* type*/
415-
//TODO: hardcoded flags
416-
out_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */
462+
out_uint8(s, flags); /* flags */
417463
out_uint16_le(s, 8); /* length (must be 8) */
418464
out_uint32_le(s, self->selectedProtocol); /* selectedProtocol */
419465
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding structure [MS-RDPBCGR] RDP_NEG_RSP "

libxrdp/xrdp_rdp.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ xrdp_rdp_read_config(const char *xrdp_ini, struct xrdp_client_info *client_info)
211211
client_info->security_layer = SECURITY_LAYER_NEGOTIATE;
212212
}
213213
}
214+
else if (g_strcasecmp(item, "vmconnect") == 0)
215+
{
216+
client_info->vmconnect = g_text2bool(value);
217+
}
214218
else if (g_strcasecmp(item, "certificate") == 0)
215219
{
216220
g_memset(client_info->certificate, 0, sizeof(char) * 1024);

libxrdp/xrdp_sec.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2252,7 +2252,11 @@ xrdp_sec_incoming(struct xrdp_sec *self)
22522252
}
22532253

22542254
/* initialize selected security layer */
2255-
if (iso->selectedProtocol > PROTOCOL_RDP)
2255+
if (self->rdp_layer->client_info.vmconnect && iso->selectedProtocol > PROTOCOL_RDP)
2256+
{
2257+
/* Security handled by host: do nothing. */
2258+
}
2259+
else if (iso->selectedProtocol > PROTOCOL_RDP)
22562260
{
22572261
/* init tls security */
22582262

xrdp/xrdp.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@ read_xrdp_ini_startup_params(struct xrdp_startup_params *startup_params)
332332

333333
else if (g_strcasecmp(name, "use_vsock") == 0)
334334
{
335+
LOG(LOG_LEVEL_WARNING,
336+
"Config parameter 'use_vsock' is obsolete. "
337+
"Use 'port=vsock://...' instead");
335338
startup_params->use_vsock = g_text2bool(val);
336339
}
337340

xrdp/xrdp.ini.in

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@ fork=true
2222
; port=vsock://<cid>:<port>
2323
port=3389
2424

25-
; 'port' above should be connected to with vsock instead of tcp
26-
; use this only with number alone in port above
27-
; prefer use vsock://<cid>:<port> above
28-
use_vsock=false
25+
; if used inside a Hyper-V VM through vmconnect and bound on vsock,
26+
; turn this on to enable wider security protocol support.
27+
#vmconnect=true
2928

3029
; Unprivileged User name and group to run the xrdp daemon.
3130
; It is HIGHLY RECOMMENDED you set these values. See the xrdp.ini(5)

0 commit comments

Comments
 (0)