diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c index f36335aa..8a7b1284 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.c @@ -131,6 +131,43 @@ static void guac_rdpdr_send_client_capability(guac_rdpdrPlugin* rdpdr) { } +static void guac_rdpdr_send_client_device_list_announce_request(guac_rdpdrPlugin* rdpdr) { + + STREAM* output_stream = stream_new(256); + + /* Write header */ + stream_write_uint16(output_stream, RDPDR_CTYP_CORE); + stream_write_uint16(output_stream, PAKID_CORE_DEVICELIST_ANNOUNCE); + + /* Only one device for now */ + stream_write_uint32(output_stream, 1); + + /* Printer header */ + guac_client_log_info(rdpdr->client, "Sending printer"); + stream_write_uint32(output_stream, RDPDR_DTYP_PRINT); + stream_write_uint32(output_stream, GUAC_PRINTER_DEVICE_ID); + stream_write(output_stream, "PRN1\0\0\0\0", 8); /* DOS name */ + + /* Printer data */ + stream_write_uint32(output_stream, 24 + GUAC_PRINTER_DRIVER_LENGTH + GUAC_PRINTER_NAME_LENGTH); + stream_write_uint32(output_stream, + RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII + | RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER + | RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER); + stream_write_uint32(output_stream, 0); /* reserved - must be 0 */ + stream_write_uint32(output_stream, 0); /* PnPName length (PnPName is ultimately ignored) */ + stream_write_uint32(output_stream, GUAC_PRINTER_DRIVER_LENGTH); /* DriverName length */ + stream_write_uint32(output_stream, GUAC_PRINTER_NAME_LENGTH); /* PrinterName length */ + stream_write_uint32(output_stream, 0); /* CachedFields length */ + + stream_write(output_stream, GUAC_PRINTER_DRIVER, GUAC_PRINTER_DRIVER_LENGTH); + stream_write(output_stream, GUAC_PRINTER_NAME, GUAC_PRINTER_NAME_LENGTH); + + svc_plugin_send((rdpSvcPlugin*) rdpdr, output_stream); + guac_client_log_info(rdpdr->client, "All supported devices sent."); + +} + void guac_rdpdr_process_server_announce(guac_rdpdrPlugin* rdpdr, STREAM* input_stream) { @@ -141,6 +178,10 @@ void guac_rdpdr_process_server_announce(guac_rdpdrPlugin* rdpdr, stream_read_uint16(input_stream, minor); stream_read_uint32(input_stream, client_id); + /* Must choose own client ID if minor not >= 12 */ + if (minor < 12) + client_id = random() & 0xFFFF; + guac_client_log_info(rdpdr->client, "Connected to RDPDR %u.%u as client 0x%04x", major, minor, client_id); /* Respond to announce */ @@ -153,15 +194,40 @@ void guac_rdpdr_process_server_announce(guac_rdpdrPlugin* rdpdr, void guac_rdpdr_process_clientid_confirm(guac_rdpdrPlugin* rdpdr, STREAM* input_stream) { - /* STUB */ - guac_client_log_info(rdpdr->client, "STUB: clientid_confirm"); + guac_client_log_info(rdpdr->client, "Client ID confirmed"); + guac_rdpdr_send_client_device_list_announce_request(rdpdr); } void guac_rdpdr_process_device_reply(guac_rdpdrPlugin* rdpdr, STREAM* input_stream) { - /* STUB */ - guac_client_log_info(rdpdr->client, "STUB: device_reply"); + unsigned int device_id, ntstatus; + int severity, c, n, facility, code; + + stream_read_uint32(input_stream, device_id); + stream_read_uint32(input_stream, ntstatus); + + severity = ntstatus & 0xC0000000; + c = ntstatus & 0x20000000; + n = ntstatus & 0x10000000; + facility = ntstatus & 0x0FFF0000; + code = ntstatus & 0x0000FFFF; + + /* Log error / information */ + if (device_id == GUAC_PRINTER_DEVICE_ID) { + + if (severity == 0x0) + guac_client_log_info(rdpdr->client, "Printer connected successfully"); + + else + guac_client_log_error(rdpdr->client, "Problem connecting printer: " + "severity=0x%x, c=0x%x, n=0x%x, facility=0x%x, code=0x%x", + severity, c, n, facility, code); + + } + + else + guac_client_log_error(rdpdr->client, "Unknown device ID: 0x%08x", device_id); } @@ -210,8 +276,8 @@ void guac_rdpdr_process_server_capability(guac_rdpdrPlugin* rdpdr, STREAM* input void guac_rdpdr_process_user_loggedon(guac_rdpdrPlugin* rdpdr, STREAM* input_stream) { - /* STUB */ - guac_client_log_info(rdpdr->client, "STUB: user_loggedon"); + guac_client_log_info(rdpdr->client, "User logged on"); + guac_rdpdr_send_client_device_list_announce_request(rdpdr); } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h index 536e37ab..495decaa 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h @@ -75,6 +75,23 @@ */ #define GUAC_OS_TYPE (*((uint32_t*) "GUAC")) +/** + * Arbitray 32-bit unique integer representing the printer device. + */ +#define GUAC_PRINTER_DEVICE_ID (*((uint32_t*) "GPR1")) + +/** + * Name of the printer driver that should be used on the server. + */ +#define GUAC_PRINTER_DRIVER "MS Publisher Imagesetter" +#define GUAC_PRINTER_DRIVER_LENGTH (strlen(GUAC_PRINTER_DRIVER)+1) + +/** + * Name of the printer itself. + */ +#define GUAC_PRINTER_NAME "\0G\0u\0a\0c\0a\0m\0o\0l\0e\0\0" +#define GUAC_PRINTER_NAME_LENGTH 20 + /* * Capability types */ @@ -121,6 +138,26 @@ #define RDPDR_CLIENT_DISPLAY_NAME 0x2 #define RDPDR_USER_LOGGEDON_PDU 0x4 +/* + * Device types. + */ + +#define RDPDR_DTYP_SERIAL 0x00000001 +#define RDPDR_DTYP_PARALLEL 0x00000002 +#define RDPDR_DTYP_PRINT 0x00000004 +#define RDPDR_DTYP_FILESYSTEM 0x00000008 +#define RDPDR_DTYP_SMARTCARD 0x00000020 + +/* + * Printer flags. + */ + +#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010 + /* * Message handlers. */