mirror of https://github.com/FreeRDP/FreeRDP
added command line options to specify preconnection PDU information
This commit is contained in:
parent
3c6df95978
commit
d9c260f221
|
@ -296,7 +296,10 @@ struct rdp_settings
|
|||
ALIGN64 boolean local; /* 68 */
|
||||
ALIGN64 boolean authentication_only; /* 69 */
|
||||
ALIGN64 boolean from_stdin; /* 70 */
|
||||
ALIGN64 uint64 paddingC[80 - 71]; /* 71 */
|
||||
ALIGN64 boolean send_preconnection_pdu; /* 71 */
|
||||
ALIGN64 uint32 preconnection_id; /* 72 */
|
||||
ALIGN64 char* preconnection_blob; /* 73 */
|
||||
ALIGN64 uint64 paddingC[80 - 74]; /* 74 */
|
||||
|
||||
/* User Interface Parameters */
|
||||
ALIGN64 boolean sw_gdi; /* 80 */
|
||||
|
|
|
@ -55,25 +55,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// XXX: Send a PCB (preconnection BLOB) as specified in MS-RDPEPS (RDP_PRECONNECTION_PDU_V2)
|
||||
boolean rdp_send_pcb(rdpNego* nego) {
|
||||
STREAM* s;
|
||||
// XXX: this is a fixed RDP_PRECONNECTION_PDU_V2, with Id=0 and a Hyper-V instance id as string
|
||||
// must be customizable in the final version.
|
||||
// 49ECFD99-8A50-43DC-B2EF-39965652C371
|
||||
uint8 buf[] = {0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 52, 0, 57, 0, 69, 0, 67, 0, 70, 0, 68, 0, 57, 0, 57, 0, 45, 0, 56, 0, 65, 0, 53, 0, 48, 0, 45, 0, 52, 0, 51, 0, 68, 0, 67, 0, 45, 0, 66, 0, 50, 0, 69, 0, 70, 0, 45, 0, 51, 0, 57, 0, 57, 0, 54, 0, 53, 0, 54, 0, 53, 0, 50, 0, 67, 0, 51, 0, 55, 0, 49, 0, 0x00, 0x00};
|
||||
|
||||
if(!nego_tcp_connect(nego)) return false;
|
||||
|
||||
s = transport_send_stream_init(nego->transport, 93);
|
||||
stream_write(s, buf, 92);
|
||||
|
||||
if (transport_write(nego->transport, s) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish RDP Connection based on the settings given in the 'rdp' paremeter.
|
||||
* @msdn{cc240452}
|
||||
|
@ -88,6 +69,10 @@ boolean rdp_client_connect(rdpRdp* rdp)
|
|||
nego_init(rdp->nego);
|
||||
nego_set_target(rdp->nego, settings->hostname, settings->port);
|
||||
nego_set_cookie(rdp->nego, settings->username);
|
||||
nego_set_send_preconnection_pdu(rdp->nego, settings->send_preconnection_pdu);
|
||||
nego_set_preconnection_id(rdp->nego, settings->preconnection_id);
|
||||
nego_set_preconnection_blob(rdp->nego, settings->preconnection_blob);
|
||||
|
||||
nego_set_negotiation_enabled(rdp->nego, settings->security_layer_negotiation);
|
||||
nego_enable_rdp(rdp->nego, settings->rdp_security);
|
||||
|
||||
|
@ -97,8 +82,6 @@ boolean rdp_client_connect(rdpRdp* rdp)
|
|||
nego_enable_tls(rdp->nego, settings->tls_security);
|
||||
}
|
||||
|
||||
rdp_send_pcb(rdp->nego); // XXX: different name?!
|
||||
|
||||
if (!nego_connect(rdp->nego))
|
||||
{
|
||||
printf("Error: protocol security negotiation failure\n");
|
||||
|
|
|
@ -81,6 +81,13 @@ boolean nego_connect(rdpNego* nego)
|
|||
else if (nego->state == NEGO_STATE_RDP)
|
||||
nego->enabled_protocols[PROTOCOL_RDP] = 1;
|
||||
}
|
||||
|
||||
if(!nego_send_preconnection_pdu(nego))
|
||||
{
|
||||
DEBUG_NEGO("Failed to send preconnection information");
|
||||
nego->state = NEGO_STATE_FINAL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
|
@ -143,9 +150,7 @@ boolean nego_security_connect(rdpNego* nego)
|
|||
boolean nego_tcp_connect(rdpNego* nego)
|
||||
{
|
||||
if (!nego->tcp_connected)
|
||||
{
|
||||
nego->tcp_connected = transport_connect(nego->transport, nego->hostname, nego->port);
|
||||
}
|
||||
return nego->tcp_connected;
|
||||
}
|
||||
|
||||
|
@ -160,10 +165,7 @@ boolean nego_transport_connect(rdpNego* nego)
|
|||
nego_tcp_connect(nego);
|
||||
|
||||
if (nego->tcp_connected && !nego->security_layer_negotiation_enabled)
|
||||
{
|
||||
nego_security_connect(nego);
|
||||
return nego->security_connected;
|
||||
}
|
||||
return nego_security_connect(nego);
|
||||
|
||||
return nego->tcp_connected;
|
||||
}
|
||||
|
@ -184,6 +186,55 @@ int nego_transport_disconnect(rdpNego* nego)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send preconnection information if enabled.
|
||||
* @param nego
|
||||
* @return
|
||||
*/
|
||||
|
||||
boolean nego_send_preconnection_pdu(rdpNego* nego)
|
||||
{
|
||||
STREAM* s;
|
||||
uint32 cbSize;
|
||||
UNICONV* uniconv;
|
||||
uint16 cchPCB_times2 = 0;
|
||||
char* wszPCB = NULL;
|
||||
|
||||
if(!nego->send_preconnection_pdu)
|
||||
return true;
|
||||
|
||||
DEBUG_NEGO("Sending preconnection PDU");
|
||||
if(!nego_tcp_connect(nego))
|
||||
return false;
|
||||
|
||||
/* it's easier to always send the version 2 PDU, and it's just 2 bytes overhead */
|
||||
cbSize = PRECONNECTION_PDU_V2_MIN_SIZE;
|
||||
if(nego->preconnection_blob) {
|
||||
uniconv = freerdp_uniconv_new();
|
||||
wszPCB = freerdp_uniconv_out(uniconv, nego->preconnection_blob, &cchPCB_times2);
|
||||
freerdp_uniconv_free(uniconv);
|
||||
cchPCB_times2 += 2; /* zero-termination */
|
||||
cbSize += cchPCB_times2;
|
||||
}
|
||||
|
||||
s = transport_send_stream_init(nego->transport, cbSize);
|
||||
stream_write_uint32(s, cbSize); /* cbSize */
|
||||
stream_write_uint32(s, 0); /* Flags */
|
||||
stream_write_uint32(s, PRECONNECTION_PDU_V2); /* Version */
|
||||
stream_write_uint32(s, nego->preconnection_id); /* Id */
|
||||
stream_write_uint16(s, cchPCB_times2 / 2); /* cchPCB */
|
||||
if(wszPCB)
|
||||
{
|
||||
stream_write(s, wszPCB, cchPCB_times2); /* wszPCB */
|
||||
xfree(wszPCB);
|
||||
}
|
||||
|
||||
if (transport_write(nego->transport, s) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt negotiating NLA + TLS security.
|
||||
* @param nego
|
||||
|
@ -821,3 +872,36 @@ void nego_set_cookie(rdpNego* nego, char* cookie)
|
|||
{
|
||||
nego->cookie = cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable / disable preconnection PDU.
|
||||
* @param nego
|
||||
* @param send_pcpdu
|
||||
*/
|
||||
|
||||
void nego_set_send_preconnection_pdu(rdpNego* nego, boolean send_pcpdu)
|
||||
{
|
||||
nego->send_preconnection_pdu = send_pcpdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set preconnection id.
|
||||
* @param nego
|
||||
* @param id
|
||||
*/
|
||||
|
||||
void nego_set_preconnection_id(rdpNego* nego, uint32 id)
|
||||
{
|
||||
nego->preconnection_id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set preconnection blob.
|
||||
* @param nego
|
||||
* @param blob
|
||||
*/
|
||||
|
||||
void nego_set_preconnection_blob(rdpNego* nego, char* blob)
|
||||
{
|
||||
nego->preconnection_blob = blob;
|
||||
}
|
||||
|
|
|
@ -68,28 +68,41 @@ enum RDP_NEG_MSG
|
|||
|
||||
#define EXTENDED_CLIENT_DATA_SUPPORTED 0x01
|
||||
|
||||
#define PRECONNECTION_PDU_V1_SIZE 16
|
||||
#define PRECONNECTION_PDU_V2_MIN_SIZE (PRECONNECTION_PDU_V1_SIZE+2)
|
||||
|
||||
#define PRECONNECTION_PDU_V1 1
|
||||
#define PRECONNECTION_PDU_V2 2
|
||||
|
||||
struct rdp_nego
|
||||
{
|
||||
int port;
|
||||
uint32 flags;
|
||||
char* hostname;
|
||||
char* cookie;
|
||||
rdpBlob* routing_token;
|
||||
boolean send_preconnection_pdu;
|
||||
uint32 preconnection_id;
|
||||
char* preconnection_blob;
|
||||
|
||||
NEGO_STATE state;
|
||||
boolean tcp_connected;
|
||||
boolean security_connected;
|
||||
rdpBlob* routing_token;
|
||||
|
||||
uint32 selected_protocol;
|
||||
uint32 requested_protocols;
|
||||
boolean security_layer_negotiation_enabled;
|
||||
uint8 enabled_protocols[3];
|
||||
|
||||
rdpTransport* transport;
|
||||
};
|
||||
typedef struct rdp_nego rdpNego;
|
||||
|
||||
boolean nego_connect(rdpNego* nego);
|
||||
boolean nego_tcp_connect(rdpNego* nego);
|
||||
boolean nego_security_connect(rdpNego* nego);
|
||||
|
||||
boolean nego_send_preconnection_pdu(rdpNego* nego);
|
||||
|
||||
void nego_attempt_nla(rdpNego* nego);
|
||||
void nego_attempt_tls(rdpNego* nego);
|
||||
void nego_attempt_rdp(rdpNego* nego);
|
||||
|
@ -115,6 +128,9 @@ void nego_enable_nla(rdpNego* nego, boolean enable_nla);
|
|||
void nego_enable_tls(rdpNego* nego, boolean enable_tls);
|
||||
void nego_set_routing_token(rdpNego* nego, rdpBlob* routing_token);
|
||||
void nego_set_cookie(rdpNego* nego, char* cookie);
|
||||
void nego_set_send_preconnection_pdu(rdpNego* nego, boolean send_pcpdu);
|
||||
void nego_set_preconnection_id(rdpNego* nego, uint32 id);
|
||||
void nego_set_preconnection_blob(rdpNego* nego, char* blob);
|
||||
|
||||
#ifdef WITH_DEBUG_NEGO
|
||||
#define DEBUG_NEGO(fmt, ...) DEBUG_CLASS(NEGO, fmt, ## __VA_ARGS__)
|
||||
|
|
|
@ -133,6 +133,8 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
|||
" --tsg: Terminal Server Gateway (<username> <password> <hostname>)\n"
|
||||
" --kbd-list: list all keyboard layout ids used by -k\n"
|
||||
" --no-salted-checksum: disable salted checksums with Standard RDP encryption\n"
|
||||
" --pcid: preconnection id\n"
|
||||
" --pcb: preconnection blob\n"
|
||||
" --version: print version information\n"
|
||||
"\n", argv[0]);
|
||||
return FREERDP_ARGS_PARSE_HELP; /* TODO: What is the correct return? */
|
||||
|
@ -703,6 +705,28 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
|||
{
|
||||
settings->salted_checksum = false;
|
||||
}
|
||||
else if (strcmp("--pcid", argv[index]) == 0)
|
||||
{
|
||||
index++;
|
||||
if (index == argc)
|
||||
{
|
||||
printf("missing preconnection id value\n");
|
||||
return -1;
|
||||
}
|
||||
settings->send_preconnection_pdu = true;
|
||||
settings->preconnection_id = atoi(argv[index]);
|
||||
}
|
||||
else if (strcmp("--pcb", argv[index]) == 0)
|
||||
{
|
||||
index++;
|
||||
if (index == argc)
|
||||
{
|
||||
printf("missing preconnection blob value\n");
|
||||
return -1;
|
||||
}
|
||||
settings->send_preconnection_pdu = true;
|
||||
settings->preconnection_blob = xstrdup(argv[index]);
|
||||
}
|
||||
else if (strcmp("--version", argv[index]) == 0)
|
||||
{
|
||||
printf("This is FreeRDP version %s\n", FREERDP_VERSION_FULL);
|
||||
|
|
Loading…
Reference in New Issue