diff --git a/common/log.h b/common/log.h index 6cbd0a62..ad2eb086 100644 --- a/common/log.h +++ b/common/log.h @@ -22,6 +22,7 @@ #include #include "arch.h" +#include "defines.h" #include "list.h" /* logging buffer size */ @@ -95,7 +96,7 @@ enum logReturns * @param ... the arguments for the printf format c-string */ #define LOG_DEVEL(log_level, args...) \ - log_message_with_location(__func__, __FILE__, __LINE__, log_level, args); + log_message_with_location(__func__, __FILE__, __LINE__, log_level, args) /** * @brief Logging macro for messages that are for a systeam administrator to @@ -109,7 +110,7 @@ enum logReturns * @param ... the arguments for the printf format c-string */ #define LOG(log_level, args...) \ - log_message_with_location(__func__, __FILE__, __LINE__, log_level, args); + log_message_with_location(__func__, __FILE__, __LINE__, log_level, args) /** * @brief Logging macro for logging the contents of a byte array using a hex @@ -124,12 +125,16 @@ enum logReturns * @param length, the length of the byte array to log */ #define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) \ - log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length); + log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length) #else -#define LOG_DEVEL(log_level, args...) -#define LOG(log_level, args...) log_message(log_level, args); -#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) +#define LOG(log_level, args...) log_message(log_level, args) + +/* Since log_message() returns a value ensure that the elided versions of + * LOG_DEVEL and LOG_DEVEL_HEXDUMP also "fake" returning the success value + */ +#define LOG_DEVEL(log_level, args...) UNUSED_VAR(LOG_STARTUP_OK) +#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) UNUSED_VAR(LOG_STARTUP_OK) #endif diff --git a/common/ms-rdpbcgr.h b/common/ms-rdpbcgr.h index 03e03c39..52b737b9 100644 --- a/common/ms-rdpbcgr.h +++ b/common/ms-rdpbcgr.h @@ -369,6 +369,15 @@ #define PDUTYPE_DATAPDU 0x7 #define PDUTYPE_SERVER_REDIR_PKT 0xA +#define PDUTYPE_TO_STR(pdu_type) \ + ((pdu_type) == PDUTYPE_DEMANDACTIVEPDU ? "PDUTYPE_DEMANDACTIVEPDU" : \ + (pdu_type) == PDUTYPE_CONFIRMACTIVEPDU ? "PDUTYPE_CONFIRMACTIVEPDU" : \ + (pdu_type) == PDUTYPE_DEACTIVATEALLPDU ? "PDUTYPE_DEACTIVATEALLPDU" : \ + (pdu_type) == PDUTYPE_DATAPDU ? "PDUTYPE_DATAPDU" : \ + (pdu_type) == PDUTYPE_SERVER_REDIR_PKT ? "PDUTYPE_SERVER_REDIR_PKT" : \ + "unknown" \ + ) + /* Share Data Header: pduType2 (2.2.8.1.1.1.2) */ /* TODO: to be renamed */ #define RDP_DATA_PDU_UPDATE 2 /* PDUTYPE2_UPDATE */ @@ -378,6 +387,9 @@ #define RDP_DATA_PDU_SYNCHRONISE 31 #define PDUTYPE2_REFRESH_RECT 33 #define RDP_DATA_PDU_PLAY_SOUND 34 +#define PDUTYPE2_SUPPRESS_OUTPUT 35 +#define PDUTYPE2_SHUTDOWN_REQUEST 36 +#define PDUTYPE2_SHUTDOWN_DENIED 37 #define RDP_DATA_PDU_LOGON 38 #define RDP_DATA_PDU_FONT2 39 #define RDP_DATA_PDU_DISCONNECT 47 @@ -457,6 +469,14 @@ #define RDP_UPDATE_PALETTE 2 #define RDP_UPDATE_SYNCHRONIZE 3 +#define GRAPHICS_UPDATE_TYPE_TO_STR(type) \ + ((type) == RDP_UPDATE_ORDERS ? "RDP_UPDATE_ORDERS" : \ + (type) == RDP_UPDATE_BITMAP ? "RDP_UPDATE_BITMAP" : \ + (type) == RDP_UPDATE_PALETTE ? "RDP_UPDATE_PALETTE" : \ + (type) == RDP_UPDATE_SYNCHRONIZE ? "RDP_UPDATE_SYNCHRONIZE" : \ + "unknown" \ + ) + /* Server Pointer Update PDU: messageType (2.2.9.1.1.4) */ /* TODO: to be renamed */ #define RDP_POINTER_SYSTEM 1 /* TS_PTRMSGTYPE_SYSTEM */ diff --git a/common/parse.h b/common/parse.h index b7f93bfe..4be6fbef 100644 --- a/common/parse.h +++ b/common/parse.h @@ -26,6 +26,7 @@ #define PARSE_H #include "arch.h" +#include "log.h" #if defined(L_ENDIAN) #elif defined(B_ENDIAN) @@ -54,17 +55,63 @@ struct stream }; /******************************************************************************/ -#define s_check(s) ((s)->p <= (s)->end) +#define s_check(s) s_check_rem(s, 0) /******************************************************************************/ #define s_check_rem(s, n) ((s)->p + (n) <= (s)->end) +/******************************************************************************/ +/** + * @returns true if there are at least n bytes remaining in the stream, + * else false and logs an error message + */ +#define s_check_rem_and_log(s, n, msg_prefix) \ + ( s_check_rem((s), (n)) ? \ + 1 : \ + LOG(LOG_LEVEL_ERROR, \ + "%s Not enough bytes in the stream: expected %d, remaining %d", \ + (msg_prefix), (n), s_rem(s)) \ + && 0 ) + /******************************************************************************/ #define s_check_rem_out(s, n) ((s)->p + (n) <= (s)->data + (s)->size) +/******************************************************************************/ +/** + * @returns true if there are at least n bytes remaining in the stream, + * else false and logs an error message + */ +#define s_check_rem_out_and_log(s, n, msg_prefix) \ + ( s_check_rem_out((s), (n)) ? \ + 1 : \ + LOG(LOG_LEVEL_ERROR, \ + "%s Not enough bytes in the stream: expected %d, remaining %d", \ + (msg_prefix), (n), s_rem_out(s)) \ + && 0 ) + /******************************************************************************/ #define s_check_end(s) ((s)->p == (s)->end) +/******************************************************************************/ +/** + * @returns true if there are exactly 0 bytes remaining in the stream, + * else false and logs an error message + */ +#define s_check_end_and_log(s, msg_prefix) \ + ( s_check_end((s)) ? \ + 1 : \ + LOG(LOG_LEVEL_ERROR, \ + "%s Expected to be at the end of the stream, " \ + "but there are %d bytes remaining", \ + (msg_prefix), s_rem(s)) \ + && 0 ) + +/******************************************************************************/ +#define s_rem(s) ((int) ((s)->end - (s)->p)) + +/******************************************************************************/ +#define s_rem_out(s) ((int) ((s)->data + (s)->size - (s)->p)) + /******************************************************************************/ #define make_stream(s) \ (s) = (struct stream*)g_malloc(sizeof(struct stream), 1) diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index 7b777e3d..f9eca7d6 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -95,8 +95,8 @@ * not yet sorted out */ -#define MCS_CONNECT_INITIAL 0x7f65 -#define MCS_CONNECT_RESPONSE 0x7f66 +#define MCS_CONNECT_INITIAL 0x7f65 /* MCS BER: big endian, class=application (0x4000), constructed (0x2000), tag number > 30 (0x1f00), tag number=101 (0x0065) */ +#define MCS_CONNECT_RESPONSE 0x7f66 /* MCS BER: application 102 */ #define BER_TAG_BOOLEAN 1 #define BER_TAG_INTEGER 2 diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index f36ea40e..ec4aebed 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -132,19 +132,19 @@ libxrdp_force_read(struct trans *trans) if (trans_force_read(trans, 4) != 0) { - LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: header read error"); - return 0; + LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: header read error"); + return NULL; } bytes = libxrdp_get_pdu_bytes(s->data); if (bytes < 4 || bytes > s->size) { - LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: bad header length %d", bytes); - return 0; + LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: bad header length %d", bytes); + return NULL; } if (trans_force_read(trans, bytes - 4) != 0) { - LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: Can't read PDU"); - return 0; + LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: Can't read PDU"); + return NULL; } return s; } @@ -234,12 +234,16 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) dead_lock_counter++; break; case PDUTYPE_CONFIRMACTIVEPDU: + LOG_DEVEL(LOG_LEVEL_TRACE, "Processing received " + "[MS-RDPBCGR] PDUTYPE_CONFIRMACTIVEPDU"); xrdp_caps_process_confirm_active(rdp, s); break; case PDUTYPE_DATAPDU: + LOG_DEVEL(LOG_LEVEL_TRACE, "Processing received " + "[MS-RDPBCGR] PDUTYPE_DATAPDU"); if (xrdp_rdp_process_data(rdp, s) != 0) { - LOG(LOG_LEVEL_ERROR, "libxrdp_process_data returned non zero"); + LOG(LOG_LEVEL_ERROR, "libxrdp_process_data: xrdp_rdp_process_data failed"); cont = 0; term = 1; } @@ -247,13 +251,13 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) case 2: /* FASTPATH_INPUT_EVENT */ if (xrdp_fastpath_process_input_event(rdp->sec_layer->fastpath_layer, s) != 0) { - LOG(LOG_LEVEL_ERROR, "libxrdp_process_data returned non zero"); + LOG(LOG_LEVEL_ERROR, "libxrdp_process_data: xrdp_fastpath_process_input_event failed"); cont = 0; term = 1; } break; default: - LOG(LOG_LEVEL_ERROR, "unknown in libxrdp_process_data: code= %d", code); + LOG(LOG_LEVEL_WARNING, "unknown code = %d (ignored)", code); dead_lock_counter++; break; } @@ -262,8 +266,9 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) { /*This situation can happen and this is a workaround*/ cont = 0; - LOG(LOG_LEVEL_ERROR, "Serious programming error: we were locked in a deadly loop"); - LOG(LOG_LEVEL_ERROR, "Remaining: %d", (int) (s->end - s->next_packet)); + LOG(LOG_LEVEL_WARNING, + "Serious programming error: we were locked in a deadly loop. " + "Remaining bytes: %d", (int) (s->end - s->next_packet)); s->next_packet = 0; } @@ -292,7 +297,9 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette) return 0; } - LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_palette sending palette"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "sending palette (%s)", + ((session->client_info->use_fast_path & 1) ? + "fastpath" : "slowpath")); /* clear orders */ libxrdp_orders_force_send(session); @@ -301,25 +308,25 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette) if (session->client_info->use_fast_path & 1) /* fastpath output supported */ { - LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_palette: fastpath"); if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_send_palette: xrdp_rdp_init_fastpath failed"); free_stream(s); return 1; } } else { - LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_palette: slowpath"); xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); } /* TS_UPDATE_PALETTE_DATA */ - out_uint16_le(s, RDP_UPDATE_PALETTE); - out_uint16_le(s, 0); - out_uint16_le(s, 256); /* # of colors */ - out_uint16_le(s, 0); + out_uint16_le(s, RDP_UPDATE_PALETTE); /* updateType */ + out_uint16_le(s, 0); /* pad2Octets */ + out_uint16_le(s, 256); /* # of colors (low-bytes) */ + out_uint16_le(s, 0); /* # of colors (high-bytes) */ + /* paletteEntries */ for (i = 0; i < 256; i++) { color = palette[i]; @@ -331,15 +338,24 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette) s_mark_end(s); if (session->client_info->use_fast_path & 1) /* fastpath output supported */ { + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_UPDATE_PALETTE " + "paletteUpdateData = { updateType %d (UPDATETYPE_PALETTE), " + "pad2Octets , numberColors 256, " + "paletteEntries }", RDP_UPDATE_PALETTE); if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, FASTPATH_UPDATETYPE_PALETTE) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_send_palette: xrdp_rdp_send_fastpath failed"); free_stream(s); return 1; } } else { + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_PALETTE_DATA " + "updateType %d (UPDATETYPE_PALETTE), pad2Octets , " + "numberColors 256, paletteEntries ", + RDP_UPDATE_PALETTE); xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_UPDATE); } @@ -364,14 +380,12 @@ libxrdp_send_bell(struct xrdp_session *session) { struct stream *s = (struct stream *)NULL; - LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_bell sending bell signal"); - /* see MS documentation: Server play sound PDU, TS_PLAY_SOUND_PDU_DATA */ - make_stream(s); init_stream(s, 8192); if (xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_send_bell: xrdp_rdp_init_data failed"); free_stream(s); return 1; } @@ -384,6 +398,7 @@ libxrdp_send_bell(struct xrdp_session *session) if (xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_PLAY_SOUND) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_send_bell: xrdp_rdp_send_data failed"); free_stream(s); return 1; } @@ -461,7 +476,7 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, total_bufsize = 0; num_updates = 0; xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); - out_uint16_le(s, RDP_UPDATE_BITMAP); + out_uint16_le(s, RDP_UPDATE_BITMAP); /* updateType */ p_num_updates = s->p; out_uint8s(s, 2); /* num_updates set later */ @@ -564,6 +579,11 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, p_num_updates[0] = num_updates; p_num_updates[1] = num_updates >> 8; + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_BITMAP_DATA " + "updateType %d (UPDATETYPE_BITMAP), numberRectangles %d, " + "rectangles ", + RDP_UPDATE_BITMAP, num_updates); + xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_UPDATE); @@ -668,6 +688,10 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, } s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_BITMAP_DATA " + "updateType %d (UPDATETYPE_BITMAP), numberRectangles 1, " + "rectangles ", + RDP_UPDATE_BITMAP); xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_UPDATE); i = i + lines_sending; @@ -692,7 +716,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, int j; int data_bytes; - LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_pointer sending cursor"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "sending cursor"); if (bpp == 0) { bpp = 24; @@ -702,14 +726,17 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, { if (bpp != 24) { - LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: error client does not support " - "new cursors and bpp is %d", bpp); + LOG(LOG_LEVEL_ERROR, "Send pointer: client does not support " + "new cursors. The only valid bpp is 24, received %d", bpp); return 1; } } - if ((bpp == 15) && (bpp != 16) && (bpp != 24) && (bpp != 32)) + + if ((bpp != 16) && (bpp != 24) && (bpp != 32)) { - LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: error"); + LOG(LOG_LEVEL_ERROR, + "Send pointer: invalid bpp value. Expected 16 or 24 or 32, " + "received %d", bpp); return 1; } make_stream(s); @@ -720,6 +747,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: fastpath"); if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_init_fastpath failed"); free_stream(s); return 1; } @@ -731,7 +759,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, else { data_bytes = ((bpp + 7) / 8) * 32 * 32; - out_uint16_le(s, bpp); + out_uint16_le(s, bpp); /* TS_FP_POINTERATTRIBUTE -> newPointerUpdateData.xorBpp */ } } else /* slowpath */ @@ -743,25 +771,34 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, out_uint16_le(s, RDP_POINTER_COLOR); out_uint16_le(s, 0); /* pad */ data_bytes = 3072; + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU " + "messageType %d (TS_PTRMSGTYPE_COLOR), pad2Octets ", + RDP_POINTER_COLOR); } else { out_uint16_le(s, RDP_POINTER_POINTER); out_uint16_le(s, 0); /* pad */ - out_uint16_le(s, bpp); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU " + "messageType %d (TS_PTRMSGTYPE_POINTER), pad2Octets ", + RDP_POINTER_POINTER); + + out_uint16_le(s, bpp); /* TS_POINTERATTRIBUTE -> xorBpp */ data_bytes = ((bpp + 7) / 8) * 32 * 32; } } + /* the TS_COLORPOINTERATTRIBUTE field which is shared by + all of the pointer attribute PDU types */ + out_uint16_le(s, cache_idx); /* cache_idx */ + out_uint16_le(s, x); /* hotSpot.xPos */ + out_uint16_le(s, y); /* hotSpot.yPos */ + out_uint16_le(s, 32); /* width */ + out_uint16_le(s, 32); /* height */ + out_uint16_le(s, 128); /* lengthAndMask */ + out_uint16_le(s, data_bytes); /* lengthXorMask */ - out_uint16_le(s, cache_idx); /* cache_idx */ - out_uint16_le(s, x); - out_uint16_le(s, y); - out_uint16_le(s, 32); - out_uint16_le(s, 32); - out_uint16_le(s, 128); - out_uint16_le(s, data_bytes); - + /* xorMaskData */ switch (bpp) { //case 15: /* coverity: this is logically dead code */ @@ -804,25 +841,42 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, break; } - out_uint8a(s, mask, 128); /* mask */ + out_uint8a(s, mask, 128); /* andMaskData */ out_uint8(s, 0); /* pad */ s_mark_end(s); if (session->client_info->use_fast_path & 1) /* fastpath output supported */ { if ((session->client_info->pointer_flags & 1) == 0) { + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_COLORPOINTERATTRIBUTE " + "cachedPointerUpdateData = { cacheIndex %d, " + "hotSpot.xPos %d, hotSpot.yPos %d, width 32, " + "height 32, lengthAndMask 128, lengthXorMask %d, " + "xorMaskData , " + "andMaskData }", + cache_idx, x, y, data_bytes); if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, FASTPATH_UPDATETYPE_COLOR) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_send_fastpath failed"); free_stream(s); return 1; } } else { + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_POINTERATTRIBUTE " + "newPointerUpdateData.xorBpp %d, " + "newPointerUpdateData.colorPtrAttr = { cacheIndex %d, " + "hotSpot.xPos %d, hotSpot.yPos %d, width 32, " + "height 32, lengthAndMask 128, lengthXorMask %d, " + "xorMaskData , " + "andMaskData }", + bpp, cache_idx, x, y, data_bytes); if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, FASTPATH_UPDATETYPE_POINTER) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_send_fastpath failed"); free_stream(s); return 1; } @@ -830,6 +884,26 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, } else { + if ((session->client_info->pointer_flags & 1) == 0) + { + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_COLORPOINTERATTRIBUTE " + "cacheIndex %d, " + "hotSpot.xPos %d, hotSpot.yPos %d, width 32, " + "height 32, lengthAndMask 128, lengthXorMask %d, " + "xorMaskData , " + "andMaskData ", + cache_idx, x, y, data_bytes); + } + else + { + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_POINTERATTRIBUTE " + "xorBpp %d, colorPtrAttr = { cacheIndex %d, " + "hotSpot.xPos %d, hotSpot.yPos %d, width 32, " + "height 32, lengthAndMask 128, lengthXorMask %d, " + "xorMaskData , " + "andMaskData }", + bpp, cache_idx, x, y, data_bytes); + } xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_POINTER); } @@ -843,26 +917,26 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx) { struct stream *s; - LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_set_pointer sending cursor index"); make_stream(s); init_stream(s, 8192); - if (session->client_info->use_fast_path & 1) /* fastpath output supported */ { - LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: fastpath"); if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_set_pointer: xrdp_rdp_init_fastpath failed"); free_stream(s); return 1; } } else { - LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: slowpath"); xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); out_uint16_le(s, RDP_POINTER_CACHED); out_uint16_le(s, 0); /* pad */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU " + "messageType %d (TS_PTRMSGTYPE_CACHED), pad2Octets ", + RDP_POINTER_CACHED); } out_uint16_le(s, cache_idx); /* cache_idx */ @@ -870,15 +944,20 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx) if (session->client_info->use_fast_path & 1) /* fastpath output supported */ { + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_CACHEDPOINTERATTRIBUTE " + "cachedPointerUpdateData.cacheIndex %d", cache_idx); if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, FASTPATH_UPDATETYPE_CACHED) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_set_pointer: xrdp_rdp_send_fastpath failed"); free_stream(s); return 1; } } else { + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_CACHEDPOINTERATTRIBUTE " + "cacheIndex %d", cache_idx); xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_POINTER); } @@ -1086,12 +1165,14 @@ libxrdp_reset(struct xrdp_session *session, } else { + LOG(LOG_LEVEL_ERROR, "libxrdp_reset: session->client_info is NULL"); return 1; } /* this will send any lingering orders */ if (xrdp_orders_reset((struct xrdp_orders *)session->orders) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_orders_reset failed"); return 1; } @@ -1103,12 +1184,14 @@ libxrdp_reset(struct xrdp_session *session, session->check_for_app_input = 0; if (xrdp_rdp_send_deactivate((struct xrdp_rdp *)session->rdp) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_rdp_send_deactivate failed"); return 1; } /* this should do the resizing */ if (xrdp_caps_send_demand_active((struct xrdp_rdp *)session->rdp) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_caps_send_demand_active failed"); return 1; } @@ -1178,24 +1261,26 @@ libxrdp_query_channel(struct xrdp_session *session, int index, if (index < 0 || index >= count) { - LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - Channel out of range %d", index); + LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel: Channel index out of range. " + "max channel index %d, received channel index %d", + count, index); return 1; } channel_item = (struct mcs_channel_item *) list_get_item(mcs->channel_list, index); - if (channel_item == 0) + if (channel_item == NULL) { /* this should not happen */ - LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - channel item is 0"); + LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - channel item is NULL"); return 1; } if (channel_name != 0) { g_strncpy(channel_name, channel_item->name, 8); - LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - Channel %d name %s", index, channel_name); + LOG(LOG_LEVEL_DEBUG, "libxrdp_query_channel - Channel %d name %s", index, channel_name); } if (channel_flags != 0) @@ -1265,6 +1350,7 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id, if (xrdp_channel_init(chan, s) != 0) { + LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: xrdp_channel_init failed"); free_stream(s); return 1; } @@ -1272,10 +1358,12 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id, /* here we make a copy of the data */ out_uint8a(s, data, data_len); s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] Virtual Channel PDU " + "data "); if (xrdp_channel_send(chan, s, channel_id, total_data_len, flags) != 0) { - LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: error, server channel data NOT sent to client channel"); + LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: xrdp_channel_send failed"); free_stream(s); return 1; } @@ -1297,15 +1385,20 @@ libxrdp_disable_channel(struct xrdp_session *session, int channel_id, mcs = rdp->sec_layer->mcs_layer; if (mcs->channel_list == NULL) { + LOG(LOG_LEVEL_ERROR, "Channel list is NULL"); return 1; } channel_item = (struct mcs_channel_item *) list_get_item(mcs->channel_list, channel_id); if (channel_item == NULL) { + LOG(LOG_LEVEL_ERROR, "Channel item is NULL"); return 1; } channel_item->disabled = is_disabled; + LOG(LOG_LEVEL_DEBUG, "%s channel %d (%s)", + (is_disabled ? "Disabling" : "Enabling"), channel_item->chanid, + channel_item->name); return 1; } @@ -1526,6 +1619,7 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session, LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_fastpath_send_surface:"); if ((session->client_info->use_fast_path & 1) == 0) { + LOG(LOG_LEVEL_ERROR, "Sending data via fastpath is disabled"); return 1; } max_bytes = session->client_info->max_fastpath_frag_bytes; @@ -1539,10 +1633,16 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session, cmd_bytes = 10 + 12; if (data_bytes + rdp_bytes + sec_bytes + cmd_bytes > max_bytes) { + LOG(LOG_LEVEL_ERROR, "Too much data to send via fastpath. " + "Max fastpath bytes %d, received bytes %d", + max_bytes, (data_bytes + rdp_bytes + sec_bytes + cmd_bytes)); return 1; } if (sec_bytes + rdp_bytes + cmd_bytes > pad_bytes) { + LOG(LOG_LEVEL_ERROR, "Too much header to send via fastpath. " + "Max fastpath header bytes %d, received bytes %d", + pad_bytes, (rdp_bytes + sec_bytes + cmd_bytes)); return 1; } g_memset(&ls, 0, sizeof(ls)); @@ -1558,6 +1658,13 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session, out_uint16_le(s, destTop); out_uint16_le(s, destRight); out_uint16_le(s, destBottom); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_SURFCMD_STREAM_SURF_BITS " + "cmdType 0x%4.4x (CMDTYPE_STREAM_SURFACE_BITS), destLeft %d, " + "destTop %d, destRight %d, destBottom %d, " + "bitmapData ", + CMDTYPE_STREAM_SURFACE_BITS, destLeft, destTop, destRight, + destBottom); + /* TS_BITMAP_DATA_EX */ out_uint8(s, bpp); out_uint8(s, 0); @@ -1566,9 +1673,17 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session, out_uint16_le(s, width); out_uint16_le(s, height); out_uint32_le(s, data_bytes); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding field bitmapData [MS-RDPBCGR] TS_BITMAP_DATA_EX " + "bpp %d, flags 0x00, reserved 0, codecID %d, width %d, " + "height %d, bitmapDataLength %d, exBitmapDataHeader , " + "bitmapData ", + bpp, codecID, width, height, data_bytes); + /* 4 = FASTPATH_UPDATETYPE_SURFCMDS */ if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0) { + LOG(LOG_LEVEL_ERROR, + "libxrdp_fastpath_send_surface: xrdp_rdp_send_fastpath failed"); return 1; } return 0; @@ -1585,10 +1700,12 @@ libxrdp_fastpath_send_frame_marker(struct xrdp_session *session, LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_fastpath_send_frame_marker:"); if ((session->client_info->use_fast_path & 1) == 0) { + LOG(LOG_LEVEL_ERROR, "Sending data via fastpath is disabled"); return 1; } if (session->client_info->use_frame_acks == 0) { + LOG(LOG_LEVEL_ERROR, "Fastpath frame acks is disabled"); return 1; } rdp = (struct xrdp_rdp *) (session->rdp); @@ -1599,9 +1716,15 @@ libxrdp_fastpath_send_frame_marker(struct xrdp_session *session, out_uint16_le(s, frame_action); out_uint32_le(s, frame_id); s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FRAME_MARKER " + "cmdType 0x0004 (CMDTYPE_FRAME_MARKER), frameAction 0x%4.4x, " + "frameId %d", frame_action, frame_id); + /* 4 = FASTPATH_UPDATETYPE_SURFCMDS */ if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0) { + LOG(LOG_LEVEL_ERROR, + "libxrdp_fastpath_send_frame_marker: xrdp_rdp_send_fastpath failed"); free_stream(s); return 1; } @@ -1616,7 +1739,6 @@ libxrdp_send_session_info(struct xrdp_session *session, const char *data, { struct xrdp_rdp *rdp; - LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_session_info:"); rdp = (struct xrdp_rdp *) (session->rdp); return xrdp_rdp_send_session_info(rdp, data, data_bytes); } diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index 413a9e41..b0eae8c6 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -33,6 +33,7 @@ #include "file.h" #include "libxrdpinc.h" #include "xrdp_client_info.h" +#include "log.h" /* iso */ @@ -549,9 +550,9 @@ xrdp_codec_jpeg_compress(void *handle, int cy, /* height of area to compress */ int quality, /* higher numbers compress less */ char *out_data, /* dest for jpg image */ - int *io_len /* length of out_data and on return */ - /* len of compressed data */ - ); + int *io_len /* length of out_data and on return + len of compressed data */ + ); void * xrdp_jpeg_init(void); @@ -559,7 +560,7 @@ int xrdp_jpeg_deinit(void *handle); /* xrdp_channel.c */ -struct xrdp_channel* +struct xrdp_channel * xrdp_channel_create(struct xrdp_sec *owner, struct xrdp_mcs *mcs_layer); void xrdp_channel_delete(struct xrdp_channel *self); diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c index 1994966e..567f3ceb 100644 --- a/libxrdp/xrdp_caps.c +++ b/libxrdp/xrdp_caps.c @@ -77,7 +77,8 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s, if (len < 10 + 2) { - LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_general: error"); + LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: " + "len 12, remaining %d", len); return 1; } @@ -103,6 +104,9 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s, } /*****************************************************************************/ +/* + * Process [MS-RDPBCGR] TS_ORDER_CAPABILITYSET (2.2.7.1.3) message. + */ static int xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, int len) @@ -112,10 +116,10 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, int ex_flags; int cap_flags; - LOG_DEVEL(LOG_LEVEL_TRACE, "order capabilities"); if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4) { - LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_order: error"); + LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: " + "len 84, remaining %d", len); return 1; } in_uint8s(s, 20); /* Terminal desc, pad */ @@ -127,33 +131,53 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, in_uint16_le(s, cap_flags); /* Capability flags */ in_uint8a(s, order_caps, 32); /* Orders supported */ g_memcpy(self->client_info.orders, order_caps, 32); - LOG_DEVEL(LOG_LEVEL_TRACE, "dest blt-0 %d", order_caps[0]); - LOG_DEVEL(LOG_LEVEL_TRACE, "pat blt-1 %d", order_caps[1]); - LOG_DEVEL(LOG_LEVEL_TRACE, "screen blt-2 %d", order_caps[2]); - LOG_DEVEL(LOG_LEVEL_TRACE, "memblt-3-13 %d %d", order_caps[3], order_caps[13]); - LOG_DEVEL(LOG_LEVEL_TRACE, "triblt-4-14 %d %d", order_caps[4], order_caps[14]); - LOG_DEVEL(LOG_LEVEL_TRACE, "line-8 %d", order_caps[8]); - LOG_DEVEL(LOG_LEVEL_TRACE, "line-9 %d", order_caps[9]); - LOG_DEVEL(LOG_LEVEL_TRACE, "rect-10 %d", order_caps[10]); - LOG_DEVEL(LOG_LEVEL_TRACE, "desksave-11 %d", order_caps[11]); - LOG_DEVEL(LOG_LEVEL_TRACE, "polygon-20 %d", order_caps[20]); - LOG_DEVEL(LOG_LEVEL_TRACE, "polygon2-21 %d", order_caps[21]); - LOG_DEVEL(LOG_LEVEL_TRACE, "polyline-22 %d", order_caps[22]); - LOG_DEVEL(LOG_LEVEL_TRACE, "ellipse-25 %d", order_caps[25]); - LOG_DEVEL(LOG_LEVEL_TRACE, "ellipse2-26 %d", order_caps[26]); - LOG_DEVEL(LOG_LEVEL_TRACE, "text2-27 %d", order_caps[27]); - LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "order_caps dump", order_caps, 32); + + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: terminalDescriptor (ignored as per protocol spec)"); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveXGranularity (ignored as per protocol spec)"); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveYGranularity (ignored as per protocol spec)"); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: maximumOrderLevel (ignored as per protocol spec)"); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: numberFonts (ignored as per protocol spec)"); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderFlags 0x%4.4x", cap_flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 0: DstBlt %d", order_caps[0]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 1: PatBlt %d", order_caps[1]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 2: ScrBlt %d", order_caps[2]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 3,13: MemBlt %d %d", order_caps[3], order_caps[13]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 4,14: Mem3Blt %d %d", order_caps[4], order_caps[14]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 5-6: unused index"); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 7: DrawNineGrid %d", order_caps[7]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 8: LineTo %d", order_caps[8]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 9: MultiDrawNineGrid %d", order_caps[9]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 10: unused index"); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 11: SaveBitmap %d", order_caps[11]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 12-14: unused index"); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 15: MultiDstBlt %d", order_caps[15]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 16: MultiPatBlt %d", order_caps[16]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 17: MultiScrBlt %d", order_caps[17]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 18: MultiOpaqueRect %d", order_caps[18]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 19: FastIndex %d", order_caps[19]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 20: PolygonSC %d", order_caps[20]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 21: PolygonCB %d", order_caps[21]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 22: Polyline %d", order_caps[22]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 23: unused index"); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 24: FastGlyph %d", order_caps[24]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 25: EllipseSC %d", order_caps[25]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 26: EllipseCB %d", order_caps[26]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 27: GlyphIndex %d", order_caps[27]); + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 28-31: unused index"); + LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: order_caps", order_caps, 32); in_uint8s(s, 2); /* Text capability flags */ + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: textFlags (ignored as per protocol spec)"); /* read extended order support flags */ in_uint16_le(s, ex_flags); /* Ex flags */ + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupportExFlags 0x%4.4x", ex_flags); if (cap_flags & 0x80) /* ORDER_FLAGS_EXTRA_SUPPORT */ { self->client_info.order_flags_ex = ex_flags; if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT) { - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_order: bitmap cache v3 supported"); + LOG_DEVEL(LOG_LEVEL_INFO, "Client Capability: bitmap cache v3 supported"); self->client_info.bitmap_cache_version |= 4; } } @@ -161,15 +185,15 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */ self->client_info.desktop_cache = i; - LOG_DEVEL(LOG_LEVEL_TRACE, "desktop cache size %d", i); - in_uint8s(s, 4); /* Unknown */ - in_uint8s(s, 4); /* Unknown */ + LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveSize %d", i); + in_uint8s(s, 4); /* Pad */ + in_uint8s(s, 4); /* Pad */ /* check if libpainter should be used for drawing, instead of orders */ if (!(order_caps[TS_NEG_DSTBLT_INDEX] && order_caps[TS_NEG_PATBLT_INDEX] && order_caps[TS_NEG_SCRBLT_INDEX] && order_caps[TS_NEG_MEMBLT_INDEX])) { - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_order: not enough orders supported by client, using painter."); + LOG_DEVEL(LOG_LEVEL_INFO, "Client Capability: not enough orders supported by client, using painter."); self->client_info.no_orders_supported = 1; } @@ -186,7 +210,8 @@ xrdp_caps_process_bmpcache(struct xrdp_rdp *self, struct stream *s, if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2) { - LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_bmpcache: error"); + LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: " + "len 36, remaining %d", len); return 1; } self->client_info.bitmap_cache_version |= 1; @@ -229,7 +254,8 @@ xrdp_caps_process_bmpcache2(struct xrdp_rdp *self, struct stream *s, if (len < 2 + 2 + 4 + 4 + 4) { - LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_bmpcache2: error"); + LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: " + "len 16, remaining %d", len); return 1; } self->client_info.bitmap_cache_version |= 2; @@ -271,7 +297,8 @@ xrdp_caps_process_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s, if (len < 1) { - LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_cache_v3_codec_id: error"); + LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: " + "len 1, remaining %d", len); return 1; } in_uint8(s, codec_id); @@ -421,13 +448,24 @@ xrdp_caps_process_rail(struct xrdp_rdp *self, struct stream *s, int len) if (len < 4) { - LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_rail: error"); + LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: " + "len 4, remaining %d", len); return 1; } in_uint32_le(s, i32); self->client_info.rail_support_level = i32; - LOG(LOG_LEVEL_INFO, "xrdp_process_capset_rail: rail_support_level %d", - self->client_info.rail_support_level); + LOG(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - CAPSTYPE_RAIL " + "RailSupportLevel 0x%8.8x (%s%s%s%s%s%s%s%s)", + self->client_info.rail_support_level, + (self->client_info.rail_support_level & 0x01) ? "TS_RAIL_LEVEL_SUPPORTED " : "", + (self->client_info.rail_support_level & 0x02) ? "TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED " : "", + (self->client_info.rail_support_level & 0x04) ? "TS_RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED " : "", + (self->client_info.rail_support_level & 0x08) ? "TS_RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED " : "", + (self->client_info.rail_support_level & 0x10) ? "TS_RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED " : "", + (self->client_info.rail_support_level & 0x20) ? "TS_RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED " : "", + (self->client_info.rail_support_level & 0x40) ? "TS_RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED " : "", + (self->client_info.rail_support_level & 0x80) ? "TS_RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED " : "" + ); return 0; } @@ -448,8 +486,8 @@ xrdp_caps_process_window(struct xrdp_rdp *self, struct stream *s, int len) self->client_info.wnd_num_icon_caches = i32; in_uint16_le(s, i32); self->client_info.wnd_num_icon_cache_entries = i32; - LOG(LOG_LEVEL_INFO, "xrdp_process_capset_window wnd_support_level %d " - "wnd_num_icon_caches %d wnd_num_icon_cache_entries %d", + LOG(LOG_LEVEL_INFO, "xrdp_process_capset_window wnd_support_level %d, " + "wnd_num_icon_caches %d, wnd_num_icon_cache_entries %d", self->client_info.wnd_support_level, self->client_info.wnd_num_icon_caches, self->client_info.wnd_num_icon_cache_entries); @@ -593,6 +631,7 @@ xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len) logging in debug mode */ UNUSED_VAR(cmdFlags); #endif + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_surface_cmds:"); in_uint32_le(s, cmdFlags); in_uint8s(s, 4); /* reserved */ @@ -601,6 +640,9 @@ xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len) } /*****************************************************************************/ +/* + * Process a [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU (2.2.1.13.2.1) message. + */ int xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) { @@ -612,7 +654,6 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) int len; char *p; - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_caps_process_confirm_active"); in_uint8s(s, 4); /* rdp_shareid */ in_uint8s(s, 2); /* userid */ in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */ @@ -620,118 +661,169 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) in_uint8s(s, source_len); in_uint16_le(s, num_caps); in_uint8s(s, 2); /* pad */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU " + "shareID (ignored), originatorID (ignored), lengthSourceDescriptor %d, " + "lengthCombinedCapabilities %d, sourceDescriptor (ignored), " + "numberCapabilities %d", source_len, cap_len, num_caps); if ((cap_len < 0) || (cap_len > 1024 * 1024)) { + LOG(LOG_LEVEL_ERROR, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU " + "lengthCombinedCapabilities %d is too long (> %d)", + cap_len, 1024 * 1024); return 1; } for (index = 0; index < num_caps; index++) { p = s->p; - if (!s_check_rem(s, 4)) + if (!s_check_rem_and_log(s, 4, + "Parsing [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET")) { - LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_confirm_active: error 1"); return 1; } in_uint16_le(s, type); in_uint16_le(s, len); - if ((len < 4) || !s_check_rem(s, len - 4)) + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType %d, lengthCapability %d", type, len); + if (len < 4) + { + LOG(LOG_LEVEL_ERROR, + "Protocol error [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "lengthCapability must be greater than 3, received %d", len); + return 1; + } + if (!s_check_rem_and_log(s, len - 4, + "Parsing [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET ")) { - LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_confirm_active: error: len %d, " - "remaining %d", len, (int) (s->end - s->p)); return 1; } len -= 4; switch (type) { case CAPSTYPE_GENERAL: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_GENERAL"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_GENERAL"); xrdp_caps_process_general(self, s, len); break; case CAPSTYPE_BITMAP: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BITMAP"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_BITMAP - Ignored"); break; case CAPSTYPE_ORDER: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_ORDER"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_ORDER"); xrdp_caps_process_order(self, s, len); break; case CAPSTYPE_BITMAPCACHE: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BMPCACHE"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_BITMAPCACHE"); xrdp_caps_process_bmpcache(self, s, len); break; case CAPSTYPE_CONTROL: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_CONTROL"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_CONTROL - Ignored"); break; case 6: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = 6"); xrdp_caps_process_cache_v3_codec_id(self, s, len); break; case CAPSTYPE_ACTIVATION: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_ACTIVAION"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_ACTIVATION - Ignored"); break; case CAPSTYPE_POINTER: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_POINTER"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_POINTER"); xrdp_caps_process_pointer(self, s, len); break; case CAPSTYPE_SHARE: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_SHARE"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_SHARE - Ignored"); break; case CAPSTYPE_COLORCACHE: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_COLORCACHE"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_COLORCACHE - Ignored"); break; case CAPSTYPE_SOUND: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_SOUND"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_SOUND - Ignored"); break; case CAPSTYPE_INPUT: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_INPUT"); xrdp_caps_process_input(self, s, len); break; case CAPSTYPE_FONT: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_FONT"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_FONT - Ignored"); break; case CAPSTYPE_BRUSH: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_BRUSH"); xrdp_caps_process_brushcache(self, s, len); break; case CAPSTYPE_GLYPHCACHE: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_GLYPHCACHE"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_GLYPHCACHE"); xrdp_caps_process_glyphcache(self, s, len); break; case CAPSTYPE_OFFSCREENCACHE: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_OFFSCREENCACHE"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_OFFSCREENCACHE"); xrdp_caps_process_offscreen_bmpcache(self, s, len); break; case CAPSTYPE_BITMAPCACHE_REV2: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BITMAPCACHE_REV2"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_BITMAPCACHE_REV2"); xrdp_caps_process_bmpcache2(self, s, len); break; case CAPSTYPE_VIRTUALCHANNEL: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_VIRTUALCHANNEL"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_VIRTUALCHANNEL - Ignored"); break; case CAPSTYPE_DRAWNINGRIDCACHE: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_DRAWNINGRIDCACHE"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_DRAWNINGRIDCACHE - Ignored"); break; case CAPSTYPE_DRAWGDIPLUS: - LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_DRAWGDIPLUS"); + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_DRAWGDIPLUS - Ignored"); break; case CAPSTYPE_RAIL: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_RAIL"); xrdp_caps_process_rail(self, s, len); break; case CAPSTYPE_WINDOW: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_WINDOW"); xrdp_caps_process_window(self, s, len); break; case CAPSSETTYPE_MULTIFRAGMENTUPDATE: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSSETTYPE_MULTIFRAGMENTUPDATE"); xrdp_caps_process_multifragmentupdate(self, s, len); break; case CAPSETTYPE_SURFACE_COMMANDS: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSETTYPE_SURFACE_COMMANDS"); xrdp_caps_process_surface_cmds(self, s, len); break; case CAPSSETTYPE_BITMAP_CODECS: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSSETTYPE_BITMAP_CODECS"); xrdp_caps_process_codecs(self, s, len); break; case CAPSTYPE_FRAME_ACKNOWLEDGE: + LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = CAPSTYPE_FRAME_ACKNOWLEDGE"); xrdp_caps_process_frame_ack(self, s, len); break; default: - LOG(LOG_LEVEL_WARNING, "unknown in xrdp_caps_process_confirm_active %d", type); + LOG(LOG_LEVEL_WARNING, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET " + "capabilitySetType = %d is unknown - Ignored", type); break; } @@ -741,7 +833,7 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) if (self->client_info.no_orders_supported && (self->client_info.offscreen_support_level != 0)) { - LOG(LOG_LEVEL_WARNING, "xrdp_caps_process_confirm_active: not enough orders " + LOG(LOG_LEVEL_WARNING, "Client Capability: not enough orders " "supported by client, client wants off screen bitmap but " "offscreen bitmaps disabled"); self->client_info.offscreen_support_level = 0; @@ -749,7 +841,7 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) self->client_info.offscreen_cache_entries = 0; } - LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_caps_process_confirm_active"); + LOG_DEVEL(LOG_LEVEL_TRACE, "Completed processing received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU"); return 0; } /*****************************************************************************/ @@ -771,10 +863,10 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) make_stream(s); init_stream(s, 8192); - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_caps_send_demand_active"); if (xrdp_rdp_init(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_caps_send_demand_active: xrdp_rdp_init failed"); free_stream(s); return 1; } @@ -797,6 +889,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint16_le(s, CAPSTYPE_SHARE_LEN); out_uint16_le(s, self->mcs_channel); out_uint16_be(s, 0xb5e2); /* 0x73e1 */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_SHARE " + "channel ID = 0x%x", self->mcs_channel); /* Output general capability set */ caps_count++; @@ -820,6 +915,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint16_le(s, 0); /* Compression level */ out_uint8(s, 1); /* refreshRectSupport */ out_uint8(s, 1); /* suppressOutputSupport */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_GENERAL TODO"); /* Output bitmap capability set */ caps_count++; @@ -837,11 +934,15 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint16_le(s, 0); /* unknown */ out_uint16_le(s, 0); /* unknown */ out_uint16_le(s, 0); /* pad */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_BITMAP TODO"); /* Output font capability set */ caps_count++; out_uint16_le(s, CAPSTYPE_FONT); out_uint16_le(s, CAPSTYPE_FONT_LEN); + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_FONT"); /* Output order capability set */ caps_count++; @@ -895,6 +996,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint32_le(s, 0x0f4240); /* desk save */ out_uint32_le(s, 1); /* ? */ out_uint32_le(s, 0); /* ? */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_ORDER " + "TODO"); /* Output bmpcodecs capability set */ caps_count++; @@ -912,6 +1016,11 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint8(s, 0x01); /* fAllowDynamicFidelity */ out_uint8(s, 0x01); /* fAllowSubsampling */ out_uint8(s, 0x03); /* colorLossLevel */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "NSCODEC " + "fAllowDynamicFidelity = 0x01," + "fAllowSubsampling = 0x01," + "colorLossLevel = 0x03"); #if defined(XRDP_RFXCODEC) || defined(XRDP_NEUTRINORDP) /* remotefx */ codec_caps_count++; @@ -919,12 +1028,16 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint8(s, 0); /* codec id, client sets */ out_uint16_le(s, 4); /* codecPropertiesLength */ out_uint32_le(s, 0); /* reserved */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "REMOTEFX"); /* image remotefx */ codec_caps_count++; out_uint8a(s, XR_CODEC_GUID_IMAGE_REMOTEFX, 16); out_uint8(s, 0); /* codec id, client sets */ out_uint16_le(s, 4); /* codecPropertiesLength */ out_uint32_le(s, 0); /* reserved */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "IMAGE_REMOTEFX"); #endif /* jpeg */ codec_caps_count++; @@ -932,6 +1045,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint8(s, 0); /* codec id, client sets */ out_uint16_le(s, 1); /* codecPropertiesLength */ out_uint8(s, 75); /* jpeg compression ratio */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "JPEG: " + "jpeg compression ratio = 75"); /* calculate and set size and count */ codec_caps_size = (int)(s->p - codec_caps_size_ptr); codec_caps_size += 2; /* 2 bytes for CAPSTYPE_BMPCODECS above */ @@ -945,6 +1061,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint16_le(s, CAPSTYPE_COLORCACHE_LEN); out_uint16_le(s, 6); /* cache size */ out_uint16_le(s, 0); /* pad */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_COLORCACHE: " + "colorTableCacheSize = 6"); /* Output pointer capability set */ caps_count++; @@ -953,8 +1072,14 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint16_le(s, 1); /* Colour pointer */ out_uint16_le(s, 0x19); /* Cache size */ out_uint16_le(s, 0x19); /* Cache size */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_POINTER: " + "colorPointerFlag = true" + "colorPointerCacheSize = 0x19" + "pointerCacheSize = 0x19"); /* Output input capability set */ + /* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/b3bc76ae-9ee5-454f-b197-ede845ca69cc */ caps_count++; out_uint16_le(s, CAPSTYPE_INPUT); out_uint16_le(s, CAPSTYPE_INPUT_LEN); @@ -970,6 +1095,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) } out_uint16_le(s, flags); out_uint8s(s, 82); + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_INPUT: " + "inputFlags = 0x%x", flags); if (self->client_info.rail_enable) /* MS-RDPERP 3.3.5.1.4 */ { @@ -980,6 +1108,10 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint32_le(s, 3); /* See: https://msdn.microsoft.com/en-us/library/cc242518.aspx TS_RAIL_LEVEL_SUPPORTED TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_RAIL: " + "RailSupportLevel = " + "TS_RAIL_LEVEL_SUPPORTED | TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED"); /* Window List Capability Set */ caps_count++; @@ -988,6 +1120,11 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint32_le(s, TS_WINDOW_LEVEL_SUPPORTED_EX); out_uint8(s, 3); /* NumIconCaches */ out_uint16_le(s, 12); /* NumIconCacheEntries */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_WINDOW: " + "WndSupportLevel = TS_WINDOW_LEVEL_SUPPORTED_EX, " + "NumIconCaches = 3," + "NumIconCacheEntries = 12"); } /* 6 - bitmap cache v3 codecid */ @@ -995,6 +1132,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint16_le(s, 0x0006); out_uint16_le(s, 5); out_uint8(s, 0); /* client sets */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "0x0006 = 0"); if (self->client_info.use_fast_path & FASTPATH_OUTPUT_SUPPORTED) /* fastpath output on */ { @@ -1003,12 +1142,16 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE); out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE_LEN); out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSSETTYPE_MULTIFRAGMENTUPDATE = 3MB"); /* frame acks */ caps_count++; out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE); out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE_LEN); out_uint32_le(s, 2); /* 2 frames in flight */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSTYPE_FRAME_ACKNOWLEDGE = 2 frames"); /* surface commands */ caps_count++; @@ -1018,6 +1161,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) SURFCMDS_FRAMEMARKER | SURFCMDS_STREAMSUFRACEBITS)); /* cmdFlags */ out_uint32_le(s, 0); /* reserved */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability " + "CAPSETTYPE_SURFACE_COMMANDS = " + "SURFCMDS_SETSURFACEBITS | SURFCMDS_FRAMEMARKER | SURFCMDS_STREAMSUFRACEBITS"); } out_uint8s(s, 4); /* pad */ @@ -1033,12 +1179,14 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self) caps_count_ptr[2] = caps_count >> 16; caps_count_ptr[3] = caps_count >> 24; + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: sending PDUTYPE_DEMANDACTIVEPDU " + "message with the server's capabilities"); if (xrdp_rdp_send(self, s, PDUTYPE_DEMANDACTIVEPDU) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_caps_send_demand_active: xrdp_rdp_send failed"); free_stream(s); return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, "out (1) xrdp_caps_send_demand_active"); /* send Monitor Layout PDU for dual monitor */ if (self->client_info.monitorCount > 0 && diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c index 5f506548..9a374cac 100644 --- a/libxrdp/xrdp_channel.c +++ b/libxrdp/xrdp_channel.c @@ -43,6 +43,19 @@ #define XRDP_DRDYNVC_STATUS_OPEN 2 #define XRDP_DRDYNVC_STATUS_CLOSE_SENT 3 +#define XRDP_DRDYNVC_STATUS_TO_STR(status) \ + ((status) == XRDP_DRDYNVC_STATUS_CLOSED ? "CLOSED" : \ + (status) == XRDP_DRDYNVC_STATUS_OPEN_SENT ? "OPEN_SENT" : \ + (status) == XRDP_DRDYNVC_STATUS_OPEN ? "OPEN" : \ + (status) == XRDP_DRDYNVC_STATUS_CLOSE_SENT ? "CLOSE_SENT" : \ + "unknown" \ + ) + +#define XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id) \ + (xrdp_channel_get_item((self), (chan_id)) != NULL \ + ? xrdp_channel_get_item((self), (chan_id))->name \ + : "unknown") + /*****************************************************************************/ /* returns pointer or nil on error */ static struct mcs_channel_item * @@ -52,7 +65,7 @@ xrdp_channel_get_item(struct xrdp_channel *self, int channel_id) if (self->mcs_layer->channel_list == NULL) { - LOG(LOG_LEVEL_ERROR, "xrdp_channel_get_item - No channel initialized"); + LOG(LOG_LEVEL_WARNING, "Channel list is NULL, returning NULL"); return NULL ; } @@ -95,6 +108,7 @@ xrdp_channel_init(struct xrdp_channel *self, struct stream *s) { if (xrdp_sec_init(self->sec_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_channel_init: xrdp_sec_init failed"); return 1; } @@ -115,13 +129,17 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id, if (channel == NULL) { - LOG(LOG_LEVEL_ERROR, "xrdp_channel_send - no such channel"); + LOG(LOG_LEVEL_ERROR, + "Request to send a message to non-existent channel_id %d", + channel_id); return 1; } if (channel->disabled) { - LOG(LOG_LEVEL_WARNING, "xrdp_channel_send, channel disabled"); + LOG(LOG_LEVEL_DEBUG, + "Request to send a message to the disabled channel %s (%d)", + channel->name, channel_id); return 0; /* not an error */ } @@ -145,10 +163,12 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id, // } out_uint32_le(s, flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] CHANNEL_PDU_HEADER " + "length %d, flags 0x%8.8x", total_data_len, flags); if (xrdp_sec_send(self->sec_layer, s, channel->chanid) != 0) { - LOG(LOG_LEVEL_ERROR, "xrdp_channel_send - failure sending data"); + LOG(LOG_LEVEL_ERROR, "xrdp_channel_send: xrdp_sec_send failed"); return 1; } @@ -183,18 +203,28 @@ xrdp_channel_call_callback(struct xrdp_channel *self, struct stream *s, } else { - LOG(LOG_LEVEL_TRACE, "in xrdp_channel_call_callback, session->callback is nil"); + LOG_DEVEL(LOG_LEVEL_WARNING, "session->callback is NULL"); } } else { - LOG(LOG_LEVEL_TRACE, "in xrdp_channel_call_callback, session is nil"); + LOG_DEVEL(LOG_LEVEL_WARNING, "session is NULL"); } return rv; } /*****************************************************************************/ +/** + * Write a variable length unsigned int (1, 2, or 4 bytes) to the stream. + * + * The number of bytes written is the minimum number of bytes needed to + * represent the value. + * + * @param s the stream to write to + * @param val the value to write + * @return the DYNVC cbId length code for the number of bytes written (see [MS-RDPEDYC] 2.2.2.1) + */ static int drdynvc_insert_uint_124(struct stream *s, uint32_t val) { @@ -220,6 +250,17 @@ drdynvc_insert_uint_124(struct stream *s, uint32_t val) } /*****************************************************************************/ +/** + * Read a variable length unsigned int (1, 2, or 4 bytes) from the stream. + * + * The number of bytes read is determined by the cbId bit field flag in the + * cmd argument (see [MS-RDPEDYC] 2.2.2.1). + * + * @param s [in] the stream to read from + * @param cmd [in] the cmd byte which contains the cbId bit field flag + * @param chan_id_p [out] a pointer to the value read from the stream + * @return error code + */ static int drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p) { @@ -229,7 +270,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p) cbChId = cmd & 0x03; if (cbChId == 0) { - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPEDYC] channel id")) { return 1; } @@ -237,7 +278,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p) } else if (cbChId == 1) { - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPEDYC] channel id")) { return 1; } @@ -245,7 +286,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p) } else { - if (!s_check_rem(s, 4)) + if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] channel id")) { return 1; } @@ -256,6 +297,9 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p) } /*****************************************************************************/ +/* + * Process a [MS-RDPEDYC] DYNVC_CAPS_RSP message. + */ static int drdynvc_process_capability_response(struct xrdp_channel *self, int cmd, struct stream *s) @@ -264,18 +308,22 @@ drdynvc_process_capability_response(struct xrdp_channel *self, int cap_version; int rv; - /* skip padding */ - in_uint8s(s, 1); - /* read client's version */ - in_uint16_le(s, cap_version); - if ((cap_version != 2) && (cap_version != 3)) + if (!s_check_rem_and_log(s, 3, "Parsing [MS-RDPEDYC] DYNVC_CAPS_RSP")) { - LOG(LOG_LEVEL_ERROR, "drdynvc_process_capability_response: incompatible DVC " - "version %d detected", cap_version); return 1; } - LOG(LOG_LEVEL_INFO, "drdynvc_process_capability_response: DVC version %d selected", - cap_version); + in_uint8s(s, 1); /* skip padding */ + in_uint16_le(s, cap_version); /* Version */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CAPS_RSP " + "version %d", cap_version); + + if ((cap_version != 2) && (cap_version != 3)) + { + LOG(LOG_LEVEL_ERROR, + "Dynamic Virtual Channel version %d is not supported", + cap_version); + return 1; + } self->drdynvc_state = 1; session = self->sec_layer->rdp_layer->session; rv = session->callback(session->id, 0x5558, 0, 0, 0, 0); @@ -283,6 +331,9 @@ drdynvc_process_capability_response(struct xrdp_channel *self, } /*****************************************************************************/ +/* + * Process a [MS-RDPEDYC] DYNVC_CREATE_RSP message. + */ static int drdynvc_process_open_channel_response(struct xrdp_channel *self, int cmd, struct stream *s) @@ -292,22 +343,27 @@ drdynvc_process_open_channel_response(struct xrdp_channel *self, uint32_t chan_id; struct xrdp_drdynvc *drdynvc; - if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) + if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */ + { + LOG(LOG_LEVEL_ERROR, + "Parsing [MS-RDPEDYC] DYNVC_CREATE_RSP failed"); + return 1; + } + if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] DYNVC_CREATE_RSP")) { return 1; } - if (!s_check_rem(s, 4)) - { - return 1; - } - in_uint32_le(s, creation_status); - LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_open_channel_response: chan_id 0x%x " - "creation_status %d", chan_id, creation_status); - session = self->sec_layer->rdp_layer->session; + in_uint32_le(s, creation_status); /* CreationStatus */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CREATE_RSP " + "ChannelId %d, CreationStatus %d", chan_id, creation_status); if (chan_id > 255) { + LOG(LOG_LEVEL_ERROR, "Received [MS-RDPEDYC] DYNVC_CREATE_RSP for an " + "invalid channel id. Max allowed 255, received %d", chan_id); return 1; } + + session = self->sec_layer->rdp_layer->session; drdynvc = self->drdynvcs + chan_id; if (creation_status == 0) { @@ -317,14 +373,26 @@ drdynvc_process_open_channel_response(struct xrdp_channel *self, { drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED; } + LOG_DEVEL(LOG_LEVEL_DEBUG, + "Dynamic Virtual Channel %s (%d) updated: status = %s", + XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id), + chan_id, + XRDP_DRDYNVC_STATUS_TO_STR(drdynvc->status)); if (drdynvc->open_response != NULL) { return drdynvc->open_response(session->id, chan_id, creation_status); } + LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): " + "callback 'open_response' is NULL", + XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id), + chan_id); return 0; } /*****************************************************************************/ +/* + * Process a [MS-RDPEDYC] DYNVC_CLOSE message. + */ static int drdynvc_process_close_channel_response(struct xrdp_channel *self, int cmd, struct stream *s) @@ -333,26 +401,45 @@ drdynvc_process_close_channel_response(struct xrdp_channel *self, uint32_t chan_id; struct xrdp_drdynvc *drdynvc; - if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) + if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */ { + LOG(LOG_LEVEL_ERROR, + "drdynvc_process_close_channel_response: drdynvc_get_chan_id failed"); return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_close_channel_response: chan_id 0x%x", chan_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CLOSE " + "ChannelId %d", chan_id); session = self->sec_layer->rdp_layer->session; if (chan_id > 255) { + LOG(LOG_LEVEL_ERROR, "Received message for an invalid " + "channel id. channel id %d", chan_id); return 1; } + drdynvc = self->drdynvcs + chan_id; drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED; + LOG_DEVEL(LOG_LEVEL_DEBUG, + "Dynamic Virtual Channel %s (%d) updated: status = %s", + XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id), + chan_id, + XRDP_DRDYNVC_STATUS_TO_STR(drdynvc->status)); + if (drdynvc->close_response != NULL) { return drdynvc->close_response(session->id, chan_id); } + LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): " + "callback 'close_response' is NULL", + XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id), + chan_id); return 0; } /*****************************************************************************/ +/* + * Process a [MS-RDPEDYC] DYNVC_DATA_FIRST message. + */ static int drdynvc_process_data_first(struct xrdp_channel *self, int cmd, struct stream *s) @@ -364,40 +451,47 @@ drdynvc_process_data_first(struct xrdp_channel *self, int total_bytes; struct xrdp_drdynvc *drdynvc; - if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) + if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */ { + LOG(LOG_LEVEL_ERROR, + "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST failed"); return 1; } len = (cmd >> 2) & 0x03; if (len == 0) { - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST")) { return 1; } - in_uint8(s, total_bytes); + in_uint8(s, total_bytes); /* Length */ } else if (len == 1) { - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST")) { return 1; } - in_uint16_le(s, total_bytes); + in_uint16_le(s, total_bytes); /* Length */ } else { - if (!s_check_rem(s, 4)) + if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST")) { return 1; } - in_uint32_le(s, total_bytes); + in_uint32_le(s, total_bytes); /* Length */ } bytes = (int) (s->end - s->p); - LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_data_first: bytes %d total_bytes %d", bytes, total_bytes); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_DATA_FIRST " + "ChannelId %d, Length %d, Data (omitted from the log)", + chan_id, total_bytes); + session = self->sec_layer->rdp_layer->session; if (chan_id > 255) { + LOG(LOG_LEVEL_ERROR, "Received [MS-RDPEDYC] DYNVC_DATA_FIRST for an " + "invalid channel id. Max allowed 255, received %d", chan_id); return 1; } drdynvc = self->drdynvcs + chan_id; @@ -406,10 +500,17 @@ drdynvc_process_data_first(struct xrdp_channel *self, return drdynvc->data_first(session->id, chan_id, s->p, bytes, total_bytes); } + LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): " + "callback 'data_first' is NULL", + XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id), + chan_id); return 0; } /*****************************************************************************/ +/* + * Process a [MS-RDPEDYC] DYNVC_DATA message. + */ static int drdynvc_process_data(struct xrdp_channel *self, int cmd, struct stream *s) @@ -419,15 +520,20 @@ drdynvc_process_data(struct xrdp_channel *self, int bytes; struct xrdp_drdynvc *drdynvc; - if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) + if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */ { + LOG(LOG_LEVEL_ERROR, "drdynvc_process_data: drdynvc_get_chan_id failed"); return 1; } bytes = (int) (s->end - s->p); - LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_data: bytes %d", bytes); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_DATA " + "ChannelId %d, (re-assembled) Length %d, Data (omitted from the log)", + chan_id, bytes); session = self->sec_layer->rdp_layer->session; if (chan_id > 255) { + LOG(LOG_LEVEL_ERROR, "Received message for an invalid " + "channel id. channel id %d", chan_id); return 1; } drdynvc = self->drdynvcs + chan_id; @@ -435,10 +541,18 @@ drdynvc_process_data(struct xrdp_channel *self, { return drdynvc->data(session->id, chan_id, s->p, bytes); } + LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): " + "callback 'data' is NULL", + XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id), + chan_id); return 0; } /*****************************************************************************/ +/** + * Process a [MS-RDPBCGR] 2.2.6.1 Virtual Channel PDU and re-assemble the + * data chunks as needed. + */ static int xrdp_channel_process_drdynvc(struct xrdp_channel *self, struct mcs_channel_item *channel, @@ -451,61 +565,82 @@ xrdp_channel_process_drdynvc(struct xrdp_channel *self, int rv; struct stream *ls; - if (!s_check_rem(s, 8)) + if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] CHANNEL_PDU_HEADER")) { return 1; } - in_uint32_le(s, total_length); - in_uint32_le(s, flags); - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: total_length %d flags 0x%8.8x", - total_length, flags); + in_uint32_le(s, total_length); /* length */ + in_uint32_le(s, flags); /* flags */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] CHANNEL_PDU_HEADER " + "length %d, flags 0x%8.8x", total_length, flags); ls = NULL; switch (flags & 3) { - case 0: + case 0: /* not first chunk and not last chunk */ length = (int) (s->end - s->p); - if (!s_check_rem_out(self->s, length)) + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (middle) " + "length %d", length); + if (length > s_rem_out(self->s)) { + LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than " + "the remaining chunk buffer size. length %d, remaining %d", + length, s_rem_out(self->s)); return 1; } - out_uint8a(self->s, s->p, length); - in_uint8s(s, length); + out_uint8a(self->s, s->p, length); /* append data to chunk buffer */ + in_uint8s(s, length); /* virtualChannelData */ return 0; - case 1: + case 1: /* CHANNEL_FLAG_FIRST */ free_stream(self->s); make_stream(self->s); init_stream(self->s, total_length); length = (int) (s->end - s->p); - if (!s_check_rem_out(self->s, length)) + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (first) " + "length %d", length); + if (length > s_rem_out(self->s)) { + LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than " + "the remaining chunk buffer size. length %d, remaining %d", + length, s_rem_out(self->s)); return 1; } - out_uint8a(self->s, s->p, length); - in_uint8s(s, length); + out_uint8a(self->s, s->p, length); /* append data to chunk buffer */ + in_uint8s(s, length); /* virtualChannelData */ return 0; - case 2: + case 2: /* CHANNEL_FLAG_LAST */ length = (int) (s->end - s->p); - if (!s_check_rem_out(self->s, length)) + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (last) " + "length %d", length); + if (length > s_rem_out(self->s)) { + LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than " + "the remaining chunk buffer size. length %d, remaining %d", + length, s_rem_out(self->s)); return 1; } - out_uint8a(self->s, s->p, length); - in_uint8s(s, length); + out_uint8a(self->s, s->p, length); /* append data to chunk buffer */ + in_uint8s(s, length); /* virtualChannelData */ ls = self->s; break; - case 3: + case 3: /* CHANNEL_FLAG_FIRST and CHANNEL_FLAG_LAST */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (first and last) " + "length %d", total_length); ls = s; break; default: - LOG(LOG_LEVEL_ERROR, "xrdp_channel_process_drdynvc: error"); + LOG(LOG_LEVEL_ERROR, "Received [MS-RDPBCGR] data chunk with " + "unknown flag 0x%8.8x", (int) (flags & 3)); return 1; } if (ls == NULL) { + LOG(LOG_LEVEL_ERROR, "BUG: ls must not be NULL"); return 1; } - in_uint8(ls, cmd); /* read command */ - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: cmd 0x%x", cmd); + in_uint8(ls, cmd); /* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPEDYC] " + "cbId %d, Sp %d, Cmd 0x%2.2x", + (cmd & 0x03), (cmd & 0x0c) >> 2, (cmd & 0xf0) >> 4); rv = 1; switch (cmd & 0xf0) { @@ -525,16 +660,17 @@ xrdp_channel_process_drdynvc(struct xrdp_channel *self, rv = drdynvc_process_data(self, cmd, s); break; default: - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: got unknown " - "command 0x%x", cmd); + LOG(LOG_LEVEL_ERROR, "Received header [MS-RDPEDYC] with " + "unknown command 0x%2.2x", cmd); break; } - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: rv %d", rv); return rv; } /*****************************************************************************/ -/* returns error */ +/* Process a static ([MS-RDPBCGR] 2.2.6) or dynamic (MS-RDPEDYC 2.2.3) + * virtual channel message. + * returns error */ /* This is called from the secure layer to process an incoming non global channel packet. 'chanid' passed in here is the mcs channel id so it MCS_GLOBAL_CHANNEL @@ -557,12 +693,16 @@ xrdp_channel_process(struct xrdp_channel *self, struct stream *s, channel = xrdp_channel_get_item(self, channel_id); if (channel == NULL) { - LOG(LOG_LEVEL_ERROR, "xrdp_channel_process, channel not found"); + LOG(LOG_LEVEL_ERROR, + "Received a message for an unknown channel id. channel id %d", + chanid); return 1; } if (channel->disabled) { - LOG(LOG_LEVEL_WARNING, "xrdp_channel_process, channel disabled"); + LOG(LOG_LEVEL_WARNING, + "Received a message for the disabled channel %s (%d)", + channel->name, chanid); return 0; /* not an error */ } if (channel_id == self->drdynvc_channel_id) @@ -570,14 +710,16 @@ xrdp_channel_process(struct xrdp_channel *self, struct stream *s, return xrdp_channel_process_drdynvc(self, channel, s); } rv = 0; - in_uint32_le(s, length); - in_uint32_le(s, flags); + in_uint32_le(s, length); /* length */ + in_uint32_le(s, flags); /* flags */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] CHANNEL_PDU_HEADER " + "length %d, flags 0x%8.8x", length, flags); rv = xrdp_channel_call_callback(self, s, channel_id, length, flags); return rv; } /*****************************************************************************/ -/* drdynvc */ +/* Send a [MS-RDPEDYC] DYNVC_CAPS_VERSION2 message */ static int xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self) { @@ -592,11 +734,13 @@ xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self) init_stream(s, 8192); if (xrdp_channel_init(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_channel_drdynvc_send_capability_request: xrdp_channel_init failed"); free_stream(s); return 1; } phold = s->p; - out_uint8(s, 0x50); /* insert cmd */ + out_uint8(s, 0x50); /* insert cbId (2 bits), Sp (2 bits), cmd (4 bits) */ out_uint8(s, 0x00); /* insert padding */ out_uint16_le(s, 2); /* insert version */ /* channel priority unused for now */ @@ -609,8 +753,13 @@ xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self) total_data_len = (int) (s->end - phold); flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST; channel_id = self->drdynvc_channel_id; + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CAPS_VERSION2 " + "cbId 0, Sp 0, Cmd 0x05, Version 2, PriorityCharge0 0, " + "PriorityCharge1 0, PriorityCharge2 0, PriorityCharge3 0"); if (xrdp_channel_send(self, s, channel_id, total_data_len, flags) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_channel_drdynvc_send_capability_request: xrdp_channel_send failed"); free_stream(s); return 1; } @@ -627,7 +776,7 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self) struct mcs_channel_item *ci; struct mcs_channel_item *dci; - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_drdynvc_start:"); + dci = NULL; count = self->mcs_layer->channel_list->count; for (index = 0; index < count; index++) @@ -645,12 +794,24 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self) if (dci != NULL) { self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1; + LOG_DEVEL(LOG_LEVEL_DEBUG, + "Initializing Dynamic Virtual Channel with channel id %d", + self->drdynvc_channel_id); xrdp_channel_drdynvc_send_capability_request(self); } + else + { + LOG(LOG_LEVEL_WARNING, + "Dynamic Virtual Channel named 'drdynvc' not found, " + "channel not initialized"); + } return 0; } /*****************************************************************************/ +/* + * Send a [MS-RDPEDYC] DYNVC_CREATE_REQ message to request the creation of a channel. + */ int xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name, int flags, struct xrdp_drdynvc_procs *procs, @@ -670,33 +831,46 @@ xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name, init_stream(s, 8192); if (xrdp_channel_init(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_channel_drdynvc_open: xrdp_channel_init failed"); free_stream(s); return 1; } cmd_ptr = s->p; - out_uint8(s, 0); + out_uint8(s, 0); /* set later */ ChId = 1; while (self->drdynvcs[ChId].status != XRDP_DRDYNVC_STATUS_CLOSED) { ChId++; if (ChId > 255) { + LOG(LOG_LEVEL_ERROR, + "Attempting to create a new channel when the maximum " + "number of channels have already been created. " + "XRDP only supports 255 open channels."); free_stream(s); return 1; } } - cbChId = drdynvc_insert_uint_124(s, ChId); + cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */ name_length = g_strlen(name); - out_uint8a(s, name, name_length + 1); + out_uint8a(s, name, name_length + 1); /* ChannelName */ chan_pri = 0; + /* cbId (low 2 bits), Pri (2 bits), Cmd (hi 4 bits) */ cmd_ptr[0] = CMD_DVC_OPEN_CHANNEL | ((chan_pri << 2) & 0x0c) | cbChId; static_channel_id = self->drdynvc_channel_id; static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST; s_mark_end(s); total_data_len = (int) (s->end - cmd_ptr); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CREATE_REQ " + "cbId %d, Pri %d, Cmd 0x%2.2x, ChannelId %d, ChannelName [%s]", + cbChId, chan_pri, CMD_DVC_OPEN_CHANNEL, ChId, name); if (xrdp_channel_send(self, s, static_channel_id, total_data_len, static_flags) != 0) { + LOG(LOG_LEVEL_ERROR, + "Sending [MS-RDPEDYC] DYNVC_CREATE_REQ failed"); free_stream(s); return 1; } @@ -711,6 +885,9 @@ xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name, } /*****************************************************************************/ +/* + * Send a [MS-RDPEDYC] DYNVC_CLOSE message to request the closing of a channel. + */ int xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id) { @@ -724,33 +901,48 @@ xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id) if ((chan_id < 0) || (chan_id > 255)) { + LOG(LOG_LEVEL_ERROR, "Attempting to close an invalid channel id. " + "channel id %d", chan_id); return 1; } if ((self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN) && (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN_SENT)) { /* not open */ + LOG(LOG_LEVEL_ERROR, "Attempting to close a channel that is not open. " + "channel id %d, channel status %s", + chan_id, + XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status)); return 1; } make_stream(s); init_stream(s, 8192); if (xrdp_channel_init(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_channel_drdynvc_close: xrdp_channel_init failed"); free_stream(s); return 1; } cmd_ptr = s->p; - out_uint8(s, 0); + out_uint8(s, 0); /* set later */ ChId = chan_id; - cbChId = drdynvc_insert_uint_124(s, ChId); + cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */ + /* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */ cmd_ptr[0] = CMD_DVC_CLOSE_CHANNEL | cbChId; static_channel_id = self->drdynvc_channel_id; static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST; s_mark_end(s); total_data_len = (int) (s->end - cmd_ptr); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CLOSE " + "cbId %d, Sp 0, Cmd 0x%2.2x, ChannelId %d", + cbChId, CMD_DVC_OPEN_CHANNEL, ChId); if (xrdp_channel_send(self, s, static_channel_id, total_data_len, static_flags) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_channel_drdynvc_open: xrdp_channel_send failed"); free_stream(s); return 1; } @@ -760,6 +952,9 @@ xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id) } /*****************************************************************************/ +/* + * Send a [MS-RDPEDYC] DYNVC_DATA_FIRST message. + */ int xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id, const char *data, int data_bytes, @@ -776,37 +971,53 @@ xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id, if ((chan_id < 0) || (chan_id > 255)) { + LOG(LOG_LEVEL_ERROR, "Attempting to send data to an invalid " + "channel id. channel id %d", chan_id); return 1; } if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN) { + LOG(LOG_LEVEL_ERROR, "Attempting to send data to a channel that " + "is not open. channel id %d, channel status %s", + chan_id, + XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status)); return 1; } if (data_bytes > 1590) { + LOG(LOG_LEVEL_ERROR, "Payload for channel id %d is is too big. " + "data_bytes %d", chan_id, data_bytes); return 1; } make_stream(s); init_stream(s, 8192); if (xrdp_channel_init(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_channel_drdynvc_data_first: xrdp_channel_init failed"); free_stream(s); return 1; } cmd_ptr = s->p; - out_uint8(s, 0); + out_uint8(s, 0); /* set later */ ChId = chan_id; - cbChId = drdynvc_insert_uint_124(s, ChId); - cbTotalDataSize = drdynvc_insert_uint_124(s, total_data_bytes); - out_uint8p(s, data, data_bytes); + cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */ + cbTotalDataSize = drdynvc_insert_uint_124(s, total_data_bytes); /* Length */ + out_uint8p(s, data, data_bytes); /* Data */ + /* cbId (low 2 bits), Len (2 bits), Cmd (hi 4 bits) */ cmd_ptr[0] = CMD_DVC_DATA_FIRST | (cbTotalDataSize << 2) | cbChId; static_channel_id = self->drdynvc_channel_id; static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST; s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_DATA_FIRST " + "cbId %d, Len %d, Cmd 0x%2.2x, ChannelId %d, Length %d", + cbChId, cbTotalDataSize, CMD_DVC_DATA_FIRST, ChId, total_data_bytes); total_data_len = (int) (s->end - cmd_ptr); if (xrdp_channel_send(self, s, static_channel_id, total_data_len, static_flags) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_channel_drdynvc_data_first: xrdp_channel_send failed"); free_stream(s); return 1; } @@ -815,6 +1026,9 @@ xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id, } /*****************************************************************************/ +/* + * Send a [MS-RDPEDYC] DYNVC_DATA message. + */ int xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id, const char *data, int data_bytes) @@ -829,36 +1043,52 @@ xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id, if ((chan_id < 0) || (chan_id > 255)) { + LOG(LOG_LEVEL_ERROR, "Attempting to send data to an invalid " + "channel id. channel id %d", chan_id); return 1; } if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN) { + LOG(LOG_LEVEL_ERROR, "Attempting to send data to a channel that " + "is not open. channel id %d, channel status %s", + chan_id, + XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status)); return 1; } if (data_bytes > 1590) { + LOG(LOG_LEVEL_ERROR, "Payload for channel id %d is is too big. " + "data_bytes %d", chan_id, data_bytes); return 1; } make_stream(s); init_stream(s, 8192); if (xrdp_channel_init(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_channel_drdynvc_data: xrdp_channel_init failed"); free_stream(s); return 1; } cmd_ptr = s->p; - out_uint8(s, 0); + out_uint8(s, 0); /* set later */ ChId = chan_id; - cbChId = drdynvc_insert_uint_124(s, ChId); - out_uint8p(s, data, data_bytes); + cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */ + out_uint8p(s, data, data_bytes); /* Data */ + /* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */ cmd_ptr[0] = CMD_DVC_DATA | cbChId; static_channel_id = self->drdynvc_channel_id; static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST; s_mark_end(s); total_data_len = (int) (s->end - cmd_ptr); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_DATA " + "cbId %d, Sp 0, Cmd 0x%2.2x, ChannelId %d", + cbChId, CMD_DVC_DATA_FIRST, ChId); if (xrdp_channel_send(self, s, static_channel_id, total_data_len, static_flags) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_channel_drdynvc_data: xrdp_channel_send failed"); free_stream(s); return 1; } diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c index 01853b1c..682c6015 100644 --- a/libxrdp/xrdp_fastpath.c +++ b/libxrdp/xrdp_fastpath.c @@ -30,12 +30,11 @@ xrdp_fastpath_create(struct xrdp_sec *owner, struct trans *trans) { struct xrdp_fastpath *self; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_fastpath_create"); self = (struct xrdp_fastpath *)g_malloc(sizeof(struct xrdp_fastpath), 1); self->sec_layer = owner; self->trans = trans; self->session = owner->rdp_layer->session; - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_fastpath_create"); + return self; } @@ -63,13 +62,13 @@ int xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s) { int fp_hdr; - int len = 0; /* unused */ + int len = 0; int byte; char *holdp; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_fastpath_recv"); + holdp = s->p; - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_FP_INPUT_PDU")) { return 1; } @@ -84,7 +83,7 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s) byte &= ~(0x80); len = (byte << 8); - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_INPUT_PDU length2")) { return 1; } @@ -97,7 +96,10 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s) len = byte; } s->next_packet = holdp + len; - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_fastpath_recv"); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_FP_INPUT_PDU " + "fpInputHeader.action (ignored), fpInputHeader.numEvents %d, " + "fpInputHeader.flags 0x%1.1x, length %d", + self->numEvents, self->secFlags, len); return 0; } @@ -134,6 +136,10 @@ xrdp_fastpath_session_callback(struct xrdp_fastpath *self, int msg, self->session->callback(self->session->id, msg, param1, param2, param3, param4); } + else + { + LOG_DEVEL(LOG_LEVEL_WARNING, "Bug: session is NULL"); + } return 0; } @@ -163,11 +169,14 @@ xrdp_fastpath_process_EVENT_SCANCODE(struct xrdp_fastpath *self, int code; flags = 0; - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_KEYBOARD_EVENT")) { return 1; } in_uint8(s, code); /* keyCode (1 byte) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_KEYBOARD_EVENT " + "eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), " + "keyCode %d", eventFlags, code); if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE)) { @@ -205,13 +214,16 @@ xrdp_fastpath_process_EVENT_MOUSE(struct xrdp_fastpath *self, return 1; } - if (!s_check_rem(s, 2 + 2 + 2)) + if (!s_check_rem_and_log(s, 2 + 2 + 2, "Parsing [MS-RDPBCGR] TS_FP_POINTER_EVENT")) { return 1; } in_uint16_le(s, pointerFlags); /* pointerFlags (2 bytes) */ in_uint16_le(s, xPos); /* xPos (2 bytes) */ in_uint16_le(s, yPos); /* yPos (2 bytes) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_POINTER_EVENT " + "eventHeader.eventFlags 0x00, eventHeader.eventCode (ignored), " + "pointerFlags 0x%4.4x, xPos %d, yPos %d", pointerFlags, xPos, yPos); xrdp_fastpath_session_callback(self, RDP_INPUT_MOUSE, xPos, yPos, pointerFlags, 0); @@ -235,13 +247,18 @@ xrdp_fastpath_process_EVENT_MOUSEX(struct xrdp_fastpath *self, return 1; } - if (!s_check_rem(s, 2 + 2 + 2)) + if (!s_check_rem_and_log(s, 2 + 2 + 2, + "Parsing [MS-RDPBCGR] TS_FP_POINTERX_EVENT")) { return 1; } in_uint16_le(s, pointerFlags); /* pointerFlags (2 bytes) */ in_uint16_le(s, xPos); /* xPos (2 bytes) */ in_uint16_le(s, yPos); /* yPos (2 bytes) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_POINTERX_EVENT " + "eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), " + "pointerFlags 0x%4.4x, xPos %d, yPos %d", + eventFlags, pointerFlags, xPos, yPos); xrdp_fastpath_session_callback(self, RDP_INPUT_MOUSEX, xPos, yPos, pointerFlags, 0); @@ -263,6 +280,10 @@ xrdp_fastpath_process_EVENT_SYNC(struct xrdp_fastpath *self, * status of the keyboard toggle keys. */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_SYNC_EVENT" + "eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), ", + eventFlags); + xrdp_fastpath_session_callback(self, RDP_INPUT_SYNCHRONIZE, eventFlags, 0, 0, 0); @@ -279,11 +300,16 @@ xrdp_fastpath_process_EVENT_UNICODE(struct xrdp_fastpath *self, int code; flags = 0; - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_FP_UNICODE_KEYBOARD_EVENT")) { return 1; } in_uint16_le(s, code); /* unicode (2 byte) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_UNICODE_KEYBOARD_EVENT" + "eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), " + "unicodeCode %d", + eventFlags, code); + if (eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE) { flags |= KBD_FLAG_UP; @@ -315,7 +341,7 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, /* process fastpath input events */ for (i = 0; i < self->numEvents; i++) { - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_INPUT_EVENT eventHeader")) { return 1; } @@ -323,6 +349,9 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, eventFlags = (eventHeader & 0x1F); eventCode = (eventHeader >> 5); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_INPUT_EVENT" + "eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode 0x%1.1x", + eventFlags, eventCode); switch (eventCode) { @@ -367,8 +396,8 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, } break; default: - LOG(LOG_LEVEL_WARNING, "xrdp_fastpath_process_input_event: unknown " - "eventCode %d", eventCode); + LOG(LOG_LEVEL_ERROR, "xrdp_fastpath_process_input_event: " + "unknown eventCode %d", eventCode); break; } } diff --git a/libxrdp/xrdp_iso.c b/libxrdp/xrdp_iso.c index b8256ab7..c00f4568 100644 --- a/libxrdp/xrdp_iso.c +++ b/libxrdp/xrdp_iso.c @@ -17,6 +17,11 @@ * limitations under the License. * * iso layer + * + * Note: [ITU-T X.224] and [ISO/IEC 8073] are essentially two specifications + * of the same protocol (see [ITU-T X.224] Appendix I – Differences between + * ITU-T Rec. X.224 (1993) and ISO/IEC 8073:1992). The RDP protocol + * specification [MS-RDPBCGR] makes reference to the [ITU-T X.224] specificaiton. */ #if defined(HAVE_CONFIG_H) @@ -36,11 +41,9 @@ xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans) { struct xrdp_iso *self; - LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_create"); self = (struct xrdp_iso *) g_malloc(sizeof(struct xrdp_iso), 1); self->mcs_layer = owner; self->trans = trans; - LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_create"); return self; } @@ -77,8 +80,10 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self) !g_file_readable(client_info->key_file)) { /* certificate or privkey is not readable */ - LOG(LOG_LEVEL_WARNING, "No readable certificates or " - "private keys, cannot accept TLS connections"); + LOG(LOG_LEVEL_ERROR, "Cannot accept TLS connections because " + "certificate or private key file is not readable. " + "certificate file: [%s], private key file: [%s]", + client_info->certificate, client_info->key_file); self->failureCode = SSL_CERT_NOT_ON_SERVER; rv = 1; /* error */ } @@ -89,6 +94,8 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self) } else { + LOG(LOG_LEVEL_ERROR, "Server requires TLS for security, " + "but the client did not request TLS."); self->failureCode = SSL_REQUIRED_BY_SERVER; rv = 1; /* error */ } @@ -116,40 +123,52 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self) } /*****************************************************************************/ -/* returns error */ +/* Process a [MS-RDPBCGR] RDP_NEG_REQ message. + * returns error + */ static int xrdp_iso_process_rdp_neg_req(struct xrdp_iso *self, struct stream *s) { int flags; int len; - if (!s_check_rem(s, 7)) + if (!s_check_rem_and_log(s, 7, "Parsing [MS-RDPBCGR] RDP_NEG_REQ")) { - LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: unexpected end-of-record"); return 1; } - in_uint8(s, flags); + /* 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) { - LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, flags: %x", flags); + LOG(LOG_LEVEL_ERROR, + "Unsupported [MS-RDPBCGR] RDP_NEG_REQ flags: 0x%2.2x", flags); return 1; } - in_uint16_le(s, len); + in_uint16_le(s, len); /* length */ if (len != 8) { - LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, length: %x", len); + LOG(LOG_LEVEL_ERROR, + "Protocol error: [MS-RDPBCGR] RDP_NEG_REQ length must be 8, " + "received %d", len); return 1; } - in_uint32_le(s, self->requestedProtocol); + in_uint32_le(s, self->requestedProtocol); /* requestedProtocols */ + + /* TODO: why is requestedProtocols flag value bigger than 0xb invalid? */ if (self->requestedProtocol > 0xb) { - LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, requestedProtocol: %x", - self->requestedProtocol); + LOG(LOG_LEVEL_ERROR, + "Unknown requested protocol flag [MS-RDPBCGR] RDP_NEG_REQ, " + "requestedProtocol 0x%8.8x", self->requestedProtocol); return 1; } + LOG_DEVEL(LOG_LEVEL_TRACE, "Received struct [MS-RDPBCGR] RDP_NEG_REQ " + "flags 0x%2.2x, length 8, requestedProtocol 0x%8.8x", + flags, self->requestedProtocol); return 0; } @@ -163,6 +182,10 @@ xrdp_iso_process_rdp_neg_req(struct xrdp_iso *self, struct stream *s) * On exit, the TPKT header and the fixed part of the PDU header will have been * removed from the stream. * + * @param self + * @param s [in] + * @param code [out] + * @param len [out] * Returns error *****************************************************************************/ static int @@ -175,83 +198,110 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len) if (s != self->trans->in_s) { - LOG(LOG_LEVEL_WARNING, "xrdp_iso_recv_msg error logic"); + LOG(LOG_LEVEL_WARNING, + "Bug: the input stream is not the same stream as the " + "transport input stream"); } - /* TPKT header is 4 bytes, then first 2 bytes of the X.224 CR-TPDU */ - if (!s_check_rem(s, 6)) + /* [ITU-T T.123] TPKT header is 4 bytes, then first 2 bytes of the X.224 CR-TPDU */ + if (!s_check_rem_and_log(s, 6, + "Parsing [ITU-T T.123] TPKT header and [ITU-T X.224] TPDU header")) { return 1; } - in_uint8(s, ver); - in_uint8s(s, 3); /* Skip reserved field, plus length */ - in_uint8(s, *len); - in_uint8(s, *code); + /* [ITU-T T.123] TPKT header */ + in_uint8(s, ver); /* version */ + in_uint8s(s, 3); /* Skip reserved field (1 byte), plus length (2 bytes) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [ITU-T T.123] TPKT " + "version %d, length (ignored)", ver); + + /* [ITU-T X.224] TPDU header */ + in_uint8(s, *len); /* LI (length indicator) */ + in_uint8(s, *code); /* TPDU code */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [ITU-T X.224] TPDU " + "length indicator %d, TDPU code 0x%2.2x", *len, *code); if (ver != 3) { - LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv_msg: bad ver"); - LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "header", s->data, 4); + LOG(LOG_LEVEL_ERROR, + "Unsupported [ITU-T T.123] TPKT header version: %d", ver); + LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "[ITU-T T.123] TPKT header", s->data, 4); return 1; } if (*len == 255) { /* X.224 13.2.1 - reserved value */ - LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv_msg: reserved length encountered"); - LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "header", s->data, 4); + LOG(LOG_LEVEL_ERROR, + "[ITU-T X.224] TPDU header: unsupported use of reserved length value"); + LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "[ITU-T X.224] TPDU header", s->data + 4, 4); return 1; } if (*code == ISO_PDU_DT) { - /* Data PDU : X.224 13.7 */ - if (!s_check_rem(s, 1)) + /* Data PDU : X.224 13.7 class 0 */ + if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T X.224] DT-TPDU (Data) header")) { return 1; } - in_uint8s(s, 1); + in_uint8s(s, 1); /* EOT (End of TSDU Mark) (upper 1 bit) and + TPDU-NR (Data TPDU Number) (lower 7 bits) */ } else { - /* Other supported PDUs : X.224 13.x */ - if (!s_check_rem(s, 5)) + /* Other supported X.224 class 0 PDUs all have 5 bytes remaining + in the fixed header : + CR Connection request (13.3) + CC Connection confirm (13.4) + DR Disconnect request (13.5) */ + if (!s_check_rem_and_log(s, 5, "Parsing [ITU-T X.224] Other PDU header")) { return 1; } - in_uint8s(s, 5); + in_uint8s(s, 5); /* DST-REF (2 bytes) + SRC-REF (2 bytes) + [CR, CC] CLASS OPTION (1 byte) or [DR] REASON (1 byte) */ } return 0; } /*****************************************************************************/ -/* returns error */ +/* Process the header of a [ITU-T X.224] DT-TPDU (Data) message. + * + * returns error + */ int xrdp_iso_recv(struct xrdp_iso *self, struct stream *s) { int code; int len; - LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_recv"); - if (xrdp_iso_recv_msg(self, s, &code, &len) != 0) { - LOG(LOG_LEVEL_ERROR, " out xrdp_iso_recv xrdp_iso_recv_msg return non zero"); + LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv: xrdp_iso_recv_msg failed"); return 1; } if (code != ISO_PDU_DT || len != 2) { - LOG(LOG_LEVEL_ERROR, " out xrdp_iso_recv code != ISO_PDU_DT or length != 2"); + LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv only supports processing " + "[ITU-T X.224] DT-TPDU (Data) headers. Received TPDU header: " + "length indicator %d, TDPU code 0x%2.2x", len, code); return 1; } - LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_recv"); return 0; } /*****************************************************************************/ +/* + * Send a [ITU-T X.224] CC-TPDU (Connection Confirm) message with + * [ITU-T T.123] TPKT header. + * + * returns error + */ static int xrdp_iso_send_cc(struct xrdp_iso *self) { @@ -266,35 +316,44 @@ xrdp_iso_send_cc(struct xrdp_iso *self) init_stream(s, 8192); holdp = s->p; - /* tpkt */ + /* [ITU-T T.123] TPKT header */ out_uint8(s, 3); /* version */ - out_uint8(s, 0); /* pad */ + out_uint8(s, 0); /* reserved (padding) */ len_ptr = s->p; out_uint16_be(s, 0); /* length, set later */ - /* iso */ + + /* [ITU-T X.224] CC-TPDU */ len_indicator_ptr = s->p; - out_uint8(s, 0); /* length indicator, set later */ + out_uint8(s, 0); /* length indicator, set later */ out_uint8(s, ISO_PDU_CC); /* Connection Confirm PDU */ - out_uint16_be(s, 0); - out_uint16_be(s, 0x1234); - out_uint8(s, 0); - /* rdpNegData */ + out_uint16_be(s, 0); /* DST-REF */ + out_uint16_be(s, 0x1234); /* SRC-REF */ + out_uint8(s, 0); /* CLASS OPTION */ + + /* [MS-RDPBCGR] 2.2.1.2 rdpNegData */ if (self->rdpNegData) { if (self->failureCode) { - out_uint8(s, RDP_NEG_FAILURE); - out_uint8(s, 0); /* no flags */ - out_uint16_le(s, 8); /* must be 8 */ - out_uint32_le(s, self->failureCode); /* failure code */ + /* [MS-RDPBCGR] RDP_NEG_FAILURE */ + out_uint8(s, RDP_NEG_FAILURE); /* type*/ + out_uint8(s, 0); /* flags (none) */ + out_uint16_le(s, 8); /* length (must be 8) */ + out_uint32_le(s, self->failureCode); /* failureCode */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding structure [MS-RDPBCGR] RDP_NEG_FAILURE " + "flags 0, length 8, failureCode 0x%8.8x", self->failureCode); } else { - out_uint8(s, RDP_NEG_RSP); + /* [MS-RDPBCGR] RDP_NEG_RSP */ + out_uint8(s, RDP_NEG_RSP); /* type*/ //TODO: hardcoded flags out_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ - out_uint16_le(s, 8); /* must be 8 */ - out_uint32_le(s, self->selectedProtocol); /* selected protocol */ + 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 " + "flags 0, length 8, selectedProtocol 0x%8.8x", + self->selectedProtocol); } } s_mark_end(s); @@ -305,8 +364,15 @@ xrdp_iso_send_cc(struct xrdp_iso *self) len_ptr[1] = len; len_indicator_ptr[0] = len_indicator; + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T T.123] TPKT " + "version 3, length %d", len); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [ITU-T X.224] CC-TPDU (Connection Confirm) " + "length indicator %d, DST-REF 0, SRC-REF 0, CLASS OPTION 0", + len_indicator); + if (trans_write_copy_s(self->trans, s) != 0) { + LOG(LOG_LEVEL_ERROR, "Sending [ITU-T X.224] CC-TPDU (Connection Confirm) failed"); free_stream(s); return 1; } @@ -317,7 +383,7 @@ xrdp_iso_send_cc(struct xrdp_iso *self) /***************************************************************************** * Process an X.224 connection request PDU * - * See MS-RDPCGR v20190923 sections 2.2.1.1 and 3.3.5.3.1. + * See MS-RDPBCGR v20190923 sections 2.2.1.1 and 3.3.5.3.1. * * From the latter, in particular:- * - The length embedded in the TPKT header MUST be examined for @@ -339,22 +405,26 @@ xrdp_iso_incoming(struct xrdp_iso *self) struct stream *s; int expected_pdu_len; - LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_incoming"); - + LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: receive connection request"); s = libxrdp_force_read(self->trans); if (s == NULL) { + LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: CR-TPDU (Connection Request) failed"); return 1; } if (xrdp_iso_recv_msg(self, s, &code, &len) != 0) { - LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_recv_msg returned non zero"); + LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: CR-TPDU (Connection Request) failed"); return 1; } if (code != ISO_PDU_CR) { + LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming only supports processing " + "[ITU-T X.224] CR-TPDU (Connection Request) headers. " + "Received TPDU header: length indicator %d, TDPU code 0x%2.2x", + len, code); return 1; } @@ -369,38 +439,47 @@ xrdp_iso_incoming(struct xrdp_iso *self) expected_pdu_len = (s->end - s->p) + 6; if (len != expected_pdu_len) { - LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: X.224 CR-TPDU length exp %d got %d", + LOG(LOG_LEVEL_ERROR, + "Invalid length indicator in [ITU-T X.224] CR-TPDU (Connection Request). " + "expected %d, received %d", expected_pdu_len, len); return 1; } - /* process connection request */ + /* process connection request [MS-RDPBCGR] 2.2.1.1 */ while (s_check_rem(s, 1)) { - in_uint8(s, cc_type); + in_uint8(s, cc_type); /* type or 'C' */ switch (cc_type) { default: + LOG_DEVEL(LOG_LEVEL_WARNING, + "Ignoring unknown structure type in [ITU-T X.224] CR-TPDU (Connection Request). " + "type 0x%2.2x", cc_type); break; case RDP_NEG_REQ: /* rdpNegReq 1 */ self->rdpNegData = 1; if (xrdp_iso_process_rdp_neg_req(self, s) != 0) { - LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_process_rdpNegReq returned non zero"); + LOG(LOG_LEVEL_ERROR, + "[ITU-T X.224] Connection Sequence: failed"); return 1; } break; case RDP_CORRELATION_INFO: /* rdpCorrelationInfo 6 */ // TODO - if (!s_check_rem(s, 1 + 2 + 16 + 16)) + if (!s_check_rem_and_log(s, 1 + 2 + 16 + 16, + "Parsing [MS-RDPBCGR] RDP_NEG_CORRELATION_INFO")) { - LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: short correlation info"); return 1; } in_uint8s(s, 1 + 2 + 16 + 16); + LOG_DEVEL(LOG_LEVEL_TRACE, + "Received struct [MS-RDPBCGR] RDP_NEG_CORRELATION_INFO " + "(all fields ignored)"); break; - case 'C': /* Cookie */ + case 'C': /* Cookie or routingToken */ /* The routingToken and cookie fields are both ASCII * strings starting with the word 'Cookie: ' and * ending with CR+LF. We ignore both, so we do @@ -417,6 +496,9 @@ xrdp_iso_incoming(struct xrdp_iso *self) } } } + LOG_DEVEL(LOG_LEVEL_TRACE, + "Received struct [MS-RDPBCGR] routingToken or cookie " + "(ignored)"); break; } } @@ -425,13 +507,14 @@ xrdp_iso_incoming(struct xrdp_iso *self) rv = xrdp_iso_negotiate_security(self); /* send connection confirm back to client */ + LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: send connection confirmation"); if (xrdp_iso_send_cc(self) != 0) { - LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_send_cc returned non zero"); + LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: send connection confirmation failed"); return 1; } - LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_incoming"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: completed"); return rv; } @@ -446,27 +529,39 @@ xrdp_iso_init(struct xrdp_iso *self, struct stream *s) } /*****************************************************************************/ -/* returns error */ +/* Sends a message with the [ITU-T T.123] TPKT header (T.123 section 8) and + * [ITU-T X.224] DT-TPDU (Data) header (X.224 section 13) + * returns error + */ int xrdp_iso_send(struct xrdp_iso *self, struct stream *s) { int len; - LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_send"); s_pop_layer(s, iso_hdr); len = (int) (s->end - s->p); - out_uint8(s, 3); - out_uint8(s, 0); - out_uint16_be(s, len); - out_uint8(s, 2); - out_uint8(s, ISO_PDU_DT); - out_uint8(s, 0x80); + /* [ITU-T T.123] TPKT header */ + out_uint8(s, 3); /* version */ + out_uint8(s, 0); /* reserved (padding) */ + out_uint16_be(s, len); /* length */ + + /* [ITU-T X.224] DT-TPDU (Data) header */ + out_uint8(s, 2); /* LI (length indicator) */ + out_uint8(s, ISO_PDU_DT); /* TPDU code */ + out_uint8(s, 0x80); /* EOT (End of TSDU Mark) (upper 1 bit) and + TPDU-NR (Data TPDU Number) (lower 7 bits) */ + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T T.123] TPKT " + "version 3, length %d", len); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T X.224] DT-TPDU (Data) " + "length indicator 2, TPDU code 0x%2.2x, EOT 1, TPDU-NR 0x00", + ISO_PDU_DT); if (trans_write_copy_s(self->trans, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_iso_send: trans_write_copy_s failed"); return 1; } - LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_send"); return 0; } diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index d37269a0..83b5e760 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -15,7 +15,8 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * mcs layer + * mcs layer which implements the Multipoint Communication Service protocol as + * specified in [ITU-T T.125] */ #if defined(HAVE_CONFIG_H) @@ -34,7 +35,6 @@ xrdp_mcs_create(struct xrdp_sec *owner, struct trans *trans, { struct xrdp_mcs *self; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_mcs_create"); self = (struct xrdp_mcs *)g_malloc(sizeof(struct xrdp_mcs), 1); self->sec_layer = owner; self->userid = 1; @@ -43,7 +43,7 @@ xrdp_mcs_create(struct xrdp_sec *owner, struct trans *trans, self->server_mcs_data = server_mcs_data; self->iso_layer = xrdp_iso_create(self, trans); self->channel_list = list_create(); - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_mcs_create"); + return self; } @@ -80,45 +80,58 @@ xrdp_mcs_delete(struct xrdp_mcs *self) } /*****************************************************************************/ -/* This function sends channel join confirm */ +/* Send an [ITU-T T.125] DomainMCSPDU message with type ChannelJoinConfirm */ /* returns error = 1 ok = 0 */ static int xrdp_mcs_send_cjcf(struct xrdp_mcs *self, int userid, int chanid) { struct stream *s; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_mcs_send_cjcf"); make_stream(s); init_stream(s, 8192); if (xrdp_iso_init(self->iso_layer, s) != 0) { free_stream(s); - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_send_cjcf error"); + LOG(LOG_LEVEL_ERROR, "xrdp_mcs_send_cjcf: xrdp_iso_init failed"); return 1; } - out_uint8(s, (MCS_CJCF << 2) | 2); - out_uint8(s, 0); - out_uint16_be(s, userid); - out_uint16_be(s, chanid); /* TODO Explain why we send this two times */ - out_uint16_be(s, chanid); + /* The DomainMCSPDU choice index is a 6-bit int with the next bit as the + bit field of the two optional fields in the struct (channelId, nonStandard) + */ + out_uint8(s, (MCS_CJCF << 2) | 0x02); /* DomainMCSPDU choice index, + channelId field is present, + nonStandard field is not present */ + out_uint8(s, 0); /* result choice index 0 = rt-successful */ + out_uint16_be(s, userid); /* initiator */ + out_uint16_be(s, chanid); /* requested */ + out_uint16_be(s, chanid); /* channelId (OPTIONAL) */ s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sening [ITU-T T.125] ChannelJoinConfirm " + "result SUCCESS, initiator %d, requested %d, " + "channelId %d", userid, chanid, chanid); if (xrdp_iso_send(self->iso_layer, s) != 0) { free_stream(s); - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_send_cjcf error"); + LOG(LOG_LEVEL_ERROR, "Sening [ITU-T T.125] ChannelJoinConfirm failed"); return 1; } free_stream(s); - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_mcs_send_cjcf"); return 0; } /*****************************************************************************/ -/* returns error */ +/* + * Processes an [ITU-T T.125] DomainMCSPDU message. + * + * Note: DomainMCSPDU messages use the ALIGNED BASIC-PER (Packed Encoding Rules) + * from [ITU-T X.691]. + * + * returns error + */ int xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) { @@ -127,49 +140,52 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) int len; int userid; int chanid; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_mcs_recv"); + while (1) { if (xrdp_iso_recv(self->iso_layer, s) != 0) { - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_recv, xrdp_iso_recv return non zero"); LOG(LOG_LEVEL_ERROR, "xrdp_mcs_recv: xrdp_iso_recv failed"); return 1; } - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T T.125] DomainMCSPDU")) { return 1; } + /* The DomainMCSPDU choice index is a 6-bit int with the 2 least + significant bits of the byte as padding */ in_uint8(s, opcode); - appid = opcode >> 2; + appid = opcode >> 2; /* 2-bit padding */ + LOG_DEVEL(LOG_LEVEL_TRACE, + "Received [ITU-T T.125] DomainMCSPDU choice index %d", appid); if (appid == MCS_DPUM) /* Disconnect Provider Ultimatum */ { - LOG(LOG_LEVEL_ERROR, "received Disconnect Provider Ultimatum"); - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_recv appid != MCS_DPUM"); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] DisconnectProviderUltimatum"); + LOG(LOG_LEVEL_DEBUG, "Recieved disconnection request"); return 1; } - /* this is channels getting added from the client */ + /* MCS_CJRQ: Channel Join ReQuest + this is channels getting added from the client */ if (appid == MCS_CJRQ) { - - if (!s_check_rem(s, 4)) + if (!s_check_rem_and_log(s, 4, "Parsing [ITU-T T.125] ChannelJoinRequest")) { return 1; } in_uint16_be(s, userid); in_uint16_be(s, chanid); - LOG(LOG_LEVEL_DEBUG, "MCS_CJRQ - channel join request received"); - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mcs_recv adding channel %4.4x", chanid); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] ChannelJoinRequest " + "initiator 0x%4.4x, channelId 0x%4.4x", userid, chanid); if (xrdp_mcs_send_cjcf(self, userid, chanid) != 0) { - LOG(LOG_LEVEL_ERROR, "Non handled error from xrdp_mcs_send_cjcf") ; + LOG(LOG_LEVEL_WARNING, "[ITU-T T.125] Channel join sequence: failed"); } s = libxrdp_force_read(self->iso_layer->trans); @@ -181,50 +197,73 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) continue; } - - if (appid == MCS_SDRQ || appid == MCS_SDIN) - { - break; - } - else - { - LOG(LOG_LEVEL_DEBUG, "Received an unhandled appid:%d", appid); - } - break; } if (appid != MCS_SDRQ) { - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_recv err got 0x%x need MCS_SDRQ", appid); + LOG(LOG_LEVEL_ERROR, "Received [ITU-T T.125] DomainMCSPDU " + "choice index %d is unknown. Expected the DomainMCSPDU to " + "contain the type SendDataRequest with index %d", + appid, MCS_SDRQ); return 1; } - if (!s_check_rem(s, 6)) + if (!s_check_rem_and_log(s, 6, "Parsing [ITU-T T.125] SendDataRequest")) { return 1; } - in_uint8s(s, 2); - in_uint16_be(s, *chan); - in_uint8s(s, 1); - in_uint8(s, len); + in_uint8s(s, 2); /* initiator */ + in_uint16_be(s, *chan); /* channelId */ + in_uint8s(s, 1); /* dataPriority (4-bits), segmentation (2-bits), padding (2-bits) */ + in_uint8(s, len); /* userData Length (byte 1) */ - if (len & 0x80) + if ((len & 0xC0) == 0x80) { - if (!s_check_rem(s, 1)) + /* From [ITU-T X.691] 11.9.3.7 + encoding a length determinant if "n" is greater than 127 and + less than 16K, then n is encoded using 2 bytes. + The first byte will have the two highest order bits set to 1 and 0 + (ie. len & 0xC0 == 0x80) and the length is encoded as remaining 14 bits of + the two bytes (ie. len & 0x3fff). */ + if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T T.125] SendDataRequest userData Length")) { return 1; } - in_uint8s(s, 1); + in_uint8s(s, 1); /* userData Length (byte 2) */ } + else if ((len & 0xC0) == 0xC0) + { + /* From [ITU-T X.691] 11.9.3.8 + encoding a length determinant if "n" is greater than 16K, + then the list of items is fragmented with the length of the first + fragment encoded using 1 byte. The two highest order bits are set + to 1 and 1 (ie. len & 0xC0 == 0xC0) and the remaining 6 bits contain + a multiplyer for 16K (ie. n = (len & 0x3f) * 0x3f) + */ + LOG(LOG_LEVEL_ERROR, "[ITU-T T.125] SendDataRequest with length greater " + "than 16K is not supported. len 0x%2.2x", len); + return 1; + } + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] SendDataRequest " + "initiator (ignored), channelId %d, dataPriority (ignored), " + "segmentation (ignored), userData Length (ignored)", *chan); - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_mcs_recv"); return 0; } /*****************************************************************************/ -/* returns error */ +/** + * Parse the identifier and length of a [ITU-T X.690] BER (Basic Encoding Rules) + * structure header. + * + * @param self + * @param s [in] - the stream to read from + * @param tag_val [in] - the expected tag value + * @param len [out] - the length of the structure + * @returns error + */ static int xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s, int tag_val, int *len) @@ -235,7 +274,7 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s, if (tag_val > 0xff) { - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [ITU-T X.690] Identifier")) { return 1; } @@ -243,7 +282,7 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s, } else { - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T X.690] Identifier")) { return 1; } @@ -252,10 +291,12 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s, if (tag != tag_val) { + LOG(LOG_LEVEL_ERROR, "Parsed [ITU-T X.690] Identifier: " + "expected 0x%4.4x, actual 0x%4.4x", tag_val, tag); return 1; } - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T X.690] Length")) { return 1; } @@ -269,7 +310,7 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s, while (l > 0) { - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T X.690] Length")) { return 1; } @@ -282,18 +323,14 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s, { *len = l; } + LOG_DEVEL(LOG_LEVEL_TRACE, "Parsed BER header [ITU-T X.690] " + "Identifier 0x%4.4x, Length %d", tag, *len); - if (s_check(s)) - { - return 0; - } - else - { - return 1; - } + return 0; } /*****************************************************************************/ +/* Parses a [ITU-T T.125] DomainParameters structure encoded using BER */ /* returns error */ static int xrdp_mcs_parse_domain_params(struct xrdp_mcs *self, struct stream *s) @@ -302,27 +339,30 @@ xrdp_mcs_parse_domain_params(struct xrdp_mcs *self, struct stream *s) if (xrdp_mcs_ber_parse_header(self, s, MCS_TAG_DOMAIN_PARAMS, &len) != 0) { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] DomainParameters failed"); return 1; } - if ((len < 0) || !s_check_rem(s, len)) + if (len < 0) + { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] DomainParameters length field is " + "invalid. Expected >= 0, actual %d", len); + return 1; + } + if (!s_check_rem_and_log(s, len, "Parsing [ITU-T T.125] DomainParameters")) { return 1; } - in_uint8s(s, len); + in_uint8s(s, len); /* skip all fields */ - if (s_check(s)) - { - return 0; - } - else - { - return 1; - } + return !s_check_rem_and_log(s, 0, "Parsing [ITU-T T.125] DomainParameters"); } /*****************************************************************************/ +/* Process a [ITU-T T.125] Connect-Initial message encoded using BER */ /* returns error */ static int xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) @@ -333,249 +373,346 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) s = libxrdp_force_read(self->iso_layer->trans); if (s == 0) { + LOG(LOG_LEVEL_ERROR, "Processing [ITU-T T.125] Connect-Initial failed"); return 1; } if (xrdp_iso_recv(self->iso_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "Processing [ITU-T T.125] Connect-Initial failed"); return 1; } if (xrdp_mcs_ber_parse_header(self, s, MCS_CONNECT_INITIAL, &len) != 0) { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial failed"); return 1; } if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial callingDomainSelector failed"); return 1; } - if ((len < 0) || !s_check_rem(s, len)) + if (len < 0) + { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial callingDomainSelector length field is " + "invalid. Expected >= 0, actual %d", len); + return 1; + } + if (!s_check_rem_and_log(s, len, "Parsing [ITU-T T.125] Connect-Initial callingDomainSelector")) { return 1; } - in_uint8s(s, len); + in_uint8s(s, len); /* [ITU-T T.125] Connect-Initial callingDomainSelector */ if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial calledDomainSelector failed"); return 1; } - - if ((len < 0) || !s_check_rem(s, len)) + if (len < 0) + { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial calledDomainSelector length field is " + "invalid. Expected >= 0, actual %d", len); + return 1; + } + if (!s_check_rem_and_log(s, len, "Parsing [ITU-T T.125] Connect-Initial calledDomainSelector")) { return 1; } - in_uint8s(s, len); + in_uint8s(s, len); /* [ITU-T T.125] Connect-Initial calledDomainSelector */ if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0) { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial upwardFlag failed"); return 1; } - - if ((len < 0) || !s_check_rem(s, len)) + if (len < 0) + { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial upwardFlag length field is " + "invalid. Expected >= 0, actual %d", len); + return 1; + } + if (!s_check_rem_and_log(s, len, "Parsing [ITU-T T.125] Connect-Initial upwardFlag")) { return 1; } - in_uint8s(s, len); + in_uint8s(s, len); /* [ITU-T T.125] Connect-Initial upwardFlag */ + /* [ITU-T T.125] Connect-Initial targetParameters */ if (xrdp_mcs_parse_domain_params(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial targetParameters failed"); return 1; } + /* [ITU-T T.125] Connect-Initial minimumParameters */ if (xrdp_mcs_parse_domain_params(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial minimumParameters failed"); return 1; } + /* [ITU-T T.125] Connect-Initial maximumParameters */ if (xrdp_mcs_parse_domain_params(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial maximumParameters failed"); return 1; } if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial userData failed"); return 1; } - - /* mcs data can not be zero length */ + /* mcs userData can not be zero length */ if ((len <= 0) || (len > 16 * 1024)) { + LOG(LOG_LEVEL_ERROR, + "Parsing [ITU-T T.125] Connect-Initial userData: invalid length. " + "Expected min 1, max %d; Actual %d", 16 * 1024, len); return 1; } - - if (!s_check_rem(s, len)) + if (!s_check_rem_and_log(s, len, "Parsing [ITU-T T.125] Connect-Initial userData")) { return 1; } + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [ITU-T T.125] Connect-Initial " + "callingDomainSelector (ignored), calledDomainSelector (ignored), " + "upwardFlag (ignored), targetParameters (ignored), " + "minimumParameters (ignored), maximumParameters (ignored), " + "userData (copied to client_mcs_data)"); /* make a copy of client mcs data */ init_stream(self->client_mcs_data, len); - out_uint8a(self->client_mcs_data, s->p, len); + out_uint8a(self->client_mcs_data, s->p, len); /* [ITU-T T.125] Connect-Initial userData */ in_uint8s(s, len); s_mark_end(self->client_mcs_data); - if (s_check_end(s)) - { - return 0; - } - else + if (!s_check_end_and_log(s, "MCS protocol error [ITU-T T.125] Connect-Initial")) { return 1; } + + return 0; + } /*****************************************************************************/ -/* returns error */ +/* Processes a [ITU-T T.25] DomainMCSPDU with type ErectDomainRequest + * + * Note: a parsing example can be found in [MS-RDPBCGR] 4.1.5 + * + * returns error */ static int xrdp_mcs_recv_edrq(struct xrdp_mcs *self) { int opcode; struct stream *s; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_mcs_recv_edrq"); - s = libxrdp_force_read(self->iso_layer->trans); if (s == 0) { + LOG(LOG_LEVEL_ERROR, "Processing [ITU-T T.125] ErectDomainRequest failed"); return 1; } if (xrdp_iso_recv(self->iso_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "Processing [ITU-T T.125] ErectDomainRequest failed"); return 1; } - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T T.125] DomainMCSPDU")) { return 1; } + /* The DomainMCSPDU choice index is a 6-bit int with the next bit as the + bit field of the optional field in the struct + */ in_uint8(s, opcode); if ((opcode >> 2) != MCS_EDRQ) { + LOG(LOG_LEVEL_ERROR, "Parsed [ITU-T T.125] DomainMCSPDU choice index " + "expected %d, received %d", MCS_EDRQ, (opcode >> 2)); return 1; } - if (!s_check_rem(s, 4)) + if (!s_check_rem_and_log(s, 4, "Parsing [ITU-T T.125] ErectDomainRequest")) { return 1; } - in_uint8s(s, 2); - in_uint8s(s, 2); + in_uint8s(s, 2); /* subHeight */ + in_uint8s(s, 2); /* subInterval */ - if (opcode & 2) + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] DomainMCSPDU " + "choice index %d (ErectDomainRequest)", (opcode >> 2)); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] ErectDomainRequest " + "subHeight (ignored), subInterval (ignored), " + "nonStandard (%s)", + (opcode & 2) ? "present" : "not present"); + + /* + * [MS-RDPBCGR] 2.2.1.5 says that the mcsEDrq field is 5 bytes (which have + * already been read into the opcode and previous fields), so the + * nonStandard field should never be present. + */ + if (opcode & 2) /* ErectDomainRequest v3 nonStandard optional field is present? */ { - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [ITU-T T.125] ErectDomainRequest nonStandard")) { return 1; } - in_uint16_be(s, self->userid); + in_uint16_be(s, self->userid); /* NonStandardParameter.key + NonStandardParameter.data */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] DomainMCSPDU " + "choice index %d (ErectDomainRequest)", (opcode >> 2)); } - if (!(s_check_end(s))) + if (!s_check_end_and_log(s, "MCS protocol error [ITU-T T.125] ErectDomainRequest")) { return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_mcs_recv_edrq"); return 0; } /*****************************************************************************/ -/* returns error */ +/* Processes a [ITU-T T.25] DomainMCSPDU with type AttachUserRequest + * + * Note: a parsing example can be found in [MS-RDPBCGR] 4.1.6 + * + * returns error */ static int xrdp_mcs_recv_aurq(struct xrdp_mcs *self) { int opcode; struct stream *s; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_mcs_recv_aurq"); - s = libxrdp_force_read(self->iso_layer->trans); if (s == 0) { + LOG(LOG_LEVEL_ERROR, "Processing [ITU-T T.125] AttachUserRequest failed"); return 1; } if (xrdp_iso_recv(self->iso_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "Processing [ITU-T T.125] AttachUserRequest failed"); return 1; } - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T T.125] DomainMCSPDU")) { return 1; } + /* The DomainMCSPDU choice index is a 6-bit int with the next bit as the + bit field of the optional field in the struct + */ in_uint8(s, opcode); if ((opcode >> 2) != MCS_AURQ) { + LOG(LOG_LEVEL_ERROR, "Parsed [ITU-T T.125] DomainMCSPDU choice index " + "expected %d, received %d", MCS_AURQ, (opcode >> 2)); return 1; } + /* + * [MS-RDPBCGR] 2.2.1.6 says that the mcsAUrq field is 1 bytes (which have + * already been read into the opcode), so the nonStandard field should + * never be present. + */ if (opcode & 2) { - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [ITU-T T.125] AttachUserRequest nonStandard")) { return 1; } - in_uint16_be(s, self->userid); + in_uint16_be(s, self->userid); /* NonStandardParameter.key + NonStandardParameter.data */ } + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] DomainMCSPDU " + "choice index %d (AttachUserRequest)", (opcode >> 2)); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] AttachUserRequest " + "nonStandard (%s)", + (opcode & 2) ? "present" : "not present"); - if (!(s_check_end(s))) + if (!s_check_end_and_log(s, "MCS protocol error [ITU-T T.125] AttachUserRequest")) { return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_mcs_recv_aurq"); return 0; } /*****************************************************************************/ -/* returns error */ +/* Send a [ITU-T T.125] DomainMCSPDU with type AttachUserConfirm. + * + * Note: a parsing example can be found in [MS-RDPBCGR] 4.1.7 + * + * returns error */ static int xrdp_mcs_send_aucf(struct xrdp_mcs *self) { struct stream *s; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_mcs_send_aucf"); make_stream(s); init_stream(s, 8192); if (xrdp_iso_init(self->iso_layer, s) != 0) { free_stream(s); - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_send_aucf error"); + LOG(LOG_LEVEL_ERROR, "xrdp_mcs_send_aucf: xrdp_iso_init failed"); return 1; } - out_uint8(s, ((MCS_AUCF << 2) | 2)); - out_uint8s(s, 1); - out_uint16_be(s, self->userid); + out_uint8(s, ((MCS_AUCF << 2) | 2)); /* AttachUserConfirm + optional field initiator is present */ + out_uint8s(s, 1); /* result = 0 rt-successful */ + out_uint16_be(s, self->userid); /* initiator */ s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [ITU-T T.125] DomainMCSPDU " + "of type AttachUserConfirm: result SUCCESS, initiator %d", + self->userid); if (xrdp_iso_send(self->iso_layer, s) != 0) { free_stream(s); - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_send_aucf error"); + LOG(LOG_LEVEL_ERROR, "Sending [ITU-T T.125] AttachUserConfirm failed"); return 1; } free_stream(s); - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_mcs_send_aucf"); return 0; } /*****************************************************************************/ -/* returns error */ +/* Processes a [ITU-T T.25] DomainMCSPDU with type ChannelJoinRequest + * + * Note: a parsing example can be found in [MS-RDPBCGR] 4.1.8.1.1 + * + * returns error */ static int xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) { @@ -585,43 +722,61 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) s = libxrdp_force_read(self->iso_layer->trans); if (s == 0) { + LOG(LOG_LEVEL_ERROR, "Processing [ITU-T T.25] ChannelJoinRequest failed"); return 1; } if (xrdp_iso_recv(self->iso_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "Processing [ITU-T T.25] ChannelJoinRequest failed"); return 1; } - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T T.125] DomainMCSPDU")) { return 1; } in_uint8(s, opcode); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] DomainMCSPDU " + "choice index %d (ChannelJoinRequest)", (opcode >> 2)); if ((opcode >> 2) != MCS_CJRQ) { + LOG(LOG_LEVEL_ERROR, "Parsed [ITU-T T.125] DomainMCSPDU choice index " + "expected %d, received %d", MCS_CJRQ, (opcode >> 2)); return 1; } - if (!s_check_rem(s, 4)) + if (!s_check_rem_and_log(s, 4, "Parsing [ITU-T T.125] ChannelJoinRequest")) { return 1; } - in_uint8s(s, 4); + in_uint8s(s, 4); /* initiator (2 bytes) + channelId (2 bytes) */ + /* + * [MS-RDPBCGR] 2.2.1.8 says that the mcsAUrq field is 5 bytes (which have + * already been read into the opcode and other fields), so the nonStandard + * field should never be present. + */ if (opcode & 2) { - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [ITU-T T.125] ChannelJoinRequest nonStandard")) { return 1; } - in_uint8s(s, 2); + in_uint8s(s, 2); /* NonStandardParameter.key + NonStandardParameter.data */ } - if (!(s_check_end(s))) + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] ChannelJoinRequest " + "initiator (ignored), channelId (ignored), " + "nonStandard (%s)", + (opcode & 2) ? "present" : "not present"); + + if (!s_check_end_and_log(s, "MCS protocol error [ITU-T T.125] ChannelJoinRequest")) { return 1; } @@ -630,7 +785,9 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) } /*****************************************************************************/ -/* returns error */ +/* Write the identifier and length of a [ITU-T X.690] BER (Basic Encoding Rules) + * structure header. + * returns error */ static int xrdp_mcs_ber_out_header(struct xrdp_mcs *self, struct stream *s, int tag_val, int len) @@ -654,6 +811,8 @@ xrdp_mcs_ber_out_header(struct xrdp_mcs *self, struct stream *s, out_uint8(s, len); } + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T X.690] Identifier %d, Length %d", + tag_val, len); return 0; } @@ -704,15 +863,24 @@ xrdp_mcs_out_domain_params(struct xrdp_mcs *self, struct stream *s, xrdp_mcs_ber_out_int8(self, s, max_channels); xrdp_mcs_ber_out_int8(self, s, max_users); xrdp_mcs_ber_out_int8(self, s, max_tokens); - xrdp_mcs_ber_out_int8(self, s, 1); - xrdp_mcs_ber_out_int8(self, s, 0); - xrdp_mcs_ber_out_int8(self, s, 1); + xrdp_mcs_ber_out_int8(self, s, 1); /* numPriorities */ + xrdp_mcs_ber_out_int8(self, s, 0); /* minThroughput */ + xrdp_mcs_ber_out_int8(self, s, 1); /* maxHeight */ xrdp_mcs_ber_out_int24(self, s, max_pdu_size); - xrdp_mcs_ber_out_int8(self, s, 2); + xrdp_mcs_ber_out_int8(self, s, 2); /* protocolVersion */ + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [ITU-T T.125] DomainParameters " + "maxChannelIds %d, maxUserIds %d, maxTokenIds %d, numPriorities 1, " + "minThroughput 0 B/s, maxHeight 1, maxMCSPDUsize %d, " + "protocolVersion 2", + max_channels, max_users, max_tokens, max_pdu_size); return 0; } /*****************************************************************************/ -/* prepare server gcc data to send in mcs response msg */ +/* Write an [ITU-T T.124] ConnectData (ALIGNED variant of BASIC-PER) message + * with ConnectGCCPDU, ConferenceCreateResponse, + * and [MS-RDPBCGR] Server Data Blocks as user data. + */ int xrdp_mcs_out_gcc_data(struct xrdp_sec *self) { @@ -724,142 +892,231 @@ xrdp_mcs_out_gcc_data(struct xrdp_sec *self) int gcc_size; char *gcc_size_ptr; char *ud_ptr; + int header_length = 0; + int server_cert_len = 0; + int public_key_blob_len = 0; + int key_len = 0; + int bit_len = 0; + int data_len = 0; + int modulus_len = 0; num_channels = self->mcs_layer->channel_list->count; num_channels_even = num_channels + (num_channels & 1); s = &(self->server_mcs_data); init_stream(s, 8192); - out_uint16_be(s, 5); /* AsnBerObjectIdentifier */ - out_uint16_be(s, 0x14); + + /* [ITU-T T.124] ConnectData (ALIGNED variant of BASIC-PER) */ + out_uint16_be(s, 5); /* = 0x00 0x05 */ + /* t124Identifier choice index = 0 (object) */ + /* object length = 5 */ + out_uint16_be(s, 0x14); /* t124Identifier.object = ??? (0x00 0x14 0x7c 0x00 0x01) */ out_uint8(s, 0x7c); out_uint16_be(s, 1); /* -- */ - out_uint8(s, 0x2a); /* ConnectPDULen */ - out_uint8(s, 0x14); - out_uint8(s, 0x76); + out_uint8(s, 0x2a); /* connectPDU length = 42 */ + /* connectPDU octet string of type ConnectGCCPDU + (unknown where this octet string is defined to be + of type ConnectGCCPDU) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [ITU-T T.124] ConnectData " + "t124Identifier.object 0x00 0x14 0x7c 0x00 0x01, connectPDU length %d", + 0x2a); + + /* [ITU-T T.124] ConnectGCCPDU (ALIGNED variant of BASIC-PER) */ + out_uint8(s, 0x14); /* ConnectGCCPDU choice index 1 = ConferenceCreateResponse with userData present */ + + /* [ITU-T T.124] ConferenceCreateResponse (ALIGNED variant of BASIC-PER) */ + out_uint8(s, 0x76); /* nodeID = 31219 - 1001 (PER offset for min value) + = 30218 (big-endian 0x760a) */ out_uint8(s, 0x0a); - out_uint8(s, 1); - out_uint8(s, 1); - out_uint8(s, 0); - out_uint16_le(s, 0xc001); - out_uint8(s, 0); + out_uint8(s, 1); /* tag length */ + out_uint8(s, 1); /* tag */ + out_uint8(s, 0); /* result = 0 (success) */ + out_uint16_le(s, 0xc001); /* userData set count = 1 (0x01), + userData.isPresent = 0x80 (yes) | userData.key choice index = 0x40 (1 = h221NonStandard) */ + out_uint8(s, 0); /* userData.key.h221NonStandard length + = 4 - 4 (PER offset for min value) (H221NonStandardIdentifier is an octet string SIZE (4..255)) + = 0 + */ + + /* [ITU-T H.221] H221NonStandardIdentifier uses country codes and + manufactuer codes from [ITU-T T.35]. Unknown why these values are used, + maybe this is just copied from the [MS-RDPBCGR] 4.1.4 example which uses + the value "McDn" */ out_uint8(s, 0x4d); /* M */ out_uint8(s, 0x63); /* c */ out_uint8(s, 0x44); /* D */ out_uint8(s, 0x6e); /* n */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [ITU-T T.124] ConferenceCreateResponse " + "nodeID %d, result SUCCESS", 0x760a + 1001); + + /* ConferenceCreateResponse.userData.key.value (octet string) */ /* GCC Response Total Length - 2 bytes , set later */ gcc_size_ptr = s->p; /* RDPGCCUserDataResponseLength */ out_uint8s(s, 2); ud_ptr = s->p; /* User Data */ - out_uint16_le(s, SEC_TAG_SRV_INFO); + /* [MS-RDPBCGR] TS_UD_HEADER */ + out_uint16_le(s, SEC_TAG_SRV_INFO); /* type */ if (self->mcs_layer->iso_layer->rdpNegData) { - out_uint16_le(s, 12); /* len */ + out_uint16_le(s, 12); /* length */ } else { - out_uint16_le(s, 8); /* len */ + out_uint16_le(s, 8); /* length */ } - out_uint8(s, 4); /* 4 = rdp5 1 = rdp4 */ + /* [MS-RDPBCGR] TS_UD_SC_CORE */ + out_uint8(s, 4); /* version (0x00080004 = rdp5, 0x00080001 = rdp4) */ out_uint8(s, 0); out_uint8(s, 8); - out_uint8(s, 0); + out_uint8(s, 0); /* version (last byte) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct header [MS-RDPBCGR] TS_UD_HEADER " + "type 0x%4.4x, length %d", + SEC_TAG_SRV_INFO, + self->mcs_layer->iso_layer->rdpNegData ? 12 : 8); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [MS-RDPBCGR] TS_UD_SC_CORE " + " version 0x%8.8x", 0x00080004); if (self->mcs_layer->iso_layer->rdpNegData) { /* RequestedProtocol */ - out_uint32_le(s, self->mcs_layer->iso_layer->requestedProtocol); + out_uint32_le(s, self->mcs_layer->iso_layer->requestedProtocol); /* clientRequestedProtocols */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [MS-RDPBCGR] TS_UD_SC_CORE " + " clientRequestedProtocols 0x%8.8x", + self->mcs_layer->iso_layer->requestedProtocol); } - out_uint16_le(s, SEC_TAG_SRV_CHANNELS); - out_uint16_le(s, 8 + (num_channels_even * 2)); /* len */ - out_uint16_le(s, MCS_GLOBAL_CHANNEL); /* 1003, 0x03eb main channel */ - out_uint16_le(s, num_channels); /* number of other channels */ + + /* [MS-RDPBCGR] TS_UD_HEADER */ + out_uint16_le(s, SEC_TAG_SRV_CHANNELS); /* type */ + out_uint16_le(s, 8 + (num_channels_even * 2)); /* length */ + /* [MS-RDPBCGR] TS_UD_SC_NET */ + out_uint16_le(s, MCS_GLOBAL_CHANNEL); /* 1003, 0x03eb main channel (MCSChannelId) */ + out_uint16_le(s, num_channels); /* number of other channels (channelCount) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct header [MS-RDPBCGR] TS_UD_HEADER " + "type 0x%4.4x, length %d", + SEC_TAG_SRV_CHANNELS, 8 + (num_channels_even * 2)); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [MS-RDPBCGR] TS_UD_SC_NET " + "MCSChannelId %d, channelCount %d", + MCS_GLOBAL_CHANNEL, num_channels); for (index = 0; index < num_channels_even; index++) { if (index < num_channels) { channel = MCS_GLOBAL_CHANNEL + (index + 1); - out_uint16_le(s, channel); + out_uint16_le(s, channel); /* channelIdArray[index] (channel allocated) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [MS-RDPBCGR] TS_UD_SC_NET channelIdArray[%d] " + "channelId %d", index, channel); } else { - out_uint16_le(s, 0); + out_uint16_le(s, 0); /* padding or channelIdArray[index] (channel not allocated) */ } + } - if (self->rsa_key_bytes == 64) + if (self->rsa_key_bytes == 64 || self->rsa_key_bytes == 256) { - LOG(LOG_LEVEL_DEBUG, "xrdp_sec_out_mcs_data: using 512 bit RSA key"); - out_uint16_le(s, SEC_TAG_SRV_CRYPT); - out_uint16_le(s, 0x00ec); /* len is 236 */ - out_uint32_le(s, self->crypt_method); - out_uint32_le(s, self->crypt_level); - out_uint32_le(s, 32); /* 32 bytes random len */ - out_uint32_le(s, 0xb8); /* 184 bytes rsa info(certificate) len */ - out_uint8a(s, self->server_random, 32); - /* here to end is certificate */ + if (self->rsa_key_bytes == 64) + { + header_length = 0x00ec; /* length = 236 */ + server_cert_len = 0xb8; /* serverCertLen (184 bytes) */ + public_key_blob_len = 0x005c; /* wPublicKeyBlobLen (92 bytes) */ + key_len = 0x0048; /* keylen (72 bytes = (bitlen / 8) modulus + 8 padding) */ + bit_len = 512; /* bitlen = 512 */ + data_len = 63; /* datalen (63 = (bitlen / 8) - 1) */ + modulus_len = 64; + } + else /* if (self->rsa_key_bytes == 256) */ + { + header_length = 0x01ac; /* length = 428 */ + server_cert_len = 0x178; /* serverCertLen (376 bytes) */ + public_key_blob_len = 0x011c; /* wPublicKeyBlobLen (284 bytes) */ + key_len = 0x0108; /* keylen (264 bytes = (bitlen / 8) modulus + 8 padding) */ + bit_len = 2048; /* bitlen = 2048 */ + data_len = 255; /* datalen (255 = (bitlen / 8) - 1) */ + modulus_len = 256; + } + LOG(LOG_LEVEL_DEBUG, "using %d bit RSA key", bit_len); + + /* [MS-RDPBCGR] TS_UD_HEADER */ + out_uint16_le(s, SEC_TAG_SRV_CRYPT); /* type */ + out_uint16_le(s, header_length); /* length */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct header [MS-RDPBCGR] TS_UD_HEADER " + "type 0x%4.4x, length %d", SEC_TAG_SRV_CRYPT, header_length); + + /* [MS-RDPBCGR] TS_UD_SC_SEC1 */ + out_uint32_le(s, self->crypt_method); /* encryptionMethod */ + out_uint32_le(s, self->crypt_level); /* encryptionLevel */ + out_uint32_le(s, 32); /* serverRandomLen */ + out_uint32_le(s, server_cert_len); /* serverCertLen */ + out_uint8a(s, self->server_random, 32); /* serverRandom */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [MS-RDPBCGR] TS_UD_SC_SEC1 " + "encryptionMethod 0x%8.8x, encryptionLevel 0x%8.8x, " + "serverRandomLen 32, serverCertLen %d, serverRandom (omitted), ", + self->crypt_method, self->crypt_level, server_cert_len); + + /* (field serverCertificate) [MS-RDPBCGR] SERVER_CERTIFICATE */ /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */ /* TermService\Parameters\Certificate */ - out_uint32_le(s, 1); - out_uint32_le(s, 1); - out_uint32_le(s, 1); - out_uint16_le(s, SEC_TAG_PUBKEY); /* 0x0006 */ - out_uint16_le(s, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */ - out_uint32_le(s, SEC_RSA_MAGIC); /* 0x31415352 'RSA1' */ - out_uint32_le(s, 0x0048); /* 72 bytes modulus len */ - out_uint32_be(s, 0x00020000); /* bit len */ - out_uint32_be(s, 0x3f000000); /* data len */ - out_uint8a(s, self->pub_exp, 4); /* pub exp */ - out_uint8a(s, self->pub_mod, 64); /* pub mod */ - out_uint8s(s, 8); /* pad */ - out_uint16_le(s, SEC_TAG_KEYSIG); /* 0x0008 */ - out_uint16_le(s, 72); /* len */ - out_uint8a(s, self->pub_sig, 64); /* pub sig */ - out_uint8s(s, 8); /* pad */ - } - else if (self->rsa_key_bytes == 256) - { - LOG(LOG_LEVEL_DEBUG, "xrdp_sec_out_mcs_data: using 2048 bit RSA key"); - out_uint16_le(s, SEC_TAG_SRV_CRYPT); - out_uint16_le(s, 0x01ac); /* len is 428 */ - out_uint32_le(s, self->crypt_method); - out_uint32_le(s, self->crypt_level); - out_uint32_le(s, 32); /* 32 bytes random len */ - out_uint32_le(s, 0x178); /* 376 bytes rsa info(certificate) len */ - out_uint8a(s, self->server_random, 32); - /* here to end is certificate */ - /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */ - /* TermService\Parameters\Certificate */ - out_uint32_le(s, 1); - out_uint32_le(s, 1); - out_uint32_le(s, 1); - out_uint16_le(s, SEC_TAG_PUBKEY); /* 0x0006 */ - out_uint16_le(s, 0x011c); /* 284 bytes length of SEC_TAG_PUBKEY */ - out_uint32_le(s, SEC_RSA_MAGIC); /* 0x31415352 'RSA1' */ - out_uint32_le(s, 0x0108); /* 264 bytes modulus len */ - out_uint32_be(s, 0x00080000); /* bit len */ - out_uint32_be(s, 0xff000000); /* data len */ - out_uint8a(s, self->pub_exp, 4); /* pub exp */ - out_uint8a(s, self->pub_mod, 256); /* pub mod */ - out_uint8s(s, 8); /* pad */ - out_uint16_le(s, SEC_TAG_KEYSIG); /* 0x0008 */ - out_uint16_le(s, 72); /* len */ - out_uint8a(s, self->pub_sig, 64); /* pub sig */ - out_uint8s(s, 8); /* pad */ + out_uint32_le(s, 1); /* dwVersion (1 = PROPRIETARYSERVERCERTIFICATE) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [MS-RDPBCGR] SERVER_CERTIFICATE " + "dwVersion.certChainVersion 1 (CERT_CHAIN_VERSION_1), " + "dwVersion.t 0 (permanent)"); + + /* [MS-RDPBCGR] PROPRIETARYSERVERCERTIFICATE */ + out_uint32_le(s, 1); /* dwSigAlgId (1 = RSA) */ + out_uint32_le(s, 1); /* dwKeyAlgId (1 = RSA) */ + out_uint16_le(s, SEC_TAG_PUBKEY); /* wPublicKeyBlobType (BB_RSA_KEY_BLOB) */ + out_uint16_le(s, public_key_blob_len); /* wPublicKeyBlobLen */ + + /* (field PublicKeyBlob) [MS-RDPBCGR] RSA_PUBLIC_KEY */ + out_uint32_le(s, SEC_RSA_MAGIC); /* magic (0x31415352 'RSA1') */ + out_uint32_le(s, key_len); /* keylen */ + out_uint32_le(s, bit_len); /* bitlen */ + out_uint32_le(s, data_len); /* datalen */ + out_uint8a(s, self->pub_exp, 4); /* pubExp */ + out_uint8a(s, self->pub_mod, modulus_len); /* modulus */ + out_uint8s(s, 8); /* modulus zero padding */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [MS-RDPBCGR] RSA_PUBLIC_KEY " + "magic 0x%8.8x, keylen %d, bitlen %d, datalen %d, " + "pubExp , modulus , ", + SEC_RSA_MAGIC, key_len, bit_len, data_len); + + out_uint16_le(s, SEC_TAG_KEYSIG); /* wSignatureBlobType (0x0008 RSA) */ + out_uint16_le(s, 72); /* wSignatureBlobLen */ + out_uint8a(s, self->pub_sig, 64); /* SignatureBlob */ + out_uint8s(s, 8); /* modulus zero padding */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [MS-RDPBCGR] PROPRIETARYSERVERCERTIFICATE " + "dwKeyAlgId 1, " + "wPublicKeyBlobType 0x%4.4x, " + "wPublicKeyBlobLen %d, PublicKeyBlob " + "wSignatureBlobType 0x%4.4x, " + "wSignatureBlobLen %d, " + "SignatureBlob ", + SEC_TAG_PUBKEY, public_key_blob_len, + SEC_TAG_KEYSIG, 72); } else if (self->rsa_key_bytes == 0) /* no security */ { - LOG(LOG_LEVEL_DEBUG, "xrdp_sec_out_mcs_data: using no security"); - out_uint16_le(s, SEC_TAG_SRV_CRYPT); - out_uint16_le(s, 12); /* len is 12 */ - out_uint32_le(s, self->crypt_method); - out_uint32_le(s, self->crypt_level); + LOG(LOG_LEVEL_DEBUG, "using no security"); + /* [MS-RDPBCGR] TS_UD_HEADER */ + out_uint16_le(s, SEC_TAG_SRV_CRYPT); /* type*/ + out_uint16_le(s, 12); /* length */ + /* [MS-RDPBCGR] TS_UD_SC_SEC1 */ + out_uint32_le(s, self->crypt_method); /* encryptionMethod */ + out_uint32_le(s, self->crypt_level); /* encryptionLevel */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct header [MS-RDPBCGR] TS_UD_HEADER " + "type 0x%4.4x, length %d", SEC_TAG_SRV_CRYPT, 12); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [MS-RDPBCGR] TS_UD_SC_SEC1 " + "encryptionMethod 0x%8.8x, encryptionMethod 0x%8.8x", + self->crypt_method, self->crypt_level); } else { - LOG(LOG_LEVEL_ERROR, "xrdp_sec_out_mcs_data: error"); + LOG(LOG_LEVEL_WARNING, + "Unsupported xrdp_sec.rsa_key_bytes value: %d, the client " + "will not be sent a [MS-RDPBCGR] TS_UD_SC_SEC1 message.", + self->rsa_key_bytes); } - /* end certificate */ s_mark_end(s); gcc_size = (int)(s->end - ud_ptr) | 0x8000; @@ -869,14 +1126,19 @@ xrdp_mcs_out_gcc_data(struct xrdp_sec *self) return 0; } /*****************************************************************************/ -/* returns error */ +/* Send an [ITU-T T.125] Connect-Response message. + * + * Note: the xrdp_mcs_out_gcc_data() function must be called (to populate the + * xrdp_mcs.server_mcs_data stream) before this method is called. + * + * returns error + */ static int xrdp_mcs_send_connect_response(struct xrdp_mcs *self) { int data_len; struct stream *s; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_mcs_send_connect_response"); make_stream(s); init_stream(s, 8192); data_len = (int) (self->server_mcs_data->end - self->server_mcs_data->data); @@ -885,87 +1147,112 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self) xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, data_len > 0x80 ? data_len + 38 : data_len + 36); xrdp_mcs_ber_out_header(self, s, BER_TAG_RESULT, 1); - out_uint8(s, 0); + out_uint8(s, 0); /* result choice index 0 = rt-successful */ xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1); - out_uint8(s, 0); + out_uint8(s, 0); /* calledConnectId */ xrdp_mcs_out_domain_params(self, s, 22, 3, 0, 0xfff8); xrdp_mcs_ber_out_header(self, s, BER_TAG_OCTET_STRING, data_len); /* mcs data */ out_uint8a(s, self->server_mcs_data->data, data_len); s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [ITU-T T.125] Connect-Response " + "result SUCCESS, calledConnectId 0, " + "domainParameters (see xrdp_mcs_out_domain_params() trace logs), " + "userData (see xrdp_mcs_out_gcc_data() trace logs and " + "hex dump below)"); + LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "[ITU-T T.125] Connect-Response userData", + self->server_mcs_data->data, data_len); if (xrdp_iso_send(self->iso_layer, s) != 0) { free_stream(s); - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_send_connect_response error"); + LOG(LOG_LEVEL_ERROR, "Sending [ITU-T T.125] Connect-Response failed"); return 1; } free_stream(s); - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_mcs_send_connect_response"); return 0; } /*****************************************************************************/ -/* returns error */ +/* Process and send the MCS messages for the RDP Connection Sequence + * [MS-RDPBCGR] 1.3.1.1 + * + * returns error + */ int xrdp_mcs_incoming(struct xrdp_mcs *self) { int index; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_mcs_incoming"); - + LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] receive connection request"); if (xrdp_mcs_recv_connect_initial(self) != 0) { + LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] receive connection request failed"); return 1; } /* in xrdp_sec.c */ if (xrdp_sec_process_mcs_data(self->sec_layer) != 0) { + LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] Connect Initial PDU with GCC Conference Create Request failed"); return 1; } + LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] construct connection reponse"); if (xrdp_mcs_out_gcc_data(self->sec_layer) != 0) { + LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] construct connection reponse failed"); return 1; } + LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] send connection reponse"); if (xrdp_mcs_send_connect_response(self) != 0) { + LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] send connection reponse failed"); return 1; } + LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] receive erect domain request"); if (xrdp_mcs_recv_edrq(self) != 0) { + LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] receive erect domain request failed"); return 1; } + LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] receive attach user request"); if (xrdp_mcs_recv_aurq(self) != 0) { + LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] receive attach user request failed"); return 1; } + LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] send attach user confirm"); if (xrdp_mcs_send_aucf(self) != 0) { + LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] send attach user confirm failed"); return 1; } for (index = 0; index < self->channel_list->count + 2; index++) { + LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] receive channel join request"); if (xrdp_mcs_recv_cjrq(self) != 0) { + LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] receive channel join request failed"); return 1; } + LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] send channel join confirm"); if (xrdp_mcs_send_cjcf(self, self->userid, self->userid + MCS_USERCHANNEL_BASE + index) != 0) { + LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] send channel join confirm failed"); return 1; } } - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_mcs_incoming"); + LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] completed"); return 0; } @@ -1005,19 +1292,20 @@ xrdp_mcs_call_callback(struct xrdp_mcs *self) } else { - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_mcs_send, session->callback is nil"); + LOG_DEVEL(LOG_LEVEL_WARNING, "session->callback is NULL"); } } else { - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_mcs_send, session is nil"); + LOG_DEVEL(LOG_LEVEL_WARNING, "session is NULL"); } return rv; } /*****************************************************************************/ -/* returns error */ +/* Send a [ITU-T T.125] SendDataIndication message + * returns error */ int xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan) { @@ -1025,35 +1313,31 @@ xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan) char *lp; //static int max_len = 0; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_mcs_send"); s_pop_layer(s, mcs_hdr); len = (s->end - s->p) - 8; if (len > 8192 * 2) { - LOG(LOG_LEVEL_WARNING, "error in xrdp_mcs_send, size too big: %d bytes", len); + LOG(LOG_LEVEL_WARNING, "xrdp_mcs_send: stream size too big: %d bytes", len); } - //if (len > max_len) - //{ - // max_len = len; - // g_printf("mcs max length is %d\r\n", max_len); - //} - //g_printf("mcs length %d max length is %d\r\n", len, max_len); - //g_printf("mcs length %d\r\n", len); - out_uint8(s, MCS_SDIN << 2); - out_uint16_be(s, self->userid); - out_uint16_be(s, chan); - out_uint8(s, 0x70); + /* The DomainMCSPDU choice index is a 6-bit int with the 2 least + significant bits of the byte as padding */ + out_uint8(s, MCS_SDIN << 2); /* DomainMCSPDU choice index */ + out_uint16_be(s, self->userid); /* initiator */ + out_uint16_be(s, chan); /* channelId */ + out_uint8(s, 0x70); /* dataPriority (upper 2 bits), + segmentation (next 2 bits), + padding (4 bits) */ if (len >= 128) { len = len | 0x8000; - out_uint16_be(s, len); + out_uint16_be(s, len); /* userData length */ } else { - out_uint8(s, len); + out_uint8(s, len); /* userData length */ /* move everything up one byte */ lp = s->p; @@ -1066,9 +1350,13 @@ xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan) s->end--; } + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T T.125] SendDataIndication " + "initiator %d, channelId %d, dataPriority %d, segmentation 0x0, " + "userData length %d", + self->userid, chan, 0x70 >> 6, (0x70 >> 4) & 0x03); if (xrdp_iso_send(self->iso_layer, s) != 0) { - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_send error"); + LOG(LOG_LEVEL_ERROR, "xrdp_mcs_send: xrdp_iso_send failed"); return 1; } @@ -1079,7 +1367,6 @@ xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan) xrdp_mcs_call_callback(self); } - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_mcs_send"); return 0; } @@ -1097,11 +1384,11 @@ close_rdp_socket(struct xrdp_mcs *self) trans_shutdown_tls_mode(self->iso_layer->trans); g_tcp_close(self->iso_layer->trans->sck); self->iso_layer->trans->sck = 0 ; - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mcs_disconnect - socket closed"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_mcs_disconnect - socket closed"); return; } } - LOG_DEVEL(LOG_LEVEL_TRACE, "Failed to close socket"); + LOG_DEVEL(LOG_LEVEL_WARNING, "Failed to close socket"); } /*****************************************************************************/ @@ -1111,7 +1398,6 @@ xrdp_mcs_disconnect(struct xrdp_mcs *self) { struct stream *s; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_mcs_disconnect"); make_stream(s); init_stream(s, 8192); @@ -1119,24 +1405,25 @@ xrdp_mcs_disconnect(struct xrdp_mcs *self) { free_stream(s); close_rdp_socket(self); - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_disconnect error - 1"); + LOG(LOG_LEVEL_ERROR, "xrdp_mcs_disconnect: xrdp_iso_init failed"); return 1; } out_uint8(s, (MCS_DPUM << 2) | 1); - out_uint8(s, 0x80); + out_uint8(s, 0x80); /* reason (upper 3 bits) (4 = rn-channel-purged)*/ s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [ITU T.125] DisconnectProviderUltimatum " + "reason %d", 0x80 >> 5); if (xrdp_iso_send(self->iso_layer, s) != 0) { free_stream(s); close_rdp_socket(self); - LOG(LOG_LEVEL_ERROR, " out xrdp_mcs_disconnect error - 2"); + LOG(LOG_LEVEL_ERROR, "Sending [ITU T.125] DisconnectProviderUltimatum failed"); return 1; } free_stream(s); close_rdp_socket(self); - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_mcs_disconnect - close sent"); return 0; } diff --git a/libxrdp/xrdp_mppc_enc.c b/libxrdp/xrdp_mppc_enc.c index d69953dc..a5837256 100644 --- a/libxrdp/xrdp_mppc_enc.c +++ b/libxrdp/xrdp_mppc_enc.c @@ -969,6 +969,10 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) { /* compressed data longer than uncompressed data */ /* give up */ + LOG_DEVEL(LOG_LEVEL_DEBUG, "Compression algorithim produced a compressed " + "buffer which is larger than the uncompressed buffer. " + "compression ratio %f, flags 0x%x", + (float) len / (float) opb_index, enc->flags); enc->historyOffset = 0; g_memset(hash_table, 0, enc->buf_len * 2); g_memset(enc->historyBuffer, 0, enc->buf_len); @@ -982,10 +986,10 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) enc->flags |= enc->flagsHold; enc->flagsHold = 0; - LOG_DEVEL(LOG_LEVEL_TRACE, "\n"); - - LOG_DEVEL(LOG_LEVEL_TRACE, "compression ratio: %f", (float) len / (float) enc->bytes_in_opb); - + LOG_DEVEL(LOG_LEVEL_TRACE, "Compression successful. compression ratio %f, " + "flags 0x%x, bytes_in_opb %d, historyOffset %d, uncompressed len %d", + (float) len / (float) enc->bytes_in_opb, enc->flags, + enc->bytes_in_opb, enc->historyOffset, len); return 1; } diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 7e65f02f..79b33472 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -83,6 +83,7 @@ xrdp_orders_reset(struct xrdp_orders *self) { if (xrdp_orders_force_send(self) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_orders_reset: xrdp_orders_force_send failed"); return 1; } g_free(self->orders_state.text_data); @@ -109,23 +110,29 @@ xrdp_orders_init(struct xrdp_orders *self) LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_orders_init: fastpath"); if (xrdp_rdp_init_fastpath(self->rdp_layer, self->out_s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_orders_init: xrdp_rdp_init_fastpath failed"); return 1; } self->order_count_ptr = self->out_s->p; out_uint8s(self->out_s, 2); /* number of orders, set later */ + // LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] TODO"); } else { - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_orders_init: slowpath"); if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_orders_init: xrdp_rdp_init_data failed"); return 1; } - out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); + out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); /* updateType */ out_uint8s(self->out_s, 2); /* pad */ self->order_count_ptr = self->out_s->p; out_uint8s(self->out_s, 2); /* number of orders, set later */ out_uint8s(self->out_s, 2); /* pad */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] TS_UPDATE_ORDERS_PDU_DATA " + "updateType %d (UPDATETYPE_ORDERS), pad2OctetsA , " + "numberOrders , pad2OctetsB ", + RDP_UPDATE_ORDERS); } } return 0; @@ -154,6 +161,8 @@ xrdp_orders_send(struct xrdp_orders *self) if (xrdp_rdp_send_fastpath(self->rdp_layer, self->out_s, 0) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_orders_send: xrdp_rdp_send_fastpath failed"); rv = 1; } } @@ -162,6 +171,8 @@ xrdp_orders_send(struct xrdp_orders *self) if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, RDP_DATA_PDU_UPDATE) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_orders_send: xrdp_rdp_send_data failed"); rv = 1; } } @@ -225,6 +236,9 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size) { if (max_size > max_order_size) { + LOG(LOG_LEVEL_ERROR, "Requested orders max_size (%d) " + "is greater than the client connection max_size (%d)", + max_size, max_order_size); return 1; } else @@ -237,7 +251,8 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size) size = (int)(self->out_s->p - self->order_count_ptr); if (size < 0) { - LOG(LOG_LEVEL_ERROR, "error in xrdp_orders_check, size too small: %d bytes", size); + LOG(LOG_LEVEL_ERROR, "Bug: order data length cannot be negative. " + "Found length %d bytes", size); return 1; } if (size > max_order_size) @@ -245,7 +260,9 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size) /* this suggests someone calls this function without passing the correct max_size so we end up putting more into the buffer than we indicate we can */ - LOG(LOG_LEVEL_WARNING, "error in xrdp_orders_check, size too big: %d bytes", size); + LOG(LOG_LEVEL_WARNING, "Ignoring Bug: order data length " + "is larger than maximum length. Expected %d, actual %d", + max_order_size, size); /* We where getting called with size already greater than max_order_size Which I suspect was because the sending of text did not include @@ -2175,15 +2192,23 @@ xrdp_orders_send_palette(struct xrdp_orders *self, int *palette, if (xrdp_orders_check(self, 2000) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_orders_send_palette: xrdp_orders_check failed"); return 1; } self->order_count++; order_flags = TS_STANDARD | TS_SECONDARY; out_uint8(self->out_s, order_flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] DRAWING_ORDER " + "controlFlags 0x%2.2x (TS_STANDARD | TS_SECONDARY)", order_flags); + len = 1027 - 7; /* length after type minus 7 */ - out_uint16_le(self->out_s, len); - out_uint16_le(self->out_s, 0); /* flags */ - out_uint8(self->out_s, TS_CACHE_COLOR_TABLE); /* type */ + out_uint16_le(self->out_s, len); /* orderLength */ + out_uint16_le(self->out_s, 0); /* extraFlags */ + out_uint8(self->out_s, TS_CACHE_COLOR_TABLE); /* orderType */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] SECONDARY_DRAWING_ORDER_HEADER " + "orderLength %d, extraFlags 0x0000, orderType 0x%2.2x (TS_CACHE_COLOR_TABLE)", + len, TS_CACHE_COLOR_TABLE); + out_uint8(self->out_s, cache_id); out_uint16_le(self->out_s, 256); /* num colors */ @@ -2194,7 +2219,9 @@ xrdp_orders_send_palette(struct xrdp_orders *self, int *palette, out_uint8(self->out_s, palette[i] >> 16); out_uint8(self->out_s, 0); } - + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPEGDI] CACHE_COLOR_TABLE_ORDER " + "cacheIndex %d, numberColors 256, colorTable ", + cache_id); return 0; } diff --git a/libxrdp/xrdp_orders_rail.c b/libxrdp/xrdp_orders_rail.c index 735b92e1..51e5c465 100644 --- a/libxrdp/xrdp_orders_rail.c +++ b/libxrdp/xrdp_orders_rail.c @@ -42,12 +42,19 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id) order_size = 11; if (xrdp_orders_check(self, order_size) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_orders_send_window_delete: xrdp_orders_check failed"); return 1; } self->order_count++; order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER " + "controlFlags.class 0x%1.1x (TS_SECONDARY), " + "controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)", + (order_flags & 0x3), (order_flags >> 2)); + /* orderSize (2 bytes) */ out_uint16_le(self->out_s, order_size); /* FieldsPresentFlags (4 bytes) */ @@ -55,6 +62,12 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id) out_uint32_le(self->out_s, field_present_flags); /* windowId (4 bytes) */ out_uint32_le(self->out_s, window_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER " + "OrderSize %d, " + "FieldsPresentFlags 0x%8.8x (WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_DELETED), " + "WindowId 0x%8.8x", + order_size, field_present_flags, window_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Deleted Window"); return 0; } @@ -75,12 +88,19 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self, order_size = 14; if (xrdp_orders_check(self, order_size) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_orders_send_window_cached_icon: xrdp_orders_check failed"); return 1; } self->order_count++; order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER " + "controlFlags.class 0x%1.1x (TS_SECONDARY), " + "controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)", + (order_flags & 0x3), (order_flags >> 2)); + /* orderSize (2 bytes) */ out_uint16_le(self->out_s, order_size); /* FieldsPresentFlags (4 bytes) */ @@ -89,10 +109,17 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self, out_uint32_le(self->out_s, field_present_flags); /* windowId (4 bytes) */ out_uint32_le(self->out_s, window_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER " + "OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x", + order_size, field_present_flags, window_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Cached Icon"); + /* CacheEntry (2 bytes) */ out_uint16_le(self->out_s, cache_entry); /* CacheId (1 byte) */ out_uint8(self->out_s, cache_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order field [MS-RDPERP] TS_CACHED_ICON_INFO " + "CacheEntry %d, CacheId %d", cache_entry, cache_id); return 0; } @@ -134,6 +161,18 @@ xrdp_orders_send_ts_icon(struct stream *s, int cache_entry, int cache_id, } out_uint8p(s, icon_info->data, icon_info->data_bytes); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order fields [MS-RDPERP] TS_ICON_INFO " + "CacheEntry %d, CacheId %d, Bpp %d, Width %d, Height %d, " + "CbColorTable <%s>, " + "CbBitsMask %d, CbBitsColor %d, BitsMask , " + "ColorTable <%s>, " + "BitsColor ", + cache_entry, cache_id, icon_info->bpp, icon_info->width, + icon_info->height, + (use_cmap ? "present, omitted from log" : "not present"), + icon_info->mask_bytes, icon_info->data_bytes, + (use_cmap ? "present, omitted from log" : "not present") + ); return 0; } @@ -169,12 +208,19 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self, if (xrdp_orders_check(self, order_size) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_orders_send_window_icon: xrdp_orders_check failed"); return 1; } self->order_count++; order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER " + "controlFlags.class 0x%1.1x (TS_SECONDARY), " + "controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)", + (order_flags & 0x3), (order_flags >> 2)); + /* orderSize (2 bytes) */ out_uint16_le(self->out_s, order_size); /* FieldsPresentFlags (4 bytes) */ @@ -183,6 +229,10 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self, out_uint32_le(self->out_s, field_present_flags); /* windowId (4 bytes) */ out_uint32_le(self->out_s, window_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER " + "OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x", + order_size, field_present_flags, window_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Window Icon"); xrdp_orders_send_ts_icon(self->out_s, cache_entry, cache_id, icon_info); @@ -372,23 +422,36 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, if (xrdp_orders_check(self, order_size) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_orders_send_window_new_update: xrdp_orders_check failed"); return 1; } self->order_count++; order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER " + "controlFlags.class 0x%1.1x (TS_SECONDARY), " + "controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)", + (order_flags & 0x3), (order_flags >> 2)); + /* orderSize (2 bytes) */ out_uint16_le(self->out_s, order_size); /* FieldsPresentFlags (4 bytes) */ out_uint32_le(self->out_s, field_present_flags); /* windowId (4 bytes) */ out_uint32_le(self->out_s, window_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER " + "OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x", + order_size, field_present_flags, window_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] New or Existing Window (TS_WINDOW_INFO)"); if (field_present_flags & WINDOW_ORDER_FIELD_OWNER) { /* ownerWindowId (4 bytes) */ out_uint32_le(self->out_s, window_state->owner_window_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "OwnerWindowId 0x%8.8x", window_state->owner_window_id); } if (field_present_flags & WINDOW_ORDER_FIELD_STYLE) @@ -397,18 +460,28 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, out_uint32_le(self->out_s, window_state->style); /* extendedStyle (4 bytes) */ out_uint32_le(self->out_s, window_state->extended_style); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "Style 0x%8.8x, ExtendedStyle 0x%8.8x", + window_state->style, window_state->extended_style); } if (field_present_flags & WINDOW_ORDER_FIELD_SHOW) { /* showState (1 byte) */ out_uint8(self->out_s, window_state->show_state); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "ShowState 0x%2.2x", window_state->show_state); } if (field_present_flags & WINDOW_ORDER_FIELD_TITLE) { /* titleInfo */ xrdp_orders_send_as_unicode(self->out_s, window_state->title_info); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "TitleInfo %s", window_state->title_info); } if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET) @@ -417,26 +490,61 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, out_uint32_le(self->out_s, window_state->client_offset_x); /* clientOffsetY (4 bytes) */ out_uint32_le(self->out_s, window_state->client_offset_y); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "ClientOffsetX %d, ClientOffsetY %d", + window_state->client_offset_x, window_state->client_offset_y); } + /* TODO: The [MS-RDPERP] spec says that: + * The ClientAreaWidth and ClientAreaHeight field only appears if the WndSupportLevel field of the + * Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX + * (as specified in [MS-RDPERP] section 2.2.1.1.2) + */ if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE) { /* clientAreaWidth (4 bytes) */ out_uint32_le(self->out_s, window_state->client_area_width); /* clientAreaHeight (4 bytes) */ out_uint32_le(self->out_s, window_state->client_area_height); - } + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "ClientAreaWidth %d, ClientAreaHeight %d", + window_state->client_area_width, window_state->client_area_height); + } + /* TODO: The [MS-RDPERP] spec section 2.2.1.3.1.2.1 has the following additional fields: + * WindowLeftResizeMargin (optional) + * WindowRightResizeMargin (optional) + * WindowTopResizeMargin (optional) + * WindowBottomResizeMargin (optional) + */ + + /* TODO: The [MS-RDPERP] spec says that: + * The RPContent field only appears if the WndSupportLevel field of the + * Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX + * (as specified in [MS-RDPERP] section 2.2.1.1.2) + */ if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT) { /* RPContent (1 byte) */ out_uint8(self->out_s, window_state->rp_content); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "RPContent 0x%2.2x", window_state->rp_content); } + /* TODO: The [MS-RDPERP] spec says that: + * The RootParentHandle field only appears if the WndSupportLevel field of the + * Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX + * (as specified in [MS-RDPERP] section 2.2.1.1.2) + */ if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT) { /* rootParentHandle (4 bytes) */ out_uint32_le(self->out_s, window_state->root_parent_handle); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "RootParentHandle 0x%8.8x", window_state->root_parent_handle); } if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET) @@ -445,6 +553,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, out_uint32_le(self->out_s, window_state->window_offset_x); /* windowOffsetY (4 bytes) */ out_uint32_le(self->out_s, window_state->window_offset_y); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "WindowOffsetX %d, WindowOffsetY %d", + window_state->window_offset_x, window_state->window_offset_y); } if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA) @@ -453,6 +565,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, out_uint32_le(self->out_s, window_state->window_client_delta_x); /* windowClientDeltaY (4 bytes) */ out_uint32_le(self->out_s, window_state->window_client_delta_y); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "WindowClientDeltaX %d, WindowClientDeltaY %d", + window_state->window_client_delta_x, window_state->window_client_delta_y); } if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE) @@ -461,6 +577,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, out_uint32_le(self->out_s, window_state->window_width); /* windowHeight (4 bytes) */ out_uint32_le(self->out_s, window_state->window_height); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "WindowWidth %d, WindowHeight %d", + window_state->window_width, window_state->window_height); } if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS) @@ -475,6 +595,9 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, out_uint16_le(self->out_s, window_state->window_rects[index].right); out_uint16_le(self->out_s, window_state->window_rects[index].bottom); } + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "NumWindowRects %d, WindowRects ", + window_state->num_window_rects); } if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET) @@ -483,6 +606,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, out_uint32_le(self->out_s, window_state->visible_offset_x); /* visibleOffsetY (4 bytes) */ out_uint32_le(self->out_s, window_state->visible_offset_y); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "VisibleOffsetX %d, VisibleOffsetY %d", + window_state->visible_offset_x, window_state->visible_offset_y); } if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY) @@ -497,7 +624,17 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, out_uint16_le(self->out_s, window_state->visibility_rects[index].right); out_uint16_le(self->out_s, window_state->visibility_rects[index].bottom); } + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO " + "NumVisibilityRects %d, VisibilityRects ", + window_state->num_visibility_rects); } + /* TODO: The [MS-RDPERP] spec section 2.2.1.3.1.2.1 has the following additional fields: + * OverlayDescription (optional, variable) + * TaskbarButton (optional) + * EnforceServerZOrder (optional) + * AppBarState (optional) + * AppBarEdge (optional) + */ return 0; } @@ -516,12 +653,19 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id, order_size = 15; if (xrdp_orders_check(self, order_size) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_orders_send_notify_delete: xrdp_orders_check failed"); return 1; } self->order_count++; order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER " + "controlFlags.class 0x%1.1x (TS_SECONDARY), " + "controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)", + (order_flags & 0x3), (order_flags >> 2)); + /* orderSize (2 bytes) */ out_uint16_le(self->out_s, order_size); /* FieldsPresentFlags (4 bytes) */ @@ -531,6 +675,11 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id, out_uint32_le(self->out_s, window_id); /* notifyIconId (4 bytes) */ out_uint32_le(self->out_s, notify_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_NOTIFYICON_ORDER_HEADER " + "OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x, NotifyIconId 0x%8.8x", + order_size, field_present_flags, window_id, notify_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Deleted Notification Icons"); + return 0; } @@ -610,12 +759,19 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self, if (xrdp_orders_check(self, order_size) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_orders_send_notify_new_update: xrdp_orders_check failed"); return 1; } self->order_count++; order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ out_uint8(self->out_s, order_flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER " + "controlFlags.class 0x%1.1x (TS_SECONDARY), " + "controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)", + (order_flags & 0x3), (order_flags >> 2)); + /* orderSize (2 bytes) */ out_uint16_le(self->out_s, order_size); /* FieldsPresentFlags (4 bytes) */ @@ -624,17 +780,27 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self, out_uint32_le(self->out_s, window_id); /* notifyIconId (4 bytes) */ out_uint32_le(self->out_s, notify_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_NOTIFYICON_ORDER_HEADER " + "OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x, NotifyIconId 0x%8.8x", + order_size, field_present_flags, window_id, notify_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] New or Existing Notification Icons"); if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION) { /* Version (4 bytes) */ out_uint32_le(self->out_s, notify_state->version); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] " + "Version %d", notify_state->version); } if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP) { /* ToolTip (variable) UNICODE_STRING */ xrdp_orders_send_as_unicode(self->out_s, notify_state->tool_tip); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] " + "ToolTip %s", notify_state->tool_tip); } if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) @@ -644,12 +810,20 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self, out_uint32_le(self->out_s, notify_state->infotip.flags); xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.text); xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.title); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] TS_NOTIFY_ICON_INFOTIP " + "Timeout %d, InfoFlags 0x%8.8x, InfoTipText %s, Title %s", + notify_state->infotip.timeout, notify_state->infotip.flags, + notify_state->infotip.text, notify_state->infotip.title); } if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE) { /* State (4 bytes) */ out_uint32_le(self->out_s, notify_state->state); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] " + "State %d", notify_state->state); } if (field_present_flags & WINDOW_ORDER_ICON) @@ -666,6 +840,10 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self, out_uint16_le(self->out_s, notify_state->icon_cache_entry); /* CacheId (1 byte) */ out_uint8(self->out_s, notify_state->icon_cache_id); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order field [MS-RDPERP] TS_CACHED_ICON_INFO " + "CacheEntry %d, CacheId %d", + notify_state->icon_cache_entry, notify_state->icon_cache_id); } return 0; @@ -704,21 +882,37 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self, if (xrdp_orders_check(self, order_size) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_orders_send_monitored_desktop: xrdp_orders_check failed"); return 1; } self->order_count++; order_flags = TS_SECONDARY; order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER " + "controlFlags.class 0x%1.1x (TS_SECONDARY), " + "controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)", + (order_flags & 0x3), (order_flags >> 2)); + out_uint8(self->out_s, order_flags); /* orderSize (2 bytes) */ out_uint16_le(self->out_s, order_size); /* FieldsPresentFlags (4 bytes) */ out_uint32_le(self->out_s, field_present_flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_DESKTOP_ORDER_HEADER " + "OrderSize %d, FieldsPresentFlags 0x%8.8x", + order_size, field_present_flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] %s", + ((field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_NONE) ? + "Non-Monitored Desktop" : "Actively Monitored Desktop")); if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND) { /* ActiveWindowId (4 bytes) */ out_uint32_le(self->out_s, mdo->active_window_id); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] " + "ActiveWindowId 0x%8.8x", mdo->active_window_id); } if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER) @@ -731,6 +925,10 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self, { out_uint32_le(self->out_s, mdo->window_ids[index]); } + + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] " + "NumWindowIds %d, WindowIds ", + mdo->num_window_ids); } return 0; diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 439b26bc..b645a176 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -55,14 +55,14 @@ xrdp_rdp_read_config(const char *xrdp_ini, struct xrdp_client_info *client_info) items->auto_free = 1; values = list_create(); values->auto_free = 1; - LOG_DEVEL(LOG_LEVEL_TRACE, "cfg_file %s", xrdp_ini); + LOG_DEVEL(LOG_LEVEL_TRACE, "Reading config file %s", xrdp_ini); file_by_name_read_section(xrdp_ini, "globals", items, values); for (index = 0; index < items->count; index++) { item = (char *)list_get_item(items, index); value = (char *)list_get_item(values, index); - LOG_DEVEL(LOG_LEVEL_TRACE, "item %s value %s", item, value); + LOG(LOG_LEVEL_DEBUG, "item %s, value %s", item, value); if (g_strcasecmp(item, "bitmap_cache") == 0) { @@ -100,7 +100,7 @@ xrdp_rdp_read_config(const char *xrdp_ini, struct xrdp_client_info *client_info) } else { - LOG(LOG_LEVEL_ALWAYS, "Warning: Your configured crypt level is " + LOG(LOG_LEVEL_WARNING, "Your configured crypt level is " "undefined, 'high' will be used"); client_info->crypt_level = 3; } @@ -110,7 +110,7 @@ xrdp_rdp_read_config(const char *xrdp_ini, struct xrdp_client_info *client_info) client_info->channels_allowed = g_text2bool(value); if (client_info->channels_allowed == 0) { - LOG(LOG_LEVEL_DEBUG, "Info - All channels are disabled"); + LOG(LOG_LEVEL_INFO, "All channels are disabled"); } } else if (g_strcasecmp(item, "allow_multimon") == 0) @@ -118,7 +118,7 @@ xrdp_rdp_read_config(const char *xrdp_ini, struct xrdp_client_info *client_info) client_info->multimon = g_text2bool(value); if (client_info->multimon == 0) { - LOG(LOG_LEVEL_DEBUG, "Info - Multi monitor server support disabled"); + LOG(LOG_LEVEL_INFO, "Multi monitor server support disabled"); } } else if (g_strcasecmp(item, "max_bpp") == 0) @@ -161,7 +161,7 @@ xrdp_rdp_read_config(const char *xrdp_ini, struct xrdp_client_info *client_info) } else { - LOG(LOG_LEVEL_ALWAYS, "Warning: Your configured fastpath level is " + LOG(LOG_LEVEL_WARNING, "Your configured fastpath level is " "undefined, fastpath will not be used"); client_info->use_fast_path = 0; } @@ -205,7 +205,7 @@ xrdp_rdp_read_config(const char *xrdp_ini, struct xrdp_client_info *client_info) } else { - LOG(LOG_LEVEL_ERROR, "security_layer=%s is not " + LOG(LOG_LEVEL_WARNING, "security_layer=%s is not " "recognized, will use security_layer=negotiate", value); client_info->security_layer = PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_HYBRID_EX; @@ -393,33 +393,44 @@ xrdp_rdp_delete(struct xrdp_rdp *self) } /*****************************************************************************/ +/* Initialize the stream for sending a [MS-RDPBCGR] Control PDU */ int xrdp_rdp_init(struct xrdp_rdp *self, struct stream *s) { if (xrdp_sec_init(self->sec_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_init: xrdp_sec_init failed"); return 1; } - s_push_layer(s, rdp_hdr, 6); + s_push_layer(s, rdp_hdr, 6); /* 6 = sizeof(TS_SHARECONTROLHEADER) */ return 0; } /*****************************************************************************/ +/* Initialize the stream for sending a [MS-RDPBCGR] Data PDU */ int xrdp_rdp_init_data(struct xrdp_rdp *self, struct stream *s) { if (xrdp_sec_init(self->sec_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_init_data: xrdp_sec_init failed"); return 1; } - s_push_layer(s, rdp_hdr, 18); + s_push_layer(s, rdp_hdr, 18); /* 18 = sizeof(TS_SHAREDATAHEADER) */ return 0; } /*****************************************************************************/ -/* returns error */ +/* + Receives and parses pdu code from next data unit. + + @param self + @param (in/out) s: the stream to read from. Upon return the stream is ? + @param (out) code: the pdu code from the packet + returns error + */ int xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) { @@ -429,7 +440,7 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) int chan = 0; const tui8 *header; - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_rdp_recv"); + if (s->next_packet == 0 || s->next_packet >= s->end) { /* check for fastpath first */ @@ -438,11 +449,12 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) { if (xrdp_sec_recv_fastpath(self->sec_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_recv: xrdp_sec_recv_fastpath failed"); return 1; } /* next_packet gets set in xrdp_sec_recv_fastpath */ *code = 2; // special code for fastpath input - LOG_DEVEL(LOG_LEVEL_TRACE, "out (fastpath) xrdp_rdp_recv"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_recv: out code 2 (fastpath)"); return 0; } @@ -454,13 +466,13 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) { s->next_packet = 0; *code = -1; - LOG_DEVEL(LOG_LEVEL_TRACE, "out (1) xrdp_rdp_recv"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_recv: out code -1 (send demand active)"); return 0; } if (error != 0) { - LOG(LOG_LEVEL_ERROR, "out xrdp_rdp_recv error"); + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_recv: xrdp_sec_recv failed"); return 1; } @@ -470,20 +482,23 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) { if (xrdp_channel_process(self->sec_layer->chan_layer, s, chan) != 0) { - LOG(LOG_LEVEL_ERROR, "xrdp_channel_process returned unhandled error") ; + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_recv: xrdp_channel_process failed"); } } else { if (chan != 1) { - LOG(LOG_LEVEL_ERROR, "Wrong channel Id to be handled by xrdp_channel_process %d", chan); + LOG_DEVEL(LOG_LEVEL_WARNING, + "xrdp_rdp_recv: Wrong channel Id to be handled " + "by xrdp_channel_process, channel id %d", chan); } } s->next_packet = 0; *code = 0; - LOG_DEVEL(LOG_LEVEL_TRACE, "out (2) xrdp_rdp_recv"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_recv: out code 0 (skip data) " + "data processed by channel id %d", chan); return 0; } @@ -491,55 +506,66 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) } else { - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_recv stream not touched"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_recv: stream not touched"); s->p = s->next_packet; } - if (!s_check_rem(s, 6)) + if (!s_check_rem_and_log(s, 6, "Parsing [MS-RDPBCGR] TS_SHARECONTROLHEADER")) { s->next_packet = 0; *code = 0; - len = (int)(s->end - s->p); - LOG_DEVEL(LOG_LEVEL_TRACE, "out (3) xrdp_rdp_recv: bad RDP packet, length [%d]", len); + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_recv: out code 0 (skip data) " + "bad RDP packet"); return 0; } else { - in_uint16_le(s, len); - /*LOG_DEVEL(LOG_LEVEL_TRACE, "New len received : %d next packet: %d s_end: %d",len,s->next_packet,s->end); */ - in_uint16_le(s, pdu_code); + in_uint16_le(s, len); /* totalLength */ + in_uint16_le(s, pdu_code); /* pduType */ *code = pdu_code & 0xf; - in_uint8s(s, 2); /* mcs user id */ + in_uint8s(s, 2); /* pduSource */ s->next_packet += len; - LOG_DEVEL(LOG_LEVEL_TRACE, "out (4) xrdp_rdp_recv"); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SHARECONTROLHEADER " + "totalLength %d, pduType.type %s (%d), pduType.PDUVersion %d, " + "pduSource (ignored)", len, PDUTYPE_TO_STR(*code), *code, + ((pdu_code & 0xfff0) >> 4)); return 0; } } /*****************************************************************************/ +/* Send a [MS-RDPBCGR] Control PDU with for the given pduType with the headers + added */ int xrdp_rdp_send(struct xrdp_rdp *self, struct stream *s, int pdu_type) { int len = 0; - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_rdp_send"); s_pop_layer(s, rdp_hdr); len = s->end - s->p; - out_uint16_le(s, len); - out_uint16_le(s, 0x10 | pdu_type); - out_uint16_le(s, self->mcs_channel); + + /* TS_SHARECONTROLHEADER */ + out_uint16_le(s, len); /* totalLength */ + out_uint16_le(s, 0x10 | pdu_type); /* pduType */ + out_uint16_le(s, self->mcs_channel); /* pduSource */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_SHARECONTROLHEADER " + "totalLength %d, pduType.type %s (%d), pduType.PDUVersion %d, " + "pduSource %d", len, PDUTYPE_TO_STR(pdu_type & 0xf), + pdu_type & 0xf, (((0x10 | pdu_type) & 0xfff0) >> 4), + self->mcs_channel); if (xrdp_sec_send(self->sec_layer, s, MCS_GLOBAL_CHANNEL) != 0) { - LOG(LOG_LEVEL_ERROR, "out xrdp_rdp_send error"); + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send: xrdp_sec_send failed"); return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_rdp_send"); return 0; } /*****************************************************************************/ +/* Send a [MS-RDPBCGR] Data PDU with for the given pduType2 with the headers + added and data compressed */ int xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, int data_pdu_type) @@ -558,7 +584,6 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, struct stream ls; struct xrdp_mppc_enc *mppc_enc; - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_rdp_send_data"); s_pop_layer(s, rdp_hdr); len = (int)(s->end - s->p); pdutype = 0x10 | PDUTYPE_DATAPDU; @@ -573,10 +598,6 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, mppc_enc = self->mppc_enc; if (compress_rdp(mppc_enc, (tui8 *)(s->p + 18), tocomplen)) { - LOG_DEVEL(LOG_LEVEL_TRACE, "mppc_encode ok flags 0x%x bytes_in_opb %d historyOffset %d " - "tocomplen %d", mppc_enc->flags, mppc_enc->bytes_in_opb, - mppc_enc->historyOffset, tocomplen); - clen = mppc_enc->bytes_in_opb + 18; pdulen = clen; ctype = mppc_enc->flags; @@ -600,30 +621,41 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, } else { - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_send_data: mppc_encode not ok " - "type %d flags %d", mppc_enc->protocol_type, - mppc_enc->flags); + LOG_DEVEL(LOG_LEVEL_DEBUG, + "xrdp_rdp_send_data: compress_rdp failed, sending " + "uncompressed data. type %d, flags %d", + mppc_enc->protocol_type, mppc_enc->flags); } } - out_uint16_le(s, pdulen); - out_uint16_le(s, pdutype); - out_uint16_le(s, self->mcs_channel); + /* TS_SHARECONTROLHEADER */ + out_uint16_le(s, pdulen); /* totalLength */ + out_uint16_le(s, pdutype); /* pduType */ + out_uint16_le(s, self->mcs_channel); /* pduSource */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_SHARECONTROLHEADER " + "totalLength %d, pduType.type %s (%d), pduType.PDUVersion %d, " + "pduSource %d", pdulen, PDUTYPE_TO_STR(pdutype & 0xf), + pdutype & 0xf, ((pdutype & 0xfff0) >> 4), self->mcs_channel); + + /* TS_SHAREDATAHEADER */ out_uint32_le(s, self->share_id); - out_uint8(s, 0); - out_uint8(s, 1); - out_uint16_le(s, dlen); - out_uint8(s, data_pdu_type); - out_uint8(s, ctype); - out_uint16_le(s, clen); + out_uint8(s, 0); /* pad */ + out_uint8(s, 1); /* streamID */ + out_uint16_le(s, dlen); /* uncompressedLength */ + out_uint8(s, data_pdu_type); /* pduType2 */ + out_uint8(s, ctype); /* compressedType */ + out_uint16_le(s, clen); /* compressedLength */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_SHAREDATAHEADER " + "shareID %d, streamID 1, uncompressedLength %d, " + "pduType2 0x%2.2x, compressedType 0x%2.2x, compressedLength %d", + self->share_id, dlen, data_pdu_type, ctype, clen); if (xrdp_sec_send(self->sec_layer, s, MCS_GLOBAL_CHANNEL) != 0) { - LOG(LOG_LEVEL_ERROR, "out xrdp_rdp_send_data error"); + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_data: xrdp_sec_send failed"); return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_rdp_send_data"); return 0; } @@ -645,6 +677,7 @@ xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s) { if (xrdp_sec_init_fastpath(self->sec_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_init_fastpath: xrdp_sec_init_fastpath failed"); return 1; } if (self->client_info.rdp_compression) @@ -684,8 +717,9 @@ xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, struct stream comp_s; struct stream send_s; struct xrdp_mppc_enc *mppc_enc; + char comp_type_str[7]; + comp_type_str[0] = '\0'; - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_send_fastpath:"); s_pop_layer(s, rdp_hdr); updateCode = data_pdu_type; if (self->client_info.rdp_compression) @@ -729,7 +763,7 @@ xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, } } send_len = no_comp_len; - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_send_fastpath: no_comp_len %d fragmentation %d", + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_send_fastpath: no_comp_len %d, fragmentation %d", no_comp_len, fragmentation); if ((compression != 0) && (no_comp_len > header_bytes + 16)) { @@ -739,8 +773,6 @@ xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, to_comp_len)) { comp_len = mppc_enc->bytes_in_opb + header_bytes; - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_send_fastpath: no_comp_len %d " - "comp_len %d", no_comp_len, comp_len); send_len = comp_len; comp_type = mppc_enc->flags; /* outputBuffer has 64 bytes preceding it */ @@ -756,9 +788,10 @@ xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, } else { - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_send_fastpath: mppc_encode not ok " - "type %d flags %d", mppc_enc->protocol_type, - mppc_enc->flags); + LOG(LOG_LEVEL_DEBUG, + "compress_rdp failed, sending uncompressed data. " + "type %d, flags %d", mppc_enc->protocol_type, + mppc_enc->flags); } } updateHeader = (updateCode & 15) | @@ -768,13 +801,18 @@ xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, if (compression != 0) { out_uint8(&send_s, comp_type); + g_snprintf(comp_type_str, 7, "0x%4.4x", comp_type); } send_len -= header_bytes; out_uint16_le(&send_s, send_len); send_s.end = send_s.p + send_len; + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_FP_UPDATE " + "updateCode %d, fragmentation %d, compression %d, compressionFlags %s, size %d", + updateCode, fragmentation, compression, + (compression ? comp_type_str : "(not present)"), send_len); if (xrdp_sec_send_fastpath(self->sec_layer, &send_s) != 0) { - LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_fastpath: xrdp_fastpath_send failed"); + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_fastpath: xrdp_sec_send_fastpath failed"); return 1; } frag_s.p += no_comp_len; @@ -787,6 +825,8 @@ xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, } /*****************************************************************************/ +/* Send a [MS-RDPBCGR] TS_UPDATE_SYNC or TS_FP_UPDATE_SYNCHRONIZE message + depending on if the client supports the fast path capability or not */ int xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) { @@ -794,13 +834,12 @@ xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) make_stream(s); init_stream(s, 8192); - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_rdp_send_data_update_sync"); if (self->client_info.use_fast_path & 1) /* fastpath output supported */ { - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp_send_data_update_sync: fastpath"); if (xrdp_rdp_init_fastpath(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_data_update_sync: xrdp_rdp_init_fastpath failed"); free_stream(s); return 1; } @@ -809,37 +848,42 @@ xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) { if (xrdp_rdp_init_data(self, s) != 0) { - LOG(LOG_LEVEL_ERROR, "out xrdp_rdp_send_data_update_sync error"); + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_data_update_sync: xrdp_rdp_init_data failed"); free_stream(s); return 1; } - out_uint16_le(s, RDP_UPDATE_SYNCHRONIZE); + out_uint16_le(s, RDP_UPDATE_SYNCHRONIZE); /* updateType */ out_uint16_le(s, 0); /* pad */ + } s_mark_end(s); if (self->client_info.use_fast_path & 1) /* fastpath output supported */ { + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_UPDATE_SYNCHRONIZE"); if (xrdp_rdp_send_fastpath(self, s, FASTPATH_UPDATETYPE_SYNCHRONIZE) != 0) { + LOG(LOG_LEVEL_ERROR, "Sending [MS-RDPBCGR] TS_FP_UPDATE_SYNCHRONIZE failed"); free_stream(s); return 1; } } else /* slowpath */ { + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_SYNC " + "updateType %s (%d)", + GRAPHICS_UPDATE_TYPE_TO_STR(RDP_UPDATE_SYNCHRONIZE), + RDP_UPDATE_SYNCHRONIZE); if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_UPDATE) != 0) { - LOG(LOG_LEVEL_ERROR, "out xrdp_rdp_send_data_update_sync error"); + LOG(LOG_LEVEL_ERROR, "Sending [MS-RDPBCGR] TS_UPDATE_SYNC failed"); free_stream(s); return 1; } } - - LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_rdp_send_data_update_sync"); free_stream(s); return 0; } @@ -851,15 +895,14 @@ xrdp_rdp_incoming(struct xrdp_rdp *self) struct xrdp_iso *iso; iso = self->sec_layer->mcs_layer->iso_layer; - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_rdp_incoming"); - if (xrdp_sec_incoming(self->sec_layer) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_incoming: xrdp_sec_incoming failed"); return 1; } self->mcs_channel = self->sec_layer->mcs_layer->userid + MCS_USERCHANNEL_BASE; - LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_rdp_incoming mcs channel %d", self->mcs_channel); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_rdp->mcs_channel %d", self->mcs_channel); g_strncpy(self->client_info.client_addr, iso->trans->addr, sizeof(self->client_info.client_addr) - 1); g_strncpy(self->client_info.client_port, iso->trans->port, @@ -889,14 +932,19 @@ xrdp_rdp_incoming(struct xrdp_rdp *self) } /*****************************************************************************/ +/* Process a [MS-RDPBCGR] TS_POINTER_PDU message */ static int xrdp_rdp_process_data_pointer(struct xrdp_rdp *self, struct stream *s) { + LOG_DEVEL(LOG_LEVEL_WARNING, "Protocol error ignored: a [MS-RDPBCGR] " + "TS_SHAREDATAHEADER PDUTYPE2_POINTER was received by the server " + "but this type of PDU is only suppose to be sent by the server " + "to the client."); return 0; } /*****************************************************************************/ -/* RDP_DATA_PDU_INPUT */ +/* Process a [MS-RDPBCGR] TS_INPUT_PDU_DATA message */ static int xrdp_rdp_process_data_input(struct xrdp_rdp *self, struct stream *s) { @@ -908,17 +956,18 @@ xrdp_rdp_process_data_input(struct xrdp_rdp *self, struct stream *s) int param2; int time; - if (!s_check_rem(s, 4)) + if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPBCGR] TS_INPUT_PDU_DATA")) { return 1; } in_uint16_le(s, num_events); in_uint8s(s, 2); /* pad */ - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_rdp_process_data_input %d events", num_events); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_INPUT_PDU_DATA " + "numEvents %d", num_events); for (index = 0; index < num_events; index++) { - if (!s_check_rem(s, 12)) + if (!s_check_rem_and_log(s, 12, "Parsing [MS-RDPBCGR] TS_INPUT_EVENT")) { return 1; } @@ -927,8 +976,38 @@ xrdp_rdp_process_data_input(struct xrdp_rdp *self, struct stream *s) in_uint16_le(s, device_flags); in_sint16_le(s, param1); in_sint16_le(s, param2); - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_data_input event %4.4x flags %4.4x param1 %d " - "param2 %d time %d", msg_type, device_flags, param1, param2, time); + LOG_DEVEL(LOG_LEVEL_TRACE, "With field [MS-RDPBCGR] TS_INPUT_EVENT " + "eventTime %d, messageType 0x%4.4x", time, msg_type); + + switch (msg_type) + { + case RDP_INPUT_SYNCHRONIZE: + LOG_DEVEL(LOG_LEVEL_TRACE, "With field [MS-RDPBCGR] TS_INPUT_EVENT - TS_SYNC_EVENT " + "toggleFlags 0x%8.8x", ((param2 << 16) | param1)); + break; + case RDP_INPUT_SCANCODE: + LOG_DEVEL(LOG_LEVEL_TRACE, "With field [MS-RDPBCGR] TS_INPUT_EVENT - TS_KEYBOARD_EVENT " + "keyboardFlags 0x%4.4x, keyCode %d", device_flags, param1); + break; + case RDP_INPUT_UNICODE: + LOG_DEVEL(LOG_LEVEL_TRACE, "With field [MS-RDPBCGR] TS_INPUT_EVENT - TS_UNICODE_KEYBOARD_EVENT " + "keyboardFlags 0x%4.4x, unicodeCode %d", device_flags, param1); + break; + case RDP_INPUT_MOUSE: + LOG_DEVEL(LOG_LEVEL_TRACE, "With field [MS-RDPBCGR] TS_INPUT_EVENT - TS_POINTER_EVENT " + "pointerFlags 0x%4.4x, xPos %d, yPos %d", + device_flags, param1, param2); + break; + case RDP_INPUT_MOUSEX: + LOG_DEVEL(LOG_LEVEL_TRACE, "With field [MS-RDPBCGR] TS_INPUT_EVENT - TS_POINTERX_EVENT " + "pointerFlags 0x%4.4x, xPos %d, yPos %d", + device_flags, param1, param2); + break; + default: + LOG_DEVEL(LOG_LEVEL_WARNING, "Received unknown [MS-RDPBCGR] TS_INPUT_EVENT " + "messageType 0x%4.4x", msg_type); + break; + } if (self->session->callback != 0) { @@ -941,13 +1020,19 @@ xrdp_rdp_process_data_input(struct xrdp_rdp *self, struct stream *s) self->session->callback(self->session->id, msg_type, param1, param2, device_flags, time); } + else + { + LOG_DEVEL(LOG_LEVEL_WARNING, + "Bug: no callback registered for xrdp_rdp_process_data_input"); + } } - LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_rdp_process_data_input"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "Processing [MS-RDPBCGR] TS_INPUT_PDU_DATA complete"); return 0; } /*****************************************************************************/ +/* Send a [MS-RDPBCGR] TS_SYNCHRONIZE_PDU message */ static int xrdp_rdp_send_synchronise(struct xrdp_rdp *self) { @@ -958,6 +1043,7 @@ xrdp_rdp_send_synchronise(struct xrdp_rdp *self) if (xrdp_rdp_init_data(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_synchronise: xrdp_rdp_init_data failed"); free_stream(s); return 1; } @@ -965,9 +1051,12 @@ xrdp_rdp_send_synchronise(struct xrdp_rdp *self) out_uint16_le(s, 1); /* messageType (2 bytes) */ out_uint16_le(s, 1002); /* targetUser (2 bytes) */ s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_SYNCHRONIZE_PDU " + "messageType 1, targetUser 1002"); if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_SYNCHRONISE) != 0) { + LOG(LOG_LEVEL_ERROR, "Sending [MS-RDPBCGR] TS_SYNCHRONIZE_PDU failed"); free_stream(s); return 1; } @@ -977,6 +1066,7 @@ xrdp_rdp_send_synchronise(struct xrdp_rdp *self) } /*****************************************************************************/ +/* Send a [MS-RDPBCGR] TS_CONTROL_PDU message */ static int xrdp_rdp_send_control(struct xrdp_rdp *self, int action) { @@ -987,6 +1077,7 @@ xrdp_rdp_send_control(struct xrdp_rdp *self, int action) if (xrdp_rdp_init_data(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_control: xrdp_rdp_init_data failed"); free_stream(s); return 1; } @@ -995,9 +1086,12 @@ xrdp_rdp_send_control(struct xrdp_rdp *self, int action) out_uint16_le(s, 0); /* userid */ out_uint32_le(s, 1002); /* control id */ s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_CONTROL_PDU " + "action %d, grantId 0, controlId 1002", action); if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_CONTROL) != 0) { + LOG(LOG_LEVEL_ERROR, "Sending [MS-RDPBCGR] TS_CONTROL_PDU failed"); free_stream(s); return 1; } @@ -1007,39 +1101,44 @@ xrdp_rdp_send_control(struct xrdp_rdp *self, int action) } /*****************************************************************************/ +/* Process a [MS-RDPBCGR] TS_CONTROL_PDU message */ static int xrdp_rdp_process_data_control(struct xrdp_rdp *self, struct stream *s) { int action; - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_data_control"); in_uint16_le(s, action); in_uint8s(s, 2); /* user id */ in_uint8s(s, 4); /* control id */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONTROL_PDU " + "action 0x%4.4x, grantId (ignored), controlId (ignored)", + action); if (action == RDP_CTL_REQUEST_CONTROL) { - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_data_control got RDP_CTL_REQUEST_CONTROL"); - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_data_control calling xrdp_rdp_send_synchronise"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "Responding to [MS-RDPBCGR] TS_CONTROL_PDU " + "action CTRLACTION_REQUEST_CONTROL with 3 messages: " + "TS_SYNCHRONIZE_PDU, TS_CONTROL_PDU with CTRLACTION_COOPERATE, " + " and TS_CONTROL_PDU with CTRLACTION_GRANTED_CONTROL"); xrdp_rdp_send_synchronise(self); - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_data_control sending RDP_CTL_COOPERATE"); xrdp_rdp_send_control(self, RDP_CTL_COOPERATE); - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_data_control sending RDP_CTL_GRANT_CONTROL"); xrdp_rdp_send_control(self, RDP_CTL_GRANT_CONTROL); } else { - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_data_control unknown action"); + LOG_DEVEL(LOG_LEVEL_WARNING, "Received [MS-RDPBCGR] TS_CONTROL_PDU " + "action %d is unknown (skipped)", action); } return 0; } /*****************************************************************************/ +/* Process a [MS-RDPBCGR] TS_SYNCHRONIZE_PDU message */ static int xrdp_rdp_process_data_sync(struct xrdp_rdp *self) { - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_data_sync"); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_SYNCHRONIZE_PDU - no-op"); return 0; } @@ -1057,16 +1156,17 @@ xrdp_rdp_process_screen_update(struct xrdp_rdp *self, struct stream *s) int cx; int cy; - if (!s_check_rem(s, 4)) + if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPBCGR] TS_REFRESH_RECT_PDU")) { return 1; } in_uint8(s, num_rects); in_uint8s(s, 3); /* pad */ - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_screen_update: num_rects %d", num_rects); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_REFRESH_RECT_PDU " + "numberOfAreas %d", num_rects); for (index = 0; index < num_rects; index++) { - if (!s_check_rem(s, 8)) + if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] TS_RECTANGLE16")) { return 1; } @@ -1075,7 +1175,8 @@ xrdp_rdp_process_screen_update(struct xrdp_rdp *self, struct stream *s) in_uint16_le(s, top); in_uint16_le(s, right); in_uint16_le(s, bottom); - LOG_DEVEL(LOG_LEVEL_TRACE, " left %d top %d right %d bottom %d", + LOG_DEVEL(LOG_LEVEL_TRACE, "With field [MS-RDPBCGR] TS_RECTANGLE16 " + "left %d, top %d, right %d, bottom %d", left, top, right, bottom); cx = (right - left) + 1; cy = (bottom - top) + 1; @@ -1084,11 +1185,17 @@ xrdp_rdp_process_screen_update(struct xrdp_rdp *self, struct stream *s) self->session->callback(self->session->id, 0x4444, left, top, cx, cy); } + else + { + LOG_DEVEL(LOG_LEVEL_WARNING, + "Bug: no callback registered for xrdp_rdp_process_screen_update"); + } } return 0; } /*****************************************************************************/ +/* Send a [MS-RDPBCGR] TS_FONT_MAP_PDU message */ static int xrdp_rdp_send_fontmap(struct xrdp_rdp *self) { @@ -1099,6 +1206,8 @@ xrdp_rdp_send_fontmap(struct xrdp_rdp *self) if (xrdp_rdp_init_data(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_rdp_send_fontmap: xrdp_rdp_init_data failed"); free_stream(s); return 1; } @@ -1109,9 +1218,13 @@ xrdp_rdp_send_fontmap(struct xrdp_rdp *self) out_uint16_le(s, 0x4); /* entrySize */ s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FONT_MAP_PDU " + "numberEntries 0, totalNumEntries 0, mapFlags 0x0003, entrySize 4"); if (xrdp_rdp_send_data(self, s, 0x28) != 0) { + LOG(LOG_LEVEL_ERROR, + "Sending [MS-RDPBCGR] TS_FONT_MAP_PDU failed"); free_stream(s); return 1; } @@ -1121,37 +1234,51 @@ xrdp_rdp_send_fontmap(struct xrdp_rdp *self) } /*****************************************************************************/ +/* Process a [MS-RDPBCGR] TS_FONT_LIST_PDU message */ static int xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s) { int seq; - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_rdp_process_data_font"); + if (!s_check_rem_and_log(s, 6, "Parsing [MS-RDPBCGR] TS_FONT_LIST_PDU")) + { + return 1; + } + in_uint8s(s, 2); /* NumberFonts: 0x0, SHOULD be set to 0 */ in_uint8s(s, 2); /* TotalNumberFonts: 0x0, SHOULD be set to 0 */ in_uint16_le(s, seq); /* ListFlags */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FONT_LIST_PDU " + "numberFonts (ignored), totalNumFonts (ignored), listFlags 0x%4.4x", + seq); /* 419 client sends Seq 1, then 2 */ /* 2600 clients sends only Seq 3 */ + /* listFlags SHOULD be set to 0x0003, which is the logical OR'd value of + FONTLIST_FIRST (0x0001) and FONTLIST_LAST (0x0002) */ if (seq == 2 || seq == 3) /* after second font message, we are up and */ { /* running */ - LOG_DEVEL(LOG_LEVEL_TRACE, "sending fontmap"); + LOG_DEVEL(LOG_LEVEL_DEBUG, + "Client sent FONTLIST_LAST, replying with server fontmap"); xrdp_rdp_send_fontmap(self); self->session->up_and_running = 1; - LOG_DEVEL(LOG_LEVEL_TRACE, "yeah, up_and_running"); - LOG_DEVEL(LOG_LEVEL_TRACE, "up_and_running set"); + LOG_DEVEL(LOG_LEVEL_INFO, "yeah, up_and_running"); xrdp_rdp_send_data_update_sync(self); xrdp_channel_drdynvc_start(self->sec_layer->chan_layer); } + else + { + LOG_DEVEL(LOG_LEVEL_DEBUG, "Received [MS-RDPBCGR] TS_FONT_LIST_PDU " + "without FONTLIST_LAST in the listFlags field. Ignoring message."); + } - LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_rdp_process_data_font"); return 0; } /*****************************************************************************/ -/* sent 37 pdu */ +/* Send a Sending [MS-RDPBCGR] TS_SHUTDOWN_DENIED_PDU message */ static int xrdp_rdp_send_disconnect_query_response(struct xrdp_rdp *self) { @@ -1162,14 +1289,19 @@ xrdp_rdp_send_disconnect_query_response(struct xrdp_rdp *self) if (xrdp_rdp_init_data(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_rdp_send_disconnect_query_response: xrdp_rdp_init_data failed"); free_stream(s); return 1; } s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_SHUTDOWN_DENIED_PDU"); - if (xrdp_rdp_send_data(self, s, 37) != 0) + if (xrdp_rdp_send_data(self, s, PDUTYPE2_SHUTDOWN_DENIED) != 0) { + LOG(LOG_LEVEL_ERROR, + "Sending [MS-RDPBCGR] TS_SHUTDOWN_DENIED_PDU failed"); free_stream(s); return 1; } @@ -1180,7 +1312,7 @@ xrdp_rdp_send_disconnect_query_response(struct xrdp_rdp *self) #if 0 /* not used */ /*****************************************************************************/ -/* sent RDP_DATA_PDU_DISCONNECT 47 pdu */ +/* Send a [MS-RDPBCGR] TS_SET_ERROR_INFO_PDU message */ static int xrdp_rdp_send_disconnect_reason(struct xrdp_rdp *self, int reason) { @@ -1191,15 +1323,21 @@ xrdp_rdp_send_disconnect_reason(struct xrdp_rdp *self, int reason) if (xrdp_rdp_init_data(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_rdp_send_disconnect_reason: xrdp_rdp_init_data failed"); free_stream(s); return 1; } out_uint32_le(s, reason); s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_SET_ERROR_INFO_PDU " + "errorInfo 0x%8.8x", reason); if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_DISCONNECT) != 0) { + LOG(LOG_LEVEL_ERROR, + "Sending [MS-RDPBCGR] TS_SET_ERROR_INFO_PDU failed"); free_stream(s); return 1; } @@ -1210,24 +1348,35 @@ xrdp_rdp_send_disconnect_reason(struct xrdp_rdp *self, int reason) #endif /*****************************************************************************/ +/* Process a [MS-RDPRFX] TS_FRAME_ACKNOWLEDGE_PDU message */ static int xrdp_rdp_process_frame_ack(struct xrdp_rdp *self, struct stream *s) { int frame_id; - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_frame_ack:"); + if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPRFX] TS_FRAME_ACKNOWLEDGE_PDU")) + { + return 1; + } in_uint32_le(s, frame_id); - LOG_DEVEL(LOG_LEVEL_TRACE, " frame_id %d", frame_id); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPRFX] TS_FRAME_ACKNOWLEDGE_PDU " + "frameID %d", frame_id); if (self->session->callback != 0) { /* call to xrdp_wm.c : callback */ self->session->callback(self->session->id, 0x5557, frame_id, 0, 0, 0); } + else + { + LOG_DEVEL(LOG_LEVEL_WARNING, + "Bug: no callback registered for xrdp_rdp_process_frame_ack"); + } return 0; } /*****************************************************************************/ +/* Process a [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU message */ static int xrdp_rdp_process_suppress(struct xrdp_rdp *self, struct stream *s) { @@ -1237,28 +1386,33 @@ xrdp_rdp_process_suppress(struct xrdp_rdp *self, struct stream *s) int right; int bottom; - if (!s_check_rem(s, 1)) + if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU")) { return 1; } in_uint8(s, allowDisplayUpdates); - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_suppress: allowDisplayUpdates %d bytes " - "left %d", allowDisplayUpdates, (int) (s->end - s->p)); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_SUPPRESS_OUTPUT_PDU " + "allowDisplayUpdates %d", allowDisplayUpdates); switch (allowDisplayUpdates) { case 0: /* SUPPRESS_DISPLAY_UPDATES */ self->client_info.suppress_output = 1; - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_suppress: suppress_output %d", - self->client_info.suppress_output); + LOG_DEVEL(LOG_LEVEL_DEBUG, "Client requested display output to be suppressed"); if (self->session->callback != 0) { self->session->callback(self->session->id, 0x5559, 1, 0, 0, 0); } + else + { + LOG_DEVEL(LOG_LEVEL_WARNING, + "Bug: no callback registered for xrdp_rdp_process_suppress"); + } break; case 1: /* ALLOW_DISPLAY_UPDATES */ self->client_info.suppress_output = 0; - if (!s_check_rem(s, 11)) + LOG_DEVEL(LOG_LEVEL_DEBUG, "Client requested display output to be enabled"); + if (!s_check_rem_and_log(s, 11, "Parsing [MS-RDPBCGR] Padding and TS_RECTANGLE16")) { return 1; } @@ -1267,9 +1421,8 @@ xrdp_rdp_process_suppress(struct xrdp_rdp *self, struct stream *s) in_uint16_le(s, top); in_uint16_le(s, right); in_uint16_le(s, bottom); - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_suppress: suppress_output %d " - "left %d top %d right %d bottom %d", - self->client_info.suppress_output, + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_RECTANGLE16 " + "left %d, top %d, right %d, bottom %d", left, top, right, bottom); if (self->session->callback != 0) { @@ -1277,13 +1430,18 @@ xrdp_rdp_process_suppress(struct xrdp_rdp *self, struct stream *s) MAKELONG(left, top), MAKELONG(right, bottom), 0); } + else + { + LOG_DEVEL(LOG_LEVEL_WARNING, + "Bug: no callback registered for xrdp_rdp_process_suppress"); + } break; } return 0; } /*****************************************************************************/ -/* RDP_PDU_DATA */ +/* Process a [MS-RDPBCGR] TS_SHAREDATAHEADER message based on it's pduType2 */ int xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s) { @@ -1292,25 +1450,36 @@ xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s) int compressedType; int compressedLength; - if (!s_check_rem(s, 12)) + if (!s_check_rem_and_log(s, 12, "Parsing [MS-RDPBCGR] TS_SHAREDATAHEADER")) { return 1; } - in_uint8s(s, 6); - in_uint16_le(s, uncompressedLength); + in_uint8s(s, 6); /* shareID (4 bytes), padding (1 byte), streamID (1 byte) */ + in_uint16_le(s, uncompressedLength); /* shareID */ in_uint8(s, pduType2); in_uint8(s, compressedType); in_uint16_le(s, compressedLength); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_SHAREDATAHEADER " + "shareID (ignored), streamID (ignored), uncompressedLength %d, " + "pduType2 0x%2.2x, compressedType 0x%2.2x, compressedLength %d", + uncompressedLength, pduType2, compressedType, compressedLength); + if (compressedType != 0) { /* don't support compression */ + /* PACKET_COMPR_TYPE_8K = 0x00 */ + LOG(LOG_LEVEL_ERROR, "Only RDP 4.0 bulk compression " + "(PACKET_COMPR_TYPE_8K) is supported by XRDP"); return 1; } if (compressedLength > uncompressedLength) { + LOG(LOG_LEVEL_ERROR, "The compressed length %d is larger than " + "the uncompressed length %d, failing the processing of this " + "PDU", compressedLength, uncompressedLength); return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_rdp_process_data pduType2 %d", pduType2); + switch (pduType2) { case RDP_DATA_PDU_POINTER: /* 27(0x1b) */ @@ -1328,13 +1497,14 @@ xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s) case PDUTYPE2_REFRESH_RECT: xrdp_rdp_process_screen_update(self, s); break; - case 35: /* 35(0x23) PDUTYPE2_SUPPRESS_OUTPUT */ + case PDUTYPE2_SUPPRESS_OUTPUT: /* 35(0x23) */ xrdp_rdp_process_suppress(self, s); break; - case 36: /* 36(0x24) ?? disconnect query? */ + case PDUTYPE2_SHUTDOWN_REQUEST: /* 36(0x24) ?? disconnect query? */ /* when this message comes, send a 37 back so the client */ /* is sure the connection is alive and it can ask if user */ /* really wants to disconnect */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_SHUTDOWN_REQ_PDU"); xrdp_rdp_send_disconnect_query_response(self); /* send a 37 back */ break; case RDP_DATA_PDU_FONT2: /* 39(0x27) */ @@ -1344,7 +1514,9 @@ xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s) xrdp_rdp_process_frame_ack(self, s); break; default: - LOG_DEVEL(LOG_LEVEL_TRACE, "unknown in xrdp_rdp_process_data pduType2 %d", pduType2); + LOG(LOG_LEVEL_WARNING, + "Received unknown [MS-RDPBCGR] TS_SHAREDATAHEADER pduType2 %d (ignoring)", + pduType2); break; } return 0; @@ -1353,12 +1525,7 @@ xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s) int xrdp_rdp_disconnect(struct xrdp_rdp *self) { - int rv; - - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_rdp_disconnect"); - rv = xrdp_sec_disconnect(self->sec_layer); - LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_rdp_disconnect"); - return rv; + return xrdp_sec_disconnect(self->sec_layer); } /*****************************************************************************/ @@ -1367,62 +1534,85 @@ xrdp_rdp_send_deactivate(struct xrdp_rdp *self) { struct stream *s; - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_rdp_send_deactivate"); make_stream(s); init_stream(s, 8192); if (xrdp_rdp_init(self, s) != 0) { free_stream(s); - LOG(LOG_LEVEL_ERROR, "out xrdp_rdp_send_deactivate error"); + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_deactivate: xrdp_rdp_init failed"); return 1; } + /* TODO: why are all the fields missing from the TS_DEACTIVATE_ALL_PDU? */ s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_DEACTIVATE_ALL_PDU " + "shareID , lengthSourceDescriptor , " + "sourceDescriptor "); if (xrdp_rdp_send(self, s, PDUTYPE_DEACTIVATEALLPDU) != 0) { free_stream(s); - LOG(LOG_LEVEL_ERROR, "out xrdp_rdp_send_deactivate error"); + LOG(LOG_LEVEL_ERROR, "Sending [MS-RDPBCGR] TS_DEACTIVATE_ALL_PDU failed"); return 1; } free_stream(s); - LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_rdp_send_deactivate"); return 0; } /*****************************************************************************/ +/** Send a [MS-RDPBCGR] TS_SAVE_SESSION_INFO_PDU_DATA message. + * + * @param self + * @param data the data to send to the client in the + * TS_SAVE_SESSION_INFO_PDU_DATA message. The first 4 bytes of the data + * buffer MUST by the infoType value as specified in MS-RDPBCGR 2.2.10.1.1 + * @param data_bytes the length of the data buffer + * @returns error code + */ int xrdp_rdp_send_session_info(struct xrdp_rdp *self, const char *data, int data_bytes) { struct stream *s; - LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_rdp_send_session_info: data_bytes %d", data_bytes); + if (data == NULL) + { + LOG(LOG_LEVEL_ERROR, "data must not be null"); + return 1; + } + if (data_bytes < 4) + { + LOG(LOG_LEVEL_ERROR, "data_bytes must greater than or equal to 4"); + return 1; + } + make_stream(s); init_stream(s, 8192); if (xrdp_rdp_init_data(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_session_info: xrdp_rdp_init_data failed"); free_stream(s); return 1; } - if (s_check_rem_out(s, data_bytes)) - { - out_uint8a(s, data, data_bytes); - } - else + if (!s_check_rem_out_and_log(s, data_bytes, "Sending [MS-RDPBCGR] TS_SAVE_SESSION_INFO_PDU_DATA")) { free_stream(s); return 1; } + out_uint8a(s, data, data_bytes); s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_SAVE_SESSION_INFO_PDU_DATA " + "infoType 0x%8.8x, infoData ", + *((unsigned int *) data)); if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_LOGON) != 0) { + LOG(LOG_LEVEL_ERROR, "Sending [MS-RDPBCGR] TS_SAVE_SESSION_INFO_PDU_DATA failed"); free_stream(s); return 1; } diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index e632ca36..7fdf3fc8 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -45,28 +45,94 @@ static tui8 g_pad_92[48] = 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92 }; + +/*****************************************************************************/ +/* Licensing request v2 PDU + * + * [MS-RDPBCGR] TS_SECURITY_HEADER - Basic + * [MS-RDPELE] SERVER_LICENSE_REQUEST with PREAMBLE_VERSION_2_0 + */ /* some compilers need unsigned char to avoid warnings */ static tui8 g_lic1[322] = { + /* [MS-RDPBCGR] TS_SECURITY_HEADER - Basic + * flags (2) = 0x0080 (SEC_LICENSE_PKT) + * flagsHi (2) = unused (arbitrary data) + * [MS-RDPBCGR] LICENSE_PREAMBLE + * bMsgType (1) = 0x01 (LICENSE_REQUEST) + * flags (1) = 0x02 (PREAMBLE_VERSION_2_0) + * wMsgSize (2) = 318 (excludes the 4 bytes TS_SECURITY_HEADER Basic) + */ 0x80, 0x00, 0x3e, 0x01, 0x01, 0x02, 0x3e, 0x01, + /* [MS-RDPELE] SERVER_LICENSE_REQUEST + * ServerRandom (32) = + */ 0x7b, 0x3c, 0x31, 0xa6, 0xae, 0xe8, 0x74, 0xf6, 0xb4, 0xa5, 0x03, 0x90, 0xe7, 0xc2, 0xc7, 0x39, 0xba, 0x53, 0x1c, 0x30, 0x54, 0x6e, 0x90, 0x05, 0xd0, 0x05, 0xce, 0x44, 0x18, 0x91, 0x83, 0x81, + /* [MS-RDPELE] SERVER_LICENSE_REQUEST - ProductInfo + * [MS-RDPELE] PRODUCT_INFO + * dwVersion (4) = 0x00040000 + * cbCompanyName (4) = 0x0000002c (44) + */ 0x00, 0x00, 0x04, 0x00, 0x2c, 0x00, 0x00, 0x00, + /* + * pbCompanyName (44) = UTF-16("Microsoft Corporation") + * cbProductId (4) = 0x00000008 (8) + */ 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + /* + * pbProductId (8) = UTF-16("236") + */ 0x32, 0x00, 0x33, 0x00, 0x36, 0x00, 0x00, 0x00, + /* [MS-RDPELE] SERVER_LICENSE_REQUEST - KeyExchangeList + * [MS-RDPBCGR] LICENSE_BINARY_BLOB + * wBlobType (2) = 0x000d (BB_KEY_EXCHG_ALG_BLOB) + * wBlobLen (2) = 0x0004 (4) + * blobData (4) = 0x00000001 (KEY_EXCHANGE_ALG_RSA) + */ 0x0d, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, + /* [MS-RDPELE] SERVER_LICENSE_REQUEST - ServerCertificate + * [MS-RDPBCGR] LICENSE_BINARY_BLOB + * wBlobType (2) = BB_CERTIFICATE_BLOB (0x0003) + * wBlobLen (2) = 0x00b8 (184) + * blobData = + * + * [MS-RDPBCGR] SERVER_CERTIFICATE + * dwVersion (31 bits) = 0x00000001 (CERT_CHAIN_VERSION_1) + * t (1 bit) = 0 (temporary certificate) + */ 0x03, 0x00, 0xb8, 0x00, 0x01, 0x00, 0x00, 0x00, + /* + * certData = + * + * [MS-RDPBCGR] PROPRIETARYSERVERCERTIFICATE + * dwSigAlgId (4) = 0x00000001 (SIGNATURE_ALG_RSA) + * dwKeyAlgId (4) = 0x00000001 (KEY_EXCHANGE_ALG_RSA) + * wPublicKeyBlobType (2) = 0x0006 (BB_RSA_KEY_BLOB) + * wPublicKeyBlobLen (2) = 0x005c (92) + * PublicKeyBlob = + * + * [MS-RDPBCGR] RSA_PUBLIC_KEY + * magic (4) = 0x31415352 + * keylen (4) = 0x00000048 (72) + * bitlen (4) = 0x00000200 (512) + * datalen (4) = 0x0000003f (63) + * pubExp (4) = 0x00010001 (65537) + */ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x5c, 0x00, 0x52, 0x53, 0x41, 0x31, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, + /* + * modulus (72) = + */ 0x01, 0xc7, 0xc9, 0xf7, 0x8e, 0x5a, 0x38, 0xe4, 0x29, 0xc3, 0x00, 0x95, 0x2d, 0xdd, 0x4c, 0x3e, 0x50, 0x45, 0x0b, 0x0d, 0x9e, 0x2a, 0x5d, 0x18, @@ -76,6 +142,14 @@ static tui8 g_lic1[322] = 0xc8, 0xc7, 0xb4, 0xa8, 0x47, 0xc8, 0x50, 0x71, 0x74, 0x29, 0x53, 0x89, 0x6d, 0x9c, 0xed, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* [MS-RDPELE] SERVER_LICENSE_REQUEST - ServerCertificate + * [MS-RDPBCGR] LICENSE_BINARY_BLOB - blobData + * [MS-RDPBCGR] SERVER_CERTIFICATE - certData + * [MS-RDPBCGR] PROPRIETARYSERVERCERTIFICATE + * wSignatureBlobType (2) = 0x0008 (BB_RSA_SIGNATURE_BLOB) + * wSignatureBlobLen (2) = 0x0048 (72) + * SignatureBlob (72) = + */ 0x08, 0x00, 0x48, 0x00, 0xa8, 0xf4, 0x31, 0xb9, 0xab, 0x4b, 0xe6, 0xb4, 0xf4, 0x39, 0x89, 0xd6, 0xb1, 0xda, 0xf6, 0x1e, 0xec, 0xb1, 0xf0, 0x54, @@ -85,26 +159,90 @@ static tui8 g_lic1[322] = 0xcb, 0x11, 0xc3, 0xf2, 0xdb, 0x09, 0x42, 0x68, 0x29, 0x56, 0x58, 0x01, 0x56, 0xdb, 0x59, 0x03, 0x69, 0xdb, 0x7d, 0x37, 0x00, 0x00, 0x00, 0x00, + /* + * + * [MS-RDPELE] SERVER_LICENSE_REQUEST - ScopeList + * [MS-RDPELE] SCOPE_LIST + * ScopeCount (4) = 0x00000001 (1) + * ScopeArray = + * + * [MS-RDPBCGR] LICENSE_BINARY_BLOB + * wBlobType (2) = 0x000e (BB_SCOPE_BLOB) + * wBlobLen (2) = 0x000e (14) + * blobData (14) = ISO-8859-1("microsoft.com") + */ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x00 }; +/*****************************************************************************/ +/* Licensing success response v2 PDU + * + * [MS-RDPBCGR] TS_SECURITY_HEADER - Basic + * [MS-RDPELE] LICENSE_ERROR_MESSAGE with STATUS_VALID_CLIENT + */ /* some compilers need unsigned char to avoid warnings */ static tui8 g_lic2[20] = { + /* [MS-RDPBCGR] TS_SECURITY_HEADER - Basic + * flags (2) = 0x0080 (SEC_LICENSE_PKT) + * flagsHi (2) = unused (arbitrary data) + * [MS-RDPBCGR] LICENSE_PREAMBLE + * bMsgType (1) = 0xff (ERROR_ALERT) + * flags (1) = 0x02 (PREAMBLE_VERSION_2_0) + * wMsgSize (2) = 0x10 (16, excludes the 4 bytes TS_SECURITY_HEADER Basic) + */ 0x80, 0x00, 0x10, 0x00, 0xff, 0x02, 0x10, 0x00, + /* + * [MS-RDPBCGR] LICENSE_ERROR_MESSAGE + * dwErrorCode (4) = 0x00000007 (STATUS_VALID_CLIENT) + * dwStateTransition (4) = 0x00000002 (ST_NO_TRANSITION) + * bbErrorInfo = + */ 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + /* + * [MS-RDPBCGR] LICENSE_BINARY_BLOB + * wBlobType (2) = 0x1428 (should be 0x0004 BB_ERROR_BLOB) + * wBlobLen (2) = 0x0000 (0) + */ 0x28, 0x14, 0x00, 0x00 }; -/* mce */ +/*****************************************************************************/ +/* Licensing success response v3 PDU + * + * [MS-RDPBCGR] TS_SECURITY_HEADER - Basic + * [MS-RDPELE] LICENSE_ERROR_MESSAGE with STATUS_VALID_CLIENT + * + * used for Media Center Edition + */ /* some compilers need unsigned char to avoid warnings */ static tui8 g_lic3[20] = { + /* S */ + /* [MS-RDPBCGR] TS_SECURITY_HEADER - Basic + * flags (2) = 0x0280 (SEC_LICENSE_PKT | SEC_LICENSE_ENCRYPT_CS) + * flagsHi (2) = unused (arbitrary data) + * [MS-RDPBCGR] LICENSE_PREAMBLE + * bMsgType (1) = 0xff (ERROR_ALERT) + * flags (1) = 0x03 (PREAMBLE_VERSION_3_0) + * wMsgSize (2) = 0x0010 (16, excludes the 4 bytes TS_SECURITY_HEADER Basic) + */ 0x80, 0x02, 0x10, 0x00, 0xff, 0x03, 0x10, 0x00, + /* + * [MS-RDPBCGR] LICENSE_ERROR_MESSAGE + * dwErrorCode (4) = 0x00000007 (STATUS_VALID_CLIENT) + * dwStateTransition (4) = 0x00000002 (ST_NO_TRANSITION) + * bbErrorInfo = + */ 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + /* + * [MS-RDPBCGR] LICENSE_BINARY_BLOB + * wBlobType (2) = 0x99f3 (should be 0x0004 BB_ERROR_BLOB) + * wBlobLen (2) = 0x0000 (0) + */ 0xf3, 0x99, 0x00, 0x00 }; @@ -441,7 +579,6 @@ xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans) { struct xrdp_sec *self; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_sec_create"); self = (struct xrdp_sec *) g_malloc(sizeof(struct xrdp_sec), 1); self->rdp_layer = owner; self->crypt_method = CRYPT_METHOD_NONE; /* set later */ @@ -451,7 +588,6 @@ xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans) self->fastpath_layer = xrdp_fastpath_create(self, trans); self->chan_layer = xrdp_channel_create(self, self->mcs_layer); self->is_security_header_present = 1; - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_sec_create"); return self; } @@ -462,7 +598,6 @@ xrdp_sec_delete(struct xrdp_sec *self) { if (self == 0) { - LOG(LOG_LEVEL_ERROR, "xrdp_sec_delete: self is null"); return; } @@ -488,6 +623,7 @@ xrdp_sec_init(struct xrdp_sec *self, struct stream *s) { if (xrdp_mcs_init(self->mcs_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_sec_init: xrdp_mcs_init failed"); return 1; } @@ -614,6 +750,7 @@ xrdp_sec_encrypt(struct xrdp_sec *self, char *data, int len) /***************************************************************************** * convert utf-16 encoded string from stream into utf-8 string. * note: src_bytes doesn't include the null-terminator char. + * Copied From: xrdp_sec.c */ static int unicode_utf16_in(struct stream *s, int src_bytes, char *dst, int dst_len) @@ -623,13 +760,14 @@ unicode_utf16_in(struct stream *s, int src_bytes, char *dst, int dst_len) int i; int bytes; - LOG_DEVEL(LOG_LEVEL_DEBUG, "unicode_utf16_in: uni_len %d, dst_len %d", src_bytes, dst_len); + LOG_DEVEL(LOG_LEVEL_TRACE, "unicode_utf16_in: uni_len %d, dst_len %d", src_bytes, dst_len); if (src_bytes == 0) { - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing UTF-16")) { return 1; } + LOG_DEVEL(LOG_LEVEL_TRACE, "unicode_utf16_in: num_chars 0, dst '' (empty string)"); in_uint8s(s, 2); /* null terminator */ return 0; } @@ -638,7 +776,7 @@ unicode_utf16_in(struct stream *s, int src_bytes, char *dst, int dst_len) src = g_new0(twchar, bytes); for (i = 0; i < bytes / 2; ++i) { - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing UTF-16")) { g_free(src); return 1; @@ -650,13 +788,14 @@ unicode_utf16_in(struct stream *s, int src_bytes, char *dst, int dst_len) { g_memset(dst, '\0', dst_len); } - LOG_DEVEL(LOG_LEVEL_DEBUG, "unicode_utf16_in: num_chars %d, dst %s", num_chars, dst); + LOG_DEVEL(LOG_LEVEL_TRACE, "unicode_utf16_in: num_chars %d, dst '%s'", num_chars, dst); g_free(src); return 0; } /*****************************************************************************/ +/* Process TS_INFO_PACKET */ /* returns error */ static int xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) @@ -674,57 +813,73 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) /* initialize (zero out) local variables */ g_memset(tmpdata, 0, sizeof(char) * 256); - if (!s_check_rem(s, 8)) + if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] TS_INFO_PACKET")) { return 1; } in_uint8s(s, 4); in_uint32_le(s, flags); - LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_sec_process_logon_info flags $%x", flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Parsing [MS-RDPBCGR] TS_INFO_PACKET"); /* 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, "xrdp_sec_process_logon_info: flags wrong, likely decrypt " - "not working"); + LOG(LOG_LEVEL_ERROR, "received wrong flags, likely decrypt not working"); return 1; } if (flags & RDP_LOGON_LEAVE_AUDIO) { self->rdp_layer->client_info.sound_code = 1; - LOG_DEVEL(LOG_LEVEL_TRACE, "flag RDP_LOGON_LEAVE_AUDIO found"); + 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_RAIL) { self->rdp_layer->client_info.rail_enable = 1; - LOG_DEVEL(LOG_LEVEL_TRACE, "flag RDP_LOGON_RAIL found"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "[MS-RDPBCGR] TS_INFO_PACKET flag INFO_RAIL found"); + LOG(LOG_LEVEL_DEBUG, + "Client requested Remote Application Integrated Locally (RAIL)."); } - if ((flags & RDP_LOGON_AUTO) && (!self->rdp_layer->client_info.is_mce)) - /* todo, for now not allowing autologon and mce both */ + if (flags & RDP_LOGON_AUTO) { - self->rdp_layer->client_info.rdp_autologin = 1; - LOG_DEVEL(LOG_LEVEL_TRACE, "flag RDP_LOGON_AUTO found"); + 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_TRACE, "flag RDP_COMPRESSION found"); + 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) { - LOG_DEVEL(LOG_LEVEL_TRACE, "flag RDP_COMPRESSION set"); + self->rdp_layer->client_info.rdp_compression = 1; + LOG(LOG_LEVEL_DEBUG, "Client requested compression enabled."); } else { - LOG_DEVEL(LOG_LEVEL_TRACE, "flag RDP_COMPRESSION not set"); + LOG(LOG_LEVEL_DEBUG, "Client requested compression, but server " + "compression is disabled."); } } - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_INFO_PACKET cbDomain")) { return 1; } @@ -732,11 +887,13 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) if (len_domain >= INFO_CLIENT_MAX_CB_LEN) { - LOG(LOG_LEVEL_ERROR, "ERROR [xrdp_sec_process_logon_info()]: len_domain >= %d", INFO_CLIENT_MAX_CB_LEN); + LOG(LOG_LEVEL_ERROR, + "Client supplied domain is too long. Max length %d, domain length %d", + INFO_CLIENT_MAX_CB_LEN, len_domain); return 1; } - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_INFO_PACKET cbUserName")) { return 1; } @@ -747,18 +904,21 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) * always sends autologon credentials, even when user has not * configured any */ - if (len_user == 0) + 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, "ERROR [xrdp_sec_process_logon_info()]: len_user >= %d", 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); return 1; } - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_INFO_PACKET cbPassword")) { return 1; } @@ -766,11 +926,13 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) if (len_password >= INFO_CLIENT_MAX_CB_LEN) { - LOG(LOG_LEVEL_ERROR, "ERROR [xrdp_sec_process_logon_info()]: len_password >= %d", INFO_CLIENT_MAX_CB_LEN); + LOG(LOG_LEVEL_ERROR, + "Client supplied password is too long. Max length %d, password length %d", + INFO_CLIENT_MAX_CB_LEN, len_password); return 1; } - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_INFO_PACKET cbAlternateShell")) { return 1; } @@ -778,11 +940,13 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) if (len_program >= INFO_CLIENT_MAX_CB_LEN) { - LOG(LOG_LEVEL_ERROR, "ERROR [xrdp_sec_process_logon_info()]: len_program >= %d", 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); return 1; } - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_INFO_PACKET cbWorkingDir")) { return 1; } @@ -790,35 +954,38 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) if (len_directory >= INFO_CLIENT_MAX_CB_LEN) { - LOG(LOG_LEVEL_ERROR, "ERROR [xrdp_sec_process_logon_info()]: len_directory >= %d", 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); return 1; } if (unicode_utf16_in(s, len_domain, self->rdp_layer->client_info.domain, sizeof(self->rdp_layer->client_info.domain) - 1) != 0) { - return 1; - } - LOG_DEVEL(LOG_LEVEL_TRACE, "domain %s", self->rdp_layer->client_info.domain); - if (unicode_utf16_in(s, len_user, self->rdp_layer->client_info.username, sizeof(self->rdp_layer->client_info.username) - 1) != 0) - { + LOG(LOG_LEVEL_ERROR, "ERROR reading domain"); return 1; } + if (unicode_utf16_in(s, len_user, self->rdp_layer->client_info.username, sizeof(self->rdp_layer->client_info.username) - 1) != 0) + { + LOG(LOG_LEVEL_ERROR, "ERROR reading user name"); + return 1; + } if (flags & RDP_LOGON_AUTO) { if (unicode_utf16_in(s, len_password, self->rdp_layer->client_info.password, sizeof(self->rdp_layer->client_info.password) - 1) != 0) { + LOG(LOG_LEVEL_ERROR, "ERROR reading password"); return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, "flag RDP_LOGON_AUTO found"); } else if (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_DEVEL(LOG_LEVEL_TRACE, "Logon token detected"); + LOG(LOG_LEVEL_DEBUG, "Client supplied a Logon token. Overwritting 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'; @@ -826,71 +993,118 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) } else { - if (!s_check_rem(s, len_password + 2)) + if (!s_check_rem_and_log(s, len_password + 2, "Parsing [MS-RDPBCGR] TS_INFO_PACKET Password")) { return 1; } in_uint8s(s, len_password + 2); if (self->rdp_layer->client_info.require_credentials) { - LOG(LOG_LEVEL_ERROR, "xrdp_sec_process_logon_info: credentials on cmd line is mandatory"); + 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."); return 1; /* credentials on cmd line is mandatory */ } } if (self->rdp_layer->client_info.domain_user_separator[0] != '\0' && self->rdp_layer->client_info.domain[0] != '\0') { + LOG(LOG_LEVEL_DEBUG, "Client supplied domain with user name. Overwritting user name with user name parsed from domain."); int size = sizeof(self->rdp_layer->client_info.username); g_strncat(self->rdp_layer->client_info.username, self->rdp_layer->client_info.domain_user_separator, size - 1 - g_strlen(self->rdp_layer->client_info.domain_user_separator)); g_strncat(self->rdp_layer->client_info.username, self->rdp_layer->client_info.domain, size - 1 - g_strlen(self->rdp_layer->client_info.domain)); } - LOG_DEVEL(LOG_LEVEL_TRACE, "username %s", self->rdp_layer->client_info.username); if (unicode_utf16_in(s, len_program, self->rdp_layer->client_info.program, sizeof(self->rdp_layer->client_info.program) - 1) != 0) { + LOG(LOG_LEVEL_ERROR, "ERROR reading program"); return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, "program %s", self->rdp_layer->client_info.program); + if (unicode_utf16_in(s, len_directory, self->rdp_layer->client_info.directory, sizeof(self->rdp_layer->client_info.directory) - 1) != 0) { + LOG(LOG_LEVEL_ERROR, "ERROR reading directory"); return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, "directory %s", self->rdp_layer->client_info.directory); - if (flags & RDP_LOGON_BLOB) + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_INFO_PACKET " + "CodePage (ignored), flags 0x%8.8x, cbDomain %d, cbUserName %d, " + "cbPassword %d, cbAlternateShell %d, cbWorkingDir %d, Domain %s, " + "UserName %s, Password (omitted from log), AlternateShell %s, " + "WorkingDir %s", flags, len_domain, + len_user, len_password, len_program, len_directory, + self->rdp_layer->client_info.domain, + self->rdp_layer->client_info.username, + self->rdp_layer->client_info.program, + self->rdp_layer->client_info.directory); + LOG(LOG_LEVEL_DEBUG, "Client supplied domain: %s", self->rdp_layer->client_info.domain); + LOG(LOG_LEVEL_DEBUG, "Client supplied username: %s", self->rdp_layer->client_info.username); + LOG(LOG_LEVEL_DEBUG, "Client supplied password: "); + LOG(LOG_LEVEL_DEBUG, "Client supplied program: %s", self->rdp_layer->client_info.program); + LOG(LOG_LEVEL_DEBUG, "Client supplied directory: %s", self->rdp_layer->client_info.directory); + + /* 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(s, 4)) + if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPBCGR] TS_EXTENDED_INFO_PACKET " + "clientAddressFamily and cbClientAddress")) { return 1; } - in_uint8s(s, 2); /* unknown */ + /* TS_EXTENDED_INFO_PACKET requiered fields */ + in_uint8s(s, 2); /* clientAddressFamily */ in_uint16_le(s, len_ip); if (unicode_utf16_in(s, len_ip - 2, tmpdata, sizeof(tmpdata) - 1) != 0) { + LOG(LOG_LEVEL_ERROR, "ERROR reading ip"); return 1; } - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_EXTENDED_INFO_PACKET clientDir")) { return 1; } in_uint16_le(s, len_dll); if (unicode_utf16_in(s, len_dll - 2, tmpdata, sizeof(tmpdata) - 1) != 0) { + LOG(LOG_LEVEL_ERROR, "ERROR reading clientDir"); return 1; } - if (!s_check_rem(s, 4 + 62 + 22 + 62 + 26 + 4)) + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_EXTENDED_INFO_PACKET " + " clientAddressFamily (ignored), " + "cbClientAddress (ignored), clientAddress (ignored), " + "cbClientDir (ignored), clientDir (ignored)"); + + /* TODO: MS-BCGR 2.2.1.11.1.1.1 says that all fields after the + client directory are optional. */ + if (!s_check_rem_and_log(s, 4 + 64 + 20 + 64 + 20 + 4 + 4, + "Parsing [MS-RDPBCGR] TS_EXTENDED_INFO_PACKET " + "clientTimeZone, clientSessionId, and performanceFlags")) { return 1; } - in_uint8s(s, 4); /* len of timezone */ - in_uint8s(s, 62); /* skip */ - in_uint8s(s, 22); /* skip misc. */ - in_uint8s(s, 62); /* skip */ - in_uint8s(s, 26); /* skip stuff */ + /* TS_TIME_ZONE_INFORMATION */ + in_uint8s(s, 4); /* Bias (4) */ + in_uint8s(s, 64); /* StandardName (64) */ + in_uint8s(s, 20); /* StandardDate (16), StandardBias (4) */ + in_uint8s(s, 64); /* DaylightName (64) */ + in_uint8s(s, 20); /* DaylightDate (16), DaylightBias (4) */ + in_uint8s(s, 4); /* TS_EXTENDED_INFO_PACKET clientSessionId (4) */ + + /* TS_EXTENDED_INFO_PACKET optional fields */ in_uint32_le(s, self->rdp_layer->client_info.rdp5_performanceflags); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_EXTENDED_INFO_PACKET " + " clientTimeZone (ignored), " + "clientSessionId (ignored), performanceFlags 0x%8.8x, " + "cbAutoReconnectCookie (ignored), autoReconnectCookie (ignored), " + "reserved1 (ignored), reserved2 (ignored), " + "cbDynamicDSTTimeZoneKeyName (ignored), " + "dynamicDSTTimeZoneKeyName (ignored), " + "dynamicDaylightTimeDisabled (ignored)", + self->rdp_layer->client_info.rdp5_performanceflags); } - LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_sec_process_logon_info"); return 0; } @@ -901,21 +1115,24 @@ xrdp_sec_send_lic_initial(struct xrdp_sec *self) { struct stream *s; - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_send_lic_initial:"); + make_stream(s); init_stream(s, 8192); if (xrdp_mcs_init(self->mcs_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_sec_send_lic_initial: xrdp_mcs_init failed"); free_stream(s); return 1; } - out_uint8a(s, g_lic1, 322); + out_uint8a(s, g_lic1, sizeof(g_lic1)); s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPELE] SERVER_LICENSE_REQUEST"); if (xrdp_mcs_send(self->mcs_layer, s, MCS_GLOBAL_CHANNEL) != 0) { + LOG(LOG_LEVEL_ERROR, "Sending [MS-RDPELE] SERVER_LICENSE_REQUEST failed"); free_stream(s); return 1; } @@ -925,6 +1142,10 @@ xrdp_sec_send_lic_initial(struct xrdp_sec *self) } /*****************************************************************************/ +/* + * Send a [MS-RDPELE] LICENSE_ERROR_MESSAGE with STATUS_VALID_CLIENT + * See also: [MS-RDPELE] 1.3.3 Licensing PDU Flows + */ /* returns error */ static int xrdp_sec_send_lic_response(struct xrdp_sec *self) @@ -936,15 +1157,18 @@ xrdp_sec_send_lic_response(struct xrdp_sec *self) if (xrdp_mcs_init(self->mcs_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_sec_send_lic_response: xrdp_mcs_init failed"); free_stream(s); return 1; } - out_uint8a(s, g_lic2, 20); + out_uint8a(s, g_lic2, sizeof(g_lic2)); s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPELE] LICENSE_ERROR_MESSAGE with STATUS_VALID_CLIENT"); if (xrdp_mcs_send(self->mcs_layer, s, MCS_GLOBAL_CHANNEL) != 0) { + LOG(LOG_LEVEL_ERROR, "Sending [MS-RDPELE] LICENSE_ERROR_MESSAGE with STATUS_VALID_CLIENT failed"); free_stream(s); return 1; } @@ -965,6 +1189,7 @@ xrdp_sec_send_media_lic_response(struct xrdp_sec *self) if (xrdp_mcs_init(self->mcs_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_sec_send_media_lic_response: xrdp_mcs_init failed"); free_stream(s); return 1; } @@ -972,8 +1197,10 @@ xrdp_sec_send_media_lic_response(struct xrdp_sec *self) out_uint8a(s, g_lic3, sizeof(g_lic3)); s_mark_end(s); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPELE] LICENSE_ERROR_MESSAGE with STATUS_VALID_CLIENT"); if (xrdp_mcs_send(self->mcs_layer, s, MCS_GLOBAL_CHANNEL) != 0) { + LOG(LOG_LEVEL_ERROR, "Sending [MS-RDPELE] LICENSE_ERROR_MESSAGE with STATUS_VALID_CLIENT failed"); free_stream(s); return 1; } @@ -1180,14 +1407,14 @@ xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s) int pad; #ifndef XRDP_DEBUG - /* TODO: remove UNUSED_VAR once the `var` variable is used for more than + /* TODO: remove UNUSED_VAR once the `ver` variable is used for more than logging in debug mode */ UNUSED_VAR(ver); #endif - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv_fastpath:"); if (xrdp_fastpath_recv(self->fastpath_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_sec_recv_fastpath: xrdp_fastpath_recv failed"); return 1; } @@ -1195,47 +1422,65 @@ xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s) { if (self->crypt_level == CRYPT_LEVEL_FIPS) { - if (!s_check_rem(s, 12)) + if (!s_check_rem_and_log(s, 12, "Parsing [MS-RDPBCGR] TS_FP_FIPS_INFO")) { return 1; } + /* TS_FP_FIPS_INFO */ in_uint16_le(s, len); in_uint8(s, ver); /* length (2 bytes) */ + in_uint8(s, pad); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_FP_FIPS_INFO " + "length %d, version %d, padlen %d", len, ver, pad); if (len != 0x10) /* length MUST set to 0x10 */ { + LOG(LOG_LEVEL_ERROR, "Received header [MS-RDPBCGR] TS_FP_FIPS_INFO " + "invalid fastpath length. Expected 16, received %d", len); return 1; } - in_uint8(s, pad); - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv_fastpath: len %d ver %d pad %d", len, ver, pad); + + /* remainder of TS_FP_INPUT_PDU */ in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */ - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv_fastpath: data len %d", (int)(s->end - s->p)); + LOG_DEVEL(LOG_LEVEL_TRACE, "CRYPT_LEVEL_FIPS - data len %d", + (int)(s->end - s->p)); xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); s->end -= pad; } else { - if (!s_check_rem(s, 8)) + if (!s_check_rem_and_log(s, 8, + "Parsing [MS-RDPBCGR] TS_FP_INPUT_PDU dataSignature")) { return 1; } + /* remainder of TS_FP_INPUT_PDU */ in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */ xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); } } - if (self->fastpath_layer->numEvents == 0) + if (self->fastpath_layer->numEvents == 0) /* set by xrdp_fastpath_recv() */ { /** * If numberEvents is not provided in fpInputHeader, it will be provided * as one additional byte here. */ - if (!s_check_rem(s, 8)) + if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] TS_FP_INPUT_PDU numEvents")) { return 1; } in_uint8(s, self->fastpath_layer->numEvents); /* numEvents (1 byte) (optional) */ } + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_INPUT_PDU " + "fpInputHeader.action (ignored), " + "fpInputHeader.numEvents (see final numEvents), " + "fpInputHeader.flags %d, length1 (ToDo), length2 (ToDo), " + "fipsInformation %s, dataSignature (ignored), numEvents %d", + self->fastpath_layer->secFlags, + (self->fastpath_layer->secFlags & FASTPATH_INPUT_ENCRYPTED) ? "(see above)" : "(not present)", + self->fastpath_layer->numEvents); + return 0; } /*****************************************************************************/ @@ -1248,63 +1493,85 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) int ver; int pad; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_sec_recv"); if (xrdp_mcs_recv(self->mcs_layer, s, chan) != 0) { - LOG(LOG_LEVEL_ERROR, " out xrdp_sec_recv : error"); + LOG(LOG_LEVEL_ERROR, "xrdp_sec_recv: xrdp_mcs_recv failed"); return 1; } - if (!s_check_rem(s, 4)) + /* TODO: check if moving this check until after the is_security_header_present + causes any issues. + the security header is optional (eg. TLS connections), so this + check should really be after the check if the security header is present, + 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")) { return 1; } - if (!(self->is_security_header_present)) { + /* noisy log statement with no real info since this is an + expected state for TLS connections + */ + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_sec_recv: security header NOT present"); return 0; } + /* TS_SECURITY_HEADER */ in_uint32_le(s, flags); - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_sec_recv flags $%x", flags); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SECURITY_HEADER " + "flags 0x%8.8x, flagsHi (merged with flags)", flags); if (flags & SEC_ENCRYPT) /* 0x08 */ { if (self->crypt_level == CRYPT_LEVEL_FIPS) { - if (!s_check_rem(s, 12)) + if (!s_check_rem_and_log(s, 12, "Parsing [MS-RDPBCGR] TS_SECURITY_HEADER2")) { return 1; } - in_uint16_le(s, len); - in_uint8(s, ver); - if ((len != 16) || (ver != 1)) - { - return 1; - } - in_uint8(s, pad); - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv: len %d ver %d pad %d", len, ver, pad); + /* TS_SECURITY_HEADER2 */ + in_uint16_le(s, len); /* length */ + in_uint8(s, ver); /* version */ + in_uint8(s, pad); /* padlen */ in_uint8s(s, 8); /* signature(8) */ - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv: data len %d", (int)(s->end - s->p)); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SECURITY_HEADER2 " + "length %d, version %d, padlen %d, dataSignature (ignored)", + len, ver, pad); + if (len != 16) + { + LOG(LOG_LEVEL_ERROR, "Received header [MS-RDPBCGR] TS_SECURITY_HEADER2 " + "has unexpected length. Expected 16, actual %d", len); + return 1; + } + if (ver != 1) + { + LOG(LOG_LEVEL_ERROR, "Received header [MS-RDPBCGR] TS_SECURITY_HEADER2 " + "has unexpected version. Expected 1, actual %d", ver); + return 1; + } xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); s->end -= pad; } else if (self->crypt_level > CRYPT_LEVEL_NONE) { - if (!s_check_rem(s, 8)) + if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] TS_SECURITY_HEADER1")) { return 1; } + /* TS_SECURITY_HEADER1 */ in_uint8s(s, 8); /* signature(8) */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_SECURITY_HEADER1 " + "dataSignature (ignored)"); xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); } } - if (flags & SEC_CLIENT_RANDOM) /* 0x01 */ + if (flags & SEC_CLIENT_RANDOM) /* 0x01 TS_SECURITY_PACKET */ { - if (!s_check_rem(s, 4)) + if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPBCGR] TS_SECURITY_PACKET")) { return 1; } @@ -1312,18 +1579,22 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) /* 512, 2048 bit */ if ((len != 64 + 8) && (len != 256 + 8)) { + LOG(LOG_LEVEL_ERROR, "xrdp_sec_recv : error - unexpected length %d", len); return 1; } - if (!s_check_rem(s, len - 8)) + if (!s_check_rem_and_log(s, len - 8, + "Parsing [MS-RDPBCGR] TS_SECURITY_PACKET encryptedClientRandom")) { return 1; } in_uint8a(s, self->client_crypt_random, len - 8); + xrdp_sec_rsa_op(self, self->client_random, self->client_crypt_random, len - 8, self->pub_mod, self->pri_exp); - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv: client random - len %d", len); - LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "client random", self->client_random, 256); - LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "client crypt random", self->client_crypt_random, len - 8); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_SECURITY_PACKET " + "length %d, encryptedClientRandom (see below)", len); + LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "encryptedClientRandom", self->client_crypt_random, len - 8); + LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "decrypted encryptedClientRandom", self->client_random, 256); if (self->crypt_level == CRYPT_LEVEL_FIPS) { xrdp_sec_fips_establish_keys(self); @@ -1333,15 +1604,15 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) xrdp_sec_establish_keys(self); } *chan = 1; /* just set a non existing channel and exit */ - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_sec_recv"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv: out channel 1 (non-existing channel)"); return 0; } - if (flags & SEC_LOGON_INFO) /* 0x40 */ + if (flags & SEC_LOGON_INFO) /* 0x40 SEC_INFO_PKT */ { if (xrdp_sec_process_logon_info(self, s) != 0) { - LOG(LOG_LEVEL_ERROR, " out xrdp_sec_recv error"); + LOG(LOG_LEVEL_ERROR, "xrdp_sec_recv: xrdp_sec_process_logon_info failed"); return 1; } @@ -1349,30 +1620,30 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) { if (xrdp_sec_send_media_lic_response(self) != 0) { - LOG(LOG_LEVEL_ERROR, " out xrdp_sec_recv error"); + LOG(LOG_LEVEL_ERROR, "xrdp_sec_recv: xrdp_sec_send_media_lic_response failed"); return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_sec_recv"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv: out 'send demand active'"); return -1; /* special error that means send demand active */ } if (xrdp_sec_send_lic_initial(self) != 0) { - LOG(LOG_LEVEL_ERROR, " out xrdp_sec_recv error"); + LOG(LOG_LEVEL_ERROR, "xrdp_sec_recv: xrdp_sec_send_lic_initial failed"); return 1; } *chan = 1; /* just set a non existing channel and exit */ - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_sec_recv"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv: out channel 1 (non-existing channel)"); return 0; } - if (flags & SEC_LICENCE_NEG) /* 0x80 */ + if (flags & SEC_LICENCE_NEG) /* 0x80 SEC_LICENSE_PKT */ { if (xrdp_sec_send_lic_response(self) != 0) { - LOG(LOG_LEVEL_ERROR, " out xrdp_sec_recv error"); + LOG(LOG_LEVEL_ERROR, "xrdp_sec_recv: xrdp_sec_send_lic_response failed"); return 1; } @@ -1383,11 +1654,10 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) self->is_security_header_present = 0; } - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_sec_recv"); + LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_recv: out 'send demand active'"); return -1; /* special error that means send demand active */ } - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_sec_recv"); return 0; } @@ -1458,15 +1728,12 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) int datalen; int pad; - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_send:"); - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_sec_send"); s_pop_layer(s, sec_hdr); if (self->crypt_level > CRYPT_LEVEL_NONE) { if (self->crypt_level == CRYPT_LEVEL_FIPS) { - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_send: fips"); out_uint32_le(s, SEC_ENCRYPT); datalen = (int)((s->end - s->p) - 12); out_uint16_le(s, 16); /* crypto header size */ @@ -1477,6 +1744,11 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) out_uint8(s, pad); /* fips pad */ xrdp_sec_fips_sign(self, s->p, 8, s->p + 8, datalen); xrdp_sec_fips_encrypt(self, s->p + 8, datalen + pad); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_SECURITY_HEADER2 " + "flags 0x%4.4x, flagsHi 0x%4.4x, length 16, version 1, " + "padlen %d, dataSignature 0x%8.8x 0x%8.8x", + SEC_ENCRYPT & 0xffff, (SEC_ENCRYPT & 0xffff0000) >> 16, + pad, *((uint32_t *) s->p), *((uint32_t *) (s->p + 4))); } else if (self->crypt_level > CRYPT_LEVEL_LOW) { @@ -1484,19 +1756,25 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) datalen = (int)((s->end - s->p) - 8); xrdp_sec_sign(self, s->p, 8, s->p + 8, datalen); xrdp_sec_encrypt(self, s->p + 8, datalen); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_SECURITY_HEADER1 " + "flags 0x%4.4x, flagsHi 0x%4.4x, dataSignature 0x%8.8x 0x%8.8x", + SEC_ENCRYPT & 0xffff, (SEC_ENCRYPT & 0xffff0000) >> 16, + *((uint32_t *) s->p), *((uint32_t *) (s->p + 4))); } else { out_uint32_le(s, 0); + LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_SECURITY_HEADER " + "flags 0x0000, flagsHi 0x0000"); } } if (xrdp_mcs_send(self->mcs_layer, s, chan) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_sec_send: xrdp_mcs_send failed"); return 1; } - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_sec_send"); return 0; } @@ -1523,6 +1801,8 @@ xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s) { if (xrdp_fastpath_init(self->fastpath_layer, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_sec_init_fastpath: xrdp_fastpath_init failed"); return 1; } if (self->crypt_level == CRYPT_LEVEL_FIPS) @@ -1555,7 +1835,6 @@ xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s) int error; char save[8]; - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_send_fastpath:"); error = 0; s_pop_layer(s, sec_hdr); if (self->crypt_level == CRYPT_LEVEL_FIPS) @@ -1578,6 +1857,13 @@ xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s) g_memcpy(save, s->p + 8 + datalen, pad); g_memset(s->p + 8 + datalen, 0, pad); xrdp_sec_fips_encrypt(self, s->p + 8, datalen + pad); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_UPDATE_PDU " + "fpOutputHeader.action 0, fpOutputHeader.reserved 0, " + "fpOutputHeader.flags 0x2, length1 0x%2.2x, length2 0x%2.2x, " + "fipsInformation.length 16, fipsInformation.version 1, " + "fipsInformation.padlen %d, dataSignature 0x%8.8x 0x%8.8x, ", + pdulen >> 4, pdulen & 0xff, pad, + *((uint32_t *) s->p), *((uint32_t *) (s->p + 4))); error = xrdp_fastpath_send(self->fastpath_layer, s); g_memcpy(s->p + 8 + datalen, save, pad); } @@ -1593,22 +1879,33 @@ xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s) out_uint16_be(s, pdulen); xrdp_sec_sign(self, s->p, 8, s->p + 8, datalen); xrdp_sec_encrypt(self, s->p + 8, datalen); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_UPDATE_PDU " + "fpOutputHeader.action 0, fpOutputHeader.reserved 0, " + "fpOutputHeader.flags 0x2, length1 0x%2.2x, length2 0x%2.2x, " + "dataSignature 0x%8.8x 0x%8.8x, ", + pdulen >> 4, pdulen & 0xff, + *((uint32_t *) s->p), *((uint32_t *) (s->p + 4))); error = xrdp_fastpath_send(self->fastpath_layer, s); } else { LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_send_fastpath: no crypt"); pdulen = (int)(s->end - s->p); - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_send_fastpath: pdulen %d", pdulen); secFlags = 0x0; fpOutputHeader = secFlags << 6; out_uint8(s, fpOutputHeader); pdulen |= 0x8000; out_uint16_be(s, pdulen); + LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_UPDATE_PDU " + "fpOutputHeader.action 0, fpOutputHeader.reserved 0, " + "fpOutputHeader.flags 0, length1 0x%2.2x, length2 0x%2.2x", + pdulen >> 4, pdulen & 0xff); error = xrdp_fastpath_send(self->fastpath_layer, s); } if (error != 0) { + LOG(LOG_LEVEL_ERROR, + "xrdp_sec_send_fastpath: xrdp_fastpath_send failed"); return 1; } return 0; @@ -1627,11 +1924,11 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s) int earlyCapabilityFlags; char clientName[INFO_CLIENT_NAME_BYTES / 2] = { '\0' }; + /* TS_UD_CS_CORE requiered fields */ in_uint8s(s, 4); /* version */ in_uint16_le(s, self->rdp_layer->client_info.width); in_uint16_le(s, self->rdp_layer->client_info.height); in_uint16_le(s, colorDepth); - LOG_DEVEL(LOG_LEVEL_TRACE, "colorDepth 0x%4.4x (0xca00 4bpp 0xca01 8bpp)", colorDepth); switch (colorDepth) { case RNS_UD_COLOR_4BPP: @@ -1645,14 +1942,34 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s) in_uint8s(s, 4); /* keyboardLayout */ in_uint8s(s, 4); /* clientBuild */ unicode_utf16_in(s, INFO_CLIENT_NAME_BYTES - 2, clientName, sizeof(clientName) - 1); /* clientName */ - LOG(LOG_LEVEL_INFO, "connected client computer name: %s", clientName); + LOG(LOG_LEVEL_INFO, "Connected client computer name: %s", clientName); in_uint8s(s, 4); /* keyboardType */ in_uint8s(s, 4); /* keyboardSubType */ in_uint8s(s, 4); /* keyboardFunctionKey */ in_uint8s(s, 64); /* imeFileName */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " version (ignored), desktopWidth %d, " + "desktopHeight %d, colorDepth %s, SASSequence (ingored), " + "keyboardLayout (ignored), clientBuild (ignored), " + "clientName %s, keyboardType (ignored), " + "keyboardSubType (ignored), keyboardFunctionKey (ignored), " + "imeFileName (ignroed)", + self->rdp_layer->client_info.width, + self->rdp_layer->client_info.height, + (colorDepth == 0xca00 ? "RNS_UD_COLOR_4BPP" : + colorDepth == 0xca01 ? "RNS_UD_COLOR_8BPP" : "unknown"), + clientName); + + /* TS_UD_CS_CORE optional fields */ in_uint16_le(s, postBeta2ColorDepth); - LOG_DEVEL(LOG_LEVEL_TRACE, "postBeta2ColorDepth 0x%4.4x (0xca00 4bpp 0xca01 8bpp " - "0xca02 15bpp 0xca03 16bpp 0xca04 24bpp)", postBeta2ColorDepth); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " postBeta2ColorDepth %s", + postBeta2ColorDepth == 0xca00 ? "RNS_UD_COLOR_4BPP" : + postBeta2ColorDepth == 0xca01 ? "RNS_UD_COLOR_8BPP" : + postBeta2ColorDepth == 0xca02 ? "RNS_UD_COLOR_16BPP_555" : + postBeta2ColorDepth == 0xca03 ? "RNS_UD_COLOR_16BPP_565" : + postBeta2ColorDepth == 0xca04 ? "RNS_UD_COLOR_24BPP" : + "unknown"); switch (postBeta2ColorDepth) { @@ -1677,20 +1994,30 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s) return 0; } in_uint8s(s, 2); /* clientProductId */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " clientProductId (ignored)"); if (!s_check_rem(s, 4)) { return 0; } in_uint8s(s, 4); /* serialNumber */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " serialNumber (ignored)"); if (!s_check_rem(s, 2)) { return 0; } in_uint16_le(s, highColorDepth); - LOG_DEVEL(LOG_LEVEL_TRACE, "highColorDepth 0x%4.4x (0x0004 4bpp 0x0008 8bpp 0x000f 15bpp " - "0x0010 16 bpp 0x0018 24bpp)", highColorDepth); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " highColorDepth %s", + highColorDepth == 0x0004 ? "HIGH_COLOR_4BPP" : + highColorDepth == 0x0008 ? "HIGH_COLOR_8BPP" : + highColorDepth == 0x000F ? "HIGH_COLOR_15BPP" : + highColorDepth == 0x0010 ? "HIGH_COLOR_16BPP" : + highColorDepth == 0x0018 ? "HIGH_COLOR_24BPP" : + "unknown"); self->rdp_layer->client_info.bpp = highColorDepth; if (!s_check_rem(s, 2)) @@ -1698,8 +2025,13 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s) return 0; } in_uint16_le(s, supportedColorDepths); - LOG_DEVEL(LOG_LEVEL_TRACE, "supportedColorDepths 0x%4.4x (0x0001 24bpp 0x0002 16bpp " - "0x0004 15bpp 0x0008 32bpp)", supportedColorDepths); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " supportedColorDepths %s", + supportedColorDepths == 0x0001 ? "RNS_UD_24BPP_SUPPORT" : + supportedColorDepths == 0x0002 ? "RNS_UD_16BPP_SUPPORT" : + supportedColorDepths == 0x0004 ? "RNS_UD_15BPP_SUPPORT" : + supportedColorDepths == 0x0008 ? "RNS_UD_32BPP_SUPPORT" : + "unknown"); if (!s_check_rem(s, 2)) { @@ -1707,7 +2039,8 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s) } in_uint16_le(s, earlyCapabilityFlags); self->rdp_layer->client_info.mcs_early_capability_flags = earlyCapabilityFlags; - LOG_DEVEL(LOG_LEVEL_TRACE, "earlyCapabilityFlags 0x%4.4x (0x0002 want32)", + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " earlyCapabilityFlags 0x%4.4x", earlyCapabilityFlags); if ((earlyCapabilityFlags & 0x0002) && (supportedColorDepths & 0x0008)) { @@ -1719,13 +2052,16 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s) return 0; } in_uint8s(s, 64); /* clientDigProductId */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " clientDigProductId (ignored)"); if (!s_check_rem(s, 1)) { return 0; } in_uint8(s, self->rdp_layer->client_info.mcs_connection_type); /* connectionType */ - LOG_DEVEL(LOG_LEVEL_TRACE, "got client client connection type 0x%8.8x", + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " connectionType 0x%2.2x", self->rdp_layer->client_info.mcs_connection_type); if (!s_check_rem(s, 1)) @@ -1733,67 +2069,89 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s) return 0; } in_uint8s(s, 1); /* pad1octet */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " pad1octet (ignored)"); if (!s_check_rem(s, 4)) { return 0; } in_uint8s(s, 4); /* serverSelectedProtocol */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " serverSelectedProtocol (ignored)"); if (!s_check_rem(s, 4)) { return 0; } in_uint8s(s, 4); /* desktopPhysicalWidth */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " desktopPhysicalWidth (ignored)"); if (!s_check_rem(s, 4)) { return 0; } in_uint8s(s, 4); /* desktopPhysicalHeight */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " desktopPhysicalHeight (ignored)"); if (!s_check_rem(s, 2)) { return 0; } in_uint8s(s, 2); /* reserved */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " desktopOrientation (ignored)"); return 0; } /*****************************************************************************/ +/* Process a [MS-RDPBCGR] TS_UD_CS_SEC message */ static int xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream *s) { int crypt_method; int found; - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_sec_process_mcs_data_CS_SECURITY:"); 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_INFO, " client supports 40 bit encryption"); + LOG(LOG_LEVEL_DEBUG, "Client supports 40 bit encryption"); } if (crypt_method & CRYPT_METHOD_128BIT) { - LOG(LOG_LEVEL_INFO, " client supports 128 bit encryption"); + LOG(LOG_LEVEL_DEBUG, "Client supports 128 bit encryption"); } if (crypt_method & CRYPT_METHOD_56BIT) { - LOG(LOG_LEVEL_INFO, " client supports 56 bit encryption"); + LOG(LOG_LEVEL_DEBUG, "Client supports 56 bit encryption"); } if (crypt_method & CRYPT_METHOD_FIPS) { - LOG(LOG_LEVEL_INFO, " client supports fips encryption"); + 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_INFO, " client and server support fips, using 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; @@ -1805,21 +2163,27 @@ xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream *s) { if (crypt_method & CRYPT_METHOD_128BIT) { - LOG(LOG_LEVEL_INFO, " client and server support high crypt, using " - "high crypt"); + 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-bit encryption, and why there is no cypto method for 56-bit + encryption even though there is code for checking for 56-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_INFO, " client and server support medium crypt, using " - "medium crypt"); + 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; @@ -1831,8 +2195,9 @@ xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream *s) { if (crypt_method & CRYPT_METHOD_40BIT) { - LOG(LOG_LEVEL_INFO, " client and server support low crypt, using " - "low crypt"); + 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; @@ -1843,23 +2208,30 @@ xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream *s) { if (crypt_method == CRYPT_METHOD_NONE) { - LOG(LOG_LEVEL_INFO, " client and server support none crypt, using " - "none crypt"); + 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) - // { - // LOG_DEVEL(LOG_LEVEL_TRACE, " can not find client / server agreed encryption method"); - // return 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; + } return 0; } /*****************************************************************************/ -/* this adds the mcs channels in the list of channels to be used when +/* Process a [MS-RDPBCGR] TS_UD_CS_NET message. + This adds the mcs channels in the list of channels to be used when creating the server mcs data */ static int xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) @@ -1870,47 +2242,56 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) struct mcs_channel_item *channel_item; client_info = &(self->rdp_layer->client_info); - LOG_DEVEL(LOG_LEVEL_TRACE, "processing channels, channels_allowed is %d", - client_info->channels_allowed); /* this is an option set in xrdp.ini */ if (client_info->channels_allowed == 0) /* are channels on? */ { - LOG(LOG_LEVEL_INFO, "all channels are disabled by " - "configuration"); + LOG(LOG_LEVEL_DEBUG, "All channels are disabled by configuration"); return 0; } - if (!s_check_rem(s, 4)) + if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPBCGR] TS_UD_CS_NET")) { return 1; } 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 > 31) { + LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Protocol error: too many channels requested. " + "max 31, received %d", num_channels); return 1; } for (index = 0; index < num_channels; index++) { channel_item = g_new0(struct mcs_channel_item, 1); - if (!s_check_rem(s, 12)) + if (!s_check_rem_and_log(s, 12, "Parsing [MS-RDPBCGR] TS_UD_CS_NET.CHANNEL_DEF")) { g_free(channel_item); return 1; } in_uint8a(s, channel_item->name, 8); in_uint32_le(s, channel_item->flags); - if (g_strlen(channel_item->name) > 0) + + if (g_strlen(channel_item->name) > 0 && g_strlen(channel_item->name) < 8) { + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] " + "TS_UD_CS_NET.CHANNEL_DEF %d, name %s, options 0x%8.8x", + index, channel_item->name, channel_item->flags); channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1); - LOG(LOG_LEVEL_INFO, "adding channel item name %s chan_id " - "%d flags 0x%8.8x", channel_item->name, - channel_item->chanid, channel_item->flags); list_add_item(self->mcs_layer->channel_list, (intptr_t) channel_item); - LOG_DEVEL(LOG_LEVEL_TRACE, "got channel flags %8.8x name %s", channel_item->flags, - channel_item->name); + LOG(LOG_LEVEL_DEBUG, + "Adding channel: name %s, channel id %d, flags 0x%8.8x", + channel_item->name, channel_item->chanid, channel_item->flags); } else { + LOG_DEVEL(LOG_LEVEL_WARNING, "Received [MS-RDPBCGR] " + "TS_UD_CS_NET.CHANNEL_DEF %d, skipped because of " + "malformed channel name.", index); + LOG_DEVEL_HEXDUMP(LOG_LEVEL_WARNING, + "[MS-RDPBCGR] TS_UD_CS_NET.CHANNEL_DEF name", + channel_item->name, 8); g_free(channel_item); } } @@ -1918,7 +2299,8 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) } /*****************************************************************************/ -/* reads the client monitors data */ +/* Process a [MS-RDPBCGR] TS_UD_CS_MONITOR message. + reads the client monitors data */ static int xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s) { @@ -1934,33 +2316,38 @@ xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s) client_info = &(self->rdp_layer->client_info); - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_process_mcs_data_monitors: processing monitors data, allow_multimon is %d", client_info->multimon); /* this is an option set in xrdp.ini */ if (client_info->multimon != 1) /* are multi-monitors allowed ? */ { - LOG_DEVEL(LOG_LEVEL_INFO, "[INFO] xrdp_sec_process_mcs_data_monitors: multimon is not " - "allowed, skipping"); + LOG(LOG_LEVEL_INFO, "Multi-monitor is disabled by server config"); return 0; } + if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] TS_UD_CS_MONITOR")) + { + return 1; + } in_uint32_le(s, flags); /* flags */ + in_uint32_le(s, monitorCount); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_MONITOR " + "flags 0x%8.8x, monitorCount %d", flags, monitorCount); + //verify flags - must be 0x0 if (flags != 0) { - LOG(LOG_LEVEL_ERROR, "[ERROR] xrdp_sec_process_mcs_data_monitors: flags MUST be " - "zero, detected: %d", flags); + LOG(LOG_LEVEL_ERROR, + "[MS-RDPBCGR] Protocol error: TS_UD_CS_MONITOR flags MUST be zero, " + "received: 0x%8.8x", flags); return 1; } - in_uint32_le(s, monitorCount); //verify monitorCount - max 16 if (monitorCount > 16) { - LOG(LOG_LEVEL_ERROR, "[ERROR] xrdp_sec_process_mcs_data_monitors: max allowed " - "monitors is 16, detected: %d", monitorCount); + LOG(LOG_LEVEL_ERROR, + "[MS-RDPBCGR] Protocol error: TS_UD_CS_MONITOR monitorCount " + "MUST be less than 16, received: %d", monitorCount); return 1; } - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_process_mcs_data_monitors: monitorCount= %d", monitorCount); - client_info->monitorCount = monitorCount; x1 = 0; @@ -1971,11 +2358,26 @@ xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s) /* Add client_monitor_data to client_info struct, will later pass to X11rdp */ for (index = 0; index < monitorCount; index++) { + if (!s_check_rem_and_log(s, 20, "Parsing [MS-RDPBCGR] TS_UD_CS_MONITOR.TS_MONITOR_DEF")) + { + return 1; + } in_uint32_le(s, client_info->minfo[index].left); in_uint32_le(s, client_info->minfo[index].top); in_uint32_le(s, client_info->minfo[index].right); in_uint32_le(s, client_info->minfo[index].bottom); in_uint32_le(s, client_info->minfo[index].is_primary); + + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] " + "TS_UD_CS_MONITOR.TS_MONITOR_DEF %d " + "left %d, top %d, right %d, bottom %d, flags 0x%8.8x", + index, + client_info->minfo[index].left, + client_info->minfo[index].top, + client_info->minfo[index].right, + client_info->minfo[index].bottom, + client_info->minfo[index].is_primary); + if (index == 0) { x1 = client_info->minfo[index].left; @@ -1996,13 +2398,15 @@ xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s) got_primary = 1; } - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_process_mcs_data_monitors: got a monitor [%d]: left= %d, top= %d, right= %d, bottom= %d, is_primary?= %d", - index, - client_info->minfo[index].left, - client_info->minfo[index].top, - client_info->minfo[index].right, - client_info->minfo[index].bottom, - client_info->minfo[index].is_primary); + LOG(LOG_LEVEL_DEBUG, + "Client monitor [%d]: left= %d, top= %d, right= %d, bottom= %d, " + "is_primary?= %d", + index, + client_info->minfo[index].left, + client_info->minfo[index].top, + client_info->minfo[index].right, + client_info->minfo[index].bottom, + client_info->minfo[index].is_primary); } if (!got_primary) @@ -2029,7 +2433,12 @@ xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s) if (client_info->width > 0x7FFE || client_info->width < 0xC8 || client_info->height > 0x7FFE || client_info->height < 0xC8) { - LOG(LOG_LEVEL_ERROR, "[ERROR] xrdp_sec_process_mcs_data_monitors: error, virtual desktop width / height is too large"); + LOG(LOG_LEVEL_ERROR, + "Client supplied virtual desktop width or height is invalid. " + "Allowed width range: min %d, max %d. Width received: %d. " + "Allowed height range: min %d, max %d. Height received: %d", + 0xC8, 0x7FFE, client_info->width, + 0xC8, 0x7FFE, client_info->height); return 1; /* error */ } @@ -2047,7 +2456,8 @@ xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s) } /*****************************************************************************/ -/* process client mcs data, we need some things in here to create the server +/* Process a Client MCS Connect Initial PDU with GCC Conference Create Request. + process client mcs data, we need some things in here to create the server mcs data */ int xrdp_sec_process_mcs_data(struct xrdp_sec *self) @@ -2061,51 +2471,66 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self) /* set p to beginning */ s->p = s->data; /* skip header */ - if (!s_check_rem(s, 23)) + if (!s_check_rem_and_log(s, 23, "Parsing [ITU T.124] ConferenceCreateRequest")) { return 1; } - in_uint8s(s, 23); + in_uint8s(s, 23); /* skip [ITU T.124] ConferenceCreateRequest fields until userData */ while (s_check_rem(s, 4)) { hold_p = s->p; in_uint16_le(s, tag); in_uint16_le(s, size); + LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_UD_HEADER " + "type 0x%4.4x, length %d", tag, size); - if ((size < 4) || (!s_check_rem(s, size - 4))) + if (size < 4) + { + LOG(LOG_LEVEL_WARNING, "[MS-RDPBCGR] Protocol error: Invalid TS_UD_HEADER length value. " + "expected >= 4, actual %d", size); + break; + } + if (!s_check_rem_and_log(s, size - 4, + "Parsing [MS-RDPBCGR] GCC Conference Create Request client data field")) { - LOG(LOG_LEVEL_ERROR, "error in xrdp_sec_process_mcs_data tag %d size %d", - tag, size); break; } - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_process_mcs_data: 0x%8.8x", tag); switch (tag) { case SEC_TAG_CLI_INFO: /* CS_CORE 0xC001 */ if (xrdp_sec_process_mcs_data_CS_CORE(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "Processing [MS-RDPBCGR] TS_UD_CS_CORE failed"); return 1; } break; case SEC_TAG_CLI_CRYPT: /* CS_SECURITY 0xC002 */ if (xrdp_sec_process_mcs_data_CS_SECURITY(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "Processing [MS-RDPBCGR] TS_UD_CS_SEC failed"); return 1; } break; case SEC_TAG_CLI_CHANNELS: /* CS_NET 0xC003 */ if (xrdp_sec_process_mcs_data_channels(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "Processing [MS-RDPBCGR] TS_UD_CS_NET failed"); return 1; } break; case SEC_TAG_CLI_4: /* CS_CLUSTER 0xC004 */ + LOG_DEVEL(LOG_LEVEL_DEBUG, "Received [MS-RDPBCGR] TS_UD_CS_CLUSTER - no-op"); break; case SEC_TAG_CLI_MONITOR: /* CS_MONITOR 0xC005 */ if (xrdp_sec_process_mcs_data_monitors(self, s) != 0) { + LOG(LOG_LEVEL_ERROR, + "Processing [MS-RDPBCGR] TS_UD_CS_MONITOR failed"); return 1; } break; @@ -2118,8 +2543,9 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self) SC_MCS_MSGCHANNEL 0x0C04 SC_MULTITRANSPORT 0x0C08 */ default: - LOG(LOG_LEVEL_ERROR, "error unknown xrdp_sec_process_mcs_data " - "tag 0x%4.4x size %d", tag, size); + LOG(LOG_LEVEL_WARNING, + "Received [MS-RDPBCGR] TS_UD_HEADER type 0x%4.4x " + "is unknown (ignored)", tag); break; } @@ -2131,9 +2557,11 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self) if (self->rdp_layer->client_info.bpp > self->rdp_layer->client_info.max_bpp) { - LOG(LOG_LEVEL_INFO, "xrdp_rdp_parse_client_mcs_data: client asked " - "for %dbpp connection but configuration is limited " - "to %dbpp", self->rdp_layer->client_info.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.", + self->rdp_layer->client_info.bpp, + self->rdp_layer->client_info.max_bpp, self->rdp_layer->client_info.max_bpp); self->rdp_layer->client_info.bpp = self->rdp_layer->client_info.max_bpp; @@ -2146,7 +2574,16 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self) } /*****************************************************************************/ -/* process the mcs client data we received from the mcs layer */ +/* Process the mcs client data [ITU T.124] ConferenceCreateRequest userData field + as a [MS-RDPBCGR] TS_UD_CS_CORE struct */ +/* TODO: why does this method parse the strust from back to front (resetting + after each field) instead of from front to back like the rest of the parsing + code? */ +/* TODO: why does this method exist when the same struct is parsed in + xrdp_sec_process_mcs_data_CS_CORE and there does not seem to be any + dependencies preventing a call to that function. */ +/* TODO: this is a brittle function that assumes field offsets in the stream + instead of parsing the variable length fields of [ITU T.124] ConferenceCreateRequest */ static int xrdp_sec_in_mcs_data(struct xrdp_sec *self) { @@ -2159,18 +2596,22 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self) s = &(self->client_mcs_data); /* get hostname, it's unicode */ s->p = s->data; - if (!s_check_rem(s, 47)) + if (!s_check_rem_and_log(s, 47, "Parsing [ITU T.124] ConferenceCreateRequest")) { return 1; } - in_uint8s(s, 47); + in_uint8s(s, 47); /* skip [ITU T.124] ConferenceCreateRequest up to the + userData field, and skip [MS-RDPBCGR] TS_UD_CS_CORE + up to the clientName field */ g_memset(client_info->hostname, 0, 32); c = 1; index = 0; + /* TODO: why aren't we using unicode_utf16_in to parse the client name + like we do in xrdp_sec_process_mcs_data_CS_CORE? */ while (index < 16 && c != 0) { - if (!s_check_rem(s, 2)) + if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_UD_CS_CORE clientName")) { return 1; } @@ -2181,31 +2622,45 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self) } /* get build */ s->p = s->data; - if (!s_check_rem(s, 43 + 4)) + if (!s_check_rem_and_log(s, 43 + 4, "Parsing [MS-RDPBCGR] TS_UD_CS_CORE clientBuild")) { return 1; } in_uint8s(s, 43); - in_uint32_le(s, client_info->build); + in_uint32_le(s, client_info->build); /* [MS-RDPBCGR] TS_UD_CS_CORE clientBuild */ /* get keylayout */ s->p = s->data; - if (!s_check_rem(s, 39 + 4)) + if (!s_check_rem_and_log(s, 39 + 4, "Parsing [MS-RDPBCGR] TS_UD_CS_CORE keyboardLayout")) { return 1; } in_uint8s(s, 39); - in_uint32_le(s, client_info->keylayout); + in_uint32_le(s, client_info->keylayout); /* [MS-RDPBCGR] TS_UD_CS_CORE keyboardLayout */ /* get keyboard type / subtype */ s->p = s->data; - if (!s_check_rem(s, 79 + 8)) + if (!s_check_rem_and_log(s, 79 + 8, "Parsing [MS-RDPBCGR] TS_UD_CS_CORE keyboardType")) { return 1; } in_uint8s(s, 79); - in_uint32_le(s, client_info->keyboard_type); - in_uint32_le(s, client_info->keyboard_subtype); + in_uint32_le(s, client_info->keyboard_type); /* [MS-RDPBCGR] TS_UD_CS_CORE keyboardType */ + in_uint32_le(s, client_info->keyboard_subtype); /* [MS-RDPBCGR] TS_UD_CS_CORE keyboardSubType */ + LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE " + " version (ignored), desktopWidth (ignored), " + "desktopHeight (ignored), colorDepth (ignored), SASSequence (ingored), " + "keyboardLayout 0x%8.8x, clientBuild %d, " + "clientName %s, keyboardType 0x%8.8x, " + "keyboardSubType 0x%8.8x, keyboardFunctionKey (ignored), " + "imeFileName (ignroed)", + client_info->keylayout, + client_info->build, + client_info->hostname, + client_info->keyboard_type, + client_info->keyboard_subtype); + xrdp_load_keyboard_layout(client_info); s->p = s->data; + return 0; } @@ -2237,13 +2692,15 @@ xrdp_sec_init_rdp_security(struct xrdp_sec *self) self->crypt_level = CRYPT_LEVEL_FIPS; break; default: - LOG_DEVEL(LOG_LEVEL_TRACE, "Fatal : Illegal crypt_level"); + LOG_DEVEL(LOG_LEVEL_WARNING, "Fatal : Illegal crypt_level %d", + self->rdp_layer->client_info.crypt_level); break ; } if (self->decrypt_rc4_info != NULL) { - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_sec_init_rdp_security: decrypt_rc4_info already created !!!"); + LOG_DEVEL(LOG_LEVEL_WARNING, + "xrdp_sec_init_rdp_security: decrypt_rc4_info already created !!!"); } else { @@ -2252,7 +2709,8 @@ xrdp_sec_init_rdp_security(struct xrdp_sec *self) if (self->encrypt_rc4_info != NULL) { - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_sec_init_rdp_security: encrypt_rc4_info already created !!!"); + LOG_DEVEL(LOG_LEVEL_WARNING, + "xrdp_sec_init_rdp_security: encrypt_rc4_info already created !!!"); } else { @@ -2274,7 +2732,6 @@ xrdp_sec_incoming(struct xrdp_sec *self) char *value = NULL; char key_file[256]; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_sec_incoming:"); iso = self->mcs_layer->iso_layer; /* negotiate security layer */ @@ -2288,7 +2745,6 @@ xrdp_sec_incoming(struct xrdp_sec *self) if (iso->selectedProtocol > PROTOCOL_RDP) { /* init tls security */ - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_sec_incoming: init tls security"); if (trans_set_tls_mode(self->mcs_layer->iso_layer->trans, self->rdp_layer->client_info.key_file, @@ -2296,10 +2752,12 @@ xrdp_sec_incoming(struct xrdp_sec *self) self->rdp_layer->client_info.ssl_protocols, self->rdp_layer->client_info.tls_ciphers) != 0) { - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_sec_incoming: trans_set_tls_mode failed"); + LOG(LOG_LEVEL_ERROR, "xrdp_sec_incoming: trans_set_tls_mode failed"); return 1; } + LOG(LOG_LEVEL_DEBUG, "Using TLS security, and " + "setting RDP security crypto to LEVEL_NONE and METHOD_NONE"); self->crypt_level = CRYPT_LEVEL_NONE; self->crypt_method = CRYPT_METHOD_NONE; self->rsa_key_bytes = 0; @@ -2308,14 +2766,16 @@ xrdp_sec_incoming(struct xrdp_sec *self) else { /* init rdp security */ - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_sec_incoming: init rdp security"); if (xrdp_sec_init_rdp_security(self) != 0) { - LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_sec_incoming: xrdp_sec_init_rdp_security failed"); + LOG(LOG_LEVEL_ERROR, "xrdp_sec_incoming: xrdp_sec_init_rdp_security failed"); return 1; } if (self->crypt_method != CRYPT_METHOD_NONE) { + LOG(LOG_LEVEL_DEBUG, "Using RDP security, and " + "reading the server configuration"); + g_memset(key_file, 0, sizeof(char) * 256); g_random(self->server_random, 32); items = list_create(); @@ -2327,7 +2787,7 @@ xrdp_sec_incoming(struct xrdp_sec *self) if (file_by_name_read_section(key_file, "keys", items, values) != 0) { /* this is a show stopper */ - LOG(LOG_LEVEL_ALWAYS, "XRDP cannot read file: %s " + LOG(LOG_LEVEL_ERROR, "XRDP cannot read file: %s " "(check permissions)", key_file); list_delete(items); list_delete(values); @@ -2346,7 +2806,8 @@ xrdp_sec_incoming(struct xrdp_sec *self) else if (g_strcasecmp(item, "pub_mod") == 0) { self->rsa_key_bytes = (g_strlen(value) + 1) / 5; - LOG_DEVEL(LOG_LEVEL_TRACE, "pub_mod bytes %d", self->rsa_key_bytes); + LOG_DEVEL(LOG_LEVEL_DEBUG, "Server config: pub_mod bytes %d", + self->rsa_key_bytes); hex_str_to_bin(value, self->pub_mod, self->rsa_key_bytes); } else if (g_strcasecmp(item, "pub_sig") == 0) @@ -2356,15 +2817,14 @@ xrdp_sec_incoming(struct xrdp_sec *self) else if (g_strcasecmp(item, "pri_exp") == 0) { self->rsa_key_bytes = (g_strlen(value) + 1) / 5; - LOG_DEVEL(LOG_LEVEL_TRACE, "pri_exp %d", self->rsa_key_bytes); + LOG_DEVEL(LOG_LEVEL_DEBUG, "Server config: pri_exp %d", + self->rsa_key_bytes); hex_str_to_bin(value, self->pri_exp, self->rsa_key_bytes); } } if (self->rsa_key_bytes <= 64) { - LOG_DEVEL(LOG_LEVEL_TRACE, "warning, RSA key len 512 " - "bits or less, consider creating a 2048 bit key"); LOG(LOG_LEVEL_WARNING, "warning, RSA key len 512 " "bits or less, consider creating a 2048 bit key"); } @@ -2377,20 +2837,23 @@ xrdp_sec_incoming(struct xrdp_sec *self) /* negotiate mcs layer */ if (xrdp_mcs_incoming(self->mcs_layer) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_sec_incoming: xrdp_mcs_incoming failed"); return 1; } - LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "client mcs data received", self->client_mcs_data.data, + LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "client mcs data received", + self->client_mcs_data.data, (int)(self->client_mcs_data.end - self->client_mcs_data.data)); - LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "server mcs data sent", self->server_mcs_data.data, + LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "server mcs data sent", + self->server_mcs_data.data, (int)(self->server_mcs_data.end - self->server_mcs_data.data)); - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_sec_incoming"); + if (xrdp_sec_in_mcs_data(self) != 0) { + LOG(LOG_LEVEL_ERROR, "xrdp_sec_incoming: xrdp_sec_in_mcs_data failed"); return 1; } - LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_sec_incoming: out"); return 0; } @@ -2400,8 +2863,6 @@ xrdp_sec_disconnect(struct xrdp_sec *self) { int rv; - LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_sec_disconnect"); rv = xrdp_mcs_disconnect(self->mcs_layer); - LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_sec_disconnect"); return rv; } diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index d5a53a9a..f29ea0ed 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -789,7 +789,7 @@ xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex) if (g_xfs == NULL) { LOG_DEVEL(LOG_LEVEL_ERROR, - "xfuse_add_clip_dir_item() called with no filesystem") + "xfuse_add_clip_dir_item() called with no filesystem"); } else {