/* Process a cached pointer PDU */ void process_cached_pointer_pdu(STREAM s) { uint16 cache_idx; in_uint16_le(s, cache_idx); ui_set_cursor(cache_get_cursor(cache_idx)); }
/* Receive an RDP packet */ static STREAM rdp_recv(uint8 * type) { static STREAM rdp_s; uint16 length, pdu_type; uint8 rdpver; if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL)) { rdp_s = sec_recv(&rdpver); if (rdp_s == NULL) return NULL; if (rdpver == 0xff) { g_next_packet = rdp_s->end; *type = 0; return rdp_s; } else if (rdpver != 3) { /* rdp5_process should move g_next_packet ok */ rdp5_process(rdp_s); *type = 0; return rdp_s; } g_next_packet = rdp_s->p; } else { rdp_s->p = g_next_packet; } in_uint16_le(rdp_s, length); /* 32k packets are really 8, keepalive fix */ if (length == 0x8000) { g_next_packet += 8; *type = 0; return rdp_s; } in_uint16_le(rdp_s, pdu_type); in_uint8s(rdp_s, 2); /* userid */ *type = pdu_type & 0xf; #if WITH_DEBUG DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type)); hexdump(g_next_packet, length); #endif /* */ g_next_packet += length; return rdp_s; }
/* Process a New Pointer PDU - these pointers have variable bit depth */ void process_new_pointer_pdu(STREAM s) { int xor_bpp; in_uint16_le(s, xor_bpp); process_colour_pointer_common(s, xor_bpp); }
/* Process a cached pointer PDU */ void process_cached_pointer_pdu(RDPCLIENT * This, STREAM s) { uint16 cache_idx; in_uint16_le(s, cache_idx); ui_set_cursor(This, cache_get_cursor(This, cache_idx)); }
/* Process a colour pointer PDU */ static void process_colour_pointer_common(STREAM s, int bpp) { uint16 width, height, cache_idx, masklen, datalen; sint16 x, y; uint8 *mask; uint8 *data; RD_HCURSOR cursor; in_uint16_le(s, cache_idx); in_uint16_le(s, x); in_uint16_le(s, y); in_uint16_le(s, width); in_uint16_le(s, height); in_uint16_le(s, masklen); in_uint16_le(s, datalen); in_uint8p(s, data, datalen); in_uint8p(s, mask, masklen); if ((width != 32) || (height != 32)) { warning("process_colour_pointer_common: " "width %d height %d\n", width, height); } /* sometimes x or y is out of bounds */ x = MAX(x, 0); x = MIN(x, width - 1); y = MAX(y, 0); y = MIN(y, height - 1); // TODO cursor = ui_create_cursor(x, y, width, height, mask, data, bpp); // TODO ui_set_cursor(cursor); cache_put_cursor(cache_idx, cursor); }
/* Respond to a demand active PDU */ static BOOL process_demand_active(RDPCLIENT * This, STREAM s) { uint8 type; uint16 len_src_descriptor, len_combined_caps; in_uint32_le(s, This->rdp_shareid); in_uint16_le(s, len_src_descriptor); in_uint16_le(s, len_combined_caps); in_uint8s(s, len_src_descriptor); DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", This->rdp_shareid)); rdp_process_server_caps(This, s, len_combined_caps); if ( !rdp_send_confirm_active(This) || !rdp_send_synchronise(This) || !rdp_send_control(This, RDP_CTL_COOPERATE) || !rdp_send_control(This, RDP_CTL_REQUEST_CONTROL) || !rdp_recv(This, &type) || /* RDP_PDU_SYNCHRONIZE */ !rdp_recv(This, &type) || /* RDP_CTL_COOPERATE */ !rdp_recv(This, &type) || /* RDP_CTL_GRANT_CONTROL */ !rdp_send_input(This, 0, RDP_INPUT_SYNCHRONIZE, 0, /*This->numlock_sync ? ui_get_numlock_state(This, read_keyboard_state(This)) :*/ 0, 0) // TODO: keyboard mess ) return False; if (This->use_rdp5) { if(!rdp_enum_bmpcache2(This) || !rdp_send_fonts(This, 3)) return False; } else { if(!rdp_send_fonts(This, 1) || !rdp_send_fonts(This, 2)) return False; } if(!rdp_recv(This, &type)) /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */ return False; reset_order_state(This); return True; }
void rdp_process_bitmap_capset(rdpRdp * rdp, STREAM s) { uint16 preferredBitsPerPixel; uint16 desktopWidth; uint16 desktopHeight; uint16 desktopResizeFlag; uint16 bitmapCompressionFlag; uint8 drawingFlags; /* * preferredBitsPerPixel (2 bytes): * A 16-bit, unsigned integer. Color depth of the remote session. In RDP 4.0 and 5.0, * this field MUST be set to 8 (even for a 16-color session) */ in_uint16_le(s, preferredBitsPerPixel); /* preferredBitsPerPixel */ in_uint8s(s, 6); /* Ignore receive1BitPerPixel, receive4BitPerPixel, receive8BitPerPixel */ in_uint16_le(s, desktopWidth); /* desktopWidth */ in_uint16_le(s, desktopHeight); /* desktopHeight */ in_uint8s(s, 2); /* pad */ in_uint16_le(s, desktopResizeFlag); /* desktopResizeFlag */ in_uint16_le(s, bitmapCompressionFlag); /* bitmapCompressionFlag */ in_uint8s(s, 1); /* Ignore highColorFlags */ in_uint8(s, drawingFlags); /* drawingFlags */ /* * The server may limit depth and change the size of the desktop (for * example when shadowing another session). */ if (rdp->settings->server_depth != preferredBitsPerPixel) { ui_warning(rdp->inst, "Remote desktop does not support color depth %d; falling back to %d\n", rdp->settings->server_depth, preferredBitsPerPixel); rdp->settings->server_depth = preferredBitsPerPixel; ui_resize_window(rdp->inst); } if (rdp->settings->width != desktopWidth || rdp->settings->height != desktopHeight) { ui_warning(rdp->inst, "Remote desktop changed from %dx%d to %dx%d.\n", rdp->settings->width, rdp->settings->height, desktopWidth, desktopHeight); rdp->settings->width = desktopWidth; rdp->settings->height = desktopHeight; ui_resize_window(rdp->inst); } }
/* Process a colour pointer PDU */ static void process_colour_pointer_common(STREAM s, int bpp) { uint16 width, height, cache_idx, masklen, datalen; uint16 x, y; uint8 *mask; uint8 *data; RD_HCURSOR cursor; in_uint16_le(s, cache_idx); in_uint16_le(s, x); in_uint16_le(s, y); in_uint16_le(s, width); in_uint16_le(s, height); in_uint16_le(s, masklen); in_uint16_le(s, datalen); in_uint8p(s, data, datalen); in_uint8p(s, mask, masklen); if ((width != 32) || (height != 32)) { warning("process_colour_pointer_common: " "width %d height %d\n", width, height); } /* keep hotspot within cursor bounding box */ x = MIN(x, width - 1); y = MIN(y, height - 1); cursor = ui_create_cursor(x, y, width, height, mask, data, bpp); ui_set_cursor(cursor); cache_put_cursor(cache_idx, cursor); }
static void rdpsnd_process_training(STREAM in) { uint16 tick; uint16 packsize; STREAM out; in_uint16_le(in, tick); in_uint16_le(in, packsize); logger(Sound, Debug, "rdpsnd_process_training(), tick=0x%04x", (unsigned) tick); out = rdpsnd_init_packet(SNDC_TRAINING, 4); out_uint16_le(out, tick); out_uint16_le(out, packsize); s_mark_end(out); rdpsnd_send(out); }
/* Process a general capability set */ static void rdp_process_general_caps(STREAM s) { uint16 pad2octetsB; /* rdp5 flags? */ in_uint8s(s, 10); in_uint16_le(s, pad2octetsB); if (!pad2octetsB) g_use_rdp5 = False; }
static void rdpsnd_process(STREAM s) { uint16 len; while (!s_check_end(s)) { /* New packet */ if (packet.size == 0) { if ((s->end - s->p) < 4) { error("RDPSND: Split at packet header. Things will go south from here...\n"); return; } in_uint8(s, packet_opcode); in_uint8s(s, 1); /* Padding */ in_uint16_le(s, len); DEBUG_SOUND(("RDPSND: == Opcode %x Length: %d ==\n", (int) packet_opcode, (int) len)); packet.p = packet.data; packet.end = packet.data + len; packet.size = len; } else { len = MIN(s->end - s->p, packet.end - packet.p); /* Microsoft's server is so broken it's not even funny... */ if (packet_opcode == RDPSND_WRITE) { if ((packet.p - packet.data) < 12) len = MIN(len, 12 - (packet.p - packet.data)); else if ((packet.p - packet.data) == 12) { DEBUG_SOUND(("RDPSND: Eating 4 bytes of %d bytes...\n", len)); in_uint8s(s, 4); len -= 4; } } in_uint8a(s, packet.p, len); packet.p += len; } /* Packet fully assembled */ if (packet.p == packet.end) { packet.p = packet.data; rdpsnd_process_packet(packet_opcode, &packet); packet.size = 0; } } }
/* software decode */ int surface_cmd(rdpRdp * rdp, STREAM s) { int cmdType; int frameAction; int frameId; int destLeft; int destTop; int destRight; int destBottom; int bpp; int codecID; int width; int height; int bitmapDataLength; //printf("surface_cmd: size %d\n", s->end - s->p); //hexdump(s->p, 1024); frameId = 0; while (s->p < s->end) { in_uint16_le(s, cmdType); //printf(" surface_cmd: %d\n", cmdType); switch (cmdType) { case 4: /* CMDTYPE_FRAME_MARKER */ in_uint16_le(s, frameAction); in_uint32_le(s, frameId); //printf(" surface_cmd: CMDTYPE_FRAME_MARKER %d %d\n", frameAction, frameId); if (frameAction == 1) { rdp_send_frame_ack(rdp, frameId); } break; case 6: /* CMDTYPE_STREAM_SURFACE_BITS */ in_uint16_le(s, destLeft); in_uint16_le(s, destTop); in_uint16_le(s, destRight); in_uint16_le(s, destBottom); in_uint8(s, bpp); in_uint8s(s, 2); in_uint8(s, codecID); in_uint16_le(s, width); in_uint16_le(s, height); in_uint32_le(s, bitmapDataLength); in_uint8s(s, bitmapDataLength); //printf(" surface_cmd: CMDTYPE_STREAM_SURFACE_BITS " // "id %d width %d height %d bpp %d size %d\n", // codecID, width, height, bpp, bitmapDataLength); break; } } return 0; }
int APP_CC dev_redir_clientID_confirm(struct stream* s) { log_message(&log_conf, LOG_LEVEL_DEBUG, "rdpdr channel[dev_redir_data_in]: new message: PAKID_CORE_CLIENTID_CONFIRM"); in_uint16_le(s, vers_major); in_uint32_le(s, vers_minor); in_uint32_le(s, client_id); log_message(&log_conf, LOG_LEVEL_DEBUG, "rdpdr channel[dev_redir_data_in]: version : %i:%i, client_id : %i", vers_major, vers_minor, client_id); return 0; }
/* return error */ static int APP_CC process_server_set_opcode(struct mod *mod, struct stream *s) { int rv; int opcode; in_uint16_le(s, opcode); rv = mod->server_set_opcode(mod, opcode); return rv; }
/* returns error */ static int APP_CC process_message_channel_data(struct stream* s) { int chan_id; int chan_flags; int rv; int length; int total_length; in_uint16_le(s, chan_id); in_uint16_le(s, chan_flags); in_uint16_le(s, length); in_uint32_le(s, total_length); log_message(&log_conf, LOG_LEVEL_DEBUG, "chansrv[process_message_channel_data]: " "chan_id %d chan_flags %d", chan_id, chan_flags); rv = send_channel_data_response_message(); if (rv == 0) { /* if (chan_id == g_cliprdr_chan_id) { rv = clipboard_data_in(s, chan_id, chan_flags, length, total_length); } else if (chan_id == g_rdpsnd_chan_id) { rv = sound_data_in(s, chan_id, chan_flags, length, total_length); } else if (chan_id == g_rdpdr_chan_id) { rv = dev_redir_data_in(s, chan_id, chan_flags, length, total_length); }*/ /* else if (chan_id == g_seamrdp_chan_id) { rv = seamrdp_data_in(s, chan_id, chan_flags, length, total_length); } */ // else // { rv = user_channel_data_in(s, chan_id, chan_flags, length, total_length); // } } return rv; }
/* Process a general capability set */ static void rdp_process_general_caps(RDPCLIENT * This, STREAM s) { uint16 pad2octetsB; /* rdp5 flags? */ in_uint8s(s, 10); in_uint16_le(s, pad2octetsB); if (!pad2octetsB) This->use_rdp5 = False; }
static int APP_CC rail_process_local_move_size(struct stream *s, int size) { int window_id; int is_move_size_start; int move_size_type; int pos_x; int pos_y; LOG(10, ("chansrv::rail_process_local_move_size:")); in_uint32_le(s, window_id); in_uint16_le(s, is_move_size_start); in_uint16_le(s, move_size_type); in_uint16_le(s, pos_x); in_uint16_le(s, pos_y); LOG(10, (" window_id 0x%8.8x is_move_size_start %d move_size_type %d " "pos_x %d pos_y %d", window_id, is_move_size_start, move_size_type, pos_x, pos_y)); return 0; }
static int APP_CC rail_process_window_move(struct stream *s, int size) { int window_id; int left; int top; int right; int bottom; LOG(10, ("chansrv::rail_process_window_move:")); in_uint32_le(s, window_id); in_uint16_le(s, left); in_uint16_le(s, top); in_uint16_le(s, right); in_uint16_le(s, bottom); LOG(10, (" window_id 0x%8.8x left %d top %d right %d bottom %d width %d height %d", window_id, left, top, right, bottom, right - left, bottom - top)); XMoveResizeWindow(g_display, window_id, left, top, right - left, bottom - top); return 0; }
/* Process a general capability set */ static void rdp_process_general_caps(STREAM s) { uint16 pad2octetsB; /* rdp5 flags? */ in_uint8s(s, 10); in_uint16_le(s, pad2octetsB); if (!pad2octetsB) g_rdp_version = RDP_V4; }
/* return error */ static int APP_CC process_server_screen_blt(struct mod *mod, struct stream *s) { int rv; int x; int y; int cx; int cy; int srcx; int srcy; in_sint16_le(s, x); in_sint16_le(s, y); in_uint16_le(s, cx); in_uint16_le(s, cy); in_sint16_le(s, srcx); in_sint16_le(s, srcy); rv = mod->server_screen_blt(mod, x, y, cx, cy, srcx, srcy); return rv; }
static int APP_CC rail_process_exec(struct stream *s, int size) { int flags; int ExeOrFileLength; int WorkingDirLength; int ArgumentsLen; char *ExeOrFile; char *WorkingDir; char *Arguments; LOG(0, ("chansrv::rail_process_exec:")); in_uint16_le(s, flags); in_uint16_le(s, ExeOrFileLength); in_uint16_le(s, WorkingDirLength); in_uint16_le(s, ArgumentsLen); ExeOrFile = read_uni(s, ExeOrFileLength); WorkingDir = read_uni(s, WorkingDirLength); Arguments = read_uni(s, ArgumentsLen); LOG(10, (" flags 0x%8.8x ExeOrFileLength %d WorkingDirLength %d " "ArgumentsLen %d ExeOrFile [%s] WorkingDir [%s] " "Arguments [%s]", flags, ExeOrFileLength, WorkingDirLength, ArgumentsLen, ExeOrFile, WorkingDir, Arguments)); if (g_strlen(ExeOrFile) > 0) { LOG(10, ("rail_process_exec: pre")); /* ask main thread to fork */ tc_mutex_lock(g_exec_mutex); g_exec_name = ExeOrFile; g_set_wait_obj(g_exec_event); tc_sem_dec(g_exec_sem); tc_mutex_unlock(g_exec_mutex); LOG(10, ("rail_process_exec: post")); } g_free(ExeOrFile); g_free(WorkingDir); g_free(Arguments); return 0; }
/* Respond to a demand active PDU */ static void process_demand_active(STREAM s) { uint8 type; uint16 len_src_descriptor, len_combined_caps; /* at this point we need to ensure that we have ui created */ rd_create_ui(); in_uint32_le(s, g_rdp_shareid); in_uint16_le(s, len_src_descriptor); in_uint16_le(s, len_combined_caps); in_uint8s(s, len_src_descriptor); DEBUG(("DEMAND_ACTIVE(id=0x%x)\n", g_rdp_shareid)); rdp_process_server_caps(s, len_combined_caps); rdp_send_confirm_active(); rdp_send_synchronise(); rdp_send_control(RDP_CTL_COOPERATE); rdp_send_control(RDP_CTL_REQUEST_CONTROL); rdp_recv(&type); /* RDP_PDU_SYNCHRONIZE */ rdp_recv(&type); /* RDP_CTL_COOPERATE */ rdp_recv(&type); /* RDP_CTL_GRANT_CONTROL */ rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, g_numlock_sync ? ui_get_numlock_state(read_keyboard_state()) : 0, 0); if (g_rdp_version >= RDP_V5) { rdp_enum_bmpcache2(); rdp_send_fonts(3); } else { rdp_send_fonts(1); rdp_send_fonts(2); } rdp_recv(&type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */ reset_order_state(); }
/* Process a Server New (or Upgrade) License packet */ static void licence_process_new_license(rdpLicence * licence, STREAM s) { int i; uint32 length; uint32 os_major; uint32 os_minor; CryptoRc4 crypt_key; /* Licensing Binary BLOB with EncryptedLicenseInfo: */ in_uint8s(s, 2); /* wBlobType should be 0x0009 (BB_ENCRYPTED_DATA_BLOB) */ in_uint16_le(s, length); /* wBlobLen */ /* RC4-encrypted New License Information */ if (!s_check_rem(s, length)) return; crypt_key = crypto_rc4_init(licence->licence_key, 16); crypto_rc4(crypt_key, length, s->p, s->p); /* decrypt in place */ crypto_rc4_free(crypt_key); /* dwVersion */ in_uint16_le(s, os_major); /* OS major version */ in_uint16_le(s, os_minor); /* OS minor version */ /* Skip Scope, CompanyName and ProductId */ for (i = 0; i < 3; i++) { in_uint32_le(s, length); if (!s_check_rem(s, length)) return; in_uint8s(s, length); } /* LicenseInfo - CAL from license server */ in_uint32_le(s, length); if (!s_check_rem(s, length)) return; licence->licence_issued = True; save_licence(s->p, length); }
/* return error */ static int APP_CC process_server_draw_text(struct mod *mod, struct stream *s) { int rv; int font; int flags; int mixmode; int clip_left; int clip_top; int clip_right; int clip_bottom; int box_left; int box_top; int box_right; int box_bottom; int x; int y; int len_bmpdata; char *bmpdata; in_uint16_le(s, font); in_uint16_le(s, flags); in_uint16_le(s, mixmode); in_sint16_le(s, clip_left); in_sint16_le(s, clip_top); in_sint16_le(s, clip_right); in_sint16_le(s, clip_bottom); in_sint16_le(s, box_left); in_sint16_le(s, box_top); in_sint16_le(s, box_right); in_sint16_le(s, box_bottom); in_sint16_le(s, x); in_sint16_le(s, y); in_uint16_le(s, len_bmpdata); in_uint8p(s, bmpdata, len_bmpdata); rv = mod->server_draw_text(mod, font, flags, mixmode, clip_left, clip_top, clip_right, clip_bottom, box_left, box_top, box_right, box_bottom, x, y, bmpdata, len_bmpdata); return rv; }
void rdp_process_order_capset(rdpRdp * rdp, STREAM s) { uint8 orderSupport[32]; uint16 desktopSaveXGranularity; uint16 desktopSaveYGranularity; uint16 maximumOrderLevel; uint16 orderFlags; uint16 orderSupportExFlags; uint32 desktopSaveSize; uint16 textANSICodePage; memset(orderSupport, 0, 32); in_uint8s(s, 20); /* Ignore terminalDescriptor and pad */ in_uint16_le(s, desktopSaveXGranularity); /* desktopSaveXGranularity */ in_uint16_le(s, desktopSaveYGranularity); /* desktopSaveYGranularity */ in_uint8s(s, 2); /* pad */ in_uint16_le(s, maximumOrderLevel); /* maximumOrderLevel */ in_uint8s(s, 2); /* numberFonts */ in_uint16_le(s, orderFlags); /* orderFlags */ in_uint8a(s, orderSupport, 32); /* orderSupport */ in_uint8s(s, 2); /* textFlags */ in_uint16_le(s, orderSupportExFlags); /* orderSupportExFlags */ in_uint8s(s, 4); /* pad */ in_uint32_le(s, desktopSaveSize); /* desktopSaveSize */ in_uint8s(s, 4); /* Ignore pad */ /* See [MSDN-CP]: http://msdn.microsoft.com/en-us/library/dd317756/ */ in_uint16_le(s, textANSICodePage); /* textANSICodePage */ /* pad */ }
/* get the number of client cursor cache */ static int APP_CC xrdp_caps_process_pointer(struct xrdp_rdp *self, struct stream *s, int len) { int i; int colorPointerFlag; int no_new_cursor; if (len < 2 + 2 + 2) { g_writeln("xrdp_caps_process_pointer: error"); return 1; } no_new_cursor = self->client_info.pointer_flags & 2; in_uint16_le(s, colorPointerFlag); self->client_info.pointer_flags = colorPointerFlag; in_uint16_le(s, i); i = MIN(i, 32); self->client_info.pointer_cache_entries = i; if (colorPointerFlag & 1) { g_writeln("xrdp_caps_process_pointer: client supports " "new(color) cursor"); in_uint16_le(s, i); i = MIN(i, 32); self->client_info.pointer_cache_entries = i; } else { g_writeln("xrdp_caps_process_pointer: client does not support " "new(color) cursor"); } if (no_new_cursor) { g_writeln("xrdp_caps_process_pointer: new(color) cursor is " "disabled by config"); self->client_info.pointer_flags = 0; } return 0; }
void rdp_process_window_capset(rdpRdp * rdp, STREAM s) { uint32 wndSupportLevel; uint8 numIconCaches; uint16 numIconCacheEntries; in_uint32_le(s, wndSupportLevel); /* wndSupportLevel */ in_uint8(s, numIconCaches); /* numIconCaches */ in_uint16_le(s, numIconCacheEntries); /* numIconCacheEntries */ rail_process_window_capset(rdp->rail_session, wndSupportLevel, numIconCaches, numIconCacheEntries); }
/* Process a system pointer PDU */ void process_system_pointer_pdu(STREAM s) { uint16 system_pointer_type; in_uint16_le(s, system_pointer_type); switch (system_pointer_type) { case RDP_NULL_POINTER: ui_set_null_cursor(); break; default: unimpl("System pointer message 0x%x\n", system_pointer_type); } }
/* Process a pointer PDU */ static void process_pointer_pdu(STREAM s) { uint16 message_type; uint16 x, y; in_uint16_le(s, message_type); in_uint8s(s, 2); /* pad */ switch (message_type) { case RDP_POINTER_MOVE: in_uint16_le(s, x); in_uint16_le(s, y); if (s_check(s)) ui_move_pointer(x, y); break; case RDP_POINTER_COLOR: process_colour_pointer_pdu(s); break; case RDP_POINTER_CACHED: process_cached_pointer_pdu(s); break; case RDP_POINTER_SYSTEM: process_system_pointer_pdu(s); break; case RDP_POINTER_NEW: process_new_pointer_pdu(s); break; default: unimpl("Pointer message 0x%x\n", message_type); } }
/* return error */ static int APP_CC process_server_paint_rect_os(struct mod *mod, struct stream *s) { int rv; int x; int y; int cx; int cy; int rdpid; int srcx; int srcy; in_sint16_le(s, x); in_sint16_le(s, y); in_uint16_le(s, cx); in_uint16_le(s, cy); in_uint32_le(s, rdpid); in_sint16_le(s, srcx); in_sint16_le(s, srcy); rv = mod->server_paint_rect_os(mod, x, y, cx, cy, rdpid, srcx, srcy); return rv; }