From: Steinar H. Gunderson Date: Thu, 3 Feb 2005 22:36:06 +0000 (+0000) Subject: Pull in even more rdesktop source. X-Git-Url: https://git.sesse.net/?p=rdpsrv;a=commitdiff_plain;h=86ae6f2670e6d7a62d9fbb2243c8aae28b925645 Pull in even more rdesktop source. --- diff --git a/constants.h b/constants.h new file mode 100644 index 0000000..15b6bb3 --- /dev/null +++ b/constants.h @@ -0,0 +1,319 @@ +/* + rdesktop: A Remote Desktop Protocol client. + Miscellaneous protocol constants + Copyright (C) Matthew Chapman 1999-2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* TCP port for Remote Desktop Protocol */ +#define TCP_PORT_RDP 3389 + +/* ISO PDU codes */ +enum ISO_PDU_CODE +{ + ISO_PDU_CR = 0xE0, /* Connection Request */ + ISO_PDU_CC = 0xD0, /* Connection Confirm */ + ISO_PDU_DR = 0x80, /* Disconnect Request */ + ISO_PDU_DT = 0xF0, /* Data */ + ISO_PDU_ER = 0x70 /* Error */ +}; + +/* MCS PDU codes */ +enum MCS_PDU_TYPE +{ + MCS_EDRQ = 1, /* Erect Domain Request */ + MCS_DPUM = 8, /* Disconnect Provider Ultimatum */ + MCS_AURQ = 10, /* Attach User Request */ + MCS_AUCF = 11, /* Attach User Confirm */ + MCS_CJRQ = 14, /* Channel Join Request */ + MCS_CJCF = 15, /* Channel Join Confirm */ + MCS_SDRQ = 25, /* Send Data Request */ + MCS_SDIN = 26 /* Send Data Indication */ +}; + +#define MCS_CONNECT_INITIAL 0x7f65 +#define MCS_CONNECT_RESPONSE 0x7f66 + +#define BER_TAG_BOOLEAN 1 +#define BER_TAG_INTEGER 2 +#define BER_TAG_OCTET_STRING 4 +#define BER_TAG_RESULT 10 +#define MCS_TAG_DOMAIN_PARAMS 0x30 + +#define MCS_GLOBAL_CHANNEL 1003 +#define MCS_USERCHANNEL_BASE 1001 + +/* RDP secure transport constants */ +#define SEC_RANDOM_SIZE 32 +#define SEC_MODULUS_SIZE 64 +#define SEC_PADDING_SIZE 8 +#define SEC_EXPONENT_SIZE 4 + +#define SEC_CLIENT_RANDOM 0x0001 +#define SEC_ENCRYPT 0x0008 +#define SEC_LOGON_INFO 0x0040 +#define SEC_LICENCE_NEG 0x0080 + +#define SEC_TAG_SRV_INFO 0x0c01 +#define SEC_TAG_SRV_CRYPT 0x0c02 +#define SEC_TAG_SRV_CHANNELS 0x0c03 + +#define SEC_TAG_CLI_INFO 0xc001 +#define SEC_TAG_CLI_CRYPT 0xc002 +#define SEC_TAG_CLI_CHANNELS 0xc003 +#define SEC_TAG_CLI_4 0xc004 + +#define SEC_TAG_PUBKEY 0x0006 +#define SEC_TAG_KEYSIG 0x0008 + +#define SEC_RSA_MAGIC 0x31415352 /* RSA1 */ + +/* RDP licensing constants */ +#define LICENCE_TOKEN_SIZE 10 +#define LICENCE_HWID_SIZE 20 +#define LICENCE_SIGNATURE_SIZE 16 + +#define LICENCE_TAG_DEMAND 0x01 +#define LICENCE_TAG_AUTHREQ 0x02 +#define LICENCE_TAG_ISSUE 0x03 +#define LICENCE_TAG_REISSUE 0x04 +#define LICENCE_TAG_PRESENT 0x12 +#define LICENCE_TAG_REQUEST 0x13 +#define LICENCE_TAG_AUTHRESP 0x15 +#define LICENCE_TAG_RESULT 0xff + +#define LICENCE_TAG_USER 0x000f +#define LICENCE_TAG_HOST 0x0010 + +/* RDP PDU codes */ +enum RDP_PDU_TYPE +{ + RDP_PDU_DEMAND_ACTIVE = 1, + RDP_PDU_CONFIRM_ACTIVE = 3, + RDP_PDU_DEACTIVATE = 6, + RDP_PDU_DATA = 7 +}; + +enum RDP_DATA_PDU_TYPE +{ + RDP_DATA_PDU_UPDATE = 2, + RDP_DATA_PDU_CONTROL = 20, + RDP_DATA_PDU_POINTER = 27, + RDP_DATA_PDU_INPUT = 28, + RDP_DATA_PDU_SYNCHRONISE = 31, + RDP_DATA_PDU_BELL = 34, + RDP_DATA_PDU_LOGON = 38, + RDP_DATA_PDU_FONT2 = 39, + RDP_DATA_PDU_DISCONNECT = 47 +}; + +enum RDP_CONTROL_PDU_TYPE +{ + RDP_CTL_REQUEST_CONTROL = 1, + RDP_CTL_GRANT_CONTROL = 2, + RDP_CTL_DETACH = 3, + RDP_CTL_COOPERATE = 4 +}; + +enum RDP_UPDATE_PDU_TYPE +{ + RDP_UPDATE_ORDERS = 0, + RDP_UPDATE_BITMAP = 1, + RDP_UPDATE_PALETTE = 2, + RDP_UPDATE_SYNCHRONIZE = 3 +}; + +enum RDP_POINTER_PDU_TYPE +{ + RDP_POINTER_SYSTEM = 1, + RDP_POINTER_MOVE = 3, + RDP_POINTER_COLOR = 6, + RDP_POINTER_CACHED = 7 +}; + +enum RDP_SYSTEM_POINTER_TYPE +{ + RDP_NULL_POINTER = 0, + RDP_DEFAULT_POINTER = 0x7F00 +}; + +enum RDP_INPUT_DEVICE +{ + RDP_INPUT_SYNCHRONIZE = 0, + RDP_INPUT_CODEPOINT = 1, + RDP_INPUT_VIRTKEY = 2, + RDP_INPUT_SCANCODE = 4, + RDP_INPUT_MOUSE = 0x8001 +}; + +/* Device flags */ +#define KBD_FLAG_RIGHT 0x0001 +#define KBD_FLAG_EXT 0x0100 +#define KBD_FLAG_QUIET 0x1000 +#define KBD_FLAG_DOWN 0x4000 +#define KBD_FLAG_UP 0x8000 + +/* These are for synchronization; not for keystrokes */ +#define KBD_FLAG_SCROLL 0x0001 +#define KBD_FLAG_NUMLOCK 0x0002 +#define KBD_FLAG_CAPITAL 0x0004 + +/* See T.128 */ +#define RDP_KEYPRESS 0 +#define RDP_KEYRELEASE (KBD_FLAG_DOWN | KBD_FLAG_UP) + +#define MOUSE_FLAG_MOVE 0x0800 +#define MOUSE_FLAG_BUTTON1 0x1000 +#define MOUSE_FLAG_BUTTON2 0x2000 +#define MOUSE_FLAG_BUTTON3 0x4000 +#define MOUSE_FLAG_BUTTON4 0x0280 +#define MOUSE_FLAG_BUTTON5 0x0380 +#define MOUSE_FLAG_DOWN 0x8000 + +/* Raster operation masks */ +#define ROP2_S(rop3) (rop3 & 0xf) +#define ROP2_P(rop3) ((rop3 & 0x3) | ((rop3 & 0x30) >> 2)) + +#define ROP2_COPY 0xc +#define ROP2_XOR 0x6 +#define ROP2_AND 0x8 +#define ROP2_NXOR 0x9 +#define ROP2_OR 0xe + +#define MIX_TRANSPARENT 0 +#define MIX_OPAQUE 1 + +#define TEXT2_VERTICAL 0x04 +#define TEXT2_IMPLICIT_X 0x20 + +/* RDP capabilities */ +#define RDP_CAPSET_GENERAL 1 /* Maps to generalCapabilitySet in T.128 page 138 */ +#define RDP_CAPLEN_GENERAL 0x18 +#define OS_MAJOR_TYPE_UNIX 4 +#define OS_MINOR_TYPE_XSERVER 7 + +#define RDP_CAPSET_BITMAP 2 +#define RDP_CAPLEN_BITMAP 0x1C + +#define RDP_CAPSET_ORDER 3 +#define RDP_CAPLEN_ORDER 0x58 +#define ORDER_CAP_NEGOTIATE 2 +#define ORDER_CAP_NOSUPPORT 4 + +#define RDP_CAPSET_BMPCACHE 4 +#define RDP_CAPLEN_BMPCACHE 0x28 + +#define RDP_CAPSET_CONTROL 5 +#define RDP_CAPLEN_CONTROL 0x0C + +#define RDP_CAPSET_ACTIVATE 7 +#define RDP_CAPLEN_ACTIVATE 0x0C + +#define RDP_CAPSET_POINTER 8 +#define RDP_CAPLEN_POINTER 0x08 + +#define RDP_CAPSET_SHARE 9 +#define RDP_CAPLEN_SHARE 0x08 + +#define RDP_CAPSET_COLCACHE 10 +#define RDP_CAPLEN_COLCACHE 0x08 + +#define RDP_CAPSET_UNKNOWN 13 +#define RDP_CAPLEN_UNKNOWN 0x9C + +#define RDP_SOURCE "MSTSC" + +/* Logon flags */ +#define RDP_LOGON_NORMAL 0x33 +#define RDP_LOGON_AUTO 0x8 +#define RDP_LOGON_BLOB 0x100 + +/* Keymap flags */ +#define MapRightShiftMask (1<<0) +#define MapLeftShiftMask (1<<1) +#define MapShiftMask (MapRightShiftMask | MapLeftShiftMask) + +#define MapRightAltMask (1<<2) +#define MapLeftAltMask (1<<3) +#define MapAltGrMask MapRightAltMask + +#define MapRightCtrlMask (1<<4) +#define MapLeftCtrlMask (1<<5) +#define MapCtrlMask (MapRightCtrlMask | MapLeftCtrlMask) + +#define MapRightWinMask (1<<6) +#define MapLeftWinMask (1<<7) +#define MapWinMask (MapRightWinMask | MapLeftWinMask) + +#define MapNumLockMask (1<<8) +#define MapCapsLockMask (1<<9) + +#define MapLocalStateMask (1<<10) + +#define MapInhibitMask (1<<11) + +#define MASK_ADD_BITS(var, mask) (var |= mask) +#define MASK_REMOVE_BITS(var, mask) (var &= ~mask) +#define MASK_HAS_BITS(var, mask) ((var & mask)>0) +#define MASK_CHANGE_BIT(var, mask, active) (var = ((var & ~mask) | (active ? mask : 0))) + +/* Clipboard constants, "borrowed" from GCC system headers in + the w32 cross compiler */ + +#define CF_TEXT 1 +#define CF_BITMAP 2 +#define CF_METAFILEPICT 3 +#define CF_SYLK 4 +#define CF_DIF 5 +#define CF_TIFF 6 +#define CF_OEMTEXT 7 +#define CF_DIB 8 +#define CF_PALETTE 9 +#define CF_PENDATA 10 +#define CF_RIFF 11 +#define CF_WAVE 12 +#define CF_UNICODETEXT 13 +#define CF_ENHMETAFILE 14 +#define CF_HDROP 15 +#define CF_LOCALE 16 +#define CF_MAX 17 +#define CF_OWNERDISPLAY 128 +#define CF_DSPTEXT 129 +#define CF_DSPBITMAP 130 +#define CF_DSPMETAFILEPICT 131 +#define CF_DSPENHMETAFILE 142 +#define CF_PRIVATEFIRST 512 +#define CF_PRIVATELAST 767 +#define CF_GDIOBJFIRST 768 +#define CF_GDIOBJLAST 1023 + +/* Sound format constants */ +#define WAVE_FORMAT_PCM 1 +#define WAVE_FORMAT_ADPCM 2 +#define WAVE_FORMAT_ALAW 6 +#define WAVE_FORMAT_MULAW 7 + +/* Virtual channel options */ +#define CHANNEL_OPTION_INITIALIZED 0x80000000 +#define CHANNEL_OPTION_ENCRYPT_RDP 0x40000000 +#define CHANNEL_OPTION_COMPRESS_RDP 0x00800000 +#define CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000 + +/* NT status codes for RDPDR */ +#define STATUS_SUCCESS 0x00000000 +#define STATUS_INVALID_PARAMETER 0xc000000d +#define STATUS_INVALID_DEVICE_REQUEST 0xc0000010 +#define STATUS_ACCESS_DENIED 0xc0000022 diff --git a/parse.h b/parse.h new file mode 100644 index 0000000..cacea51 --- /dev/null +++ b/parse.h @@ -0,0 +1,94 @@ +/* + rdesktop: A Remote Desktop Protocol client. + Parsing primitives + Copyright (C) Matthew Chapman 1999-2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Parser state */ +typedef struct stream +{ + unsigned char *p; + unsigned char *end; + unsigned char *data; + unsigned int size; + + /* Offsets of various headers */ + unsigned char *iso_hdr; + unsigned char *mcs_hdr; + unsigned char *sec_hdr; + unsigned char *rdp_hdr; + unsigned char *channel_hdr; + +} + *STREAM; + +#define s_push_layer(s,h,n) { (s)->h = (s)->p; (s)->p += n; } +#define s_pop_layer(s,h) (s)->p = (s)->h; +#define s_mark_end(s) (s)->end = (s)->p; +#define s_check(s) ((s)->p <= (s)->end) +#define s_check_rem(s,n) ((s)->p + n <= (s)->end) +#define s_check_end(s) ((s)->p == (s)->end) + +#if defined(L_ENDIAN) && !defined(NEED_ALIGN) +#define in_uint16_le(s,v) { v = *(uint16 *)((s)->p); (s)->p += 2; } +#define in_uint32_le(s,v) { v = *(uint32 *)((s)->p); (s)->p += 4; } +#define out_uint16_le(s,v) { *(uint16 *)((s)->p) = v; (s)->p += 2; } +#define out_uint32_le(s,v) { *(uint32 *)((s)->p) = v; (s)->p += 4; } + +#else +#define in_uint16_le(s,v) { v = *((s)->p++); v += *((s)->p++) << 8; } +#define in_uint32_le(s,v) { in_uint16_le(s,v) \ + v += *((s)->p++) << 16; v += *((s)->p++) << 24; } +#define out_uint16_le(s,v) { *((s)->p++) = (v) & 0xff; *((s)->p++) = ((v) >> 8) & 0xff; } +#define out_uint32_le(s,v) { out_uint16_le(s, (v) & 0xffff); out_uint16_le(s, ((v) >> 16) & 0xffff); } +#endif + +#if defined(B_ENDIAN) && !defined(NEED_ALIGN) +#define in_uint16_be(s,v) { v = *(uint16 *)((s)->p); (s)->p += 2; } +#define in_uint32_be(s,v) { v = *(uint32 *)((s)->p); (s)->p += 4; } +#define out_uint16_be(s,v) { *(uint16 *)((s)->p) = v; (s)->p += 2; } +#define out_uint32_be(s,v) { *(uint32 *)((s)->p) = v; (s)->p += 4; } + +#define B_ENDIAN_PREFERRED +#define in_uint16(s,v) in_uint16_be(s,v) +#define in_uint32(s,v) in_uint32_be(s,v) +#define out_uint16(s,v) out_uint16_be(s,v) +#define out_uint32(s,v) out_uint32_be(s,v) + +#else +#define next_be(s,v) v = ((v) << 8) + *((s)->p++); +#define in_uint16_be(s,v) { v = *((s)->p++); next_be(s,v); } +#define in_uint32_be(s,v) { in_uint16_be(s,v); next_be(s,v); next_be(s,v); } +#define out_uint16_be(s,v) { *((s)->p++) = ((v) >> 8) & 0xff; *((s)->p++) = (v) & 0xff; } +#define out_uint32_be(s,v) { out_uint16_be(s, ((v) >> 16) & 0xffff); out_uint16_be(s, (v) & 0xffff); } +#endif + +#ifndef B_ENDIAN_PREFERRED +#define in_uint16(s,v) in_uint16_le(s,v) +#define in_uint32(s,v) in_uint32_le(s,v) +#define out_uint16(s,v) out_uint16_le(s,v) +#define out_uint32(s,v) out_uint32_le(s,v) +#endif + +#define in_uint8(s,v) v = *((s)->p++); +#define in_uint8p(s,v,n) { v = (s)->p; (s)->p += n; } +#define in_uint8a(s,v,n) { memcpy(v,(s)->p,n); (s)->p += n; } +#define in_uint8s(s,n) (s)->p += n; +#define out_uint8(s,v) *((s)->p++) = v; +#define out_uint8p(s,v,n) { memcpy((s)->p,v,n); (s)->p += n; } +#define out_uint8a(s,v,n) out_uint8p(s,v,n); +#define out_uint8s(s,n) { memset((s)->p,0,n); (s)->p += n; } diff --git a/proto.h b/proto.h new file mode 100644 index 0000000..b08a977 --- /dev/null +++ b/proto.h @@ -0,0 +1,180 @@ +/* bitmap.c */ +BOOL bitmap_decompress(unsigned char *output, int width, int height, unsigned char *input, int size, + int Bpp); +/* cache.c */ +HBITMAP cache_get_bitmap(uint8 cache_id, uint16 cache_idx); +void cache_put_bitmap(uint8 cache_id, uint16 cache_idx, HBITMAP bitmap); +FONTGLYPH *cache_get_font(uint8 font, uint16 character); +void cache_put_font(uint8 font, uint16 character, uint16 offset, uint16 baseline, uint16 width, + uint16 height, HGLYPH pixmap); +DATABLOB *cache_get_text(uint8 cache_id); +void cache_put_text(uint8 cache_id, void *data, int length); +uint8 *cache_get_desktop(uint32 offset, int cx, int cy, int bytes_per_pixel); +void cache_put_desktop(uint32 offset, int cx, int cy, int scanline, int bytes_per_pixel, + uint8 * data); +HCURSOR cache_get_cursor(uint16 cache_idx); +void cache_put_cursor(uint16 cache_idx, HCURSOR cursor); +/* channels.c */ +VCHANNEL *channel_register(char *name, uint32 flags, void (*callback) (STREAM)); +STREAM channel_init(VCHANNEL * channel, uint32 length); +void channel_send(STREAM s, VCHANNEL * channel); +void channel_process(STREAM s, uint16 mcs_channel); +/* cliprdr.c */ +void cliprdr_send_text_format_announce(void); +void cliprdr_send_blah_format_announce(void); +void cliprdr_send_native_format_announce(uint8 * data, uint32 length); +void cliprdr_send_data_request(uint32 format); +void cliprdr_send_data(uint8 * data, uint32 length); +BOOL cliprdr_init(void); +/* ewmhints.c */ +int get_current_workarea(uint32 * x, uint32 * y, uint32 * width, uint32 * height); +/* iso.c */ +STREAM iso_init(int length); +void iso_send(STREAM s); +STREAM iso_recv(void); +BOOL iso_connect(char *server, char *username); +void iso_disconnect(void); +/* licence.c */ +void licence_process(STREAM s); +/* mcs.c */ +STREAM mcs_init(int length); +void mcs_send_to_channel(STREAM s, uint16 channel); +void mcs_send(STREAM s); +STREAM mcs_recv(uint16 * channel); +BOOL mcs_connect(char *server, STREAM mcs_data, char *username); +void mcs_disconnect(void); +/* orders.c */ +void process_orders(STREAM s, uint16 num_orders); +void reset_order_state(void); +/* printer.c */ +/* rdesktop.c */ +int main(int argc, char *argv[]); +void generate_random(uint8 * random); +void *xmalloc(int size); +void *xrealloc(void *oldmem, int size); +void xfree(void *mem); +void error(char *format, ...); +void warning(char *format, ...); +void unimpl(char *format, ...); +void hexdump(unsigned char *p, int len); +int load_licence(unsigned char **data); +void save_licence(unsigned char *data, int length); +/* rdp5.c */ +void rdp5_process(STREAM s, BOOL encryption); +/* rdp.c */ +void rdp_out_unistr(STREAM s, char *string, int len); +void rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, + uint16 param2); +void process_colour_pointer_pdu(STREAM s); +void process_cached_pointer_pdu(STREAM s); +void process_system_pointer_pdu(STREAM s); +void process_bitmap_updates(STREAM s); +void process_palette(STREAM s); +BOOL rdp_main_loop(void); +BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, char *command, + char *directory); +void rdp_disconnect(void); +/* rdpdr.c */ +void rdpdr_send_connect(void); +void rdpdr_send_name(void); +void rdpdr_send_available(void); +void rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, uint8 * buffer, + uint32 length); +BOOL rdpdr_init(void); +/* rdpsnd.c */ +STREAM rdpsnd_init_packet(uint16 type, uint16 size); +void rdpsnd_send(STREAM s); +void rdpsnd_send_completion(uint16 tick, uint8 packet_index); +void rdpsnd_process_negotiate(STREAM in); +void rdpsnd_process_unknown6(STREAM in); +void rdpsnd_process(STREAM s); +BOOL rdpsnd_init(void); +/* rdpsnd_oss.c */ +BOOL wave_out_open(void); +void wave_out_close(void); +BOOL wave_out_format_supported(WAVEFORMATEX * pwfx); +BOOL wave_out_set_format(WAVEFORMATEX * pwfx); +void wave_out_volume(uint16 left, uint16 right); +void wave_out_write(STREAM s, uint16 tick, uint8 index); +void wave_out_play(void); +/* secure.c */ +void sec_hash_48(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2, uint8 salt); +void sec_hash_16(uint8 * out, uint8 * in, uint8 * salt1, uint8 * salt2); +void buf_out_uint32(uint8 * buffer, uint32 value); +void sec_sign(uint8 * signature, int siglen, uint8 * session_key, int keylen, uint8 * data, + int datalen); +void sec_decrypt(uint8 * data, int length); +STREAM sec_init(uint32 flags, int maxlen); +void sec_send_to_channel(STREAM s, uint32 flags, uint16 channel); +void sec_send(STREAM s, uint32 flags); +void sec_process_mcs_data(STREAM s); +STREAM sec_recv(void); +BOOL sec_connect(char *server, char *username); +void sec_disconnect(void); +/* serial.c */ +/* tcp.c */ +STREAM tcp_init(uint32 maxlen); +void tcp_send(STREAM s); +STREAM tcp_recv(STREAM s, uint32 length); +BOOL tcp_connect(char *server); +void tcp_disconnect(void); +/* xclip.c */ +void ui_clip_format_announce(uint8 * data, uint32 length); +void ui_clip_handle_data(uint8 * data, uint32 length); +void ui_clip_request_data(uint32 format); +void ui_clip_sync(void); +void xclip_init(void); +/* xkeymap.c */ +void xkeymap_init(void); +BOOL handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed); +key_translation xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state); +uint16 xkeymap_translate_button(unsigned int button); +char *get_ksname(uint32 keysym); +void save_remote_modifiers(uint8 scancode); +void restore_remote_modifiers(uint32 ev_time, uint8 scancode); +void ensure_remote_modifiers(uint32 ev_time, key_translation tr); +unsigned int read_keyboard_state(void); +uint16 ui_get_numlock_state(unsigned int state); +void reset_modifier_keys(void); +void rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode); +/* xwin.c */ +BOOL get_key_state(unsigned int state, uint32 keysym); +BOOL ui_init(void); +void ui_deinit(void); +BOOL ui_create_window(void); +void ui_destroy_window(void); +void xwin_toggle_fullscreen(void); +int ui_select(int rdp_socket); +void ui_move_pointer(int x, int y); +HBITMAP ui_create_bitmap(int width, int height, uint8 * data); +void ui_paint_bitmap(int x, int y, int cx, int cy, int width, int height, uint8 * data); +void ui_destroy_bitmap(HBITMAP bmp); +HGLYPH ui_create_glyph(int width, int height, uint8 * data); +void ui_destroy_glyph(HGLYPH glyph); +HCURSOR ui_create_cursor(unsigned int x, unsigned int y, int width, int height, uint8 * andmask, + uint8 * xormask); +void ui_set_cursor(HCURSOR cursor); +void ui_destroy_cursor(HCURSOR cursor); +void ui_set_null_cursor(void); +HCOLOURMAP ui_create_colourmap(COLOURMAP * colours); +void ui_destroy_colourmap(HCOLOURMAP map); +void ui_set_colourmap(HCOLOURMAP map); +void ui_set_clip(int x, int y, int cx, int cy); +void ui_reset_clip(void); +void ui_bell(void); +void ui_destblt(uint8 opcode, int x, int y, int cx, int cy); +void ui_patblt(uint8 opcode, int x, int y, int cx, int cy, BRUSH * brush, int bgcolour, + int fgcolour); +void ui_screenblt(uint8 opcode, int x, int y, int cx, int cy, int srcx, int srcy); +void ui_memblt(uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy); +void ui_triblt(uint8 opcode, int x, int y, int cx, int cy, HBITMAP src, int srcx, int srcy, + BRUSH * brush, int bgcolour, int fgcolour); +void ui_line(uint8 opcode, int startx, int starty, int endx, int endy, PEN * pen); +void ui_rect(int x, int y, int cx, int cy, int colour); +void ui_draw_glyph(int mixmode, int x, int y, int cx, int cy, HGLYPH glyph, int srcx, int srcy, + int bgcolour, int fgcolour); +void ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y, int clipx, int clipy, + int clipcx, int clipcy, int boxx, int boxy, int boxcx, int boxcy, int bgcolour, + int fgcolour, uint8 * text, uint8 length); +void ui_desktop_save(uint32 offset, int x, int y, int cx, int cy); +void ui_desktop_restore(uint32 offset, int x, int y, int cx, int cy); diff --git a/rdesktop.h b/rdesktop.h new file mode 100644 index 0000000..3aa8982 --- /dev/null +++ b/rdesktop.h @@ -0,0 +1,68 @@ +/* + rdesktop: A Remote Desktop Protocol client. + Master include file + Copyright (C) Matthew Chapman 1999-2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#define VERSION "1.3.1" + +#define WITH_DEBUG 1 +#define WITH_DEBUG_RDP5 1 + +#ifdef WITH_DEBUG +#define DEBUG(args) printf args; +#else +#define DEBUG(args) +#endif + +#ifdef WITH_DEBUG_KBD +#define DEBUG_KBD(args) printf args; +#else +#define DEBUG_KBD(args) +#endif + +#ifdef WITH_DEBUG_RDP5 +#define DEBUG_RDP5(args) printf args; +#else +#define DEBUG_RDP5(args) +#endif + +#ifdef WITH_DEBUG_CLIPBOARD +#define DEBUG_CLIPBOARD(args) printf args; +#else +#define DEBUG_CLIPBOARD(args) +#endif + +#define STRNCPY(dst,src,n) { strncpy(dst,src,n-1); dst[n-1] = 0; } +#ifndef MIN +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#endif +#ifndef MAX +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#endif + +#include "parse.h" +#include "constants.h" +#include "types.h" + +#ifndef MAKE_PROTO +#include "proto.h" +#endif diff --git a/tcp.c b/tcp.c new file mode 100644 index 0000000..4e11422 --- /dev/null +++ b/tcp.c @@ -0,0 +1,232 @@ +/* + rdesktop: A Remote Desktop Protocol client. + Protocol services - TCP layer + Copyright (C) Matthew Chapman 1999-2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include /* select read write close */ +#include /* socket connect setsockopt */ +#include /* timeval */ +#include /* gethostbyname */ +#include /* sockaddr_in */ +#include /* TCP_NODELAY */ +#include /* inet_addr */ +#include /* errno */ +#include "rdesktop.h" + +#ifndef INADDR_NONE +#define INADDR_NONE ((unsigned long) -1) +#endif + +static int sock; +static struct stream in; +static struct stream out; +extern int tcp_port_rdp; + +/* Initialise TCP transport data packet */ +STREAM +tcp_init(uint32 maxlen) +{ + if (maxlen > out.size) + { + out.data = (uint8 *) xrealloc(out.data, maxlen); + out.size = maxlen; + } + + out.p = out.data; + out.end = out.data + out.size; + return &out; +} + +/* Send TCP transport data packet */ +void +tcp_send(STREAM s) +{ + int length = s->end - s->data; + int sent, total = 0; + + while (total < length) + { + sent = send(sock, s->data + total, length - total, 0); + if (sent <= 0) + { + error("send: %s\n", strerror(errno)); + return; + } + + total += sent; + } +} + +/* Receive a message on the TCP layer */ +STREAM +tcp_recv(STREAM s, uint32 length) +{ + unsigned int new_length, end_offset, p_offset; + int rcvd = 0; + + if (s == NULL) + { + /* read into "new" stream */ + if (length > in.size) + { + in.data = (uint8 *) xrealloc(in.data, length); + in.size = length; + } + in.end = in.p = in.data; + s = ∈ + } + else + { + /* append to existing stream */ + new_length = (s->end - s->data) + length; + if (new_length > s->size) + { + p_offset = s->p - s->data; + end_offset = s->end - s->data; + s->data = (uint8 *) xrealloc(s->data, new_length); + s->size = new_length; + s->p = s->data + p_offset; + s->end = s->data + end_offset; + } + } + + while (length > 0) + { +#if 0 + if (!ui_select(sock)) + /* User quit */ + return NULL; +#endif + + rcvd = recv(sock, s->end, length, 0); + if (rcvd < 0) + { + error("recv: %s\n", strerror(errno)); + return NULL; + } + else if (rcvd == 0) + { + error("Connection closed\n"); + return NULL; + } + + s->end += rcvd; + length -= rcvd; + } + + return s; +} + +/* Establish a connection on the TCP layer */ +BOOL +tcp_connect(char *server) +{ + int true_value = 1; + +#ifdef IPv6 + + int n; + struct addrinfo hints, *res, *ressave; + char tcp_port_rdp_s[10]; + + snprintf(tcp_port_rdp_s, 10, "%d", tcp_port_rdp); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + n = getaddrinfo(server, tcp_port_rdp_s, &hints, &res); + + if (n < 0) + { + error("getaddrinfo: %s\n", gai_strerror(n)); + return False; + } + + ressave = res; + sock = -1; + while (res) + { + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (!(sock < 0)) + { + if (connect(sock, res->ai_addr, res->ai_addrlen) == 0) + break; + close(sock); + sock = -1; + } + res = res->ai_next; + } + freeaddrinfo(ressave); + + if (sock == -1) + { + error("%s: unable to connect\n", server); + return False; + } + +#else /* no IPv6 support */ + + struct hostent *nslookup; + struct sockaddr_in servaddr; + + if ((nslookup = gethostbyname(server)) != NULL) + { + memcpy(&servaddr.sin_addr, nslookup->h_addr, sizeof(servaddr.sin_addr)); + } + else if ((servaddr.sin_addr.s_addr = inet_addr(server)) == INADDR_NONE) + { + error("%s: unable to resolve host\n", server); + return False; + } + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + error("socket: %s\n", strerror(errno)); + return False; + } + + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(tcp_port_rdp); + + if (connect(sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0) + { + error("connect: %s\n", strerror(errno)); + close(sock); + return False; + } + +#endif /* IPv6 */ + + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &true_value, sizeof(true_value)); + + in.size = 4096; + in.data = (uint8 *) xmalloc(in.size); + + out.size = 4096; + out.data = (uint8 *) xmalloc(out.size); + + return True; +} + +/* Disconnect on the TCP layer */ +void +tcp_disconnect(void) +{ + close(sock); +} diff --git a/types.h b/types.h new file mode 100644 index 0000000..ac038e3 --- /dev/null +++ b/types.h @@ -0,0 +1,149 @@ +/* + rdesktop: A Remote Desktop Protocol client. + Common data types + Copyright (C) Matthew Chapman 1999-2002 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +typedef int BOOL; + +#ifndef True +#define True (1) +#define False (0) +#endif + +typedef unsigned char uint8; +typedef signed char sint8; +typedef unsigned short uint16; +typedef signed short sint16; +typedef unsigned int uint32; +typedef signed int sint32; + +typedef void *HBITMAP; +typedef void *HGLYPH; +typedef void *HCOLOURMAP; +typedef void *HCURSOR; + +typedef struct _COLOURENTRY +{ + uint8 red; + uint8 green; + uint8 blue; + +} +COLOURENTRY; + +typedef struct _COLOURMAP +{ + uint16 ncolours; + COLOURENTRY *colours; + +} +COLOURMAP; + +typedef struct _BOUNDS +{ + sint16 left; + sint16 top; + sint16 right; + sint16 bottom; + +} +BOUNDS; + +typedef struct _PEN +{ + uint8 style; + uint8 width; + uint32 colour; + +} +PEN; + +typedef struct _BRUSH +{ + uint8 xorigin; + uint8 yorigin; + uint8 style; + uint8 pattern[8]; + +} +BRUSH; + +typedef struct _FONTGLYPH +{ + sint16 offset; + sint16 baseline; + uint16 width; + uint16 height; + HBITMAP pixmap; + +} +FONTGLYPH; + +typedef struct _DATABLOB +{ + void *data; + int size; + +} +DATABLOB; + +typedef struct _key_translation +{ + uint8 scancode; + uint16 modifiers; +} +key_translation; + +typedef struct _VCHANNEL +{ + uint16 mcs_id; + char name[8]; + uint32 flags; + struct stream in; + void (*process) (STREAM); +} +VCHANNEL; + +#define MAX_CBSIZE 256 + +/* RDPSND */ +typedef struct +{ + uint16 wFormatTag; + uint16 nChannels; + uint32 nSamplesPerSec; + uint32 nAvgBytesPerSec; + uint16 nBlockAlign; + uint16 wBitsPerSample; + uint16 cbSize; + uint8 cb[MAX_CBSIZE]; +} WAVEFORMATEX; + +/* RDPDR */ +typedef uint32 NTSTATUS; +typedef uint32 HANDLE; + +typedef struct _DEVICE_FNS +{ + NTSTATUS(*create) (HANDLE * handle); + NTSTATUS(*close) (HANDLE handle); + NTSTATUS(*read) (HANDLE handle, uint8 * data, uint32 length, uint32 * result); + NTSTATUS(*write) (HANDLE handle, uint8 * data, uint32 length, uint32 * result); + NTSTATUS(*device_control) (HANDLE handle, uint32 request, STREAM in, STREAM out); +} +DEVICE_FNS; diff --git a/util.c b/util.c new file mode 100644 index 0000000..2376a61 --- /dev/null +++ b/util.c @@ -0,0 +1,178 @@ +/* -*- c-basic-offset: 8 -*- + rdesktop: A Remote Desktop Protocol client. + Entrypoint and utility functions + Copyright (C) Matthew Chapman 1999-2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include /* va_list va_start va_end */ +#include /* read close getuid getgid getpid getppid gethostname */ +#include /* open */ +#include /* getpwuid */ +#include /* tcgetattr tcsetattr */ +#include /* stat */ +#include /* gettimeofday */ +#include /* times */ +#include +#include /* Window */ +#include "rdesktop.h" + +#ifdef EGD_SOCKET +#include /* socket connect */ +#include /* sockaddr_un */ +#endif + +#include + +#ifdef EGD_SOCKET +/* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */ +static BOOL +generate_random_egd(uint8 * buf) +{ + struct sockaddr_un addr; + BOOL ret = False; + int fd; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + return False; + + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET)); + if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) + goto err; + + /* PRNGD and EGD use a simple communications protocol */ + buf[0] = 1; /* Non-blocking (similar to /dev/urandom) */ + buf[1] = 32; /* Number of requested random bytes */ + if (write(fd, buf, 2) != 2) + goto err; + + if ((read(fd, buf, 1) != 1) || (buf[0] == 0)) /* Available? */ + goto err; + + if (read(fd, buf, 32) != 32) + goto err; + + ret = True; + + err: + close(fd); + return ret; +} +#endif + +/* malloc; exit if out of memory */ +void * +xmalloc(int size) +{ + void *mem = malloc(size); + if (mem == NULL) + { + error("xmalloc %d\n", size); + exit(1); + } + return mem; +} + +/* realloc; exit if out of memory */ +void * +xrealloc(void *oldmem, int size) +{ + void *mem = realloc(oldmem, size); + if (mem == NULL) + { + error("xrealloc %d\n", size); + exit(1); + } + return mem; +} + +/* free */ +void +xfree(void *mem) +{ + free(mem); +} + +/* report an error */ +void +error(char *format, ...) +{ + va_list ap; + + fprintf(stderr, "ERROR: "); + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); +} + +/* report a warning */ +void +warning(char *format, ...) +{ + va_list ap; + + fprintf(stderr, "WARNING: "); + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); +} + +/* report an unimplemented protocol feature */ +void +unimpl(char *format, ...) +{ + va_list ap; + + fprintf(stderr, "NOT IMPLEMENTED: "); + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); +} + +/* produce a hex dump */ +void +hexdump(unsigned char *p, int len) +{ + unsigned char *line = p; + int i, thisline, offset = 0; + + while (offset < len) + { + printf("%04x ", offset); + thisline = len - offset; + if (thisline > 16) + thisline = 16; + + for (i = 0; i < thisline; i++) + printf("%02x ", line[i]); + + for (; i < 16; i++) + printf(" "); + + for (i = 0; i < thisline; i++) + printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + + printf("\n"); + offset += thisline; + line += thisline; + } +} +