diff options
Diffstat (limited to 'rdp')
| -rw-r--r-- | rdp/rdp.c | 539 | ||||
| -rw-r--r-- | rdp/rdp.h | 42 | ||||
| -rw-r--r-- | rdp/rdp_bitmap.c | 1743 | ||||
| -rw-r--r-- | rdp/rdp_iso.c | 350 | ||||
| -rw-r--r-- | rdp/rdp_lic.c | 577 | ||||
| -rw-r--r-- | rdp/rdp_mcs.c | 922 | ||||
| -rw-r--r-- | rdp/rdp_orders.c | 2830 | ||||
| -rw-r--r-- | rdp/rdp_rdp.c | 1770 | ||||
| -rw-r--r-- | rdp/rdp_sec.c | 1082 | ||||
| -rw-r--r-- | rdp/rdp_tcp.c | 260 |
10 files changed, 5303 insertions, 4812 deletions
@@ -1,333 +1,352 @@ -/* - 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. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - librdp main file - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * librdp main file + */ #include "rdp.h" /******************************************************************************/ /* return error */ int DEFAULT_CC -lib_mod_start(struct mod* mod, int w, int h, int bpp) +lib_mod_start(struct mod *mod, int w, int h, int bpp) { - DEBUG(("in lib_mod_start")); - mod->width = w; - mod->height = h; - mod->rdp_bpp = bpp; - mod->xrdp_bpp = bpp; - mod->keylayout = 0x409; - g_strncpy(mod->port, "3389", 255); /* default */ - DEBUG(("out lib_mod_start")); - return 0; + DEBUG(("in lib_mod_start")); + mod->width = w; + mod->height = h; + mod->rdp_bpp = bpp; + mod->xrdp_bpp = bpp; + mod->keylayout = 0x409; + g_strncpy(mod->port, "3389", 255); /* default */ + DEBUG(("out lib_mod_start")); + return 0; } /******************************************************************************/ /* return error */ int DEFAULT_CC -lib_mod_connect(struct mod* mod) +lib_mod_connect(struct mod *mod) { - DEBUG(("in lib_mod_connect")); - /* clear screen */ - mod->server_begin_update(mod); - mod->server_set_fgcolor(mod, 0); - mod->server_fill_rect(mod, 0, 0, mod->width, mod->height); - mod->server_end_update(mod); - /* connect */ - if (rdp_rdp_connect(mod->rdp_layer, mod->ip, mod->port) == 0) - { - mod->sck = mod->rdp_layer->sec_layer->mcs_layer->iso_layer->tcp_layer->sck; - g_tcp_set_non_blocking(mod->sck); - g_tcp_set_no_delay(mod->sck); - mod->sck_obj = g_create_wait_obj_from_socket(mod->sck, 0); - DEBUG(("out lib_mod_connect")); - return 0; - } - DEBUG(("out lib_mod_connect error")); - return 1; + DEBUG(("in lib_mod_connect")); + /* clear screen */ + mod->server_begin_update(mod); + mod->server_set_fgcolor(mod, 0); + mod->server_fill_rect(mod, 0, 0, mod->width, mod->height); + mod->server_end_update(mod); + + /* connect */ + if (rdp_rdp_connect(mod->rdp_layer, mod->ip, mod->port) == 0) + { + mod->sck = mod->rdp_layer->sec_layer->mcs_layer->iso_layer->tcp_layer->sck; + g_tcp_set_non_blocking(mod->sck); + g_tcp_set_no_delay(mod->sck); + mod->sck_obj = g_create_wait_obj_from_socket(mod->sck, 0); + DEBUG(("out lib_mod_connect")); + return 0; + } + + DEBUG(("out lib_mod_connect error")); + return 1; } /******************************************************************************/ /* return error */ int DEFAULT_CC -lib_mod_event(struct mod* mod, int msg, long param1, long param2, +lib_mod_event(struct mod *mod, int msg, long param1, long param2, long param3, long param4) { - struct stream* s; + struct stream *s; + + if (!mod->up_and_running) + { + return 0; + } + + DEBUG(("in lib_mod_event")); + make_stream(s); + init_stream(s, 8192 * 2); - if (!mod->up_and_running) - { + switch (msg) + { + case 15: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_SCANCODE, + param4, param3, 0); + break; + case 16: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_SCANCODE, + param4, param3, 0); + break; + case 17: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_SYNCHRONIZE, + param4, param3, 0); + break; + case 100: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_MOVE, param1, param2); + break; + case 101: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_BUTTON1, param1, param2); + break; + case 102: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_BUTTON1 | MOUSE_FLAG_DOWN, + param1, param2); + break; + case 103: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_BUTTON2, param1, param2); + break; + case 104: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_BUTTON2 | MOUSE_FLAG_DOWN, + param1, param2); + break; + case 105: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_BUTTON3, param1, param2); + break; + case 106: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_BUTTON3 | MOUSE_FLAG_DOWN, + param1, param2); + break; + case 107: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_BUTTON4, param1, param2); + break; + case 108: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_BUTTON4 | MOUSE_FLAG_DOWN, + param1, param2); + break; + case 109: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_BUTTON5, param1, param2); + break; + case 110: + rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, + MOUSE_FLAG_BUTTON5 | MOUSE_FLAG_DOWN, + param1, param2); + break; + case 200: + rdp_rdp_send_invalidate(mod->rdp_layer, s, + (param1 >> 16) & 0xffff, param1 & 0xffff, + (param2 >> 16) & 0xffff, param2 & 0xffff); + break; + } + + free_stream(s); + DEBUG(("out lib_mod_event")); return 0; - } - DEBUG(("in lib_mod_event")); - make_stream(s); - init_stream(s, 8192 * 2); - switch (msg) - { - case 15: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_SCANCODE, - param4, param3, 0); - break; - case 16: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_SCANCODE, - param4, param3, 0); - break; - case 17: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_SYNCHRONIZE, - param4, param3, 0); - break; - case 100: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_MOVE, param1, param2); - break; - case 101: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_BUTTON1, param1, param2); - break; - case 102: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_BUTTON1 | MOUSE_FLAG_DOWN, - param1, param2); - break; - case 103: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_BUTTON2, param1, param2); - break; - case 104: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_BUTTON2 | MOUSE_FLAG_DOWN, - param1, param2); - break; - case 105: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_BUTTON3, param1, param2); - break; - case 106: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_BUTTON3 | MOUSE_FLAG_DOWN, - param1, param2); - break; - case 107: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_BUTTON4, param1, param2); - break; - case 108: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_BUTTON4 | MOUSE_FLAG_DOWN, - param1, param2); - break; - case 109: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_BUTTON5, param1, param2); - break; - case 110: - rdp_rdp_send_input(mod->rdp_layer, s, 0, RDP_INPUT_MOUSE, - MOUSE_FLAG_BUTTON5 | MOUSE_FLAG_DOWN, - param1, param2); - break; - case 200: - rdp_rdp_send_invalidate(mod->rdp_layer, s, - (param1 >> 16) & 0xffff, param1 & 0xffff, - (param2 >> 16) & 0xffff, param2 & 0xffff); - break; - } - free_stream(s); - DEBUG(("out lib_mod_event")); - return 0; } /******************************************************************************/ /* return error */ int DEFAULT_CC -lib_mod_signal(struct mod* mod) +lib_mod_signal(struct mod *mod) { - int type; - int cont; - struct stream* s; - - DEBUG(("in lib_mod_signal")); - if (mod->in_s == 0) - { - make_stream(mod->in_s); - } - s = mod->in_s; - init_stream(s, 8192 * 2); - cont = 1; - while (cont) - { - type = 0; - if (rdp_rdp_recv(mod->rdp_layer, s, &type) != 0) + int type; + int cont; + struct stream *s; + + DEBUG(("in lib_mod_signal")); + + if (mod->in_s == 0) { - DEBUG(("out lib_mod_signal error rdp_rdp_recv failed")); - return 1; + make_stream(mod->in_s); } - DEBUG(("lib_mod_signal type %d", type)); - switch (type) + + s = mod->in_s; + init_stream(s, 8192 * 2); + cont = 1; + + while (cont) { - case RDP_PDU_DATA: - rdp_rdp_process_data_pdu(mod->rdp_layer, s); - break; - case RDP_PDU_DEMAND_ACTIVE: - rdp_rdp_process_demand_active(mod->rdp_layer, s); - mod->up_and_running = 1; - break; - case RDP_PDU_DEACTIVATE: - mod->up_and_running = 0; - break; - case RDP_PDU_REDIRECT: - break; - case 0: - break; - default: - break; + type = 0; + + if (rdp_rdp_recv(mod->rdp_layer, s, &type) != 0) + { + DEBUG(("out lib_mod_signal error rdp_rdp_recv failed")); + return 1; + } + + DEBUG(("lib_mod_signal type %d", type)); + + switch (type) + { + case RDP_PDU_DATA: + rdp_rdp_process_data_pdu(mod->rdp_layer, s); + break; + case RDP_PDU_DEMAND_ACTIVE: + rdp_rdp_process_demand_active(mod->rdp_layer, s); + mod->up_and_running = 1; + break; + case RDP_PDU_DEACTIVATE: + mod->up_and_running = 0; + break; + case RDP_PDU_REDIRECT: + break; + case 0: + break; + default: + break; + } + + cont = s->next_packet < s->end; } - cont = s->next_packet < s->end; - } - DEBUG(("out lib_mod_signal")); - return 0; + + DEBUG(("out lib_mod_signal")); + return 0; } /******************************************************************************/ /* return error */ int DEFAULT_CC -lib_mod_end(struct mod* mod) +lib_mod_end(struct mod *mod) { - rdp_rdp_delete(mod->rdp_layer); - mod->rdp_layer = 0; - free_stream(mod->in_s); - mod->in_s = 0; - if (mod->sck_obj != 0) - { - g_delete_wait_obj_from_socket(mod->sck_obj); - mod->sck_obj = 0; - } - if (mod->sck != 0) - { - g_tcp_close(mod->sck); - mod->sck = 0; - } - return 0; + rdp_rdp_delete(mod->rdp_layer); + mod->rdp_layer = 0; + free_stream(mod->in_s); + mod->in_s = 0; + + if (mod->sck_obj != 0) + { + g_delete_wait_obj_from_socket(mod->sck_obj); + mod->sck_obj = 0; + } + + if (mod->sck != 0) + { + g_tcp_close(mod->sck); + mod->sck = 0; + } + + return 0; } /******************************************************************************/ /* return error */ int DEFAULT_CC -lib_mod_set_param(struct mod* mod, char* name, char* value) +lib_mod_set_param(struct mod *mod, char *name, char *value) { - if (g_strncasecmp(name, "ip", 255) == 0) - { - g_strncpy(mod->ip, value, 255); - } - else if (g_strncasecmp(name, "port", 255) == 0) - { - g_strncpy(mod->port, value, 255); - } - else if (g_strncasecmp(name, "username", 255) == 0) - { - g_strncpy(mod->username, value, 255); - } - else if (g_strncasecmp(name, "password", 255) == 0) - { - g_strncpy(mod->password, value, 255); - } - else if (g_strncasecmp(name, "hostname", 255) == 0) - { - g_strncpy(mod->hostname, value, 255); - } - else if (g_strncasecmp(name, "keylayout", 255) == 0) - { - mod->keylayout = g_atoi(value); - } - return 0; + if (g_strncasecmp(name, "ip", 255) == 0) + { + g_strncpy(mod->ip, value, 255); + } + else if (g_strncasecmp(name, "port", 255) == 0) + { + g_strncpy(mod->port, value, 255); + } + else if (g_strncasecmp(name, "username", 255) == 0) + { + g_strncpy(mod->username, value, 255); + } + else if (g_strncasecmp(name, "password", 255) == 0) + { + g_strncpy(mod->password, value, 255); + } + else if (g_strncasecmp(name, "hostname", 255) == 0) + { + g_strncpy(mod->hostname, value, 255); + } + else if (g_strncasecmp(name, "keylayout", 255) == 0) + { + mod->keylayout = g_atoi(value); + } + + return 0; } /******************************************************************************/ /* return error */ int DEFAULT_CC -lib_mod_get_wait_objs(struct mod* mod, tbus* read_objs, int* rcount, - tbus* write_objs, int* wcount, int* timeout) +lib_mod_get_wait_objs(struct mod *mod, tbus *read_objs, int *rcount, + tbus *write_objs, int *wcount, int *timeout) { - int i; + int i; - i = *rcount; - if (mod != 0) - { - if (mod->sck_obj != 0) + i = *rcount; + + if (mod != 0) { - read_objs[i++] = mod->sck_obj; + if (mod->sck_obj != 0) + { + read_objs[i++] = mod->sck_obj; + } } - } - *rcount = i; - return 0; + + *rcount = i; + return 0; } /******************************************************************************/ /* return error */ int DEFAULT_CC -lib_mod_check_wait_objs(struct mod* mod) +lib_mod_check_wait_objs(struct mod *mod) { - int rv; + int rv; - rv = 0; - if (mod != 0) - { - if (mod->sck_obj != 0) + rv = 0; + + if (mod != 0) { - if (g_is_wait_obj_set(mod->sck_obj)) - { - rv = lib_mod_signal(mod); - } + if (mod->sck_obj != 0) + { + if (g_is_wait_obj_set(mod->sck_obj)) + { + rv = lib_mod_signal(mod); + } + } } - } - return rv; + + return rv; } /******************************************************************************/ -struct mod* EXPORT_CC +struct mod *EXPORT_CC mod_init(void) { - struct mod* mod; - - DEBUG(("in mod_init")); - mod = (struct mod*)g_malloc(sizeof(struct mod), 1); - mod->size = sizeof(struct mod); - mod->version = CURRENT_MOD_VER; - mod->handle = (long)mod; - mod->mod_connect = lib_mod_connect; - mod->mod_start = lib_mod_start; - mod->mod_event = lib_mod_event; - mod->mod_signal = lib_mod_signal; - mod->mod_end = lib_mod_end; - mod->mod_set_param = lib_mod_set_param; - mod->mod_get_wait_objs = lib_mod_get_wait_objs; - mod->mod_check_wait_objs = lib_mod_check_wait_objs; - mod->rdp_layer = rdp_rdp_create(mod); - DEBUG(("out mod_init")); - return mod; + struct mod *mod; + + DEBUG(("in mod_init")); + mod = (struct mod *)g_malloc(sizeof(struct mod), 1); + mod->size = sizeof(struct mod); + mod->version = CURRENT_MOD_VER; + mod->handle = (long)mod; + mod->mod_connect = lib_mod_connect; + mod->mod_start = lib_mod_start; + mod->mod_event = lib_mod_event; + mod->mod_signal = lib_mod_signal; + mod->mod_end = lib_mod_end; + mod->mod_set_param = lib_mod_set_param; + mod->mod_get_wait_objs = lib_mod_get_wait_objs; + mod->mod_check_wait_objs = lib_mod_check_wait_objs; + mod->rdp_layer = rdp_rdp_create(mod); + DEBUG(("out mod_init")); + return mod; } /******************************************************************************/ int EXPORT_CC -mod_exit(struct mod* mod) +mod_exit(struct mod *mod) { - DEBUG(("in mod_exit")); - g_free(mod); - DEBUG(("out mod_exit")); - return 0; + DEBUG(("in mod_exit")); + g_free(mod); + DEBUG(("out mod_exit")); + return 0; } @@ -1,24 +1,22 @@ -/* - 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. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - librdp main header file - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * librdp main header file + */ /* include other h files */ #include "arch.h" @@ -269,7 +267,7 @@ struct mod int (*mod_get_wait_objs)(struct mod* v, tbus* read_objs, int* rcount, tbus* write_objs, int* wcount, int* timeout); int (*mod_check_wait_objs)(struct mod* v); - long mod_dumby[100 - 9]; /* align, 100 minus the number of mod + long mod_dumby[100 - 9]; /* align, 100 minus the number of mod functions above */ /* server functions */ int (*server_begin_update)(struct mod* v); diff --git a/rdp/rdp_bitmap.c b/rdp/rdp_bitmap.c index f2d31dae..adba5f6f 100644 --- a/rdp/rdp_bitmap.c +++ b/rdp/rdp_bitmap.c @@ -1,24 +1,22 @@ -/* - 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. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - librdp bitmap routines - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * librdp bitmap routines + */ #include "rdp.h" @@ -35,891 +33,964 @@ /******************************************************************************/ #define REPEAT(statement) \ -{ \ - while ((count > 0) && (x < width)) \ - { \ - statement; \ - count--; \ - x++; \ - } \ -} + { \ + while ((count > 0) && (x < width)) \ + { \ + statement; \ + count--; \ + x++; \ + } \ + } /******************************************************************************/ #define MASK_UPDATE \ -{ \ - mixmask <<= 1; \ - if ((mixmask & 0xff) == 0) \ - { \ - mask = fom_mask ? fom_mask : CVAL(input); \ - mixmask = 1; \ - } \ -} + { \ + mixmask <<= 1; \ + if ((mixmask & 0xff) == 0) \ + { \ + mask = fom_mask ? fom_mask : CVAL(input); \ + mixmask = 1; \ + } \ + } /******************************************************************************/ /* 1 byte bitmap decompress */ /* returns boolean */ static int APP_CC -bitmap_decompress1(char* output, int width, int height, char* input, int size) +bitmap_decompress1(char *output, int width, int height, char *input, int size) { - char* prevline; - char* line; - char* end; - char color1; - char color2; - char mix; - int code; - int mixmask; - int mask; - int opcode; - int count; - int offset; - int isfillormix; - int x; - int lastopcode; - int insertmix; - int bicolor; - int fom_mask; - - end = input + size; - prevline = 0; - line = 0; - x = width; - lastopcode = -1; - insertmix = 0; - bicolor = 0; - color1 = 0; - color2 = 0; - mix = 0xff; - mask = 0; - fom_mask = 0; - - while (input < end) - { + char *prevline; + char *line; + char *end; + char color1; + char color2; + char mix; + int code; + int mixmask; + int mask; + int opcode; + int count; + int offset; + int isfillormix; + int x; + int lastopcode; + int insertmix; + int bicolor; + int fom_mask; + + end = input + size; + prevline = 0; + line = 0; + x = width; + lastopcode = -1; + insertmix = 0; + bicolor = 0; + color1 = 0; + color2 = 0; + mix = 0xff; + mask = 0; fom_mask = 0; - code = CVAL(input); - opcode = code >> 4; - /* Handle different opcode forms */ - switch (opcode) - { - case 0xc: - case 0xd: - case 0xe: - opcode -= 6; - count = code & 0xf; - offset = 16; - break; - case 0xf: - opcode = code & 0xf; - if (opcode < 9) - { - count = CVAL(input); - count |= CVAL(input) << 8; - } - else - { - count = (opcode < 0xb) ? 8 : 1; - } - offset = 0; - break; - default: - opcode >>= 1; - count = code & 0x1f; - offset = 32; - break; - } - /* Handle strange cases for counts */ - if (offset != 0) - { - isfillormix = ((opcode == 2) || (opcode == 7)); - if (count == 0) - { - if (isfillormix) - { - count = CVAL(input) + 1; - } - else - { - count = CVAL(input) + offset; - } - } - else if (isfillormix) - { - count <<= 3; - } - } - /* Read preliminary data */ - switch (opcode) + + while (input < end) { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + + /* Handle different opcode forms */ + switch (opcode) { - insertmix = 1; + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < 0xb) ? 8 : 1; + } + + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; } - break; - case 8: /* Bicolor */ - color1 = CVAL(input); - case 3: /* Color */ - color2 = CVAL(input); - break; - case 6: /* SetMix/Mix */ - case 7: /* SetMix/FillOrMix */ - mix = CVAL(input); - opcode -= 5; - break; - case 9: /* FillOrMix_1 */ - mask = 0x03; - opcode = 0x02; - fom_mask = 3; - break; - case 0x0a: /* FillOrMix_2 */ - mask = 0x05; - opcode = 0x02; - fom_mask = 5; - break; - } - lastopcode = opcode; - mixmask = 0; - /* Output body */ - while (count > 0) - { - if (x >= width) - { - if (height <= 0) + + /* Handle strange cases for counts */ + if (offset != 0) { - return 0; - } - x = 0; - height--; - prevline = line; - line = output + height * width; - } - switch (opcode) - { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == 0) + isfillormix = ((opcode == 2) || (opcode == 7)); + + if (count == 0) { - line[x] = mix; + if (isfillormix) + { + count = CVAL(input) + 1; + } + else + { + count = CVAL(input) + offset; + } } - else + else if (isfillormix) { - line[x] = prevline[x] ^ mix; + count <<= 3; } - insertmix = 0; - count--; - x++; - } - if (prevline == 0) - { - REPEAT(line[x] = 0) - } - else - { - REPEAT(line[x] = prevline[x]) - } - break; - case 1: /* Mix */ - if (prevline == 0) - { - REPEAT(line[x] = mix) - } - else - { - REPEAT(line[x] = prevline[x] ^ mix) - } - break; - case 2: /* Fill or Mix */ - if (prevline == 0) - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x] = mix; - } - else - { - line[x] = 0; - } - ) - } - else - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x] = prevline[x] ^ mix; - } - else - { - line[x] = prevline[x]; - } - ) - } - break; - case 3: /* Color */ - REPEAT(line[x] = color2) - break; - case 4: /* Copy */ - REPEAT(line[x] = CVAL(input)) - break; - case 8: /* Bicolor */ - REPEAT - ( - if (bicolor) + } + + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + + if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + { + insertmix = 1; + } + + break; + case 8: /* Bicolor */ + color1 = CVAL(input); + case 3: /* Color */ + color2 = CVAL(input); + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + mix = CVAL(input); + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + + lastopcode = opcode; + mixmask = 0; + + /* Output body */ + while (count > 0) + { + if (x >= width) { - line[x] = color2; - bicolor = 0; + if (height <= 0) + { + return 0; + } + + x = 0; + height--; + prevline = line; + line = output + height * width; } - else + + switch (opcode) { - line[x] = color1; - bicolor = 1; - count++; + case 0: /* Fill */ + + if (insertmix) + { + if (prevline == 0) + { + line[x] = mix; + } + else + { + line[x] = prevline[x] ^ mix; + } + + insertmix = 0; + count--; + x++; + } + + if (prevline == 0) + { + REPEAT(line[x] = 0) + } + else + { + REPEAT(line[x] = prevline[x]) + } + + break; + case 1: /* Mix */ + + if (prevline == 0) + { + REPEAT(line[x] = mix) + } + else + { + REPEAT(line[x] = prevline[x] ^ mix) + } + + break; + case 2: /* Fill or Mix */ + + if (prevline == 0) + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x] = mix; + } + else + { + line[x] = 0; + } + ) + } + else + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x] = prevline[x] ^ mix; + } + else + { + line[x] = prevline[x]; + } + ) + } + + break; + case 3: /* Color */ + REPEAT(line[x] = color2) + break; + case 4: /* Copy */ + REPEAT(line[x] = CVAL(input)) + break; + case 8: /* Bicolor */ + REPEAT + ( + + if (bicolor) + { + line[x] = color2; + bicolor = 0; + } + else + { + line[x] = color1; + bicolor = 1; + count++; + } + ) + break; + case 0xd: /* White */ + REPEAT(line[x] = 0xff) + break; + case 0xe: /* Black */ + REPEAT(line[x] = 0) + break; + default: + return 0; + break; } - ) - break; - case 0xd: /* White */ - REPEAT(line[x] = 0xff) - break; - case 0xe: /* Black */ - REPEAT(line[x] = 0) - break; - default: - return 0; - break; - } + } } - } - return 1; + + return 1; } /******************************************************************************/ /* 2 byte bitmap decompress */ /* returns boolean */ static int APP_CC -bitmap_decompress2(char* output, int width, int height, char* input, int size) +bitmap_decompress2(char *output, int width, int height, char *input, int size) { - char* prevline; - char* line; - char* end; - char color1[2]; - char color2[2]; - char mix[2]; - int code; - int mixmask; - int mask; - int opcode; - int count; - int offset; - int isfillormix; - int x; - int lastopcode; - int insertmix; - int bicolor; - int fom_mask; - - end = input + size; - prevline = 0; - line = 0; - x = width; - lastopcode = -1; - insertmix = 0; - bicolor = 0; - color1[0] = 0; - color1[1] = 0; - color2[0] = 0; - color2[1] = 0; - mix[0] = 0xff; - mix[1] = 0xff; - mask = 0; - fom_mask = 0; - - while (input < end) - { + char *prevline; + char *line; + char *end; + char color1[2]; + char color2[2]; + char mix[2]; + int code; + int mixmask; + int mask; + int opcode; + int count; + int offset; + int isfillormix; + int x; + int lastopcode; + int insertmix; + int bicolor; + int fom_mask; + + end = input + size; + prevline = 0; + line = 0; + x = width; + lastopcode = -1; + insertmix = 0; + bicolor = 0; + color1[0] = 0; + color1[1] = 0; + color2[0] = 0; + color2[1] = 0; + mix[0] = 0xff; + mix[1] = 0xff; + mask = 0; fom_mask = 0; - code = CVAL(input); - opcode = code >> 4; - /* Handle different opcode forms */ - switch (opcode) - { - case 0xc: - case 0xd: - case 0xe: - opcode -= 6; - count = code & 0xf; - offset = 16; - break; - case 0xf: - opcode = code & 0xf; - if (opcode < 9) - { - count = CVAL(input); - count |= CVAL(input) << 8; - } - else - { - count = (opcode < 0xb) ? 8 : 1; - } - offset = 0; - break; - default: - opcode >>= 1; - count = code & 0x1f; - offset = 32; - break; - } - /* Handle strange cases for counts */ - if (offset != 0) - { - isfillormix = ((opcode == 2) || (opcode == 7)); - if (count == 0) - { - if (isfillormix) - { - count = CVAL(input) + 1; - } - else - { - count = CVAL(input) + offset; - } - } - else if (isfillormix) - { - count <<= 3; - } - } - /* Read preliminary data */ - switch (opcode) + + while (input < end) { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + + /* Handle different opcode forms */ + switch (opcode) { - insertmix = 1; + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < 0xb) ? 8 : 1; + } + + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; } - break; - case 8: /* Bicolor */ - color1[EIK0] = CVAL(input); - color1[EIK1] = CVAL(input); - case 3: /* Color */ - color2[EIK0] = CVAL(input); - color2[EIK1] = CVAL(input); - break; - case 6: /* SetMix/Mix */ - case 7: /* SetMix/FillOrMix */ - mix[EIK0] = CVAL(input); - mix[EIK1] = CVAL(input); - opcode -= 5; - break; - case 9: /* FillOrMix_1 */ - mask = 0x03; - opcode = 0x02; - fom_mask = 3; - break; - case 0x0a: /* FillOrMix_2 */ - mask = 0x05; - opcode = 0x02; - fom_mask = 5; - break; - } - lastopcode = opcode; - mixmask = 0; - /* Output body */ - while (count > 0) - { - if (x >= width) - { - if (height <= 0) + + /* Handle strange cases for counts */ + if (offset != 0) { - return 0; - } - x = 0; - height--; - prevline = line; - line = output + height * (width * 2); - } - switch (opcode) - { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == 0) + isfillormix = ((opcode == 2) || (opcode == 7)); + + if (count == 0) { - line[x * 2 + 0] = mix[0]; - line[x * 2 + 1] = mix[1]; + if (isfillormix) + { + count = CVAL(input) + 1; + } + else + { + count = CVAL(input) + offset; + } } - else + else if (isfillormix) { - line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; - line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; + count <<= 3; } - insertmix = 0; - count--; - x++; - } - if (prevline == 0) - { - REPEAT - ( - line[x * 2 + 0] = 0; - line[x * 2 + 1] = 0; - ) - } - else - { - REPEAT - ( - line[x * 2 + 0] = prevline[x * 2 + 0]; - line[x * 2 + 1] = prevline[x * 2 + 1]; - ) - } - break; - case 1: /* Mix */ - if (prevline == 0) - { - REPEAT - ( - line[x * 2 + 0] = mix[0]; - line[x * 2 + 1] = mix[1]; - ) - } - else - { - REPEAT - ( - line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; - line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; - ) - } - break; - case 2: /* Fill or Mix */ - if (prevline == 0) - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x * 2 + 0] = mix[0]; - line[x * 2 + 1] = mix[1]; - } - else - { - line[x * 2 + 0] = 0; - line[x * 2 + 1] = 0; - } - ) - } - else - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; - line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; - } - else - { - line[x * 2 + 0] = prevline[x * 2 + 0]; - line[x * 2 + 1] = prevline[x * 2 + 1]; - } - ) - } - break; - case 3: /* Color */ - REPEAT - ( - line[x * 2 + 0] = color2[0]; - line[x * 2 + 1] = color2[1]; - ) - break; - case 4: /* Copy */ - REPEAT - ( - line[x * 2 + EIK0] = CVAL(input); - line[x * 2 + EIK1] = CVAL(input); - ) - break; - case 8: /* Bicolor */ - REPEAT - ( - if (bicolor) + } + + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + + if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + { + insertmix = 1; + } + + break; + case 8: /* Bicolor */ + color1[EIK0] = CVAL(input); + color1[EIK1] = CVAL(input); + case 3: /* Color */ + color2[EIK0] = CVAL(input); + color2[EIK1] = CVAL(input); + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + mix[EIK0] = CVAL(input); + mix[EIK1] = CVAL(input); + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + + lastopcode = opcode; + mixmask = 0; + + /* Output body */ + while (count > 0) + { + if (x >= width) { - line[x * 2 + 0] = color2[0]; - line[x * 2 + 1] = color2[1]; - bicolor = 0; + if (height <= 0) + { + return 0; + } + + x = 0; + height--; + prevline = line; + line = output + height * (width * 2); } - else + + switch (opcode) { - line[x * 2 + 0] = color1[0]; - line[x * 2 + 1] = color1[1]; - bicolor = 1; - count++; + case 0: /* Fill */ + + if (insertmix) + { + if (prevline == 0) + { + line[x * 2 + 0] = mix[0]; + line[x * 2 + 1] = mix[1]; + } + else + { + line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; + line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; + } + + insertmix = 0; + count--; + x++; + } + + if (prevline == 0) + { + REPEAT + ( + line[x * 2 + 0] = 0; + line[x * 2 + 1] = 0; + ) + } + else + { + REPEAT + ( + line[x * 2 + 0] = prevline[x * 2 + 0]; + line[x * 2 + 1] = prevline[x * 2 + 1]; + ) + } + + break; + case 1: /* Mix */ + + if (prevline == 0) + { + REPEAT + ( + line[x * 2 + 0] = mix[0]; + line[x * 2 + 1] = mix[1]; + ) + } + else + { + REPEAT + ( + line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; + line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; + ) + } + + break; + case 2: /* Fill or Mix */ + + if (prevline == 0) + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x * 2 + 0] = mix[0]; + line[x * 2 + 1] = mix[1]; + } + else + { + line[x * 2 + 0] = 0; + line[x * 2 + 1] = 0; + } + ) + } + else + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x * 2 + 0] = prevline[x * 2 + 0] ^ mix[0]; + line[x * 2 + 1] = prevline[x * 2 + 1] ^ mix[1]; + } + else + { + line[x * 2 + 0] = prevline[x * 2 + 0]; + line[x * 2 + 1] = prevline[x * 2 + 1]; + } + ) + } + + break; + case 3: /* Color */ + REPEAT + ( + line[x * 2 + 0] = color2[0]; + line[x * 2 + 1] = color2[1]; + ) + break; + case 4: /* Copy */ + REPEAT + ( + line[x * 2 + EIK0] = CVAL(input); + line[x * 2 + EIK1] = CVAL(input); + ) + break; + case 8: /* Bicolor */ + REPEAT + ( + + if (bicolor) + { + line[x * 2 + 0] = color2[0]; + line[x * 2 + 1] = color2[1]; + bicolor = 0; + } + else + { + line[x * 2 + 0] = color1[0]; + line[x * 2 + 1] = color1[1]; + bicolor = 1; + count++; + } + ) + break; + case 0xd: /* White */ + REPEAT + ( + line[x * 2 + 0] = 0xff; + line[x * 2 + 1] = 0xff; + ) + break; + case 0xe: /* Black */ + REPEAT + ( + line[x * 2 + 0] = 0; + line[x * 2 + 1] = 0; + ) + break; + default: + return 0; + break; } - ) - break; - case 0xd: /* White */ - REPEAT - ( - line[x * 2 + 0] = 0xff; - line[x * 2 + 1] = 0xff; - ) - break; - case 0xe: /* Black */ - REPEAT - ( - line[x * 2 + 0] = 0; - line[x * 2 + 1] = 0; - ) - break; - default: - return 0; - break; - } + } } - } - return 1; + + return 1; } /******************************************************************************/ /* 3 byte bitmap decompress */ /* returns boolean */ static int APP_CC -bitmap_decompress3(char* output, int width, int height, char* input, int size) +bitmap_decompress3(char *output, int width, int height, char *input, int size) { - char* prevline; - char* line; - char* end; - char color1[3]; - char color2[3]; - char mix[3]; - int code; - int mixmask; - int mask; - int opcode; - int count; - int offset; - int isfillormix; - int x; - int lastopcode; - int insertmix; - int bicolor; - int fom_mask; - - end = input + size; - prevline = 0; - line = 0; - x = width; - lastopcode = -1; - insertmix = 0; - bicolor = 0; - color1[0] = 0; - color1[1] = 0; - color1[2] = 0; - color2[0] = 0; - color2[1] = 0; - color2[2] = 0; - mix[0] = 0xff; - mix[1] = 0xff; - mix[2] = 0xff; - mask = 0; - fom_mask = 0; - - while (input < end) - { + char *prevline; + char *line; + char *end; + char color1[3]; + char color2[3]; + char mix[3]; + int code; + int mixmask; + int mask; + int opcode; + int count; + int offset; + int isfillormix; + int x; + int lastopcode; + int insertmix; + int bicolor; + int fom_mask; + + end = input + size; + prevline = 0; + line = 0; + x = width; + lastopcode = -1; + insertmix = 0; + bicolor = 0; + color1[0] = 0; + color1[1] = 0; + color1[2] = 0; + color2[0] = 0; + color2[1] = 0; + color2[2] = 0; + mix[0] = 0xff; + mix[1] = 0xff; + mix[2] = 0xff; + mask = 0; fom_mask = 0; - code = CVAL(input); - opcode = code >> 4; - /* Handle different opcode forms */ - switch (opcode) - { - case 0xc: - case 0xd: - case 0xe: - opcode -= 6; - count = code & 0xf; - offset = 16; - break; - case 0xf: - opcode = code & 0xf; - if (opcode < 9) - { - count = CVAL(input); - count |= CVAL(input) << 8; - } - else - { - count = (opcode < 0xb) ? 8 : 1; - } - offset = 0; - break; - default: - opcode >>= 1; - count = code & 0x1f; - offset = 32; - break; - } - /* Handle strange cases for counts */ - if (offset != 0) - { - isfillormix = ((opcode == 2) || (opcode == 7)); - if (count == 0) - { - if (isfillormix) - { - count = CVAL(input) + 1; - } - else - { - count = CVAL(input) + offset; - } - } - else if (isfillormix) - { - count <<= 3; - } - } - /* Read preliminary data */ - switch (opcode) + + while (input < end) { - case 0: /* Fill */ - if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + fom_mask = 0; + code = CVAL(input); + opcode = code >> 4; + + /* Handle different opcode forms */ + switch (opcode) { - insertmix = 1; + case 0xc: + case 0xd: + case 0xe: + opcode -= 6; + count = code & 0xf; + offset = 16; + break; + case 0xf: + opcode = code & 0xf; + + if (opcode < 9) + { + count = CVAL(input); + count |= CVAL(input) << 8; + } + else + { + count = (opcode < 0xb) ? 8 : 1; + } + + offset = 0; + break; + default: + opcode >>= 1; + count = code & 0x1f; + offset = 32; + break; } - break; - case 8: /* Bicolor */ - color1[0] = CVAL(input); - color1[1] = CVAL(input); - color1[2] = CVAL(input); - case 3: /* Color */ - color2[0] = CVAL(input); - color2[1] = CVAL(input); - color2[2] = CVAL(input); - break; - case 6: /* SetMix/Mix */ - case 7: /* SetMix/FillOrMix */ - mix[0] = CVAL(input); - mix[1] = CVAL(input); - mix[2] = CVAL(input); - opcode -= 5; - break; - case 9: /* FillOrMix_1 */ - mask = 0x03; - opcode = 0x02; - fom_mask = 3; - break; - case 0x0a: /* FillOrMix_2 */ - mask = 0x05; - opcode = 0x02; - fom_mask = 5; - break; - } - lastopcode = opcode; - mixmask = 0; - /* Output body */ - while (count > 0) - { - if (x >= width) - { - if (height <= 0) + + /* Handle strange cases for counts */ + if (offset != 0) { - return 0; - } - x = 0; - height--; - prevline = line; - line = output + height * (width * 3); - } - switch (opcode) - { - case 0: /* Fill */ - if (insertmix) - { - if (prevline == 0) + isfillormix = ((opcode == 2) || (opcode == 7)); + + if (count == 0) { - line[x * 3 + 0] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; + if (isfillormix) + { + count = CVAL(input) + 1; + } + else + { + count = CVAL(input) + offset; + } } - else + else if (isfillormix) { - line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; - line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; - line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; + count <<= 3; } - insertmix = 0; - count--; - x++; - } - if (prevline == 0) - { - REPEAT - ( - line[x * 3 + 0] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - ) - } - else - { - REPEAT - ( - line[x * 3 + 0] = prevline[x * 3 + 0]; - line[x * 3 + 1] = prevline[x * 3 + 1]; - line[x * 3 + 2] = prevline[x * 3 + 2]; - ) - } - break; - case 1: /* Mix */ - if (prevline == 0) - { - REPEAT - ( - line[x * 3 + 0] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; - ) - } - else - { - REPEAT - ( - line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; - line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; - line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; - ) - } - break; - case 2: /* Fill or Mix */ - if (prevline == 0) - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x * 3 + 0] = mix[0]; - line[x * 3 + 1] = mix[1]; - line[x * 3 + 2] = mix[2]; - } - else - { - line[x * 3 + 0] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - } - ) - } - else - { - REPEAT - ( - MASK_UPDATE; - if (mask & mixmask) - { - line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; - line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; - line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; - } - else - { - line[x * 3 + 0] = prevline[x * 3 + 0]; - line[x * 3 + 1] = prevline[x * 3 + 1]; - line[x * 3 + 2] = prevline[x * 3 + 2]; - } - ) - } - break; - case 3: /* Color */ - REPEAT - ( - line[x * 3 + 0] = color2[0]; - line[x * 3 + 1] = color2[1]; - line[x * 3 + 2] = color2[2]; - ) - break; - case 4: /* Copy */ - REPEAT - ( - line[x * 3 + 0] = CVAL(input); - line[x * 3 + 1] = CVAL(input); - line[x * 3 + 2] = CVAL(input); - ) - break; - case 8: /* Bicolor */ - REPEAT - ( - if (bicolor) + } + + /* Read preliminary data */ + switch (opcode) + { + case 0: /* Fill */ + + if ((lastopcode == opcode) && !((x == width) && (prevline == 0))) + { + insertmix = 1; + } + + break; + case 8: /* Bicolor */ + color1[0] = CVAL(input); + color1[1] = CVAL(input); + color1[2] = CVAL(input); + case 3: /* Color */ + color2[0] = CVAL(input); + color2[1] = CVAL(input); + color2[2] = CVAL(input); + break; + case 6: /* SetMix/Mix */ + case 7: /* SetMix/FillOrMix */ + mix[0] = CVAL(input); + mix[1] = CVAL(input); + mix[2] = CVAL(input); + opcode -= 5; + break; + case 9: /* FillOrMix_1 */ + mask = 0x03; + opcode = 0x02; + fom_mask = 3; + break; + case 0x0a: /* FillOrMix_2 */ + mask = 0x05; + opcode = 0x02; + fom_mask = 5; + break; + } + + lastopcode = opcode; + mixmask = 0; + + /* Output body */ + while (count > 0) + { + if (x >= width) { - line[x * 3 + 0] = color2[0]; - line[x * 3 + 1] = color2[1]; - line[x * 3 + 2] = color2[2]; - bicolor = 0; + if (height <= 0) + { + return 0; + } + + x = 0; + height--; + prevline = line; + line = output + height * (width * 3); } - else + + switch (opcode) { - line[x * 3 + 0] = color1[0]; - line[x * 3 + 1] = color1[1]; - line[x * 3 + 2] = color1[2]; - bicolor = 1; - count++; + case 0: /* Fill */ + + if (insertmix) + { + if (prevline == 0) + { + line[x * 3 + 0] = mix[0]; + line[x * 3 + 1] = mix[1]; + line[x * 3 + 2] = mix[2]; + } + else + { + line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; + line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; + line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; + } + + insertmix = 0; + count--; + x++; + } + + if (prevline == 0) + { + REPEAT + ( + line[x * 3 + 0] = 0; + line[x * 3 + 1] = 0; + line[x * 3 + 2] = 0; + ) + } + else + { + REPEAT + ( + line[x * 3 + 0] = prevline[x * 3 + 0]; + line[x * 3 + 1] = prevline[x * 3 + 1]; + line[x * 3 + 2] = prevline[x * 3 + 2]; + ) + } + + break; + case 1: /* Mix */ + + if (prevline == 0) + { + REPEAT + ( + line[x * 3 + 0] = mix[0]; + line[x * 3 + 1] = mix[1]; + line[x * 3 + 2] = mix[2]; + ) + } + else + { + REPEAT + ( + line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; + line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; + line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; + ) + } + + break; + case 2: /* Fill or Mix */ + + if (prevline == 0) + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x * 3 + 0] = mix[0]; + line[x * 3 + 1] = mix[1]; + line[x * 3 + 2] = mix[2]; + } + else + { + line[x * 3 + 0] = 0; + line[x * 3 + 1] = 0; + line[x * 3 + 2] = 0; + } + ) + } + else + { + REPEAT + ( + MASK_UPDATE; + + if (mask & mixmask) + { + line[x * 3 + 0] = prevline[x * 3 + 0] ^ mix[0]; + line[x * 3 + 1] = prevline[x * 3 + 1] ^ mix[1]; + line[x * 3 + 2] = prevline[x * 3 + 2] ^ mix[2]; + } + else + { + line[x * 3 + 0] = prevline[x * 3 + 0]; + line[x * 3 + 1] = prevline[x * 3 + 1]; + line[x * 3 + 2] = prevline[x * 3 + 2]; + } + ) + } + + break; + case 3: /* Color */ + REPEAT + ( + line[x * 3 + 0] = color2[0]; + line[x * 3 + 1] = color2[1]; + line[x * 3 + 2] = color2[2]; + ) + break; + case 4: /* Copy */ + REPEAT + ( + line[x * 3 + 0] = CVAL(input); + line[x * 3 + 1] = CVAL(input); + line[x * 3 + 2] = CVAL(input); + ) + break; + case 8: /* Bicolor */ + REPEAT + ( + + if (bicolor) + { + line[x * 3 + 0] = color2[0]; + line[x * 3 + 1] = color2[1]; + line[x * 3 + 2] = color2[2]; + bicolor = 0; + } + else + { + line[x * 3 + 0] = color1[0]; + line[x * 3 + 1] = color1[1]; + line[x * 3 + 2] = color1[2]; + bicolor = 1; + count++; + } + ) + break; + case 0xd: /* White */ + REPEAT + ( + line[x * 3 + 0] = 0xff; + line[x * 3 + 1] = 0xff; + line[x * 3 + 2] = 0xff; + ) + break; + case 0xe: /* Black */ + REPEAT + ( + line[x * 3 + 0] = 0; + line[x * 3 + 1] = 0; + line[x * 3 + 2] = 0; + ) + break; + default: + return 0; + break; } - ) - break; - case 0xd: /* White */ - REPEAT - ( - line[x * 3 + 0] = 0xff; - line[x * 3 + 1] = 0xff; - line[x * 3 + 2] = 0xff; - ) - break; - case 0xe: /* Black */ - REPEAT - ( - line[x * 3 + 0] = 0; - line[x * 3 + 1] = 0; - line[x * 3 + 2] = 0; - ) - break; - default: - return 0; - break; - } + } } - } - return 1; + + return 1; } /*****************************************************************************/ /* returns boolean */ int APP_CC -rdp_bitmap_decompress(char* output, int width, int height, char* input, +rdp_bitmap_decompress(char *output, int width, int height, char *input, int size, int Bpp) { - int rv; - - switch (Bpp) - { - case 1: - rv = bitmap_decompress1(output, width, height, input, size); - break; - case 2: - rv = bitmap_decompress2(output, width, height, input, size); - break; - case 3: - rv = bitmap_decompress3(output, width, height, input, size); - break; - default: - rv = 0; - break; - } - return rv; + int rv; + + switch (Bpp) + { + case 1: + rv = bitmap_decompress1(output, width, height, input, size); + break; + case 2: + rv = bitmap_decompress2(output, width, height, input, size); + break; + case 3: + rv = bitmap_decompress3(output, width, height, input, size); + break; + default: + rv = 0; + break; + } + + return rv; } diff --git a/rdp/rdp_iso.c b/rdp/rdp_iso.c index 3db99dd4..09c874b6 100644 --- a/rdp/rdp_iso.c +++ b/rdp/rdp_iso.c @@ -1,219 +1,239 @@ -/* - 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. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - librdp iso layer - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * librdp iso layer + */ #include "rdp.h" /*****************************************************************************/ -struct rdp_iso* APP_CC -rdp_iso_create(struct rdp_mcs* owner) +struct rdp_iso *APP_CC +rdp_iso_create(struct rdp_mcs *owner) { - struct rdp_iso* self; + struct rdp_iso *self; - self = (struct rdp_iso*)g_malloc(sizeof(struct rdp_iso), 1); - self->mcs_layer = owner; - self->tcp_layer = rdp_tcp_create(self); - return self; + self = (struct rdp_iso *)g_malloc(sizeof(struct rdp_iso), 1); + self->mcs_layer = owner; + self->tcp_layer = rdp_tcp_create(self); + return self; } /*****************************************************************************/ void APP_CC -rdp_iso_delete(struct rdp_iso* self) +rdp_iso_delete(struct rdp_iso *self) { - if (self == 0) - { - return; - } - rdp_tcp_delete(self->tcp_layer); - g_free(self); + if (self == 0) + { + return; + } + + rdp_tcp_delete(self->tcp_layer); + g_free(self); } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_iso_recv_msg(struct rdp_iso* self, struct stream* s, int* code) +rdp_iso_recv_msg(struct rdp_iso *self, struct stream *s, int *code) { - int ver; - int len; - - *code = 0; - if (rdp_tcp_recv(self->tcp_layer, s, 4) != 0) - { - DEBUG((" out rdp_iso_recv_msg error rdp_tcp_recv 1 failed")); - return 1; - } - in_uint8(s, ver); - if (ver != 3) - { - DEBUG((" out rdp_iso_recv_msg error ver != 3")); - return 1; - } - in_uint8s(s, 1); - in_uint16_be(s, len); - if (rdp_tcp_recv(self->tcp_layer, s, len - 4) != 0) - { - DEBUG((" out rdp_iso_recv_msg error rdp_tcp_recv 2 failed")); - return 1; - } - in_uint8s(s, 1); - in_uint8(s, *code); - if (*code == ISO_PDU_DT) - { + int ver; + int len; + + *code = 0; + + if (rdp_tcp_recv(self->tcp_layer, s, 4) != 0) + { + DEBUG((" out rdp_iso_recv_msg error rdp_tcp_recv 1 failed")); + return 1; + } + + in_uint8(s, ver); + + if (ver != 3) + { + DEBUG((" out rdp_iso_recv_msg error ver != 3")); + return 1; + } + + in_uint8s(s, 1); + in_uint16_be(s, len); + + if (rdp_tcp_recv(self->tcp_layer, s, len - 4) != 0) + { + DEBUG((" out rdp_iso_recv_msg error rdp_tcp_recv 2 failed")); + return 1; + } + in_uint8s(s, 1); - } - else - { - in_uint8s(s, 5); - } - return 0; + in_uint8(s, *code); + + if (*code == ISO_PDU_DT) + { + in_uint8s(s, 1); + } + else + { + in_uint8s(s, 5); + } + + return 0; } /*****************************************************************************/ static int APP_CC -rdp_iso_send_msg(struct rdp_iso* self, struct stream* s, int code) +rdp_iso_send_msg(struct rdp_iso *self, struct stream *s, int code) { - if (rdp_tcp_init(self->tcp_layer, s) != 0) - { - return 1; - } - out_uint8(s, 3); - out_uint8(s, 0); - out_uint16_be(s, 11); /* length */ - out_uint8(s, 6); - out_uint8(s, code); - out_uint16_le(s, 0); - out_uint16_le(s, 0); - out_uint8(s, 0); - s_mark_end(s); - if (rdp_tcp_send(self->tcp_layer, s) != 0) - { - return 1; - } - return 0; + if (rdp_tcp_init(self->tcp_layer, s) != 0) + { + return 1; + } + + out_uint8(s, 3); + out_uint8(s, 0); + out_uint16_be(s, 11); /* length */ + out_uint8(s, 6); + out_uint8(s, code); + out_uint16_le(s, 0); + out_uint16_le(s, 0); + out_uint8(s, 0); + s_mark_end(s); + + if (rdp_tcp_send(self->tcp_layer, s) != 0) + { + return 1; + } + + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_iso_recv(struct rdp_iso* self, struct stream* s) +rdp_iso_recv(struct rdp_iso *self, struct stream *s) { - int code; - - if (rdp_iso_recv_msg(self, s, &code) != 0) - { - return 1; - } - if (code != ISO_PDU_DT) - { - return 1; - } - return 0; + int code; + + if (rdp_iso_recv_msg(self, s, &code) != 0) + { + return 1; + } + + if (code != ISO_PDU_DT) + { + return 1; + } + + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_iso_init(struct rdp_iso* self, struct stream* s) +rdp_iso_init(struct rdp_iso *self, struct stream *s) { - rdp_tcp_init(self->tcp_layer, s); - s_push_layer(s, iso_hdr, 7); - return 0; + rdp_tcp_init(self->tcp_layer, s); + s_push_layer(s, iso_hdr, 7); + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_iso_send(struct rdp_iso* self, struct stream* s) +rdp_iso_send(struct rdp_iso *self, struct stream *s) { - int len; - - s_pop_layer(s, iso_hdr); - len = 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); - if (rdp_tcp_send(self->tcp_layer, s) != 0) - { - return 1; - } - return 0; + int len; + + s_pop_layer(s, iso_hdr); + len = 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); + + if (rdp_tcp_send(self->tcp_layer, s) != 0) + { + return 1; + } + + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_iso_connect(struct rdp_iso* self, char* ip, char* port) +rdp_iso_connect(struct rdp_iso *self, char *ip, char *port) { - int code; - struct stream* s; - - DEBUG((" in rdp_iso_connect")); - make_stream(s); - init_stream(s, 8192); - if (rdp_tcp_connect(self->tcp_layer, ip, port) != 0) - { - free_stream(s); - DEBUG((" out rdp_iso_connect error rdp_tcp_connect failed")); - return 1; - } - if (rdp_iso_send_msg(self, s, ISO_PDU_CR) != 0) - { - free_stream(s); - rdp_tcp_disconnect(self->tcp_layer); - DEBUG((" out rdp_iso_connect error rdp_iso_send_msg failed")); - return 1; - } - init_stream(s, 8192); - if (rdp_iso_recv_msg(self, s, &code) != 0) - { - free_stream(s); - rdp_tcp_disconnect(self->tcp_layer); - DEBUG((" out rdp_iso_connect error rdp_iso_recv_msg failed")); - return 1; - } - if (code != ISO_PDU_CC) - { + int code; + struct stream *s; + + DEBUG((" in rdp_iso_connect")); + make_stream(s); + init_stream(s, 8192); + + if (rdp_tcp_connect(self->tcp_layer, ip, port) != 0) + { + free_stream(s); + DEBUG((" out rdp_iso_connect error rdp_tcp_connect failed")); + return 1; + } + + if (rdp_iso_send_msg(self, s, ISO_PDU_CR) != 0) + { + free_stream(s); + rdp_tcp_disconnect(self->tcp_layer); + DEBUG((" out rdp_iso_connect error rdp_iso_send_msg failed")); + return 1; + } + + init_stream(s, 8192); + + if (rdp_iso_recv_msg(self, s, &code) != 0) + { + free_stream(s); + rdp_tcp_disconnect(self->tcp_layer); + DEBUG((" out rdp_iso_connect error rdp_iso_recv_msg failed")); + return 1; + } + + if (code != ISO_PDU_CC) + { + free_stream(s); + rdp_tcp_disconnect(self->tcp_layer); + DEBUG((" out rdp_iso_connect error code != ISO_PDU_CC")); + return 1; + } + free_stream(s); - rdp_tcp_disconnect(self->tcp_layer); - DEBUG((" out rdp_iso_connect error code != ISO_PDU_CC")); - return 1; - } - free_stream(s); - DEBUG((" out rdp_iso_connect")); - return 0; + DEBUG((" out rdp_iso_connect")); + return 0; } /*****************************************************************************/ int APP_CC -rdp_iso_disconnect(struct rdp_iso* self) +rdp_iso_disconnect(struct rdp_iso *self) { - struct stream* s; - - make_stream(s); - init_stream(s, 8192); - rdp_iso_send_msg(self, s, ISO_PDU_DR); - rdp_tcp_disconnect(self->tcp_layer); - free_stream(s); - return 0; + struct stream *s; + + make_stream(s); + init_stream(s, 8192); + rdp_iso_send_msg(self, s, ISO_PDU_DR); + rdp_tcp_disconnect(self->tcp_layer); + free_stream(s); + return 0; } diff --git a/rdp/rdp_lic.c b/rdp/rdp_lic.c index a729a7bc..ce9a0624 100644 --- a/rdp/rdp_lic.c +++ b/rdp/rdp_lic.c @@ -1,358 +1,369 @@ -/* - 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. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - licence - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * licence + */ #include "rdp.h" /*****************************************************************************/ -struct rdp_lic* APP_CC -rdp_lic_create(struct rdp_sec* owner) +struct rdp_lic *APP_CC +rdp_lic_create(struct rdp_sec *owner) { - struct rdp_lic* self; + struct rdp_lic *self; - self = (struct rdp_lic*)g_malloc(sizeof(struct rdp_lic), 1); - self->sec_layer = owner; - return self; + self = (struct rdp_lic *)g_malloc(sizeof(struct rdp_lic), 1); + self->sec_layer = owner; + return self; } /*****************************************************************************/ void APP_CC -rdp_lic_delete(struct rdp_lic* self) +rdp_lic_delete(struct rdp_lic *self) { - if (self == 0) - { - return; - } - g_free(self); + if (self == 0) + { + return; + } + + g_free(self); } /*****************************************************************************/ /* Generate a session key and RC4 keys, given client and server randoms */ static void APP_CC -rdp_lic_generate_keys(struct rdp_lic* self, char* client_random, - char* server_random, char* pre_master_secret) +rdp_lic_generate_keys(struct rdp_lic *self, char *client_random, + char *server_random, char *pre_master_secret) { - char master_secret[48]; - char key_block[48]; - - /* Generate master secret and then key material */ - rdp_sec_hash_48(master_secret, pre_master_secret, client_random, - server_random, 65); - rdp_sec_hash_48(key_block, master_secret, server_random, - client_random, 65); - /* Store first 16 bytes of session key as MAC secret */ - g_memcpy(self->licence_sign_key, key_block, 16); - /* Generate RC4 key from next 16 bytes */ - rdp_sec_hash_16(self->licence_key, key_block + 16, client_random, - server_random); + char master_secret[48]; + char key_block[48]; + + /* Generate master secret and then key material */ + rdp_sec_hash_48(master_secret, pre_master_secret, client_random, + server_random, 65); + rdp_sec_hash_48(key_block, master_secret, server_random, + client_random, 65); + /* Store first 16 bytes of session key as MAC secret */ + g_memcpy(self->licence_sign_key, key_block, 16); + /* Generate RC4 key from next 16 bytes */ + rdp_sec_hash_16(self->licence_key, key_block + 16, client_random, + server_random); } /*****************************************************************************/ static void APP_CC -rdp_lic_generate_hwid(struct rdp_lic* self, char* hwid) +rdp_lic_generate_hwid(struct rdp_lic *self, char *hwid) { - rdp_sec_buf_out_uint32(hwid, 2); - g_strncpy(hwid + 4, self->sec_layer->rdp_layer->mod->hostname, - LICENCE_HWID_SIZE - 4); + rdp_sec_buf_out_uint32(hwid, 2); + g_strncpy(hwid + 4, self->sec_layer->rdp_layer->mod->hostname, + LICENCE_HWID_SIZE - 4); } /*****************************************************************************/ /* Present an existing licence to the server */ static void APP_CC -rdp_lic_present(struct rdp_lic* self, char* client_random, char* rsa_data, - char* licence_data, int licence_size, char* hwid, - char* signature) +rdp_lic_present(struct rdp_lic *self, char *client_random, char *rsa_data, + char *licence_data, int licence_size, char *hwid, + char *signature) { - int sec_flags; - int length; - struct stream* s; - - sec_flags = SEC_LICENCE_NEG; - length = 16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE + - licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE; - make_stream(s); - init_stream(s, 8192); - rdp_sec_init(self->sec_layer, s, sec_flags); - out_uint8(s, LICENCE_TAG_PRESENT); - out_uint8(s, 2); /* version */ - out_uint16_le(s, length); - out_uint32_le(s, 1); - out_uint16_le(s, 0); - out_uint16_le(s, 0x0201); - out_uint8p(s, client_random, SEC_RANDOM_SIZE); - out_uint16_le(s, 0); - out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE)); - out_uint8p(s, rsa_data, SEC_MODULUS_SIZE); - out_uint8s(s, SEC_PADDING_SIZE); - out_uint16_le(s, 1); - out_uint16_le(s, licence_size); - out_uint8p(s, licence_data, licence_size); - out_uint16_le(s, 1); - out_uint16_le(s, LICENCE_HWID_SIZE); - out_uint8p(s, hwid, LICENCE_HWID_SIZE); - out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE); - s_mark_end(s); - rdp_sec_send(self->sec_layer, s, sec_flags); - free_stream(s); + int sec_flags; + int length; + struct stream *s; + + sec_flags = SEC_LICENCE_NEG; + length = 16 + SEC_RANDOM_SIZE + SEC_MODULUS_SIZE + SEC_PADDING_SIZE + + licence_size + LICENCE_HWID_SIZE + LICENCE_SIGNATURE_SIZE; + make_stream(s); + init_stream(s, 8192); + rdp_sec_init(self->sec_layer, s, sec_flags); + out_uint8(s, LICENCE_TAG_PRESENT); + out_uint8(s, 2); /* version */ + out_uint16_le(s, length); + out_uint32_le(s, 1); + out_uint16_le(s, 0); + out_uint16_le(s, 0x0201); + out_uint8p(s, client_random, SEC_RANDOM_SIZE); + out_uint16_le(s, 0); + out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE)); + out_uint8p(s, rsa_data, SEC_MODULUS_SIZE); + out_uint8s(s, SEC_PADDING_SIZE); + out_uint16_le(s, 1); + out_uint16_le(s, licence_size); + out_uint8p(s, licence_data, licence_size); + out_uint16_le(s, 1); + out_uint16_le(s, LICENCE_HWID_SIZE); + out_uint8p(s, hwid, LICENCE_HWID_SIZE); + out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE); + s_mark_end(s); + rdp_sec_send(self->sec_layer, s, sec_flags); + free_stream(s); } /*****************************************************************************/ /* Send a licence request packet */ static void APP_CC -rdp_lic_send_request(struct rdp_lic* self, char* client_random, - char* rsa_data, char* user, char* host) +rdp_lic_send_request(struct rdp_lic *self, char *client_random, + char *rsa_data, char *user, char *host) { - int sec_flags; - int userlen; - int hostlen; - int length; - struct stream* s; - - sec_flags = SEC_LICENCE_NEG; - userlen = g_strlen(user) + 1; - hostlen = g_strlen(host) + 1; - length = 128 + userlen + hostlen; - make_stream(s); - init_stream(s, 8192); - rdp_sec_init(self->sec_layer, s, sec_flags); - out_uint8(s, LICENCE_TAG_REQUEST); - out_uint8(s, 2); /* version */ - out_uint16_le(s, length); - out_uint32_le(s, 1); - out_uint16_le(s, 0); - out_uint16_le(s, 0xff01); - out_uint8p(s, client_random, SEC_RANDOM_SIZE); - out_uint16_le(s, 0); - out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE)); - out_uint8p(s, rsa_data, SEC_MODULUS_SIZE); - out_uint8s(s, SEC_PADDING_SIZE); - out_uint16_le(s, LICENCE_TAG_USER); - out_uint16_le(s, userlen); - out_uint8p(s, user, userlen); - out_uint16_le(s, LICENCE_TAG_HOST); - out_uint16_le(s, hostlen); - out_uint8p(s, host, hostlen); - s_mark_end(s); - rdp_sec_send(self->sec_layer, s, sec_flags); - free_stream(s); + int sec_flags; + int userlen; + int hostlen; + int length; + struct stream *s; + + sec_flags = SEC_LICENCE_NEG; + userlen = g_strlen(user) + 1; + hostlen = g_strlen(host) + 1; + length = 128 + userlen + hostlen; + make_stream(s); + init_stream(s, 8192); + rdp_sec_init(self->sec_layer, s, sec_flags); + out_uint8(s, LICENCE_TAG_REQUEST); + out_uint8(s, 2); /* version */ + out_uint16_le(s, length); + out_uint32_le(s, 1); + out_uint16_le(s, 0); + out_uint16_le(s, 0xff01); + out_uint8p(s, client_random, SEC_RANDOM_SIZE); + out_uint16_le(s, 0); + out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE)); + out_uint8p(s, rsa_data, SEC_MODULUS_SIZE); + out_uint8s(s, SEC_PADDING_SIZE); + out_uint16_le(s, LICENCE_TAG_USER); + out_uint16_le(s, userlen); + out_uint8p(s, user, userlen); + out_uint16_le(s, LICENCE_TAG_HOST); + out_uint16_le(s, hostlen); + out_uint8p(s, host, hostlen); + s_mark_end(s); + rdp_sec_send(self->sec_layer, s, sec_flags); + free_stream(s); } /*****************************************************************************/ /* Process a licence demand packet */ static void APP_CC -rdp_lic_process_demand(struct rdp_lic* self, struct stream* s) +rdp_lic_process_demand(struct rdp_lic *self, struct stream *s) { - char null_data[SEC_MODULUS_SIZE]; - char* server_random; - char signature[LICENCE_SIGNATURE_SIZE]; - char hwid[LICENCE_HWID_SIZE]; - char* licence_data; - int licence_size; - void* crypt_key; - - licence_data = 0; - /* Retrieve the server random from the incoming packet */ - in_uint8p(s, server_random, SEC_RANDOM_SIZE); - /* We currently use null client keys. This is a bit naughty but, hey, - the security of licence negotiation isn't exactly paramount. */ - g_memset(null_data, 0, sizeof(null_data)); - rdp_lic_generate_keys(self, null_data, server_random, null_data); - licence_size = 0; /* todo load_licence(&licence_data); */ - if (licence_size > 0) - { - /* Generate a signature for the HWID buffer */ - rdp_lic_generate_hwid(self, hwid); - rdp_sec_sign(signature, 16, self->licence_sign_key, 16, - hwid, sizeof(hwid)); - /* Now encrypt the HWID */ - crypt_key = ssl_rc4_info_create(); - ssl_rc4_set_key(crypt_key, self->licence_key, 16); - ssl_rc4_crypt(crypt_key, hwid, sizeof(hwid)); - ssl_rc4_info_delete(crypt_key); - rdp_lic_present(self, null_data, null_data, licence_data, - licence_size, hwid, signature); - g_free(licence_data); - return; - } - rdp_lic_send_request(self, null_data, null_data, - self->sec_layer->rdp_layer->mod->username, - self->sec_layer->rdp_layer->mod->hostname); + char null_data[SEC_MODULUS_SIZE]; + char *server_random; + char signature[LICENCE_SIGNATURE_SIZE]; + char hwid[LICENCE_HWID_SIZE]; + char *licence_data; + int licence_size; + void *crypt_key; + + licence_data = 0; + /* Retrieve the server random from the incoming packet */ + in_uint8p(s, server_random, SEC_RANDOM_SIZE); + /* We currently use null client keys. This is a bit naughty but, hey, + the security of licence negotiation isn't exactly paramount. */ + g_memset(null_data, 0, sizeof(null_data)); + rdp_lic_generate_keys(self, null_data, server_random, null_data); + licence_size = 0; /* todo load_licence(&licence_data); */ + + if (licence_size > 0) + { + /* Generate a signature for the HWID buffer */ + rdp_lic_generate_hwid(self, hwid); + rdp_sec_sign(signature, 16, self->licence_sign_key, 16, + hwid, sizeof(hwid)); + /* Now encrypt the HWID */ + crypt_key = ssl_rc4_info_create(); + ssl_rc4_set_key(crypt_key, self->licence_key, 16); + ssl_rc4_crypt(crypt_key, hwid, sizeof(hwid)); + ssl_rc4_info_delete(crypt_key); + rdp_lic_present(self, null_data, null_data, licence_data, + licence_size, hwid, signature); + g_free(licence_data); + return; + } + + rdp_lic_send_request(self, null_data, null_data, + self->sec_layer->rdp_layer->mod->username, + self->sec_layer->rdp_layer->mod->hostname); } /*****************************************************************************/ /* Send an authentication response packet */ static void APP_CC -rdp_lic_send_authresp(struct rdp_lic* self, char* token, char* crypt_hwid, - char* signature) +rdp_lic_send_authresp(struct rdp_lic *self, char *token, char *crypt_hwid, + char *signature) { - int sec_flags; - int length; - struct stream* s; - - sec_flags = SEC_LICENCE_NEG; - length = 58; - make_stream(s); - init_stream(s, 8192); - rdp_sec_init(self->sec_layer, s, sec_flags); - out_uint8(s, LICENCE_TAG_AUTHRESP); - out_uint8(s, 2); /* version */ - out_uint16_le(s, length); - out_uint16_le(s, 1); - out_uint16_le(s, LICENCE_TOKEN_SIZE); - out_uint8p(s, token, LICENCE_TOKEN_SIZE); - out_uint16_le(s, 1); - out_uint16_le(s, LICENCE_HWID_SIZE); - out_uint8p(s, crypt_hwid, LICENCE_HWID_SIZE); - out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE); - s_mark_end(s); - rdp_sec_send(self->sec_layer, s, sec_flags); - free_stream(s); + int sec_flags; + int length; + struct stream *s; + + sec_flags = SEC_LICENCE_NEG; + length = 58; + make_stream(s); + init_stream(s, 8192); + rdp_sec_init(self->sec_layer, s, sec_flags); + out_uint8(s, LICENCE_TAG_AUTHRESP); + out_uint8(s, 2); /* version */ + out_uint16_le(s, length); + out_uint16_le(s, 1); + out_uint16_le(s, LICENCE_TOKEN_SIZE); + out_uint8p(s, token, LICENCE_TOKEN_SIZE); + out_uint16_le(s, 1); + out_uint16_le(s, LICENCE_HWID_SIZE); + out_uint8p(s, crypt_hwid, LICENCE_HWID_SIZE); + out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE); + s_mark_end(s); + rdp_sec_send(self->sec_layer, s, sec_flags); + free_stream(s); } /*****************************************************************************/ /* Parse an authentication request packet */ /* returns boolean */ static int APP_CC -rdp_lic_parse_authreq(struct rdp_lic* self, struct stream* s, - char** token, char** signature) +rdp_lic_parse_authreq(struct rdp_lic *self, struct stream *s, + char **token, char **signature) { - int tokenlen; - - in_uint8s(s, 6); /* unknown: f8 3d 15 00 04 f6 */ - in_uint16_le(s, tokenlen); - if (tokenlen != LICENCE_TOKEN_SIZE) - { - /* error("token len %d\n", tokenlen); */ - return 0; - } - in_uint8p(s, *token, tokenlen); - in_uint8p(s, *signature, LICENCE_SIGNATURE_SIZE); - return s_check_end(s); + int tokenlen; + + in_uint8s(s, 6); /* unknown: f8 3d 15 00 04 f6 */ + in_uint16_le(s, tokenlen); + + if (tokenlen != LICENCE_TOKEN_SIZE) + { + /* error("token len %d\n", tokenlen); */ + return 0; + } + + in_uint8p(s, *token, tokenlen); + in_uint8p(s, *signature, LICENCE_SIGNATURE_SIZE); + return s_check_end(s); } /*****************************************************************************/ /* Process an authentication request packet */ static void APP_CC -rdp_lic_process_authreq(struct rdp_lic* self, struct stream* s) +rdp_lic_process_authreq(struct rdp_lic *self, struct stream *s) { - char* in_token; - char* in_sig; - char out_token[LICENCE_TOKEN_SIZE]; - char decrypt_token[LICENCE_TOKEN_SIZE]; - char hwid[LICENCE_HWID_SIZE]; - char crypt_hwid[LICENCE_HWID_SIZE]; - char sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE]; - char out_sig[LICENCE_SIGNATURE_SIZE]; - void* crypt_key; - - in_token = 0; - in_sig = 0; - /* Parse incoming packet and save the encrypted token */ - rdp_lic_parse_authreq(self, s, &in_token, &in_sig); - g_memcpy(out_token, in_token, LICENCE_TOKEN_SIZE); - /* Decrypt the token. It should read TEST in Unicode. */ - crypt_key = ssl_rc4_info_create(); - ssl_rc4_set_key(crypt_key, self->licence_key, 16); - g_memcpy(decrypt_token, in_token, LICENCE_TOKEN_SIZE); - ssl_rc4_crypt(crypt_key, decrypt_token, LICENCE_TOKEN_SIZE); - /* Generate a signature for a buffer of token and HWID */ - rdp_lic_generate_hwid(self, hwid); - g_memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE); - g_memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE); - rdp_sec_sign(out_sig, 16, self->licence_sign_key, 16, sealed_buffer, - sizeof(sealed_buffer)); - /* Now encrypt the HWID */ - ssl_rc4_set_key(crypt_key, self->licence_key, 16); - g_memcpy(crypt_hwid, hwid, LICENCE_HWID_SIZE); - ssl_rc4_crypt(crypt_key, crypt_hwid, LICENCE_HWID_SIZE); - rdp_lic_send_authresp(self, out_token, crypt_hwid, out_sig); - ssl_rc4_info_delete(crypt_key); + char *in_token; + char *in_sig; + char out_token[LICENCE_TOKEN_SIZE]; + char decrypt_token[LICENCE_TOKEN_SIZE]; + char hwid[LICENCE_HWID_SIZE]; + char crypt_hwid[LICENCE_HWID_SIZE]; + char sealed_buffer[LICENCE_TOKEN_SIZE + LICENCE_HWID_SIZE]; + char out_sig[LICENCE_SIGNATURE_SIZE]; + void *crypt_key; + + in_token = 0; + in_sig = 0; + /* Parse incoming packet and save the encrypted token */ + rdp_lic_parse_authreq(self, s, &in_token, &in_sig); + g_memcpy(out_token, in_token, LICENCE_TOKEN_SIZE); + /* Decrypt the token. It should read TEST in Unicode. */ + crypt_key = ssl_rc4_info_create(); + ssl_rc4_set_key(crypt_key, self->licence_key, 16); + g_memcpy(decrypt_token, in_token, LICENCE_TOKEN_SIZE); + ssl_rc4_crypt(crypt_key, decrypt_token, LICENCE_TOKEN_SIZE); + /* Generate a signature for a buffer of token and HWID */ + rdp_lic_generate_hwid(self, hwid); + g_memcpy(sealed_buffer, decrypt_token, LICENCE_TOKEN_SIZE); + g_memcpy(sealed_buffer + LICENCE_TOKEN_SIZE, hwid, LICENCE_HWID_SIZE); + rdp_sec_sign(out_sig, 16, self->licence_sign_key, 16, sealed_buffer, + sizeof(sealed_buffer)); + /* Now encrypt the HWID */ + ssl_rc4_set_key(crypt_key, self->licence_key, 16); + g_memcpy(crypt_hwid, hwid, LICENCE_HWID_SIZE); + ssl_rc4_crypt(crypt_key, crypt_hwid, LICENCE_HWID_SIZE); + rdp_lic_send_authresp(self, out_token, crypt_hwid, out_sig); + ssl_rc4_info_delete(crypt_key); } /*****************************************************************************/ /* Process an licence issue packet */ static void APP_CC -rdp_lic_process_issue(struct rdp_lic* self, struct stream* s) +rdp_lic_process_issue(struct rdp_lic *self, struct stream *s) { - void* crypt_key; - int length; - int check; - int i; - - in_uint8s(s, 2); /* 3d 45 - unknown */ - in_uint16_le(s, length); - if (!s_check_rem(s, length)) - { - return; - } - crypt_key = ssl_rc4_info_create(); - ssl_rc4_set_key(crypt_key, self->licence_key, 16); - ssl_rc4_crypt(crypt_key, s->p, length); - ssl_rc4_info_delete(crypt_key); - in_uint16_le(s, check); - if (check != 0) - { - return; - } - self->licence_issued = 1; - in_uint8s(s, 2); /* pad */ - /* advance to fourth string */ - length = 0; - for (i = 0; i < 4; i++) - { - in_uint8s(s, length); - in_uint32_le(s, length); + void *crypt_key; + int length; + int check; + int i; + + in_uint8s(s, 2); /* 3d 45 - unknown */ + in_uint16_le(s, length); + if (!s_check_rem(s, length)) { - return; + return; + } + + crypt_key = ssl_rc4_info_create(); + ssl_rc4_set_key(crypt_key, self->licence_key, 16); + ssl_rc4_crypt(crypt_key, s->p, length); + ssl_rc4_info_delete(crypt_key); + in_uint16_le(s, check); + + if (check != 0) + { + return; } - } - /* todo save_licence(s->p, length); */ + + self->licence_issued = 1; + in_uint8s(s, 2); /* pad */ + /* advance to fourth string */ + length = 0; + + for (i = 0; i < 4; i++) + { + in_uint8s(s, length); + in_uint32_le(s, length); + + if (!s_check_rem(s, length)) + { + return; + } + } + + /* todo save_licence(s->p, length); */ } /******************************************************************************/ /* Process a licence packet */ void APP_CC -rdp_lic_process(struct rdp_lic* self, struct stream* s) +rdp_lic_process(struct rdp_lic *self, struct stream *s) { - int tag; - - in_uint8(s, tag); - in_uint8s(s, 3); /* version, length */ - switch (tag) - { - case LICENCE_TAG_DEMAND: - rdp_lic_process_demand(self, s); - break; - case LICENCE_TAG_AUTHREQ: - rdp_lic_process_authreq(self, s); - break; - case LICENCE_TAG_ISSUE: - rdp_lic_process_issue(self, s); - break; - case LICENCE_TAG_REISSUE: - case LICENCE_TAG_RESULT: - break; - default: - break; - /* todo unimpl("licence tag 0x%x\n", tag); */ - } + int tag; + + in_uint8(s, tag); + in_uint8s(s, 3); /* version, length */ + + switch (tag) + { + case LICENCE_TAG_DEMAND: + rdp_lic_process_demand(self, s); + break; + case LICENCE_TAG_AUTHREQ: + rdp_lic_process_authreq(self, s); + break; + case LICENCE_TAG_ISSUE: + rdp_lic_process_issue(self, s); + break; + case LICENCE_TAG_REISSUE: + case LICENCE_TAG_RESULT: + break; + default: + break; + /* todo unimpl("licence tag 0x%x\n", tag); */ + } } diff --git a/rdp/rdp_mcs.c b/rdp/rdp_mcs.c index 4b8993da..3f5162f3 100644 --- a/rdp/rdp_mcs.c +++ b/rdp/rdp_mcs.c @@ -1,562 +1,628 @@ -/* - 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. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - librdp mcs layer - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * librdp mcs layer + */ #include "rdp.h" /*****************************************************************************/ -struct rdp_mcs* APP_CC -rdp_mcs_create(struct rdp_sec* owner, - struct stream* client_mcs_data, - struct stream* server_mcs_data) +struct rdp_mcs *APP_CC +rdp_mcs_create(struct rdp_sec *owner, + struct stream *client_mcs_data, + struct stream *server_mcs_data) { - struct rdp_mcs* self; - - self = (struct rdp_mcs*)g_malloc(sizeof(struct rdp_mcs), 1); - self->sec_layer = owner; - self->userid = 1; - self->client_mcs_data = client_mcs_data; - self->server_mcs_data = server_mcs_data; - self->iso_layer = rdp_iso_create(self); - return self; + struct rdp_mcs *self; + + self = (struct rdp_mcs *)g_malloc(sizeof(struct rdp_mcs), 1); + self->sec_layer = owner; + self->userid = 1; + self->client_mcs_data = client_mcs_data; + self->server_mcs_data = server_mcs_data; + self->iso_layer = rdp_iso_create(self); + return self; } /*****************************************************************************/ void APP_CC -rdp_mcs_delete(struct rdp_mcs* self) +rdp_mcs_delete(struct rdp_mcs *self) { - if (self == 0) - { - return; - } - rdp_iso_delete(self->iso_layer); - g_free(self); + if (self == 0) + { + return; + } + + rdp_iso_delete(self->iso_layer); + g_free(self); } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_mcs_recv(struct rdp_mcs* self, struct stream* s, int* chan) +rdp_mcs_recv(struct rdp_mcs *self, struct stream *s, int *chan) { - int appid; - int opcode; - int len; - - DEBUG((" in rdp_mcs_recv")); - if (rdp_iso_recv(self->iso_layer, s) != 0) - { - return 1; - } - in_uint8(s, opcode); - appid = opcode >> 2; - if (appid != MCS_SDIN) - { - DEBUG((" out rdp_mcs_recv error")); - return 1; - } - in_uint8s(s, 2); - in_uint16_be(s, *chan); - in_uint8s(s, 1); - in_uint8(s, len); - if (len & 0x80) - { + int appid; + int opcode; + int len; + + DEBUG((" in rdp_mcs_recv")); + + if (rdp_iso_recv(self->iso_layer, s) != 0) + { + return 1; + } + + in_uint8(s, opcode); + appid = opcode >> 2; + + if (appid != MCS_SDIN) + { + DEBUG((" out rdp_mcs_recv error")); + return 1; + } + + in_uint8s(s, 2); + in_uint16_be(s, *chan); in_uint8s(s, 1); - } - DEBUG((" out rdp_mcs_recv")); - return 0; + in_uint8(s, len); + + if (len & 0x80) + { + in_uint8s(s, 1); + } + + DEBUG((" out rdp_mcs_recv")); + return 0; } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_ber_out_header(struct rdp_mcs* self, struct stream* s, - int tag_val, int len) +rdp_mcs_ber_out_header(struct rdp_mcs *self, struct stream *s, + int tag_val, int len) { - if (tag_val > 0xff) - { - out_uint16_be(s, tag_val); - } - else - { - out_uint8(s, tag_val); - } - if (len >= 0x80) - { - out_uint8(s, 0x82); - out_uint16_be(s, len); - } - else - { - out_uint8(s, len); - } - return 0; + if (tag_val > 0xff) + { + out_uint16_be(s, tag_val); + } + else + { + out_uint8(s, tag_val); + } + + if (len >= 0x80) + { + out_uint8(s, 0x82); + out_uint16_be(s, len); + } + else + { + out_uint8(s, len); + } + + return 0; } #if 0 /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_ber_out_int8(struct rdp_mcs* self, struct stream* s, int value) +rdp_mcs_ber_out_int8(struct rdp_mcs *self, struct stream *s, int value) { - rdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1); - out_uint8(s, value); - return 0; + rdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1); + out_uint8(s, value); + return 0; } #endif /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_ber_out_int16(struct rdp_mcs* self, struct stream* s, int value) +rdp_mcs_ber_out_int16(struct rdp_mcs *self, struct stream *s, int value) { - rdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 2); - out_uint8(s, (value >> 8)); - out_uint8(s, value); - return 0; + rdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 2); + out_uint8(s, (value >> 8)); + out_uint8(s, value); + return 0; } #if 0 /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_ber_out_int24(struct rdp_mcs* self, struct stream* s, int value) +rdp_mcs_ber_out_int24(struct rdp_mcs *self, struct stream *s, int value) { - rdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 3); - out_uint8(s, (value >> 16)); - out_uint8(s, (value >> 8)); - out_uint8(s, value); - return 0; + rdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 3); + out_uint8(s, (value >> 16)); + out_uint8(s, (value >> 8)); + out_uint8(s, value); + return 0; } #endif /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_out_domain_params(struct rdp_mcs* self, struct stream* s, - int max_channels, - int max_users, int max_tokens, - int max_pdu_size) +rdp_mcs_out_domain_params(struct rdp_mcs *self, struct stream *s, + int max_channels, + int max_users, int max_tokens, + int max_pdu_size) { - rdp_mcs_ber_out_header(self, s, MCS_TAG_DOMAIN_PARAMS, 32); - rdp_mcs_ber_out_int16(self, s, max_channels); - rdp_mcs_ber_out_int16(self, s, max_users); - rdp_mcs_ber_out_int16(self, s, max_tokens); - rdp_mcs_ber_out_int16(self, s, 1); - rdp_mcs_ber_out_int16(self, s, 0); - rdp_mcs_ber_out_int16(self, s, 1); - rdp_mcs_ber_out_int16(self, s, max_pdu_size); - rdp_mcs_ber_out_int16(self, s, 2); - return 0; + rdp_mcs_ber_out_header(self, s, MCS_TAG_DOMAIN_PARAMS, 32); + rdp_mcs_ber_out_int16(self, s, max_channels); + rdp_mcs_ber_out_int16(self, s, max_users); + rdp_mcs_ber_out_int16(self, s, max_tokens); + rdp_mcs_ber_out_int16(self, s, 1); + rdp_mcs_ber_out_int16(self, s, 0); + rdp_mcs_ber_out_int16(self, s, 1); + rdp_mcs_ber_out_int16(self, s, max_pdu_size); + rdp_mcs_ber_out_int16(self, s, 2); + return 0; } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_send_connection_initial(struct rdp_mcs* self) +rdp_mcs_send_connection_initial(struct rdp_mcs *self) { - int data_len; - int len; - struct stream* s; - - make_stream(s); - init_stream(s, 8192); - data_len = self->client_mcs_data->end - self->client_mcs_data->data; - len = 7 + 3 * 34 + 4 + data_len; - if (rdp_iso_init(self->iso_layer, s) != 0) - { - free_stream(s); - return 1; - } - rdp_mcs_ber_out_header(self, s, MCS_CONNECT_INITIAL, len); - rdp_mcs_ber_out_header(self, s, BER_TAG_OCTET_STRING, 0); /* calling domain */ - rdp_mcs_ber_out_header(self, s, BER_TAG_OCTET_STRING, 0); /* called domain */ - rdp_mcs_ber_out_header(self, s, BER_TAG_BOOLEAN, 1); - out_uint8(s, 0xff); /* upward flag */ - rdp_mcs_out_domain_params(self, s, 2, 2, 0, 0xffff); /* target params */ - rdp_mcs_out_domain_params(self, s, 1, 1, 1, 0x420); /* min params */ - rdp_mcs_out_domain_params(self, s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */ - rdp_mcs_ber_out_header(self, s, BER_TAG_OCTET_STRING, data_len); - out_uint8p(s, self->client_mcs_data->data, data_len); - s_mark_end(s); - if (rdp_iso_send(self->iso_layer, s) != 0) - { + int data_len; + int len; + struct stream *s; + + make_stream(s); + init_stream(s, 8192); + data_len = self->client_mcs_data->end - self->client_mcs_data->data; + len = 7 + 3 * 34 + 4 + data_len; + + if (rdp_iso_init(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } + + rdp_mcs_ber_out_header(self, s, MCS_CONNECT_INITIAL, len); + rdp_mcs_ber_out_header(self, s, BER_TAG_OCTET_STRING, 0); /* calling domain */ + rdp_mcs_ber_out_header(self, s, BER_TAG_OCTET_STRING, 0); /* called domain */ + rdp_mcs_ber_out_header(self, s, BER_TAG_BOOLEAN, 1); + out_uint8(s, 0xff); /* upward flag */ + rdp_mcs_out_domain_params(self, s, 2, 2, 0, 0xffff); /* target params */ + rdp_mcs_out_domain_params(self, s, 1, 1, 1, 0x420); /* min params */ + rdp_mcs_out_domain_params(self, s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */ + rdp_mcs_ber_out_header(self, s, BER_TAG_OCTET_STRING, data_len); + out_uint8p(s, self->client_mcs_data->data, data_len); + s_mark_end(s); + + if (rdp_iso_send(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); - return 1; - } - free_stream(s); - return 0; + return 0; } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_ber_parse_header(struct rdp_mcs* self, struct stream* s, - int tag_val, int* len) +rdp_mcs_ber_parse_header(struct rdp_mcs *self, struct stream *s, + int tag_val, int *len) { - int tag; - int l; - int i; - - if (tag_val > 0xff) - { - in_uint16_be(s, tag); - } - else - { - in_uint8(s, tag); - } - if (tag != tag_val) - { - return 1; - } - in_uint8(s, l); - if (l & 0x80) - { - l = l & ~0x80; - *len = 0; - while (l > 0) - { - in_uint8(s, i); - *len = (*len << 8) | i; - l--; - } - } - else - { - *len = l; - } - if (s_check(s)) - { - return 0; - } - else - { - return 1; - } + int tag; + int l; + int i; + + if (tag_val > 0xff) + { + in_uint16_be(s, tag); + } + else + { + in_uint8(s, tag); + } + + if (tag != tag_val) + { + return 1; + } + + in_uint8(s, l); + + if (l & 0x80) + { + l = l & ~0x80; + *len = 0; + + while (l > 0) + { + in_uint8(s, i); + *len = (*len << 8) | i; + l--; + } + } + else + { + *len = l; + } + + if (s_check(s)) + { + return 0; + } + else + { + return 1; + } } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_parse_domain_params(struct rdp_mcs* self, struct stream* s) +rdp_mcs_parse_domain_params(struct rdp_mcs *self, struct stream *s) { - int len; - - if (rdp_mcs_ber_parse_header(self, s, MCS_TAG_DOMAIN_PARAMS, &len) != 0) - { - return 1; - } - in_uint8s(s, len); - if (s_check(s)) - { - return 0; - } - else - { - return 1; - } + int len; + + if (rdp_mcs_ber_parse_header(self, s, MCS_TAG_DOMAIN_PARAMS, &len) != 0) + { + return 1; + } + + in_uint8s(s, len); + + if (s_check(s)) + { + return 0; + } + else + { + return 1; + } } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_recv_connection_response(struct rdp_mcs* self) +rdp_mcs_recv_connection_response(struct rdp_mcs *self) { - int len; - int res; - struct stream* s; - - make_stream(s); - init_stream(s, 8192); - if (rdp_iso_recv(self->iso_layer, s) != 0) - { - free_stream(s); - return 1; - } - rdp_mcs_ber_parse_header(self, s, MCS_CONNECT_RESPONSE, &len); - rdp_mcs_ber_parse_header(self, s, BER_TAG_RESULT, &len); - in_uint8(s, res); - if (res != 0) - { - free_stream(s); - return 1; - } - rdp_mcs_ber_parse_header(self, s, BER_TAG_INTEGER, &len); - in_uint8s(s, len); /* connect id */ - rdp_mcs_parse_domain_params(self, s); - rdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len); - if (len > self->server_mcs_data->size) - { - len = self->server_mcs_data->size; - } - in_uint8a(s, self->server_mcs_data->data, len); - self->server_mcs_data->p = self->server_mcs_data->data; - self->server_mcs_data->end = self->server_mcs_data->data + len; - if (s_check_end(s)) - { - free_stream(s); - return 0; - } - else - { - free_stream(s); - return 1; - } + int len; + int res; + struct stream *s; + + make_stream(s); + init_stream(s, 8192); + + if (rdp_iso_recv(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } + + rdp_mcs_ber_parse_header(self, s, MCS_CONNECT_RESPONSE, &len); + rdp_mcs_ber_parse_header(self, s, BER_TAG_RESULT, &len); + in_uint8(s, res); + + if (res != 0) + { + free_stream(s); + return 1; + } + + rdp_mcs_ber_parse_header(self, s, BER_TAG_INTEGER, &len); + in_uint8s(s, len); /* connect id */ + rdp_mcs_parse_domain_params(self, s); + rdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len); + + if (len > self->server_mcs_data->size) + { + len = self->server_mcs_data->size; + } + + in_uint8a(s, self->server_mcs_data->data, len); + self->server_mcs_data->p = self->server_mcs_data->data; + self->server_mcs_data->end = self->server_mcs_data->data + len; + + if (s_check_end(s)) + { + free_stream(s); + return 0; + } + else + { + free_stream(s); + return 1; + } } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_send_edrq(struct rdp_mcs* self) +rdp_mcs_send_edrq(struct rdp_mcs *self) { - struct stream* s; + struct stream *s; + + make_stream(s); + init_stream(s, 8192); + + if (rdp_iso_init(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } + + out_uint8(s, (MCS_EDRQ << 2)); + out_uint16_be(s, 0x100); /* height */ + out_uint16_be(s, 0x100); /* interval */ + s_mark_end(s); + + if (rdp_iso_send(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } - make_stream(s); - init_stream(s, 8192); - if (rdp_iso_init(self->iso_layer, s) != 0) - { - free_stream(s); - return 1; - } - out_uint8(s, (MCS_EDRQ << 2)); - out_uint16_be(s, 0x100); /* height */ - out_uint16_be(s, 0x100); /* interval */ - s_mark_end(s); - if (rdp_iso_send(self->iso_layer, s) != 0) - { free_stream(s); - return 1; - } - free_stream(s); - return 0; + return 0; } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_send_aurq(struct rdp_mcs* self) +rdp_mcs_send_aurq(struct rdp_mcs *self) { - struct stream* s; + struct stream *s; + + make_stream(s); + init_stream(s, 8192); + + if (rdp_iso_init(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } + + out_uint8(s, (MCS_AURQ << 2)); + s_mark_end(s); + + if (rdp_iso_send(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } - make_stream(s); - init_stream(s, 8192); - if (rdp_iso_init(self->iso_layer, s) != 0) - { - free_stream(s); - return 1; - } - out_uint8(s, (MCS_AURQ << 2)); - s_mark_end(s); - if (rdp_iso_send(self->iso_layer, s) != 0) - { free_stream(s); - return 1; - } - free_stream(s); - return 0; + return 0; } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_recv_aucf(struct rdp_mcs* self) +rdp_mcs_recv_aucf(struct rdp_mcs *self) { - int opcode; - int res; - struct stream* s; - - make_stream(s); - init_stream(s, 8192); - if (rdp_iso_recv(self->iso_layer, s) != 0) - { - free_stream(s); - return 1; - } - in_uint8(s, opcode); - if ((opcode >> 2) != MCS_AUCF) - { - free_stream(s); - return 1; - } - in_uint8(s, res); - if (res != 0) - { - free_stream(s); - return 1; - } - if (opcode & 2) - { - in_uint16_be(s, self->userid); - } - if (!(s_check_end(s))) - { + int opcode; + int res; + struct stream *s; + + make_stream(s); + init_stream(s, 8192); + + if (rdp_iso_recv(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } + + in_uint8(s, opcode); + + if ((opcode >> 2) != MCS_AUCF) + { + free_stream(s); + return 1; + } + + in_uint8(s, res); + + if (res != 0) + { + free_stream(s); + return 1; + } + + if (opcode & 2) + { + in_uint16_be(s, self->userid); + } + + if (!(s_check_end(s))) + { + free_stream(s); + return 1; + } + free_stream(s); - return 1; - } - free_stream(s); - return 0; + return 0; } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_send_cjrq(struct rdp_mcs* self, int chanid) +rdp_mcs_send_cjrq(struct rdp_mcs *self, int chanid) { - struct stream* s; + struct stream *s; + + make_stream(s); + init_stream(s, 8192); + + if (rdp_iso_init(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } + + out_uint8(s, (MCS_CJRQ << 2)); + out_uint16_be(s, self->userid); + out_uint16_be(s, chanid); + s_mark_end(s); + + if (rdp_iso_send(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } - make_stream(s); - init_stream(s, 8192); - if (rdp_iso_init(self->iso_layer, s) != 0) - { - free_stream(s); - return 1; - } - out_uint8(s, (MCS_CJRQ << 2)); - out_uint16_be(s, self->userid); - out_uint16_be(s, chanid); - s_mark_end(s); - if (rdp_iso_send(self->iso_layer, s) != 0) - { free_stream(s); - return 1; - } - free_stream(s); - return 0; + return 0; } /*****************************************************************************/ /* returns error */ static int APP_CC -rdp_mcs_recv_cjcf(struct rdp_mcs* self) +rdp_mcs_recv_cjcf(struct rdp_mcs *self) { - int opcode; - int res; - struct stream* s; - - make_stream(s); - init_stream(s, 8192); - if (rdp_iso_recv(self->iso_layer, s) != 0) - { - free_stream(s); - return 1; - } - in_uint8(s, opcode); - if ((opcode >> 2) != MCS_CJCF) - { - free_stream(s); - return 1; - } - in_uint8(s, res); - if (res != 0) - { - free_stream(s); - return 1; - } - in_uint8s(s, 4); /* mcs_userid, req_chanid */ - if (opcode & 2) - { - in_uint8s(s, 2); /* join_chanid */ - } - if (!(s_check_end(s))) - { + int opcode; + int res; + struct stream *s; + + make_stream(s); + init_stream(s, 8192); + + if (rdp_iso_recv(self->iso_layer, s) != 0) + { + free_stream(s); + return 1; + } + + in_uint8(s, opcode); + + if ((opcode >> 2) != MCS_CJCF) + { + free_stream(s); + return 1; + } + + in_uint8(s, res); + + if (res != 0) + { + free_stream(s); + return 1; + } + + in_uint8s(s, 4); /* mcs_userid, req_chanid */ + + if (opcode & 2) + { + in_uint8s(s, 2); /* join_chanid */ + } + + if (!(s_check_end(s))) + { + free_stream(s); + return 1; + } + free_stream(s); - return 1; - } - free_stream(s); - return 0; + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_mcs_connect(struct rdp_mcs* self, char* ip, char* port) +rdp_mcs_connect(struct rdp_mcs *self, char *ip, char *port) { - DEBUG((" in rdp_mcs_connect")); - if (rdp_iso_connect(self->iso_layer, ip, port) != 0) - { - DEBUG((" out rdp_mcs_connect error rdp_iso_connect failed")); - return 1; - } - rdp_mcs_send_connection_initial(self); - if (rdp_mcs_recv_connection_response(self) != 0) - { - rdp_iso_disconnect(self->iso_layer); - DEBUG((" out rdp_mcs_connect error rdp_mcs_recv_connection_response \ + DEBUG((" in rdp_mcs_connect")); + + if (rdp_iso_connect(self->iso_layer, ip, port) != 0) + { + DEBUG((" out rdp_mcs_connect error rdp_iso_connect failed")); + return 1; + } + + rdp_mcs_send_connection_initial(self); + + if (rdp_mcs_recv_connection_response(self) != 0) + { + rdp_iso_disconnect(self->iso_layer); + DEBUG((" out rdp_mcs_connect error rdp_mcs_recv_connection_response \ failed")); - return 1; - } - rdp_mcs_send_edrq(self); - rdp_mcs_send_aurq(self); - if (rdp_mcs_recv_aucf(self) != 0) - { - rdp_iso_disconnect(self->iso_layer); - DEBUG((" out rdp_mcs_connect error rdp_mcs_recv_aucf failed")); - return 1; - } - rdp_mcs_send_cjrq(self, self->userid + 1001); - if (rdp_mcs_recv_cjcf(self) != 0) - { - rdp_iso_disconnect(self->iso_layer); - DEBUG((" out rdp_mcs_connect error rdp_mcs_recv_cjcf 1 failed")); - return 1; - } - rdp_mcs_send_cjrq(self, MCS_GLOBAL_CHANNEL); - if (rdp_mcs_recv_cjcf(self) != 0) - { - rdp_iso_disconnect(self->iso_layer); - DEBUG((" out rdp_mcs_connect error rdp_mcs_recv_cjcf 2 failed")); - return 1; - } - DEBUG((" out rdp_mcs_connect")); - return 0; + return 1; + } + + rdp_mcs_send_edrq(self); + rdp_mcs_send_aurq(self); + + if (rdp_mcs_recv_aucf(self) != 0) + { + rdp_iso_disconnect(self->iso_layer); + DEBUG((" out rdp_mcs_connect error rdp_mcs_recv_aucf failed")); + return 1; + } + + rdp_mcs_send_cjrq(self, self->userid + 1001); + + if (rdp_mcs_recv_cjcf(self) != 0) + { + rdp_iso_disconnect(self->iso_layer); + DEBUG((" out rdp_mcs_connect error rdp_mcs_recv_cjcf 1 failed")); + return 1; + } + + rdp_mcs_send_cjrq(self, MCS_GLOBAL_CHANNEL); + + if (rdp_mcs_recv_cjcf(self) != 0) + { + rdp_iso_disconnect(self->iso_layer); + DEBUG((" out rdp_mcs_connect error rdp_mcs_recv_cjcf 2 failed")); + return 1; + } + + DEBUG((" out rdp_mcs_connect")); + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_mcs_init(struct rdp_mcs* self, struct stream* s) +rdp_mcs_init(struct rdp_mcs *self, struct stream *s) { - rdp_iso_init(self->iso_layer, s); - s_push_layer(s, mcs_hdr, 8); - return 0; + rdp_iso_init(self->iso_layer, s); + s_push_layer(s, mcs_hdr, 8); + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_mcs_send(struct rdp_mcs* self, struct stream* s) +rdp_mcs_send(struct rdp_mcs *self, struct stream *s) { - int len; - - s_pop_layer(s, mcs_hdr); - len = (s->end - s->p) - 8; - len = len | 0x8000; - out_uint8(s, MCS_SDRQ << 2); - out_uint16_be(s, self->userid); - out_uint16_be(s, MCS_GLOBAL_CHANNEL); - out_uint8(s, 0x70); - out_uint16_be(s, len); - if (rdp_iso_send(self->iso_layer, s) != 0) - { - return 1; - } - return 0; + int len; + + s_pop_layer(s, mcs_hdr); + len = (s->end - s->p) - 8; + len = len | 0x8000; + out_uint8(s, MCS_SDRQ << 2); + out_uint16_be(s, self->userid); + out_uint16_be(s, MCS_GLOBAL_CHANNEL); + out_uint8(s, 0x70); + out_uint16_be(s, len); + + if (rdp_iso_send(self->iso_layer, s) != 0) + { + return 1; + } + + return 0; } diff --git a/rdp/rdp_orders.c b/rdp/rdp_orders.c index c0da6c35..b686c925 100644 --- a/rdp/rdp_orders.c +++ b/rdp/rdp_orders.c @@ -1,24 +1,22 @@ -/* - 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. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - librdp orders - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ibrdp orders + */ #include "rdp.h" @@ -27,1506 +25,1668 @@ #endif /*****************************************************************************/ -struct rdp_orders* APP_CC -rdp_orders_create(struct rdp_rdp* owner) +struct rdp_orders *APP_CC +rdp_orders_create(struct rdp_rdp *owner) { - struct rdp_orders* self = (struct rdp_orders *)NULL; + struct rdp_orders *self = (struct rdp_orders *)NULL; - self = (struct rdp_orders*)g_malloc(sizeof(struct rdp_orders), 1); - self->rdp_layer = owner; - return self; + self = (struct rdp_orders *)g_malloc(sizeof(struct rdp_orders), 1); + self->rdp_layer = owner; + return self; } /*****************************************************************************/ void APP_CC -rdp_orders_delete(struct rdp_orders* self) +rdp_orders_delete(struct rdp_orders *self) { - int i = 0; - int j = 0; - - if (self == 0) - { - return; - } - /* free the colormap cache */ - for (i = 0; i < 6; i++) - { - g_free(self->cache_colormap[i]); - } - /* free the bitmap cache */ - for (i = 0; i < 3; i++) - { - for (j = 0; j < 600; j++) - { - if (self->cache_bitmap[i][j] != 0) - { - g_free(self->cache_bitmap[i][j]->data); - } - g_free(self->cache_bitmap[i][j]); - } - } - g_free(self); + int i = 0; + int j = 0; + + if (self == 0) + { + return; + } + + /* free the colormap cache */ + for (i = 0; i < 6; i++) + { + g_free(self->cache_colormap[i]); + } + + /* free the bitmap cache */ + for (i = 0; i < 3; i++) + { + for (j = 0; j < 600; j++) + { + if (self->cache_bitmap[i][j] != 0) + { + g_free(self->cache_bitmap[i][j]->data); + } + + g_free(self->cache_bitmap[i][j]); + } + } + + g_free(self); } /*****************************************************************************/ void APP_CC -rdp_orders_reset_state(struct rdp_orders* self) +rdp_orders_reset_state(struct rdp_orders *self) { - g_memset(&self->state, 0, sizeof(self->state)); + g_memset(&self->state, 0, sizeof(self->state)); } /*****************************************************************************/ /* Read field indicating which parameters are present */ static void APP_CC -rdp_orders_in_present(struct stream* s, int* present, +rdp_orders_in_present(struct stream *s, int *present, int flags, int size) { - int bits = 0; - int i = 0; + int bits = 0; + int i = 0; - if (flags & RDP_ORDER_SMALL) - { - size--; - } - if (flags & RDP_ORDER_TINY) - { - if (size < 2) + if (flags & RDP_ORDER_SMALL) { - size = 0; + size--; } - else + + if (flags & RDP_ORDER_TINY) { - size -= 2; + if (size < 2) + { + size = 0; + } + else + { + size -= 2; + } + } + + *present = 0; + + for (i = 0; i < size; i++) + { + in_uint8(s, bits); + *present |= bits << (i * 8); } - } - *present = 0; - for (i = 0; i < size; i++) - { - in_uint8(s, bits); - *present |= bits << (i * 8); - } } /*****************************************************************************/ /* Read a co-ordinate (16-bit, or 8-bit delta) */ static void APP_CC -rdp_orders_in_coord(struct stream* s, int* coord, int delta) +rdp_orders_in_coord(struct stream *s, int *coord, int delta) { - int change = 0; - - if (delta) - { - in_sint8(s, change); - *coord += change; - } - else - { - in_sint16_le(s, *coord); - } + int change = 0; + + if (delta) + { + in_sint8(s, change); + *coord += change; + } + else + { + in_sint16_le(s, *coord); + } } /*****************************************************************************/ /* Parse bounds information */ static void APP_CC -rdp_orders_parse_bounds(struct rdp_orders* self, struct stream* s) +rdp_orders_parse_bounds(struct rdp_orders *self, struct stream *s) { - int present = 0; - - in_uint8(s, present); - if (present & 1) - { - rdp_orders_in_coord(s, &self->state.clip_left, 0); - } - else if (present & 16) - { - rdp_orders_in_coord(s, &self->state.clip_left, 1); - } - if (present & 2) - { - rdp_orders_in_coord(s, &self->state.clip_top, 0); - } - else if (present & 32) - { - rdp_orders_in_coord(s, &self->state.clip_top, 1); - } - if (present & 4) - { - rdp_orders_in_coord(s, &self->state.clip_right, 0); - } - else if (present & 64) - { - rdp_orders_in_coord(s, &self->state.clip_right, 1); - } - if (present & 8) - { - rdp_orders_in_coord(s, &self->state.clip_bottom, 0); - } - else if (present & 128) - { - rdp_orders_in_coord(s, &self->state.clip_bottom, 1); - } + int present = 0; + + in_uint8(s, present); + + if (present & 1) + { + rdp_orders_in_coord(s, &self->state.clip_left, 0); + } + else if (present & 16) + { + rdp_orders_in_coord(s, &self->state.clip_left, 1); + } + + if (present & 2) + { + rdp_orders_in_coord(s, &self->state.clip_top, 0); + } + else if (present & 32) + { + rdp_orders_in_coord(s, &self->state.clip_top, 1); + } + + if (present & 4) + { + rdp_orders_in_coord(s, &self->state.clip_right, 0); + } + else if (present & 64) + { + rdp_orders_in_coord(s, &self->state.clip_right, 1); + } + + if (present & 8) + { + rdp_orders_in_coord(s, &self->state.clip_bottom, 0); + } + else if (present & 128) + { + rdp_orders_in_coord(s, &self->state.clip_bottom, 1); + } } /*****************************************************************************/ /* Process a colormap cache order */ static void APP_CC -rdp_orders_process_colcache(struct rdp_orders* self, struct stream* s, +rdp_orders_process_colcache(struct rdp_orders *self, struct stream *s, int flags) { - struct rdp_colormap* colormap = (struct rdp_colormap *)NULL; - struct stream* rec_s = (struct stream *)NULL; - int cache_id = 0; - int i = 0; - - colormap = (struct rdp_colormap*)g_malloc(sizeof(struct rdp_colormap), 1); - in_uint8(s, cache_id); - in_uint16_le(s, colormap->ncolors); - for (i = 0; i < colormap->ncolors; i++) - { - in_uint32_le(s, colormap->colors[i]); - } - g_free(self->cache_colormap[cache_id]); - self->cache_colormap[cache_id] = colormap; - if (self->rdp_layer->rec_mode) - { - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, 4096); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 10); - out_uint8(rec_s, cache_id); - for (i = 0; i < 256; i++) - { - out_uint32_le(rec_s, colormap->colors[i]); - } - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } + struct rdp_colormap *colormap = (struct rdp_colormap *)NULL; + struct stream *rec_s = (struct stream *)NULL; + int cache_id = 0; + int i = 0; + + colormap = (struct rdp_colormap *)g_malloc(sizeof(struct rdp_colormap), 1); + in_uint8(s, cache_id); + in_uint16_le(s, colormap->ncolors); + + for (i = 0; i < colormap->ncolors; i++) + { + in_uint32_le(s, colormap->colors[i]); + } + + g_free(self->cache_colormap[cache_id]); + self->cache_colormap[cache_id] = colormap; + + if (self->rdp_layer->rec_mode) + { + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, 4096); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 10); + out_uint8(rec_s, cache_id); + + for (i = 0; i < 256; i++) + { + out_uint32_le(rec_s, colormap->colors[i]); + } + + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } } /*****************************************************************************/ /* Process a raw bitmap cache order */ static void APP_CC -rdp_orders_process_raw_bmpcache(struct rdp_orders* self, struct stream* s, +rdp_orders_process_raw_bmpcache(struct rdp_orders *self, struct stream *s, int flags) { - int cache_idx = 0; - int bufsize = 0; - int cache_id = 0; - int width = 0; - int height = 0; - int bpp = 0; - int Bpp = 0; - int x = 0; - int y = 0; - char* inverted = (char *)NULL; - char* dst = (char *)NULL; - struct rdp_bitmap* bitmap = (struct rdp_bitmap *)NULL; - struct stream* rec_s = (struct stream *)NULL; - - in_uint8(s, cache_id); - in_uint8s(s, 1); - in_uint8(s, width); - in_uint8(s, height); - in_uint8(s, bpp); - Bpp = (bpp + 7) / 8; - in_uint16_le(s, bufsize); - in_uint16_le(s, cache_idx); - inverted = (char*)g_malloc(width * height * Bpp, 0); - for (y = 0; y < height; y++) - { - dst = inverted + (((height - y) - 1) * (width * Bpp)); - if (Bpp == 1) - { - for (x = 0; x < width; x++) - { - in_uint8(s, dst[x]); - } - } - else if (Bpp == 2) - { - for (x = 0; x < width; x++) - { - in_uint16_le(s, ((tui16*)dst)[x]); - } - } - else if (Bpp == 3) - { - for (x = 0; x < width; x++) - { - in_uint8(s, dst[x * 3 + 0]); - in_uint8(s, dst[x * 3 + 1]); - in_uint8(s, dst[x * 3 + 2]); - } - } - } - bitmap = (struct rdp_bitmap*)g_malloc(sizeof(struct rdp_bitmap), 0); - bitmap->width = width; - bitmap->height = height; - bitmap->bpp = bpp; - bitmap->data = inverted; - if (self->cache_bitmap[cache_id][cache_idx] != 0) - { - g_free(self->cache_bitmap[cache_id][cache_idx]->data); - } - g_free(self->cache_bitmap[cache_id][cache_idx]); - self->cache_bitmap[cache_id][cache_idx] = bitmap; - if (self->rdp_layer->rec_mode) - { - y = width * height * Bpp; - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, y + 256); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 8); - out_uint8(rec_s, cache_id); - out_uint16_le(rec_s, cache_idx); - out_uint16_le(rec_s, width); - out_uint16_le(rec_s, height); - out_uint16_le(rec_s, y); - out_uint8a(rec_s, inverted, y); - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } + int cache_idx = 0; + int bufsize = 0; + int cache_id = 0; + int width = 0; + int height = 0; + int bpp = 0; + int Bpp = 0; + int x = 0; + int y = 0; + char *inverted = (char *)NULL; + char *dst = (char *)NULL; + struct rdp_bitmap *bitmap = (struct rdp_bitmap *)NULL; + struct stream *rec_s = (struct stream *)NULL; + + in_uint8(s, cache_id); + in_uint8s(s, 1); + in_uint8(s, width); + in_uint8(s, height); + in_uint8(s, bpp); + Bpp = (bpp + 7) / 8; + in_uint16_le(s, bufsize); + in_uint16_le(s, cache_idx); + inverted = (char *)g_malloc(width * height * Bpp, 0); + + for (y = 0; y < height; y++) + { + dst = inverted + (((height - y) - 1) * (width * Bpp)); + + if (Bpp == 1) + { + for (x = 0; x < width; x++) + { + in_uint8(s, dst[x]); + } + } + else if (Bpp == 2) + { + for (x = 0; x < width; x++) + { + in_uint16_le(s, ((tui16 *)dst)[x]); + } + } + else if (Bpp == 3) + { + for (x = 0; x < width; x++) + { + in_uint8(s, dst[x * 3 + 0]); + in_uint8(s, dst[x * 3 + 1]); + in_uint8(s, dst[x * 3 + 2]); + } + } + } + + bitmap = (struct rdp_bitmap *)g_malloc(sizeof(struct rdp_bitmap), 0); + bitmap->width = width; + bitmap->height = height; + bitmap->bpp = bpp; + bitmap->data = inverted; + + if (self->cache_bitmap[cache_id][cache_idx] != 0) + { + g_free(self->cache_bitmap[cache_id][cache_idx]->data); + } + + g_free(self->cache_bitmap[cache_id][cache_idx]); + self->cache_bitmap[cache_id][cache_idx] = bitmap; + + if (self->rdp_layer->rec_mode) + { + y = width * height * Bpp; + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, y + 256); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 8); + out_uint8(rec_s, cache_id); + out_uint16_le(rec_s, cache_idx); + out_uint16_le(rec_s, width); + out_uint16_le(rec_s, height); + out_uint16_le(rec_s, y); + out_uint8a(rec_s, inverted, y); + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } } /*****************************************************************************/ /* Process a bitmap cache order */ static void APP_CC -rdp_orders_process_bmpcache(struct rdp_orders* self, struct stream* s, +rdp_orders_process_bmpcache(struct rdp_orders *self, struct stream *s, int flags) { - char* data = (char *)NULL; - char* bmpdata = (char *)NULL; - int cache_idx = 0; - int size = 0; - int cache_id = 0; - int width = 0; - int height = 0; - int bpp = 0; - int Bpp = 0; - int bufsize = 0; - int pad1 = 0; - int pad2 = 0; - int row_size = 0; - int final_size = 0; - struct rdp_bitmap* bitmap = (struct rdp_bitmap *)NULL; - struct stream* rec_s = (struct stream *)NULL; - - in_uint8(s, cache_id); - in_uint8(s, pad1); - in_uint8(s, width); - in_uint8(s, height); - in_uint8(s, bpp); - Bpp = (bpp + 7) / 8; - in_uint16_le(s, bufsize); - in_uint16_le(s, cache_idx); - if (flags & 1024) - { - size = bufsize; - } - else - { - in_uint16_le(s, pad2); - in_uint16_le(s, size); - in_uint16_le(s, row_size); - in_uint16_le(s, final_size); - } - in_uint8p(s, data, size); - bmpdata = (char*)g_malloc(width * height * Bpp, 0); - if (rdp_bitmap_decompress(bmpdata, width, height, data, size, Bpp)) - { - } - else - { - /* error */ - } - bitmap = (struct rdp_bitmap*)g_malloc(sizeof(struct rdp_bitmap), 0); - bitmap->width = width; - bitmap->height = height; - bitmap->bpp = bpp; - bitmap->data = bmpdata; - if (self->cache_bitmap[cache_id][cache_idx] != 0) - { - g_free(self->cache_bitmap[cache_id][cache_idx]->data); - } - g_free(self->cache_bitmap[cache_id][cache_idx]); - self->cache_bitmap[cache_id][cache_idx] = bitmap; - if (self->rdp_layer->rec_mode) - { - size = width * height * Bpp; - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, size + 256); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 8); - out_uint8(rec_s, cache_id); - out_uint16_le(rec_s, cache_idx); - out_uint16_le(rec_s, width); - out_uint16_le(rec_s, height); - out_uint16_le(rec_s, size); - out_uint8a(rec_s, bmpdata, size); - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } + char *data = (char *)NULL; + char *bmpdata = (char *)NULL; + int cache_idx = 0; + int size = 0; + int cache_id = 0; + int width = 0; + int height = 0; + int bpp = 0; + int Bpp = 0; + int bufsize = 0; + int pad1 = 0; + int pad2 = 0; + int row_size = 0; + int final_size = 0; + struct rdp_bitmap *bitmap = (struct rdp_bitmap *)NULL; + struct stream *rec_s = (struct stream *)NULL; + + in_uint8(s, cache_id); + in_uint8(s, pad1); + in_uint8(s, width); + in_uint8(s, height); + in_uint8(s, bpp); + Bpp = (bpp + 7) / 8; + in_uint16_le(s, bufsize); + in_uint16_le(s, cache_idx); + + if (flags & 1024) + { + size = bufsize; + } + else + { + in_uint16_le(s, pad2); + in_uint16_le(s, size); + in_uint16_le(s, row_size); + in_uint16_le(s, final_size); + } + + in_uint8p(s, data, size); + bmpdata = (char *)g_malloc(width * height * Bpp, 0); + + if (rdp_bitmap_decompress(bmpdata, width, height, data, size, Bpp)) + { + } + else + { + /* error */ + } + + bitmap = (struct rdp_bitmap *)g_malloc(sizeof(struct rdp_bitmap), 0); + bitmap->width = width; + bitmap->height = height; + bitmap->bpp = bpp; + bitmap->data = bmpdata; + + if (self->cache_bitmap[cache_id][cache_idx] != 0) + { + g_free(self->cache_bitmap[cache_id][cache_idx]->data); + } + + g_free(self->cache_bitmap[cache_id][cache_idx]); + self->cache_bitmap[cache_id][cache_idx] = bitmap; + + if (self->rdp_layer->rec_mode) + { + size = width * height * Bpp; + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, size + 256); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 8); + out_uint8(rec_s, cache_id); + out_uint16_le(rec_s, cache_idx); + out_uint16_le(rec_s, width); + out_uint16_le(rec_s, height); + out_uint16_le(rec_s, size); + out_uint8a(rec_s, bmpdata, size); + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } } /*****************************************************************************/ /* Process a font cache order */ static void APP_CC -rdp_orders_process_fontcache(struct rdp_orders* self, struct stream* s, +rdp_orders_process_fontcache(struct rdp_orders *self, struct stream *s, int flags) { - struct stream* rec_s = (struct stream *)NULL; - int font = 0; - int nglyphs = 0; - int character = 0; - int offset = 0; - int baseline = 0; - int width = 0; - int height = 0; - int i = 0; - int datasize = 0; - char* data = (char *)NULL; - - in_uint8(s, font); - in_uint8(s, nglyphs); - for (i = 0; i < nglyphs; i++) - { - in_uint16_le(s, character); - in_uint16_le(s, offset); - in_uint16_le(s, baseline); - in_uint16_le(s, width); - in_uint16_le(s, height); - datasize = (height * ((width + 7) / 8) + 3) & ~3; - in_uint8p(s, data, datasize); - self->rdp_layer->mod->server_add_char(self->rdp_layer->mod, font, - character, offset, baseline, - width, height, data); - if (self->rdp_layer->rec_mode) + struct stream *rec_s = (struct stream *)NULL; + int font = 0; + int nglyphs = 0; + int character = 0; + int offset = 0; + int baseline = 0; + int width = 0; + int height = 0; + int i = 0; + int datasize = 0; + char *data = (char *)NULL; + + in_uint8(s, font); + in_uint8(s, nglyphs); + + for (i = 0; i < nglyphs; i++) { - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, datasize + 256); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 9); - out_uint8(rec_s, font); - out_uint16_le(rec_s, character); - out_uint16_le(rec_s, offset); - out_uint16_le(rec_s, baseline); - out_uint16_le(rec_s, width); - out_uint16_le(rec_s, height); - out_uint16_le(rec_s, datasize); - out_uint8a(rec_s, data, datasize); - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } - } + in_uint16_le(s, character); + in_uint16_le(s, offset); + in_uint16_le(s, baseline); + in_uint16_le(s, width); + in_uint16_le(s, height); + datasize = (height * ((width + 7) / 8) + 3) & ~3; + in_uint8p(s, data, datasize); + self->rdp_layer->mod->server_add_char(self->rdp_layer->mod, font, + character, offset, baseline, + width, height, data); + + if (self->rdp_layer->rec_mode) + { + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, datasize + 256); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 9); + out_uint8(rec_s, font); + out_uint16_le(rec_s, character); + out_uint16_le(rec_s, offset); + out_uint16_le(rec_s, baseline); + out_uint16_le(rec_s, width); + out_uint16_le(rec_s, height); + out_uint16_le(rec_s, datasize); + out_uint8a(rec_s, data, datasize); + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } + } } /*****************************************************************************/ /* Process a secondary order */ static int APP_CC -rdp_orders_process_secondary_order(struct rdp_orders* self, struct stream* s) +rdp_orders_process_secondary_order(struct rdp_orders *self, struct stream *s) { - short length = 0; - int flags = 0; - int type = 0; - char* next_order = (char *)NULL; - - in_uint16_le(s, length); - in_uint16_le(s, flags); - in_uint8(s, type); - next_order = s->p + length + 7; - switch (type) - { - case RDP_ORDER_COLCACHE: - rdp_orders_process_colcache(self, s, flags); - break; - case RDP_ORDER_RAW_BMPCACHE: - rdp_orders_process_raw_bmpcache(self, s, flags); - break; - case RDP_ORDER_BMPCACHE: - rdp_orders_process_bmpcache(self, s, flags); - break; - case RDP_ORDER_FONTCACHE: - rdp_orders_process_fontcache(self, s, flags); - break; - default: - /* error, unknown order */ - break; - } - s->p = next_order; - return 0; + short length = 0; + int flags = 0; + int type = 0; + char *next_order = (char *)NULL; + + in_uint16_le(s, length); + in_uint16_le(s, flags); + in_uint8(s, type); + next_order = s->p + length + 7; + + switch (type) + { + case RDP_ORDER_COLCACHE: + rdp_orders_process_colcache(self, s, flags); + break; + case RDP_ORDER_RAW_BMPCACHE: + rdp_orders_process_raw_bmpcache(self, s, flags); + break; + case RDP_ORDER_BMPCACHE: + rdp_orders_process_bmpcache(self, s, flags); + break; + case RDP_ORDER_FONTCACHE: + rdp_orders_process_fontcache(self, s, flags); + break; + default: + /* error, unknown order */ + break; + } + + s->p = next_order; + return 0; } /*****************************************************************************/ /* Read a color entry */ static void APP_CC -rdp_orders_in_color(struct stream* s, int* color) +rdp_orders_in_color(struct stream *s, int *color) { - int i = 0; - - in_uint8(s, i); - *color = i; - in_uint8(s, i); - *color |= i << 8; - in_uint8(s, i); - *color |= i << 16; + int i = 0; + + in_uint8(s, i); + *color = i; + in_uint8(s, i); + *color |= i << 8; + in_uint8(s, i); + *color |= i << 16; } /*****************************************************************************/ /* Parse a brush */ static void APP_CC -rdp_orders_parse_brush(struct stream* s, struct rdp_brush* brush, int present) +rdp_orders_parse_brush(struct stream *s, struct rdp_brush *brush, int present) { - if (present & 1) - { - in_uint8(s, brush->xorigin); - } - if (present & 2) - { - in_uint8(s, brush->yorigin); - } - if (present & 4) - { - in_uint8(s, brush->style); - } - if (present & 8) - { - in_uint8(s, brush->pattern[0]); - } - if (present & 16) - { - in_uint8a(s, brush->pattern + 1, 7); - } + if (present & 1) + { + in_uint8(s, brush->xorigin); + } + + if (present & 2) + { + in_uint8(s, brush->yorigin); + } + + if (present & 4) + { + in_uint8(s, brush->style); + } + + if (present & 8) + { + in_uint8(s, brush->pattern[0]); + } + + if (present & 16) + { + in_uint8a(s, brush->pattern + 1, 7); + } } /*****************************************************************************/ /* Parse a pen */ static void APP_CC -rdp_orders_parse_pen(struct stream* s, struct rdp_pen* pen, int present) +rdp_orders_parse_pen(struct stream *s, struct rdp_pen *pen, int present) { - if (present & 1) - { - in_uint8(s, pen->style); - } - if (present & 2) - { - in_uint8(s, pen->width); - } - if (present & 4) - { - rdp_orders_in_color(s, &pen->color); - } + if (present & 1) + { + in_uint8(s, pen->style); + } + + if (present & 2) + { + in_uint8(s, pen->width); + } + + if (present & 4) + { + rdp_orders_in_color(s, &pen->color); + } } /*****************************************************************************/ /* Process a text order */ static void APP_CC -rdp_orders_process_text2(struct rdp_orders* self, struct stream* s, +rdp_orders_process_text2(struct rdp_orders *self, struct stream *s, int present, int delta) { - int fgcolor = 0; - int bgcolor = 0; - struct stream* rec_s = (struct stream *)NULL; - - if (present & 0x000001) - { - in_uint8(s, self->state.text_font); - } - if (present & 0x000002) - { - in_uint8(s, self->state.text_flags); - } - if (present & 0x000004) - { - in_uint8(s, self->state.text_opcode); - } - if (present & 0x000008) - { - in_uint8(s, self->state.text_mixmode); - } - if (present & 0x000010) - { - rdp_orders_in_color(s, &self->state.text_fgcolor); - } - if (present & 0x000020) - { - rdp_orders_in_color(s, &self->state.text_bgcolor); - } - if (present & 0x000040) - { - in_sint16_le(s, self->state.text_clipleft); - } - if (present & 0x000080) - { - in_sint16_le(s, self->state.text_cliptop); - } - if (present & 0x000100) - { - in_sint16_le(s, self->state.text_clipright); - } - if (present & 0x000200) - { - in_sint16_le(s, self->state.text_clipbottom); - } - if (present & 0x000400) - { - in_sint16_le(s, self->state.text_boxleft); - } - if (present & 0x000800) - { - in_sint16_le(s, self->state.text_boxtop); - } - if (present & 0x001000) - { - in_sint16_le(s, self->state.text_boxright); - } - if (present & 0x002000) - { - in_sint16_le(s, self->state.text_boxbottom); - } - rdp_orders_parse_brush(s, &self->state.text_brush, present >> 14); - if (present & 0x080000) - { - in_sint16_le(s, self->state.text_x); - } - if (present & 0x100000) - { - in_sint16_le(s, self->state.text_y); - } - if (present & 0x200000) - { - in_uint8(s, self->state.text_length); - in_uint8a(s, self->state.text_text, self->state.text_length); - } - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, - self->state.text_opcode); - fgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, - self->rdp_layer->mod->xrdp_bpp, - self->state.text_fgcolor, - self->rdp_layer->colormap.colors); - self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, fgcolor); - bgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, - self->rdp_layer->mod->xrdp_bpp, - self->state.text_bgcolor, - self->rdp_layer->colormap.colors); - self->rdp_layer->mod->server_set_bgcolor(self->rdp_layer->mod, bgcolor); - self->rdp_layer->mod->server_draw_text(self->rdp_layer->mod, - self->state.text_font, - self->state.text_flags, - self->state.text_mixmode, - self->state.text_clipleft, - self->state.text_cliptop, - self->state.text_clipright, - self->state.text_clipbottom, - self->state.text_boxleft, - self->state.text_boxtop, - self->state.text_boxright, - self->state.text_boxbottom, - self->state.text_x, - self->state.text_y, - self->state.text_text, - self->state.text_length); - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); - if (self->rdp_layer->rec_mode) - { - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, 512); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 7); - out_uint8(rec_s, self->state.text_font); - out_uint8(rec_s, self->state.text_flags); - out_uint8(rec_s, self->state.text_opcode); - out_uint8(rec_s, self->state.text_mixmode); - out_uint32_le(rec_s, self->state.text_fgcolor); - out_uint32_le(rec_s, self->state.text_bgcolor); - out_uint16_le(rec_s, self->state.text_clipleft); - out_uint16_le(rec_s, self->state.text_cliptop); - out_uint16_le(rec_s, self->state.text_clipright); - out_uint16_le(rec_s, self->state.text_clipbottom); - out_uint16_le(rec_s, self->state.text_boxleft); - out_uint16_le(rec_s, self->state.text_boxtop); - out_uint16_le(rec_s, self->state.text_boxright); - out_uint16_le(rec_s, self->state.text_boxbottom); - out_uint16_le(rec_s, self->state.text_x); - out_uint16_le(rec_s, self->state.text_y); - out_uint16_le(rec_s, self->state.text_length); - out_uint8a(rec_s, self->state.text_text, self->state.text_length); - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } + int fgcolor = 0; + int bgcolor = 0; + struct stream *rec_s = (struct stream *)NULL; + + if (present & 0x000001) + { + in_uint8(s, self->state.text_font); + } + + if (present & 0x000002) + { + in_uint8(s, self->state.text_flags); + } + + if (present & 0x000004) + { + in_uint8(s, self->state.text_opcode); + } + + if (present & 0x000008) + { + in_uint8(s, self->state.text_mixmode); + } + + if (present & 0x000010) + { + rdp_orders_in_color(s, &self->state.text_fgcolor); + } + + if (present & 0x000020) + { + rdp_orders_in_color(s, &self->state.text_bgcolor); + } + + if (present & 0x000040) + { + in_sint16_le(s, self->state.text_clipleft); + } + + if (present & 0x000080) + { + in_sint16_le(s, self->state.text_cliptop); + } + + if (present & 0x000100) + { + in_sint16_le(s, self->state.text_clipright); + } + + if (present & 0x000200) + { + in_sint16_le(s, self->state.text_clipbottom); + } + + if (present & 0x000400) + { + in_sint16_le(s, self->state.text_boxleft); + } + + if (present & 0x000800) + { + in_sint16_le(s, self->state.text_boxtop); + } + + if (present & 0x001000) + { + in_sint16_le(s, self->state.text_boxright); + } + + if (present & 0x002000) + { + in_sint16_le(s, self->state.text_boxbottom); + } + + rdp_orders_parse_brush(s, &self->state.text_brush, present >> 14); + + if (present & 0x080000) + { + in_sint16_le(s, self->state.text_x); + } + + if (present & 0x100000) + { + in_sint16_le(s, self->state.text_y); + } + + if (present & 0x200000) + { + in_uint8(s, self->state.text_length); + in_uint8a(s, self->state.text_text, self->state.text_length); + } + + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.text_opcode); + fgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, + self->rdp_layer->mod->xrdp_bpp, + self->state.text_fgcolor, + self->rdp_layer->colormap.colors); + self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, fgcolor); + bgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, + self->rdp_layer->mod->xrdp_bpp, + self->state.text_bgcolor, + self->rdp_layer->colormap.colors); + self->rdp_layer->mod->server_set_bgcolor(self->rdp_layer->mod, bgcolor); + self->rdp_layer->mod->server_draw_text(self->rdp_layer->mod, + self->state.text_font, + self->state.text_flags, + self->state.text_mixmode, + self->state.text_clipleft, + self->state.text_cliptop, + self->state.text_clipright, + self->state.text_clipbottom, + self->state.text_boxleft, + self->state.text_boxtop, + self->state.text_boxright, + self->state.text_boxbottom, + self->state.text_x, + self->state.text_y, + self->state.text_text, + self->state.text_length); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); + + if (self->rdp_layer->rec_mode) + { + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, 512); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 7); + out_uint8(rec_s, self->state.text_font); + out_uint8(rec_s, self->state.text_flags); + out_uint8(rec_s, self->state.text_opcode); + out_uint8(rec_s, self->state.text_mixmode); + out_uint32_le(rec_s, self->state.text_fgcolor); + out_uint32_le(rec_s, self->state.text_bgcolor); + out_uint16_le(rec_s, self->state.text_clipleft); + out_uint16_le(rec_s, self->state.text_cliptop); + out_uint16_le(rec_s, self->state.text_clipright); + out_uint16_le(rec_s, self->state.text_clipbottom); + out_uint16_le(rec_s, self->state.text_boxleft); + out_uint16_le(rec_s, self->state.text_boxtop); + out_uint16_le(rec_s, self->state.text_boxright); + out_uint16_le(rec_s, self->state.text_boxbottom); + out_uint16_le(rec_s, self->state.text_x); + out_uint16_le(rec_s, self->state.text_y); + out_uint16_le(rec_s, self->state.text_length); + out_uint8a(rec_s, self->state.text_text, self->state.text_length); + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } } /*****************************************************************************/ /* Process a destination blt order */ static void APP_CC -rdp_orders_process_destblt(struct rdp_orders* self, struct stream* s, +rdp_orders_process_destblt(struct rdp_orders *self, struct stream *s, int present, int delta) { - struct stream* rec_s = (struct stream *)NULL; - - if (present & 0x01) - { - rdp_orders_in_coord(s, &self->state.dest_x, delta); - } - if (present & 0x02) - { - rdp_orders_in_coord(s, &self->state.dest_y, delta); - } - if (present & 0x04) - { - rdp_orders_in_coord(s, &self->state.dest_cx, delta); - } - if (present & 0x08) - { - rdp_orders_in_coord(s, &self->state.dest_cy, delta); - } - if (present & 0x10) - { - in_uint8(s, self->state.dest_opcode); - } - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, - self->state.dest_opcode); - self->rdp_layer->mod->server_fill_rect(self->rdp_layer->mod, - self->state.dest_x, - self->state.dest_y, - self->state.dest_cx, - self->state.dest_cy); - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); - if (self->rdp_layer->rec_mode) - { - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, 512); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 6); - out_uint16_le(rec_s, self->state.dest_x); - out_uint16_le(rec_s, self->state.dest_y); - out_uint16_le(rec_s, self->state.dest_cx); - out_uint16_le(rec_s, self->state.dest_cy); - out_uint8(rec_s, self->state.dest_opcode); - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } + struct stream *rec_s = (struct stream *)NULL; + + if (present & 0x01) + { + rdp_orders_in_coord(s, &self->state.dest_x, delta); + } + + if (present & 0x02) + { + rdp_orders_in_coord(s, &self->state.dest_y, delta); + } + + if (present & 0x04) + { + rdp_orders_in_coord(s, &self->state.dest_cx, delta); + } + + if (present & 0x08) + { + rdp_orders_in_coord(s, &self->state.dest_cy, delta); + } + + if (present & 0x10) + { + in_uint8(s, self->state.dest_opcode); + } + + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.dest_opcode); + self->rdp_layer->mod->server_fill_rect(self->rdp_layer->mod, + self->state.dest_x, + self->state.dest_y, + self->state.dest_cx, + self->state.dest_cy); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); + + if (self->rdp_layer->rec_mode) + { + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, 512); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 6); + out_uint16_le(rec_s, self->state.dest_x); + out_uint16_le(rec_s, self->state.dest_y); + out_uint16_le(rec_s, self->state.dest_cx); + out_uint16_le(rec_s, self->state.dest_cy); + out_uint8(rec_s, self->state.dest_opcode); + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } } /*****************************************************************************/ /* Process a pattern blt order */ static void APP_CC -rdp_orders_process_patblt(struct rdp_orders* self, struct stream* s, +rdp_orders_process_patblt(struct rdp_orders *self, struct stream *s, int present, int delta) { - int fgcolor = 0; - int bgcolor = 0; - struct stream* rec_s = (struct stream *)NULL; - - if (present & 0x0001) - { - rdp_orders_in_coord(s, &self->state.pat_x, delta); - } - if (present & 0x0002) - { - rdp_orders_in_coord(s, &self->state.pat_y, delta); - } - if (present & 0x0004) - { - rdp_orders_in_coord(s, &self->state.pat_cx, delta); - } - if (present & 0x0008) - { - rdp_orders_in_coord(s, &self->state.pat_cy, delta); - } - if (present & 0x0010) - { - in_uint8(s, self->state.pat_opcode); - } - if (present & 0x0020) - { - rdp_orders_in_color(s, &self->state.pat_bgcolor); - } - if (present & 0x0040) - { - rdp_orders_in_color(s, &self->state.pat_fgcolor); - } - rdp_orders_parse_brush(s, &self->state.pat_brush, present >> 7); - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, - self->state.pat_opcode); - self->rdp_layer->mod->server_set_mixmode(self->rdp_layer->mod, 1); - fgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, - self->rdp_layer->mod->xrdp_bpp, - self->state.pat_fgcolor, - self->rdp_layer->colormap.colors); - self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, fgcolor); - bgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, - self->rdp_layer->mod->xrdp_bpp, - self->state.pat_bgcolor, - self->rdp_layer->colormap.colors); - self->rdp_layer->mod->server_set_bgcolor(self->rdp_layer->mod, bgcolor); - self->rdp_layer->mod->server_set_brush(self->rdp_layer->mod, - self->state.pat_brush.xorigin, - self->state.pat_brush.yorigin, - self->state.pat_brush.style, - self->state.pat_brush.pattern); - self->rdp_layer->mod->server_fill_rect(self->rdp_layer->mod, - self->state.pat_x, - self->state.pat_y, - self->state.pat_cx, - self->state.pat_cy); - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); - self->rdp_layer->mod->server_set_mixmode(self->rdp_layer->mod, 0); - if (self->rdp_layer->rec_mode) - { - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, 512); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 5); - out_uint16_le(rec_s, self->state.pat_x); - out_uint16_le(rec_s, self->state.pat_y); - out_uint16_le(rec_s, self->state.pat_cx); - out_uint16_le(rec_s, self->state.pat_cy); - out_uint8(rec_s, self->state.pat_opcode); - out_uint32_le(rec_s, self->state.pat_fgcolor); - out_uint32_le(rec_s, self->state.pat_bgcolor); - out_uint8(rec_s, self->state.pat_brush.xorigin); - out_uint8(rec_s, self->state.pat_brush.yorigin); - out_uint8(rec_s, self->state.pat_brush.style); - out_uint8a(rec_s, self->state.pat_brush.pattern, 8); - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } + int fgcolor = 0; + int bgcolor = 0; + struct stream *rec_s = (struct stream *)NULL; + + if (present & 0x0001) + { + rdp_orders_in_coord(s, &self->state.pat_x, delta); + } + + if (present & 0x0002) + { + rdp_orders_in_coord(s, &self->state.pat_y, delta); + } + + if (present & 0x0004) + { + rdp_orders_in_coord(s, &self->state.pat_cx, delta); + } + + if (present & 0x0008) + { + rdp_orders_in_coord(s, &self->state.pat_cy, delta); + } + + if (present & 0x0010) + { + in_uint8(s, self->state.pat_opcode); + } + + if (present & 0x0020) + { + rdp_orders_in_color(s, &self->state.pat_bgcolor); + } + + if (present & 0x0040) + { + rdp_orders_in_color(s, &self->state.pat_fgcolor); + } + + rdp_orders_parse_brush(s, &self->state.pat_brush, present >> 7); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.pat_opcode); + self->rdp_layer->mod->server_set_mixmode(self->rdp_layer->mod, 1); + fgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, + self->rdp_layer->mod->xrdp_bpp, + self->state.pat_fgcolor, + self->rdp_layer->colormap.colors); + self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, fgcolor); + bgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, + self->rdp_layer->mod->xrdp_bpp, + self->state.pat_bgcolor, + self->rdp_layer->colormap.colors); + self->rdp_layer->mod->server_set_bgcolor(self->rdp_layer->mod, bgcolor); + self->rdp_layer->mod->server_set_brush(self->rdp_layer->mod, + self->state.pat_brush.xorigin, + self->state.pat_brush.yorigin, + self->state.pat_brush.style, + self->state.pat_brush.pattern); + self->rdp_layer->mod->server_fill_rect(self->rdp_layer->mod, + self->state.pat_x, + self->state.pat_y, + self->state.pat_cx, + self->state.pat_cy); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); + self->rdp_layer->mod->server_set_mixmode(self->rdp_layer->mod, 0); + + if (self->rdp_layer->rec_mode) + { + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, 512); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 5); + out_uint16_le(rec_s, self->state.pat_x); + out_uint16_le(rec_s, self->state.pat_y); + out_uint16_le(rec_s, self->state.pat_cx); + out_uint16_le(rec_s, self->state.pat_cy); + out_uint8(rec_s, self->state.pat_opcode); + out_uint32_le(rec_s, self->state.pat_fgcolor); + out_uint32_le(rec_s, self->state.pat_bgcolor); + out_uint8(rec_s, self->state.pat_brush.xorigin); + out_uint8(rec_s, self->state.pat_brush.yorigin); + out_uint8(rec_s, self->state.pat_brush.style); + out_uint8a(rec_s, self->state.pat_brush.pattern, 8); + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } } /*****************************************************************************/ /* Process a screen blt order */ static void APP_CC -rdp_orders_process_screenblt(struct rdp_orders* self, struct stream* s, +rdp_orders_process_screenblt(struct rdp_orders *self, struct stream *s, int present, int delta) { - struct stream* rec_s; - - if (present & 0x0001) - { - rdp_orders_in_coord(s, &self->state.screenblt_x, delta); - } - if (present & 0x0002) - { - rdp_orders_in_coord(s, &self->state.screenblt_y, delta); - } - if (present & 0x0004) - { - rdp_orders_in_coord(s, &self->state.screenblt_cx, delta); - } - if (present & 0x0008) - { - rdp_orders_in_coord(s, &self->state.screenblt_cy, delta); - } - if (present & 0x0010) - { - in_uint8(s, self->state.screenblt_opcode); - } - if (present & 0x0020) - { - rdp_orders_in_coord(s, &self->state.screenblt_srcx, delta); - } - if (present & 0x0040) - { - rdp_orders_in_coord(s, &self->state.screenblt_srcy, delta); - } - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, - self->state.screenblt_opcode); - self->rdp_layer->mod->server_screen_blt(self->rdp_layer->mod, - self->state.screenblt_x, - self->state.screenblt_y, - self->state.screenblt_cx, - self->state.screenblt_cy, - self->state.screenblt_srcx, - self->state.screenblt_srcy); - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); - if (self->rdp_layer->rec_mode) - { - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, 512); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 4); - out_uint16_le(rec_s, self->state.screenblt_x); - out_uint16_le(rec_s, self->state.screenblt_y); - out_uint16_le(rec_s, self->state.screenblt_cx); - out_uint16_le(rec_s, self->state.screenblt_cy); - out_uint16_le(rec_s, self->state.screenblt_srcx); - out_uint16_le(rec_s, self->state.screenblt_srcy); - out_uint8(rec_s, self->state.screenblt_opcode); - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } + struct stream *rec_s; + + if (present & 0x0001) + { + rdp_orders_in_coord(s, &self->state.screenblt_x, delta); + } + + if (present & 0x0002) + { + rdp_orders_in_coord(s, &self->state.screenblt_y, delta); + } + + if (present & 0x0004) + { + rdp_orders_in_coord(s, &self->state.screenblt_cx, delta); + } + + if (present & 0x0008) + { + rdp_orders_in_coord(s, &self->state.screenblt_cy, delta); + } + + if (present & 0x0010) + { + in_uint8(s, self->state.screenblt_opcode); + } + + if (present & 0x0020) + { + rdp_orders_in_coord(s, &self->state.screenblt_srcx, delta); + } + + if (present & 0x0040) + { + rdp_orders_in_coord(s, &self->state.screenblt_srcy, delta); + } + + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.screenblt_opcode); + self->rdp_layer->mod->server_screen_blt(self->rdp_layer->mod, + self->state.screenblt_x, + self->state.screenblt_y, + self->state.screenblt_cx, + self->state.screenblt_cy, + self->state.screenblt_srcx, + self->state.screenblt_srcy); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); + + if (self->rdp_layer->rec_mode) + { + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, 512); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 4); + out_uint16_le(rec_s, self->state.screenblt_x); + out_uint16_le(rec_s, self->state.screenblt_y); + out_uint16_le(rec_s, self->state.screenblt_cx); + out_uint16_le(rec_s, self->state.screenblt_cy); + out_uint16_le(rec_s, self->state.screenblt_srcx); + out_uint16_le(rec_s, self->state.screenblt_srcy); + out_uint8(rec_s, self->state.screenblt_opcode); + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } } /*****************************************************************************/ /* Process a line order */ static void APP_CC -rdp_orders_process_line(struct rdp_orders* self, struct stream* s, +rdp_orders_process_line(struct rdp_orders *self, struct stream *s, int present, int delta) { - int bgcolor = 0; - int fgcolor = 0; - struct stream* rec_s = (struct stream *)NULL; - - if (present & 0x0001) - { - in_uint16_le(s, self->state.line_mixmode); - } - if (present & 0x0002) - { - rdp_orders_in_coord(s, &self->state.line_startx, delta); - } - if (present & 0x0004) - { - rdp_orders_in_coord(s, &self->state.line_starty, delta); - } - if (present & 0x0008) - { - rdp_orders_in_coord(s, &self->state.line_endx, delta); - } - if (present & 0x0010) - { - rdp_orders_in_coord(s, &self->state.line_endy, delta); - } - if (present & 0x0020) - { - rdp_orders_in_color(s, &self->state.line_bgcolor); - } - if (present & 0x0040) - { - in_uint8(s, self->state.line_opcode); - } - rdp_orders_parse_pen(s, &self->state.line_pen, present >> 7); - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, - self->state.line_opcode); - bgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, - self->rdp_layer->mod->xrdp_bpp, - self->state.line_bgcolor, - self->rdp_layer->colormap.colors); - fgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, - self->rdp_layer->mod->xrdp_bpp, - self->state.line_pen.color, - self->rdp_layer->colormap.colors); - self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, fgcolor); - self->rdp_layer->mod->server_set_bgcolor(self->rdp_layer->mod, bgcolor); - self->rdp_layer->mod->server_set_pen(self->rdp_layer->mod, - self->state.line_pen.style, - self->state.line_pen.width); - self->rdp_layer->mod->server_draw_line(self->rdp_layer->mod, - self->state.line_startx, - self->state.line_starty, - self->state.line_endx, - self->state.line_endy); - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); - if (self->rdp_layer->rec_mode) - { - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, 512); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 3); - out_uint16_le(rec_s, self->state.line_mixmode); - out_uint16_le(rec_s, self->state.line_startx); - out_uint16_le(rec_s, self->state.line_starty); - out_uint16_le(rec_s, self->state.line_endx); - out_uint16_le(rec_s, self->state.line_endy); - out_uint32_le(rec_s, self->state.line_bgcolor); - out_uint8(rec_s, self->state.line_opcode); - out_uint8(rec_s, self->state.line_pen.style); - out_uint8(rec_s, self->state.line_pen.width); - out_uint32_le(rec_s, self->state.line_pen.color); - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } + int bgcolor = 0; + int fgcolor = 0; + struct stream *rec_s = (struct stream *)NULL; + + if (present & 0x0001) + { + in_uint16_le(s, self->state.line_mixmode); + } + + if (present & 0x0002) + { + rdp_orders_in_coord(s, &self->state.line_startx, delta); + } + + if (present & 0x0004) + { + rdp_orders_in_coord(s, &self->state.line_starty, delta); + } + + if (present & 0x0008) + { + rdp_orders_in_coord(s, &self->state.line_endx, delta); + } + + if (present & 0x0010) + { + rdp_orders_in_coord(s, &self->state.line_endy, delta); + } + + if (present & 0x0020) + { + rdp_orders_in_color(s, &self->state.line_bgcolor); + } + + if (present & 0x0040) + { + in_uint8(s, self->state.line_opcode); + } + + rdp_orders_parse_pen(s, &self->state.line_pen, present >> 7); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.line_opcode); + bgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, + self->rdp_layer->mod->xrdp_bpp, + self->state.line_bgcolor, + self->rdp_layer->colormap.colors); + fgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, + self->rdp_layer->mod->xrdp_bpp, + self->state.line_pen.color, + self->rdp_layer->colormap.colors); + self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, fgcolor); + self->rdp_layer->mod->server_set_bgcolor(self->rdp_layer->mod, bgcolor); + self->rdp_layer->mod->server_set_pen(self->rdp_layer->mod, + self->state.line_pen.style, + self->state.line_pen.width); + self->rdp_layer->mod->server_draw_line(self->rdp_layer->mod, + self->state.line_startx, + self->state.line_starty, + self->state.line_endx, + self->state.line_endy); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); + + if (self->rdp_layer->rec_mode) + { + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, 512); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 3); + out_uint16_le(rec_s, self->state.line_mixmode); + out_uint16_le(rec_s, self->state.line_startx); + out_uint16_le(rec_s, self->state.line_starty); + out_uint16_le(rec_s, self->state.line_endx); + out_uint16_le(rec_s, self->state.line_endy); + out_uint32_le(rec_s, self->state.line_bgcolor); + out_uint8(rec_s, self->state.line_opcode); + out_uint8(rec_s, self->state.line_pen.style); + out_uint8(rec_s, self->state.line_pen.width); + out_uint32_le(rec_s, self->state.line_pen.color); + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } } /*****************************************************************************/ /* Process an opaque rectangle order */ static void APP_CC -rdp_orders_process_rect(struct rdp_orders* self, struct stream* s, +rdp_orders_process_rect(struct rdp_orders *self, struct stream *s, int present, int delta) { - int i = 0; - int fgcolor = 0; - struct stream* rec_s = (struct stream *)NULL; - - if (present & 0x01) - { - rdp_orders_in_coord(s, &self->state.rect_x, delta); - } - if (present & 0x02) - { - rdp_orders_in_coord(s, &self->state.rect_y, delta); - } - if (present & 0x04) - { - rdp_orders_in_coord(s, &self->state.rect_cx, delta); - } - if (present & 0x08) - { - rdp_orders_in_coord(s, &self->state.rect_cy, delta); - } - if (present & 0x10) - { - in_uint8(s, i); - self->state.rect_color = (self->state.rect_color & 0xffffff00) | i; - } - if (present & 0x20) - { - in_uint8(s, i); - self->state.rect_color = (self->state.rect_color & 0xffff00ff) | (i << 8); - } - if (present & 0x40) - { - in_uint8(s, i); - self->state.rect_color = (self->state.rect_color & 0xff00ffff) | (i << 16); - } - fgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, - self->rdp_layer->mod->xrdp_bpp, - self->state.rect_color, - self->rdp_layer->colormap.colors); - self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, fgcolor); - self->rdp_layer->mod->server_fill_rect(self->rdp_layer->mod, - self->state.rect_x, - self->state.rect_y, - self->state.rect_cx, - self->state.rect_cy); - if (self->rdp_layer->rec_mode) - { - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, 512); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 1); - out_uint16_le(rec_s, self->state.rect_x); - out_uint16_le(rec_s, self->state.rect_y); - out_uint16_le(rec_s, self->state.rect_cx); - out_uint16_le(rec_s, self->state.rect_cy); - out_uint32_le(rec_s, self->state.rect_color); - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } + int i = 0; + int fgcolor = 0; + struct stream *rec_s = (struct stream *)NULL; + + if (present & 0x01) + { + rdp_orders_in_coord(s, &self->state.rect_x, delta); + } + + if (present & 0x02) + { + rdp_orders_in_coord(s, &self->state.rect_y, delta); + } + + if (present & 0x04) + { + rdp_orders_in_coord(s, &self->state.rect_cx, delta); + } + + if (present & 0x08) + { + rdp_orders_in_coord(s, &self->state.rect_cy, delta); + } + + if (present & 0x10) + { + in_uint8(s, i); + self->state.rect_color = (self->state.rect_color & 0xffffff00) | i; + } + + if (present & 0x20) + { + in_uint8(s, i); + self->state.rect_color = (self->state.rect_color & 0xffff00ff) | (i << 8); + } + + if (present & 0x40) + { + in_uint8(s, i); + self->state.rect_color = (self->state.rect_color & 0xff00ffff) | (i << 16); + } + + fgcolor = rdp_orders_convert_color(self->rdp_layer->mod->rdp_bpp, + self->rdp_layer->mod->xrdp_bpp, + self->state.rect_color, + self->rdp_layer->colormap.colors); + self->rdp_layer->mod->server_set_fgcolor(self->rdp_layer->mod, fgcolor); + self->rdp_layer->mod->server_fill_rect(self->rdp_layer->mod, + self->state.rect_x, + self->state.rect_y, + self->state.rect_cx, + self->state.rect_cy); + + if (self->rdp_layer->rec_mode) + { + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, 512); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 1); + out_uint16_le(rec_s, self->state.rect_x); + out_uint16_le(rec_s, self->state.rect_y); + out_uint16_le(rec_s, self->state.rect_cx); + out_uint16_le(rec_s, self->state.rect_cy); + out_uint32_le(rec_s, self->state.rect_color); + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } } /*****************************************************************************/ /* Process a desktop save order */ static void APP_CC -rdp_orders_process_desksave(struct rdp_orders* self, struct stream* s, +rdp_orders_process_desksave(struct rdp_orders *self, struct stream *s, int present, int delta) { - int width = 0; - int height = 0; - - if (present & 0x01) - { - in_uint32_le(s, self->state.desksave_offset); - } - if (present & 0x02) - { - rdp_orders_in_coord(s, &self->state.desksave_left, delta); - } - if (present & 0x04) - { - rdp_orders_in_coord(s, &self->state.desksave_top, delta); - } - if (present & 0x08) - { - rdp_orders_in_coord(s, &self->state.desksave_right, delta); - } - if (present & 0x10) - { - rdp_orders_in_coord(s, &self->state.desksave_bottom, delta); - } - if (present & 0x20) - { - in_uint8(s, self->state.desksave_action); - } -// width = (self->state.desksave_right - self->state.desksave_left) + 1; -// height = (self->state.desksave_bottom - self->state.desksave_top) + 1; - if (self->state.desksave_action == 0) - { -// ui_desktop_save(os->offset, os->left, os->top, width, height); - } - else - { -// ui_desktop_restore(os->offset, os->left, os->top, width, height); - } + int width = 0; + int height = 0; + + if (present & 0x01) + { + in_uint32_le(s, self->state.desksave_offset); + } + + if (present & 0x02) + { + rdp_orders_in_coord(s, &self->state.desksave_left, delta); + } + + if (present & 0x04) + { + rdp_orders_in_coord(s, &self->state.desksave_top, delta); + } + + if (present & 0x08) + { + rdp_orders_in_coord(s, &self->state.desksave_right, delta); + } + + if (present & 0x10) + { + rdp_orders_in_coord(s, &self->state.desksave_bottom, delta); + } + + if (present & 0x20) + { + in_uint8(s, self->state.desksave_action); + } + + // width = (self->state.desksave_right - self->state.desksave_left) + 1; + // height = (self->state.desksave_bottom - self->state.desksave_top) + 1; + if (self->state.desksave_action == 0) + { + // ui_desktop_save(os->offset, os->left, os->top, width, height); + } + else + { + // ui_desktop_restore(os->offset, os->left, os->top, width, height); + } } /*****************************************************************************/ /* Process a memory blt order */ static void APP_CC -rdp_orders_process_memblt(struct rdp_orders* self, struct stream* s, +rdp_orders_process_memblt(struct rdp_orders *self, struct stream *s, int present, int delta) { - struct rdp_bitmap* bitmap = (struct rdp_bitmap *)NULL; - struct stream* rec_s = (struct stream *)NULL; - char* bmpdata = (char *)NULL; - - if (present & 0x0001) - { - in_uint8(s, self->state.memblt_cache_id); - in_uint8(s, self->state.memblt_color_table); - } - if (present & 0x0002) - { - rdp_orders_in_coord(s, &self->state.memblt_x, delta); - } - if (present & 0x0004) - { - rdp_orders_in_coord(s, &self->state.memblt_y, delta); - } - if (present & 0x0008) - { - rdp_orders_in_coord(s, &self->state.memblt_cx, delta); - } - if (present & 0x0010) - { - rdp_orders_in_coord(s, &self->state.memblt_cy, delta); - } - if (present & 0x0020) - { - in_uint8(s, self->state.memblt_opcode); - } - if (present & 0x0040) - { - rdp_orders_in_coord(s, &self->state.memblt_srcx, delta); - } - if (present & 0x0080) - { - rdp_orders_in_coord(s, &self->state.memblt_srcy, delta); - } - if (present & 0x0100) - { - in_uint16_le(s, self->state.memblt_cache_idx); - } - bitmap = self->cache_bitmap[self->state.memblt_cache_id] - [self->state.memblt_cache_idx]; - if (bitmap != 0) - { - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, - self->state.memblt_opcode); - bmpdata = rdp_orders_convert_bitmap(self->rdp_layer->mod->rdp_bpp, - self->rdp_layer->mod->xrdp_bpp, - bitmap->data, bitmap->width, - bitmap->height, - self->cache_colormap - [self->state.memblt_color_table]->colors); - self->rdp_layer->mod->server_paint_rect(self->rdp_layer->mod, - self->state.memblt_x, - self->state.memblt_y, - self->state.memblt_cx, - self->state.memblt_cy, - bmpdata, - bitmap->width, - bitmap->height, - self->state.memblt_srcx, - self->state.memblt_srcy); - self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); - if (self->rdp_layer->rec_mode) + struct rdp_bitmap *bitmap = (struct rdp_bitmap *)NULL; + struct stream *rec_s = (struct stream *)NULL; + char *bmpdata = (char *)NULL; + + if (present & 0x0001) + { + in_uint8(s, self->state.memblt_cache_id); + in_uint8(s, self->state.memblt_color_table); + } + + if (present & 0x0002) + { + rdp_orders_in_coord(s, &self->state.memblt_x, delta); + } + + if (present & 0x0004) { - rdp_rec_check_file(self->rdp_layer); - make_stream(rec_s); - init_stream(rec_s, 512); - s_push_layer(rec_s, iso_hdr, 4); - out_uint8(rec_s, 2); - out_uint8(rec_s, self->state.memblt_opcode); - out_uint16_le(rec_s, self->state.memblt_x); - out_uint16_le(rec_s, self->state.memblt_y); - out_uint16_le(rec_s, self->state.memblt_cx); - out_uint16_le(rec_s, self->state.memblt_cy); - out_uint16_le(rec_s, self->state.memblt_cache_id); - out_uint16_le(rec_s, self->state.memblt_cache_idx); - out_uint16_le(rec_s, self->state.memblt_srcx); - out_uint16_le(rec_s, self->state.memblt_srcy); - rdp_rec_write_item(self->rdp_layer, rec_s); - free_stream(rec_s); - } - if (bmpdata != bitmap->data) - { - g_free(bmpdata); - } - } + rdp_orders_in_coord(s, &self->state.memblt_y, delta); + } + + if (present & 0x0008) + { + rdp_orders_in_coord(s, &self->state.memblt_cx, delta); + } + + if (present & 0x0010) + { + rdp_orders_in_coord(s, &self->state.memblt_cy, delta); + } + + if (present & 0x0020) + { + in_uint8(s, self->state.memblt_opcode); + } + + if (present & 0x0040) + { + rdp_orders_in_coord(s, &self->state.memblt_srcx, delta); + } + + if (present & 0x0080) + { + rdp_orders_in_coord(s, &self->state.memblt_srcy, delta); + } + + if (present & 0x0100) + { + in_uint16_le(s, self->state.memblt_cache_idx); + } + + bitmap = self->cache_bitmap[self->state.memblt_cache_id] + [self->state.memblt_cache_idx]; + + if (bitmap != 0) + { + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, + self->state.memblt_opcode); + bmpdata = rdp_orders_convert_bitmap(self->rdp_layer->mod->rdp_bpp, + self->rdp_layer->mod->xrdp_bpp, + bitmap->data, bitmap->width, + bitmap->height, + self->cache_colormap + [self->state.memblt_color_table]->colors); + self->rdp_layer->mod->server_paint_rect(self->rdp_layer->mod, + self->state.memblt_x, + self->state.memblt_y, + self->state.memblt_cx, + self->state.memblt_cy, + bmpdata, + bitmap->width, + bitmap->height, + self->state.memblt_srcx, + self->state.memblt_srcy); + self->rdp_layer->mod->server_set_opcode(self->rdp_layer->mod, 0xcc); + + if (self->rdp_layer->rec_mode) + { + rdp_rec_check_file(self->rdp_layer); + make_stream(rec_s); + init_stream(rec_s, 512); + s_push_layer(rec_s, iso_hdr, 4); + out_uint8(rec_s, 2); + out_uint8(rec_s, self->state.memblt_opcode); + out_uint16_le(rec_s, self->state.memblt_x); + out_uint16_le(rec_s, self->state.memblt_y); + out_uint16_le(rec_s, self->state.memblt_cx); + out_uint16_le(rec_s, self->state.memblt_cy); + out_uint16_le(rec_s, self->state.memblt_cache_id); + out_uint16_le(rec_s, self->state.memblt_cache_idx); + out_uint16_le(rec_s, self->state.memblt_srcx); + out_uint16_le(rec_s, self->state.memblt_srcy); + rdp_rec_write_item(self->rdp_layer, rec_s); + free_stream(rec_s); + } + + if (bmpdata != bitmap->data) + { + g_free(bmpdata); + } + } } /*****************************************************************************/ /* Process a 3-way blt order */ static void APP_CC -rdp_orders_process_triblt(struct rdp_orders* self, struct stream* s, +rdp_orders_process_triblt(struct rdp_orders *self, struct stream *s, int present, int delta) { - /* not used */ + /* not used */ } /*****************************************************************************/ /* Process a polyline order */ static void APP_CC -rdp_orders_process_polyline(struct rdp_orders* self, struct stream* s, +rdp_orders_process_polyline(struct rdp_orders *self, struct stream *s, int present, int delta) { - if (present & 0x01) - { - rdp_orders_in_coord(s, &self->state.polyline_x, delta); - } - if (present & 0x02) - { - rdp_orders_in_coord(s, &self->state.polyline_y, delta); - } - if (present & 0x04) - { - in_uint8(s, self->state.polyline_opcode); - } - if (present & 0x10) - { - rdp_orders_in_color(s, &self->state.polyline_fgcolor); - } - if (present & 0x20) - { - in_uint8(s, self->state.polyline_lines); - } - if (present & 0x40) - { - in_uint8(s, self->state.polyline_datasize); - in_uint8a(s, self->state.polyline_data, self->state.polyline_datasize); - } - /* todo */ + if (present & 0x01) + { + rdp_orders_in_coord(s, &self->state.polyline_x, delta); + } + + if (present & 0x02) + { + rdp_orders_in_coord(s, &self->state.polyline_y, delta); + } + + if (present & 0x04) + { + in_uint8(s, self->state.polyline_opcode); + } + + if (present & 0x10) + { + rdp_orders_in_color(s, &self->state.polyline_fgcolor); + } + + if (present & 0x20) + { + in_uint8(s, self->state.polyline_lines); + } + + if (present & 0x40) + { + in_uint8(s, self->state.polyline_datasize); + in_uint8a(s, self->state.polyline_data, self->state.polyline_datasize); + } + + /* todo */ } /*****************************************************************************/ int APP_CC -rdp_orders_process_orders(struct rdp_orders* self, struct stream* s, +rdp_orders_process_orders(struct rdp_orders *self, struct stream *s, int num_orders) { - int processed = 0; - int order_flags = 0; - int size = 0; - int present = 0; - int delta = 0; + int processed = 0; + int order_flags = 0; + int size = 0; + int present = 0; + int delta = 0; - processed = 0; - while (processed < num_orders) - { - in_uint8(s, order_flags); - if (!(order_flags & RDP_ORDER_STANDARD)) + processed = 0; + + while (processed < num_orders) { - /* error, this should always be set */ - break; + in_uint8(s, order_flags); + + if (!(order_flags & RDP_ORDER_STANDARD)) + { + /* error, this should always be set */ + break; + } + + if (order_flags & RDP_ORDER_SECONDARY) + { + rdp_orders_process_secondary_order(self, s); + } + else + { + if (order_flags & RDP_ORDER_CHANGE) + { + in_uint8(s, self->state.order_type); + } + + switch (self->state.order_type) + { + case RDP_ORDER_TRIBLT: + case RDP_ORDER_TEXT2: + size = 3; + break; + case RDP_ORDER_PATBLT: + case RDP_ORDER_MEMBLT: + case RDP_ORDER_LINE: + size = 2; + break; + default: + size = 1; + break; + } + + rdp_orders_in_present(s, &present, order_flags, size); + + if (order_flags & RDP_ORDER_BOUNDS) + { + if (!(order_flags & RDP_ORDER_LASTBOUNDS)) + { + rdp_orders_parse_bounds(self, s); + } + + self->rdp_layer->mod->server_set_clip(self->rdp_layer->mod, + self->state.clip_left, + self->state.clip_top, + (self->state.clip_right - self->state.clip_left) + 1, + (self->state.clip_bottom - self->state.clip_top) + 1); + } + + delta = order_flags & RDP_ORDER_DELTA; + + switch (self->state.order_type) + { + case RDP_ORDER_TEXT2: + rdp_orders_process_text2(self, s, present, delta); + break; + case RDP_ORDER_DESTBLT: + rdp_orders_process_destblt(self, s, present, delta); + break; + case RDP_ORDER_PATBLT: + rdp_orders_process_patblt(self, s, present, delta); + break; + case RDP_ORDER_SCREENBLT: + rdp_orders_process_screenblt(self, s, present, delta); + break; + case RDP_ORDER_LINE: + rdp_orders_process_line(self, s, present, delta); + break; + case RDP_ORDER_RECT: + rdp_orders_process_rect(self, s, present, delta); + break; + case RDP_ORDER_DESKSAVE: + rdp_orders_process_desksave(self, s, present, delta); + break; + case RDP_ORDER_MEMBLT: + rdp_orders_process_memblt(self, s, present, delta); + break; + case RDP_ORDER_TRIBLT: + rdp_orders_process_triblt(self, s, present, delta); + break; + case RDP_ORDER_POLYLINE: + rdp_orders_process_polyline(self, s, present, delta); + break; + default: + /* error unknown order */ + break; + } + + if (order_flags & RDP_ORDER_BOUNDS) + { + self->rdp_layer->mod->server_reset_clip(self->rdp_layer->mod); + } + } + + processed++; } - if (order_flags & RDP_ORDER_SECONDARY) + + return 0; +} + +/*****************************************************************************/ +/* returns pointer, it might return bmpdata if the data dosen't need to + be converted, else it mallocs it. The calling function must free + it if needed */ +char *APP_CC +rdp_orders_convert_bitmap(int in_bpp, int out_bpp, char *bmpdata, + int width, int height, int *palette) +{ + char *out = (char *)NULL; + char *src = (char *)NULL; + char *dst = (char *)NULL; + int i = 0; + int j = 0; + int red = 0; + int green = 0; + int blue = 0; + int pixel = 0; + + if ((in_bpp == 8) && (out_bpp == 8)) { - rdp_orders_process_secondary_order(self, s); + out = (char *)g_malloc(width * height, 0); + src = bmpdata; + dst = out; + + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + pixel = *((tui8 *)src); + pixel = palette[pixel]; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR8(red, green, blue); + *dst = pixel; + src++; + dst++; + } + } + + return out; } - else + + if ((in_bpp == 8) && (out_bpp == 16)) { - if (order_flags & RDP_ORDER_CHANGE) - { - in_uint8(s, self->state.order_type); - } - switch (self->state.order_type) - { - case RDP_ORDER_TRIBLT: - case RDP_ORDER_TEXT2: - size = 3; - break; - case RDP_ORDER_PATBLT: - case RDP_ORDER_MEMBLT: - case RDP_ORDER_LINE: - size = 2; - break; - default: - size = 1; - break; - } - rdp_orders_in_present(s, &present, order_flags, size); - if (order_flags & RDP_ORDER_BOUNDS) - { - if (!(order_flags & RDP_ORDER_LASTBOUNDS)) + out = (char *)g_malloc(width * height * 2, 0); + src = bmpdata; + dst = out; + + for (i = 0; i < height; i++) { - rdp_orders_parse_bounds(self, s); + for (j = 0; j < width; j++) + { + pixel = *((tui8 *)src); + pixel = palette[pixel]; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR16(red, green, blue); + *((tui16 *)dst) = pixel; + src++; + dst += 2; + } } - self->rdp_layer->mod->server_set_clip(self->rdp_layer->mod, - self->state.clip_left, - self->state.clip_top, - (self->state.clip_right - self->state.clip_left) + 1, - (self->state.clip_bottom - self->state.clip_top) + 1); - } - delta = order_flags & RDP_ORDER_DELTA; - switch (self->state.order_type) - { - case RDP_ORDER_TEXT2: - rdp_orders_process_text2(self, s, present, delta); - break; - case RDP_ORDER_DESTBLT: - rdp_orders_process_destblt(self, s, present, delta); - break; - case RDP_ORDER_PATBLT: - rdp_orders_process_patblt(self, s, present, delta); - break; - case RDP_ORDER_SCREENBLT: - rdp_orders_process_screenblt(self, s, present, delta); - break; - case RDP_ORDER_LINE: - rdp_orders_process_line(self, s, present, delta); - break; - case RDP_ORDER_RECT: - rdp_orders_process_rect(self, s, present, delta); - break; - case RDP_ORDER_DESKSAVE: - rdp_orders_process_desksave(self, s, present, delta); - break; - case RDP_ORDER_MEMBLT: - rdp_orders_process_memblt(self, s, present, delta); - break; - case RDP_ORDER_TRIBLT: - rdp_orders_process_triblt(self, s, present, delta); - break; - case RDP_ORDER_POLYLINE: - rdp_orders_process_polyline(self, s, present, delta); - break; - default: - /* error unknown order */ - break; - } - if (order_flags & RDP_ORDER_BOUNDS) - { - self->rdp_layer->mod->server_reset_clip(self->rdp_layer->mod); - } - } - processed++; - } - return 0; + + return out; + } + + if ((in_bpp == 8) && (out_bpp == 24)) + { + out = (char *)g_malloc(width * height * 4, 0); + src = bmpdata; + dst = out; + + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + pixel = *((tui8 *)src); + pixel = palette[pixel]; + SPLITCOLOR32(red, green, blue, pixel); + pixel = COLOR24RGB(red, green, blue); + *((tui32 *)dst) = pixel; + src++; + dst += 4; + } + } + + return out; + } + + if ((in_bpp == 15) && (out_bpp == 16)) + { + out = (char *)g_malloc(width * height * 2, 0); + src = bmpdata; + dst = out; + + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + pixel = *((tui16 *)src); + SPLITCOLOR15(red, green, blue, pixel); + pixel = COLOR16(red, green, blue); + *((tui16 *)dst) = pixel; + src += 2; + dst += 2; + } + } + + return out; + } + + if ((in_bpp == 15) && (out_bpp == 24)) + { + out = (char *)g_malloc(width * height * 4, 0); + src = bmpdata; + dst = out; + + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + pixel = *((tui16 *)src); + SPLITCOLOR15(red, green, blue, pixel); + pixel = COLOR24RGB(red, green, blue); + *((tui32 *)dst) = pixel; + src += 2; + dst += 4; + } + } + + return out; + } + + if ((in_bpp == 16) && (out_bpp == 16)) + { + return bmpdata; + } + + if ((in_bpp == 16) && (out_bpp == 24)) + { + out = (char *)g_malloc(width * height * 4, 0); + src = bmpdata; + dst = out; + + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + pixel = *((tui16 *)src); + SPLITCOLOR16(red, green, blue, pixel); + pixel = COLOR24RGB(red, green, blue); + *((tui32 *)dst) = pixel; + src += 2; + dst += 4; + } + } + + return out; + } + + if ((in_bpp == 24) && (out_bpp == 24)) + { + out = (char *)g_malloc(width * height * 4, 0); + src = bmpdata; + dst = out; + + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + blue = *((tui8 *)src); + src++; + green = *((tui8 *)src); + src++; + red = *((tui8 *)src); + src++; + pixel = COLOR24RGB(red, green, blue); + *((tui32 *)dst) = pixel; + dst += 4; + } + } + + return out; + } + + return 0; } /*****************************************************************************/ -/* returns pointer, it might return bmpdata if the data dosen't need to - be converted, else it mallocs it. The calling function must free - it if needed */ -char* APP_CC -rdp_orders_convert_bitmap(int in_bpp, int out_bpp, char* bmpdata, - int width, int height, int* palette) +/* returns color or 0 */ +int APP_CC +rdp_orders_convert_color(int in_bpp, int out_bpp, int in_color, int *palette) { - char* out = (char *)NULL; - char* src = (char *)NULL; - char* dst = (char *)NULL; - int i = 0; - int j = 0; - int red = 0; - int green = 0; - int blue = 0; - int pixel = 0; - - if ((in_bpp == 8) && (out_bpp == 8)) - { - out = (char*)g_malloc(width * height, 0); - src = bmpdata; - dst = out; - for (i = 0; i < height; i++) - { - for (j = 0; j < width; j++) - { - pixel = *((tui8*)src); - pixel = palette[pixel]; + int pixel = 0; + int red = 0; + int green = 0; + int blue = 0; + + if ((in_bpp == 8) && (out_bpp == 8)) + { + pixel = palette[in_color]; SPLITCOLOR32(red, green, blue, pixel); pixel = COLOR8(red, green, blue); - *dst = pixel; - src++; - dst++; - } - } - return out; - } - if ((in_bpp == 8) && (out_bpp == 16)) - { - out = (char*)g_malloc(width * height * 2, 0); - src = bmpdata; - dst = out; - for (i = 0; i < height; i++) - { - for (j = 0; j < width; j++) - { - pixel = *((tui8*)src); - pixel = palette[pixel]; + return pixel; + } + + if ((in_bpp == 8) && (out_bpp == 16)) + { + pixel = palette[in_color]; SPLITCOLOR32(red, green, blue, pixel); pixel = COLOR16(red, green, blue); - *((tui16*)dst) = pixel; - src++; - dst += 2; - } - } - return out; - } - if ((in_bpp == 8) && (out_bpp == 24)) - { - out = (char*)g_malloc(width * height * 4, 0); - src = bmpdata; - dst = out; - for (i = 0; i < height; i++) - { - for (j = 0; j < width; j++) - { - pixel = *((tui8*)src); - pixel = palette[pixel]; + return pixel; + } + + if ((in_bpp == 8) && (out_bpp == 24)) + { + pixel = palette[in_color]; SPLITCOLOR32(red, green, blue, pixel); - pixel = COLOR24RGB(red, green, blue); - *((tui32*)dst) = pixel; - src++; - dst += 4; - } - } - return out; - } - if ((in_bpp == 15) && (out_bpp == 16)) - { - out = (char*)g_malloc(width * height * 2, 0); - src = bmpdata; - dst = out; - for (i = 0; i < height; i++) - { - for (j = 0; j < width; j++) - { - pixel = *((tui16*)src); + pixel = COLOR24BGR(red, green, blue); + return pixel; + } + + if ((in_bpp == 15) && (out_bpp == 16)) + { + pixel = in_color; SPLITCOLOR15(red, green, blue, pixel); pixel = COLOR16(red, green, blue); - *((tui16*)dst) = pixel; - src += 2; - dst += 2; - } - } - return out; - } - if ((in_bpp == 15) && (out_bpp == 24)) - { - out = (char*)g_malloc(width * height * 4, 0); - src = bmpdata; - dst = out; - for (i = 0; i < height; i++) - { - for (j = 0; j < width; j++) - { - pixel = *((tui16*)src); + return pixel; + } + + if ((in_bpp == 15) && (out_bpp == 24)) + { + pixel = in_color; SPLITCOLOR15(red, green, blue, pixel); - pixel = COLOR24RGB(red, green, blue); - *((tui32*)dst) = pixel; - src += 2; - dst += 4; - } - } - return out; - } - if ((in_bpp == 16) && (out_bpp == 16)) - { - return bmpdata; - } - if ((in_bpp == 16) && (out_bpp == 24)) - { - out = (char*)g_malloc(width * height * 4, 0); - src = bmpdata; - dst = out; - for (i = 0; i < height; i++) - { - for (j = 0; j < width; j++) - { - pixel = *((tui16*)src); + pixel = COLOR24BGR(red, green, blue); + return pixel; + } + + if ((in_bpp == 16) && (out_bpp == 16)) + { + return in_color; + } + + if ((in_bpp == 16) && (out_bpp == 24)) + { + pixel = in_color; SPLITCOLOR16(red, green, blue, pixel); - pixel = COLOR24RGB(red, green, blue); - *((tui32*)dst) = pixel; - src += 2; - dst += 4; - } - } - return out; - } - if ((in_bpp == 24) && (out_bpp == 24)) - { - out = (char*)g_malloc(width * height * 4, 0); - src = bmpdata; - dst = out; - for (i = 0; i < height; i++) - { - for (j = 0; j < width; j++) - { - blue = *((tui8*)src); - src++; - green = *((tui8*)src); - src++; - red = *((tui8*)src); - src++; - pixel = COLOR24RGB(red, green, blue); - *((tui32*)dst) = pixel; - dst += 4; - } - } - return out; - } - return 0; -} + pixel = COLOR24BGR(red, green, blue); + return pixel; + } -/*****************************************************************************/ -/* returns color or 0 */ -int APP_CC -rdp_orders_convert_color(int in_bpp, int out_bpp, int in_color, int* palette) -{ - int pixel = 0; - int red = 0; - int green = 0; - int blue = 0; - - if ((in_bpp == 8) && (out_bpp == 8)) - { - pixel = palette[in_color]; - SPLITCOLOR32(red, green, blue, pixel); - pixel = COLOR8(red, green, blue); - return pixel; - } - if ((in_bpp == 8) && (out_bpp == 16)) - { - pixel = palette[in_color]; - SPLITCOLOR32(red, green, blue, pixel); - pixel = COLOR16(red, green, blue); - return pixel; - } - if ((in_bpp == 8) && (out_bpp == 24)) - { - pixel = palette[in_color]; - SPLITCOLOR32(red, green, blue, pixel); - pixel = COLOR24BGR(red, green, blue); - return pixel; - } - if ((in_bpp == 15) && (out_bpp == 16)) - { - pixel = in_color; - SPLITCOLOR15(red, green, blue, pixel); - pixel = COLOR16(red, green, blue); - return pixel; - } - if ((in_bpp == 15) && (out_bpp == 24)) - { - pixel = in_color; - SPLITCOLOR15(red, green, blue, pixel); - pixel = COLOR24BGR(red, green, blue); - return pixel; - } - if ((in_bpp == 16) && (out_bpp == 16)) - { - return in_color; - } - if ((in_bpp == 16) && (out_bpp == 24)) - { - pixel = in_color; - SPLITCOLOR16(red, green, blue, pixel); - pixel = COLOR24BGR(red, green, blue); - return pixel; - } - if ((in_bpp == 24) && (out_bpp == 24)) - { - return in_color; - } - return 0; + if ((in_bpp == 24) && (out_bpp == 24)) + { + return in_color; + } + + return 0; } diff --git a/rdp/rdp_rdp.c b/rdp/rdp_rdp.c index b3c6d42a..c42d6e5f 100644 --- a/rdp/rdp_rdp.c +++ b/rdp/rdp_rdp.c @@ -1,24 +1,22 @@ -/* - 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. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - librdp rdp layer - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * librdp rdp layer + */ #include "rdp.h" @@ -27,321 +25,332 @@ #endif /*****************************************************************************/ -struct rdp_rdp* APP_CC -rdp_rdp_create(struct mod* owner) +struct rdp_rdp *APP_CC +rdp_rdp_create(struct mod *owner) { - struct rdp_rdp* self; - - self = (struct rdp_rdp*)g_malloc(sizeof(struct rdp_rdp), 1); - self->mod = owner; - self->sec_layer = rdp_sec_create(self); - self->bitmap_compression = 1; - self->bitmap_cache = 1; - self->desktop_save = 0; - self->orders = rdp_orders_create(self); - self->rec_mode = 0; - return self; + struct rdp_rdp *self; + + self = (struct rdp_rdp *)g_malloc(sizeof(struct rdp_rdp), 1); + self->mod = owner; + self->sec_layer = rdp_sec_create(self); + self->bitmap_compression = 1; + self->bitmap_cache = 1; + self->desktop_save = 0; + self->orders = rdp_orders_create(self); + self->rec_mode = 0; + return self; } /*****************************************************************************/ void APP_CC -rdp_rdp_delete(struct rdp_rdp* self) +rdp_rdp_delete(struct rdp_rdp *self) { - if (self == 0) - { - return; - } - rdp_orders_delete(self->orders); - rdp_sec_delete(self->sec_layer); - if (self->rec_fd != 0) - { - g_file_close(self->rec_fd); - self->rec_fd = 0; - } - g_free(self); + if (self == 0) + { + return; + } + + rdp_orders_delete(self->orders); + rdp_sec_delete(self->sec_layer); + + if (self->rec_fd != 0) + { + g_file_close(self->rec_fd); + self->rec_fd = 0; + } + + g_free(self); } /******************************************************************************/ /* Initialise an RDP packet */ int APP_CC -rdp_rdp_init(struct rdp_rdp* self, struct stream* s) +rdp_rdp_init(struct rdp_rdp *self, struct stream *s) { - if (rdp_sec_init(self->sec_layer, s, SEC_ENCRYPT) != 0) - { - return 1; - } - s_push_layer(s, rdp_hdr, 6); - return 0; + if (rdp_sec_init(self->sec_layer, s, SEC_ENCRYPT) != 0) + { + return 1; + } + + s_push_layer(s, rdp_hdr, 6); + return 0; } /******************************************************************************/ /* Send an RDP packet */ int APP_CC -rdp_rdp_send(struct rdp_rdp* self, struct stream* s, int pdu_type) +rdp_rdp_send(struct rdp_rdp *self, struct stream *s, int pdu_type) { - int len; - int sec_flags; - - s_pop_layer(s, rdp_hdr); - len = s->end - s->p; - out_uint16_le(s, len); - out_uint16_le(s, pdu_type | 0x10); - out_uint16_le(s, self->sec_layer->mcs_layer->userid); - sec_flags = SEC_ENCRYPT; - if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0) - { - return 1; - } - return 0; + int len; + int sec_flags; + + s_pop_layer(s, rdp_hdr); + len = s->end - s->p; + out_uint16_le(s, len); + out_uint16_le(s, pdu_type | 0x10); + out_uint16_le(s, self->sec_layer->mcs_layer->userid); + sec_flags = SEC_ENCRYPT; + + if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0) + { + return 1; + } + + return 0; } /******************************************************************************/ /* Initialise an RDP data packet */ int APP_CC -rdp_rdp_init_data(struct rdp_rdp* self, struct stream* s) +rdp_rdp_init_data(struct rdp_rdp *self, struct stream *s) { - if (rdp_sec_init(self->sec_layer, s, SEC_ENCRYPT) != 0) - { - return 1; - } - s_push_layer(s, rdp_hdr, 18); - return 0; + if (rdp_sec_init(self->sec_layer, s, SEC_ENCRYPT) != 0) + { + return 1; + } + + s_push_layer(s, rdp_hdr, 18); + return 0; } /******************************************************************************/ /* Send an RDP data packet */ int APP_CC -rdp_rdp_send_data(struct rdp_rdp* self, struct stream* s, int pdu_data_type) +rdp_rdp_send_data(struct rdp_rdp *self, struct stream *s, int pdu_data_type) { - int len; - int sec_flags; - - s_pop_layer(s, rdp_hdr); - len = s->end - s->p; - out_uint16_le(s, len); - out_uint16_le(s, RDP_PDU_DATA | 0x10); - out_uint16_le(s, self->sec_layer->mcs_layer->userid); - out_uint32_le(s, self->share_id); - out_uint8(s, 0); - out_uint8(s, 1); - out_uint16_le(s, len - 14); - out_uint8(s, pdu_data_type); - out_uint8(s, 0); /* compress type */ - out_uint16_le(s, 0); /* compress len */ - sec_flags = SEC_ENCRYPT; - if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0) - { - return 1; - } - return 0; + int len; + int sec_flags; + + s_pop_layer(s, rdp_hdr); + len = s->end - s->p; + out_uint16_le(s, len); + out_uint16_le(s, RDP_PDU_DATA | 0x10); + out_uint16_le(s, self->sec_layer->mcs_layer->userid); + out_uint32_le(s, self->share_id); + out_uint8(s, 0); + out_uint8(s, 1); + out_uint16_le(s, len - 14); + out_uint8(s, pdu_data_type); + out_uint8(s, 0); /* compress type */ + out_uint16_le(s, 0); /* compress len */ + sec_flags = SEC_ENCRYPT; + + if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0) + { + return 1; + } + + return 0; } /******************************************************************************/ /* Output general capability set */ static int APP_CC -rdp_rdp_out_general_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_out_general_caps(struct rdp_rdp *self, struct stream *s) { - out_uint16_le(s, RDP_CAPSET_GENERAL); - out_uint16_le(s, RDP_CAPLEN_GENERAL); - out_uint16_le(s, 1); /* OS major type */ - out_uint16_le(s, 3); /* OS minor type */ - out_uint16_le(s, 0x200); /* Protocol version */ - out_uint16_le(s, 0); /* Pad */ - out_uint16_le(s, 0); /* Compression types */ - out_uint16_le(s, self->use_rdp5 ? 0x40d : 0); - out_uint16_le(s, 0); /* Update capability */ - out_uint16_le(s, 0); /* Remote unshare capability */ - out_uint16_le(s, 0); /* Compression level */ - out_uint16_le(s, 0); /* Pad */ - return 0; + out_uint16_le(s, RDP_CAPSET_GENERAL); + out_uint16_le(s, RDP_CAPLEN_GENERAL); + out_uint16_le(s, 1); /* OS major type */ + out_uint16_le(s, 3); /* OS minor type */ + out_uint16_le(s, 0x200); /* Protocol version */ + out_uint16_le(s, 0); /* Pad */ + out_uint16_le(s, 0); /* Compression types */ + out_uint16_le(s, self->use_rdp5 ? 0x40d : 0); + out_uint16_le(s, 0); /* Update capability */ + out_uint16_le(s, 0); /* Remote unshare capability */ + out_uint16_le(s, 0); /* Compression level */ + out_uint16_le(s, 0); /* Pad */ + return 0; } /******************************************************************************/ /* Output bitmap capability set */ static int APP_CC -rdp_rdp_out_bitmap_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_out_bitmap_caps(struct rdp_rdp *self, struct stream *s) { - out_uint16_le(s, RDP_CAPSET_BITMAP); - out_uint16_le(s, RDP_CAPLEN_BITMAP); - out_uint16_le(s, self->mod->rdp_bpp); /* Preferred BPP */ - out_uint16_le(s, 1); /* Receive 1 BPP */ - out_uint16_le(s, 1); /* Receive 4 BPP */ - out_uint16_le(s, 1); /* Receive 8 BPP */ - out_uint16_le(s, 800); /* Desktop width */ - out_uint16_le(s, 600); /* Desktop height */ - out_uint16_le(s, 0); /* Pad */ - out_uint16_le(s, 1); /* Allow resize */ - out_uint16_le(s, self->bitmap_compression); /* Support compression */ - out_uint16_le(s, 0); /* Unknown */ - out_uint16_le(s, 1); /* Unknown */ - out_uint16_le(s, 0); /* Pad */ - return 0; + out_uint16_le(s, RDP_CAPSET_BITMAP); + out_uint16_le(s, RDP_CAPLEN_BITMAP); + out_uint16_le(s, self->mod->rdp_bpp); /* Preferred BPP */ + out_uint16_le(s, 1); /* Receive 1 BPP */ + out_uint16_le(s, 1); /* Receive 4 BPP */ + out_uint16_le(s, 1); /* Receive 8 BPP */ + out_uint16_le(s, 800); /* Desktop width */ + out_uint16_le(s, 600); /* Desktop height */ + out_uint16_le(s, 0); /* Pad */ + out_uint16_le(s, 1); /* Allow resize */ + out_uint16_le(s, self->bitmap_compression); /* Support compression */ + out_uint16_le(s, 0); /* Unknown */ + out_uint16_le(s, 1); /* Unknown */ + out_uint16_le(s, 0); /* Pad */ + return 0; } /******************************************************************************/ /* Output order capability set */ static int APP_CC -rdp_rdp_out_order_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_out_order_caps(struct rdp_rdp *self, struct stream *s) { - char order_caps[32]; - - g_memset(order_caps, 0, 32); - order_caps[0] = 1; /* dest blt */ - order_caps[1] = 1; /* pat blt */ - order_caps[2] = 1; /* screen blt */ - order_caps[3] = self->bitmap_cache; /* memblt */ - order_caps[4] = 0; /* triblt */ - order_caps[8] = 1; /* line */ - order_caps[9] = 1; /* line */ - order_caps[10] = 1; /* rect */ - order_caps[11] = self->desktop_save; /* desksave */ - order_caps[13] = 1; /* memblt another above */ - order_caps[14] = 1; /* triblt another above */ - order_caps[20] = self->polygon_ellipse_orders; /* polygon */ - order_caps[21] = self->polygon_ellipse_orders; /* polygon2 */ - order_caps[22] = 0; /* todo polyline */ - order_caps[25] = self->polygon_ellipse_orders; /* ellipse */ - order_caps[26] = self->polygon_ellipse_orders; /* ellipse2 */ - order_caps[27] = 1; /* text2 */ - out_uint16_le(s, RDP_CAPSET_ORDER); - out_uint16_le(s, RDP_CAPLEN_ORDER); - out_uint8s(s, 20); /* Terminal desc, pad */ - out_uint16_le(s, 1); /* Cache X granularity */ - out_uint16_le(s, 20); /* Cache Y granularity */ - out_uint16_le(s, 0); /* Pad */ - out_uint16_le(s, 1); /* Max order level */ - out_uint16_le(s, 0x147); /* Number of fonts */ - out_uint16_le(s, 0x2a); /* Capability flags */ - out_uint8p(s, order_caps, 32); /* Orders supported */ - out_uint16_le(s, 0x6a1); /* Text capability flags */ - out_uint8s(s, 6); /* Pad */ - out_uint32_le(s, self->desktop_save * 0x38400); /* Desktop cache size */ - out_uint32_le(s, 0); /* Unknown */ - out_uint32_le(s, 0x4e4); /* Unknown */ - return 0; + char order_caps[32]; + + g_memset(order_caps, 0, 32); + order_caps[0] = 1; /* dest blt */ + order_caps[1] = 1; /* pat blt */ + order_caps[2] = 1; /* screen blt */ + order_caps[3] = self->bitmap_cache; /* memblt */ + order_caps[4] = 0; /* triblt */ + order_caps[8] = 1; /* line */ + order_caps[9] = 1; /* line */ + order_caps[10] = 1; /* rect */ + order_caps[11] = self->desktop_save; /* desksave */ + order_caps[13] = 1; /* memblt another above */ + order_caps[14] = 1; /* triblt another above */ + order_caps[20] = self->polygon_ellipse_orders; /* polygon */ + order_caps[21] = self->polygon_ellipse_orders; /* polygon2 */ + order_caps[22] = 0; /* todo polyline */ + order_caps[25] = self->polygon_ellipse_orders; /* ellipse */ + order_caps[26] = self->polygon_ellipse_orders; /* ellipse2 */ + order_caps[27] = 1; /* text2 */ + out_uint16_le(s, RDP_CAPSET_ORDER); + out_uint16_le(s, RDP_CAPLEN_ORDER); + out_uint8s(s, 20); /* Terminal desc, pad */ + out_uint16_le(s, 1); /* Cache X granularity */ + out_uint16_le(s, 20); /* Cache Y granularity */ + out_uint16_le(s, 0); /* Pad */ + out_uint16_le(s, 1); /* Max order level */ + out_uint16_le(s, 0x147); /* Number of fonts */ + out_uint16_le(s, 0x2a); /* Capability flags */ + out_uint8p(s, order_caps, 32); /* Orders supported */ + out_uint16_le(s, 0x6a1); /* Text capability flags */ + out_uint8s(s, 6); /* Pad */ + out_uint32_le(s, self->desktop_save * 0x38400); /* Desktop cache size */ + out_uint32_le(s, 0); /* Unknown */ + out_uint32_le(s, 0x4e4); /* Unknown */ + return 0; } /******************************************************************************/ /* Output bitmap cache capability set */ static int APP_CC -rdp_rdp_out_bmpcache_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_out_bmpcache_caps(struct rdp_rdp *self, struct stream *s) { - int Bpp = 0; - - out_uint16_le(s, RDP_CAPSET_BMPCACHE); - out_uint16_le(s, RDP_CAPLEN_BMPCACHE); - Bpp = (self->mod->rdp_bpp + 7) / 8; - out_uint8s(s, 24); /* unused */ - out_uint16_le(s, 0x258); /* entries */ - out_uint16_le(s, 0x100 * Bpp); /* max cell size */ - out_uint16_le(s, 0x12c); /* entries */ - out_uint16_le(s, 0x400 * Bpp); /* max cell size */ - out_uint16_le(s, 0x106); /* entries */ - out_uint16_le(s, 0x1000 * Bpp); /* max cell size */ - return 0; + int Bpp = 0; + + out_uint16_le(s, RDP_CAPSET_BMPCACHE); + out_uint16_le(s, RDP_CAPLEN_BMPCACHE); + Bpp = (self->mod->rdp_bpp + 7) / 8; + out_uint8s(s, 24); /* unused */ + out_uint16_le(s, 0x258); /* entries */ + out_uint16_le(s, 0x100 * Bpp); /* max cell size */ + out_uint16_le(s, 0x12c); /* entries */ + out_uint16_le(s, 0x400 * Bpp); /* max cell size */ + out_uint16_le(s, 0x106); /* entries */ + out_uint16_le(s, 0x1000 * Bpp); /* max cell size */ + return 0; } /******************************************************************************/ /* Output control capability set */ static int APP_CC -rdp_rdp_out_control_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_out_control_caps(struct rdp_rdp *self, struct stream *s) { - out_uint16_le(s, RDP_CAPSET_CONTROL); - out_uint16_le(s, RDP_CAPLEN_CONTROL); - out_uint16_le(s, 0); /* Control capabilities */ - out_uint16_le(s, 0); /* Remote detach */ - out_uint16_le(s, 2); /* Control interest */ - out_uint16_le(s, 2); /* Detach interest */ - return 0; + out_uint16_le(s, RDP_CAPSET_CONTROL); + out_uint16_le(s, RDP_CAPLEN_CONTROL); + out_uint16_le(s, 0); /* Control capabilities */ + out_uint16_le(s, 0); /* Remote detach */ + out_uint16_le(s, 2); /* Control interest */ + out_uint16_le(s, 2); /* Detach interest */ + return 0; } /******************************************************************************/ /* Output activation capability set */ static int APP_CC -rdp_rdp_out_activate_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_out_activate_caps(struct rdp_rdp *self, struct stream *s) { - out_uint16_le(s, RDP_CAPSET_ACTIVATE); - out_uint16_le(s, RDP_CAPLEN_ACTIVATE); - out_uint16_le(s, 0); /* Help key */ - out_uint16_le(s, 0); /* Help index key */ - out_uint16_le(s, 0); /* Extended help key */ - out_uint16_le(s, 0); /* Window activate */ - return 0; + out_uint16_le(s, RDP_CAPSET_ACTIVATE); + out_uint16_le(s, RDP_CAPLEN_ACTIVATE); + out_uint16_le(s, 0); /* Help key */ + out_uint16_le(s, 0); /* Help index key */ + out_uint16_le(s, 0); /* Extended help key */ + out_uint16_le(s, 0); /* Window activate */ + return 0; } /******************************************************************************/ /* Output pointer capability set */ static int APP_CC -rdp_rdp_out_pointer_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_out_pointer_caps(struct rdp_rdp *self, struct stream *s) { - out_uint16_le(s, RDP_CAPSET_POINTER); - out_uint16_le(s, RDP_CAPLEN_POINTER_MONO); - out_uint16_le(s, 0); /* Color pointer */ - out_uint16_le(s, 20); /* Cache size */ - return 0; + out_uint16_le(s, RDP_CAPSET_POINTER); + out_uint16_le(s, RDP_CAPLEN_POINTER_MONO); + out_uint16_le(s, 0); /* Color pointer */ + out_uint16_le(s, 20); /* Cache size */ + return 0; } /******************************************************************************/ /* Output share capability set */ static int APP_CC -rdp_rdp_out_share_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_out_share_caps(struct rdp_rdp *self, struct stream *s) { - out_uint16_le(s, RDP_CAPSET_SHARE); - out_uint16_le(s, RDP_CAPLEN_SHARE); - out_uint16_le(s, 0); /* userid */ - out_uint16_le(s, 0); /* pad */ - return 0; + out_uint16_le(s, RDP_CAPSET_SHARE); + out_uint16_le(s, RDP_CAPLEN_SHARE); + out_uint16_le(s, 0); /* userid */ + out_uint16_le(s, 0); /* pad */ + return 0; } /******************************************************************************/ /* Output color cache capability set */ static int APP_CC -rdp_rdp_out_colcache_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_out_colcache_caps(struct rdp_rdp *self, struct stream *s) { - out_uint16_le(s, RDP_CAPSET_COLCACHE); - out_uint16_le(s, RDP_CAPLEN_COLCACHE); - out_uint16_le(s, 6); /* cache size */ - out_uint16_le(s, 0); /* pad */ - return 0; + out_uint16_le(s, RDP_CAPSET_COLCACHE); + out_uint16_le(s, RDP_CAPLEN_COLCACHE); + out_uint16_le(s, 6); /* cache size */ + out_uint16_le(s, 0); /* pad */ + return 0; } -static char caps_0x0d[] = { -0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, -0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00 +static char caps_0x0d[] = +{ + 0x01, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; static char caps_0x0c[] = { 0x01, 0x00, 0x00, 0x00 }; static char caps_0x0e[] = { 0x01, 0x00, 0x00, 0x00 }; -static char caps_0x10[] = { -0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, -0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00, -0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, -0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00, -0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, -0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00 +static char caps_0x10[] = +{ + 0xFE, 0x00, 0x04, 0x00, 0xFE, 0x00, 0x04, 0x00, + 0xFE, 0x00, 0x08, 0x00, 0xFE, 0x00, 0x08, 0x00, + 0xFE, 0x00, 0x10, 0x00, 0xFE, 0x00, 0x20, 0x00, + 0xFE, 0x00, 0x40, 0x00, 0xFE, 0x00, 0x80, 0x00, + 0xFE, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, + 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00 }; /******************************************************************************/ /* Output unknown capability sets */ static int APP_CC -rdp_rdp_out_unknown_caps(struct rdp_rdp* self, struct stream* s, int id, - int length, char* caps) +rdp_rdp_out_unknown_caps(struct rdp_rdp *self, struct stream *s, int id, + int length, char *caps) { - out_uint16_le(s, id); - out_uint16_le(s, length); - out_uint8p(s, caps, length - 4); - return 0; + out_uint16_le(s, id); + out_uint16_le(s, length); + out_uint8p(s, caps, length - 4); + return 0; } #define RDP5_FLAG 0x0030 @@ -349,774 +358,843 @@ rdp_rdp_out_unknown_caps(struct rdp_rdp* self, struct stream* s, int id, /******************************************************************************/ /* Send a confirm active PDU */ static int APP_CC -rdp_rdp_send_confirm_active(struct rdp_rdp* self, struct stream* s) +rdp_rdp_send_confirm_active(struct rdp_rdp *self, struct stream *s) { - int sec_flags; - int caplen; - - sec_flags = SEC_ENCRYPT; - //sec_flags = RDP5_FLAG | SEC_ENCRYPT; - caplen = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER + - RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + - RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL + - RDP_CAPLEN_POINTER_MONO + RDP_CAPLEN_SHARE + - 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ + - 4 /* w2k fix, why? */ ; - if (rdp_sec_init(self->sec_layer, s, sec_flags) != 0) - { - return 1; - } - out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE)); - out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */ - out_uint16_le(s, (self->sec_layer->mcs_layer->userid + 1001)); - out_uint32_le(s, self->share_id); - out_uint16_le(s, 0x3ea); /* userid */ - out_uint16_le(s, sizeof(RDP_SOURCE)); - out_uint16_le(s, caplen); - out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE)); - out_uint16_le(s, 0xd); /* num_caps */ - out_uint8s(s, 2); /* pad */ - rdp_rdp_out_general_caps(self, s); - rdp_rdp_out_bitmap_caps(self, s); - rdp_rdp_out_order_caps(self, s); - rdp_rdp_out_bmpcache_caps(self, s); - rdp_rdp_out_colcache_caps(self, s); - rdp_rdp_out_activate_caps(self, s); - rdp_rdp_out_control_caps(self, s); - rdp_rdp_out_pointer_caps(self, s); - rdp_rdp_out_share_caps(self, s); - rdp_rdp_out_unknown_caps(self, s, 0x0d, 0x58, caps_0x0d); /* international? */ - rdp_rdp_out_unknown_caps(self, s, 0x0c, 0x08, caps_0x0c); - rdp_rdp_out_unknown_caps(self, s, 0x0e, 0x08, caps_0x0e); - rdp_rdp_out_unknown_caps(self, s, 0x10, 0x34, caps_0x10); /* glyph cache? */ - s_mark_end(s); - if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0) - { - return 1; - } - return 0; + int sec_flags; + int caplen; + + sec_flags = SEC_ENCRYPT; + //sec_flags = RDP5_FLAG | SEC_ENCRYPT; + caplen = RDP_CAPLEN_GENERAL + RDP_CAPLEN_BITMAP + RDP_CAPLEN_ORDER + + RDP_CAPLEN_BMPCACHE + RDP_CAPLEN_COLCACHE + + RDP_CAPLEN_ACTIVATE + RDP_CAPLEN_CONTROL + + RDP_CAPLEN_POINTER_MONO + RDP_CAPLEN_SHARE + + 0x58 + 0x08 + 0x08 + 0x34 /* unknown caps */ + + 4 /* w2k fix, why? */ ; + + if (rdp_sec_init(self->sec_layer, s, sec_flags) != 0) + { + return 1; + } + + out_uint16_le(s, 2 + 14 + caplen + sizeof(RDP_SOURCE)); + out_uint16_le(s, (RDP_PDU_CONFIRM_ACTIVE | 0x10)); /* Version 1 */ + out_uint16_le(s, (self->sec_layer->mcs_layer->userid + 1001)); + out_uint32_le(s, self->share_id); + out_uint16_le(s, 0x3ea); /* userid */ + out_uint16_le(s, sizeof(RDP_SOURCE)); + out_uint16_le(s, caplen); + out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE)); + out_uint16_le(s, 0xd); /* num_caps */ + out_uint8s(s, 2); /* pad */ + rdp_rdp_out_general_caps(self, s); + rdp_rdp_out_bitmap_caps(self, s); + rdp_rdp_out_order_caps(self, s); + rdp_rdp_out_bmpcache_caps(self, s); + rdp_rdp_out_colcache_caps(self, s); + rdp_rdp_out_activate_caps(self, s); + rdp_rdp_out_control_caps(self, s); + rdp_rdp_out_pointer_caps(self, s); + rdp_rdp_out_share_caps(self, s); + rdp_rdp_out_unknown_caps(self, s, 0x0d, 0x58, caps_0x0d); /* international? */ + rdp_rdp_out_unknown_caps(self, s, 0x0c, 0x08, caps_0x0c); + rdp_rdp_out_unknown_caps(self, s, 0x0e, 0x08, caps_0x0e); + rdp_rdp_out_unknown_caps(self, s, 0x10, 0x34, caps_0x10); /* glyph cache? */ + s_mark_end(s); + + if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0) + { + return 1; + } + + return 0; } /******************************************************************************/ /* Process a color pointer PDU */ static int APP_CC -rdp_rdp_process_color_pointer_pdu(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_color_pointer_pdu(struct rdp_rdp *self, struct stream *s) { - int cache_idx; - int dlen; - int mlen; - struct rdp_cursor* cursor; - - in_uint16_le(s, cache_idx); - if (cache_idx >= sizeof(self->cursors) / sizeof(cursor)) - { - return 1; - } - cursor = self->cursors + cache_idx; - in_uint16_le(s, cursor->x); - in_uint16_le(s, cursor->y); - in_uint16_le(s, cursor->width); - in_uint16_le(s, cursor->height); - in_uint16_le(s, mlen); /* mask length */ - in_uint16_le(s, dlen); /* data length */ - if ((mlen > sizeof(cursor->mask)) || (dlen > sizeof(cursor->data))) - { - return 1; - } - in_uint8a(s, cursor->data, dlen); - in_uint8a(s, cursor->mask, mlen); - self->mod->server_set_cursor(self->mod, cursor->x, cursor->y, - cursor->data, cursor->mask); - return 0; + int cache_idx; + int dlen; + int mlen; + struct rdp_cursor *cursor; + + in_uint16_le(s, cache_idx); + + if (cache_idx >= sizeof(self->cursors) / sizeof(cursor)) + { + return 1; + } + + cursor = self->cursors + cache_idx; + in_uint16_le(s, cursor->x); + in_uint16_le(s, cursor->y); + in_uint16_le(s, cursor->width); + in_uint16_le(s, cursor->height); + in_uint16_le(s, mlen); /* mask length */ + in_uint16_le(s, dlen); /* data length */ + + if ((mlen > sizeof(cursor->mask)) || (dlen > sizeof(cursor->data))) + { + return 1; + } + + in_uint8a(s, cursor->data, dlen); + in_uint8a(s, cursor->mask, mlen); + self->mod->server_set_cursor(self->mod, cursor->x, cursor->y, + cursor->data, cursor->mask); + return 0; } /******************************************************************************/ /* Process a cached pointer PDU */ static int APP_CC -rdp_rdp_process_cached_pointer_pdu(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_cached_pointer_pdu(struct rdp_rdp *self, struct stream *s) { - int cache_idx; - struct rdp_cursor* cursor; - - in_uint16_le(s, cache_idx); - if (cache_idx >= sizeof(self->cursors) / sizeof(cursor)) - { - return 1; - } - cursor = self->cursors + cache_idx; - self->mod->server_set_cursor(self->mod, cursor->x, cursor->y, - cursor->data, cursor->mask); - return 0; + int cache_idx; + struct rdp_cursor *cursor; + + in_uint16_le(s, cache_idx); + + if (cache_idx >= sizeof(self->cursors) / sizeof(cursor)) + { + return 1; + } + + cursor = self->cursors + cache_idx; + self->mod->server_set_cursor(self->mod, cursor->x, cursor->y, + cursor->data, cursor->mask); + return 0; } /******************************************************************************/ /* Process a system pointer PDU */ static int APP_CC -rdp_rdp_process_system_pointer_pdu(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_system_pointer_pdu(struct rdp_rdp *self, struct stream *s) { - int system_pointer_type; - struct rdp_cursor* cursor; - - in_uint16_le(s, system_pointer_type); - switch (system_pointer_type) - { - case RDP_NULL_POINTER: - cursor = (struct rdp_cursor*)g_malloc(sizeof(struct rdp_cursor), 1); - g_memset(cursor->mask, 0xff, sizeof(cursor->mask)); - self->mod->server_set_cursor(self->mod, cursor->x, cursor->y, - cursor->data, cursor->mask); - g_free(cursor); - break; - default: - break; - } - return 0; + int system_pointer_type; + struct rdp_cursor *cursor; + + in_uint16_le(s, system_pointer_type); + + switch (system_pointer_type) + { + case RDP_NULL_POINTER: + cursor = (struct rdp_cursor *)g_malloc(sizeof(struct rdp_cursor), 1); + g_memset(cursor->mask, 0xff, sizeof(cursor->mask)); + self->mod->server_set_cursor(self->mod, cursor->x, cursor->y, + cursor->data, cursor->mask); + g_free(cursor); + break; + default: + break; + } + + return 0; } /******************************************************************************/ /* Process a pointer PDU */ static int APP_CC -rdp_rdp_process_pointer_pdu(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_pointer_pdu(struct rdp_rdp *self, struct stream *s) { - int message_type; - int x; - int y; - int rv; - - rv = 0; - 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); - break; - case RDP_POINTER_COLOR: - rv = rdp_rdp_process_color_pointer_pdu(self, s); - break; - case RDP_POINTER_CACHED: - rv = rdp_rdp_process_cached_pointer_pdu(self, s); - break; - case RDP_POINTER_SYSTEM: - rv = rdp_rdp_process_system_pointer_pdu(self, s); - break; - default: - break; - } - return rv; + int message_type; + int x; + int y; + int rv; + + rv = 0; + 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); + break; + case RDP_POINTER_COLOR: + rv = rdp_rdp_process_color_pointer_pdu(self, s); + break; + case RDP_POINTER_CACHED: + rv = rdp_rdp_process_cached_pointer_pdu(self, s); + break; + case RDP_POINTER_SYSTEM: + rv = rdp_rdp_process_system_pointer_pdu(self, s); + break; + default: + break; + } + + return rv; } /******************************************************************************/ /* Process bitmap updates */ static void APP_CC -rdp_rdp_process_bitmap_updates(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_bitmap_updates(struct rdp_rdp *self, struct stream *s) { - int num_updates = 0; - int left = 0; - int top = 0; - int right = 0; - int bottom = 0; - int width = 0; - int height = 0; - int cx = 0; - int cy = 0; - int bpp = 0; - int Bpp = 0; - int compress = 0; - int bufsize = 0; - int size = 0; - int i = 0; - int x = 0; - int y = 0; - char* data = NULL; - char* bmpdata0 = NULL; - char* bmpdata1 = NULL; - - in_uint16_le(s, num_updates); - for (i = 0; i < num_updates; i++) - { - in_uint16_le(s, left); - in_uint16_le(s, top); - in_uint16_le(s, right); - in_uint16_le(s, bottom); - in_uint16_le(s, width); - in_uint16_le(s, height); - in_uint16_le(s, bpp); - Bpp = (bpp + 7) / 8; - in_uint16_le(s, compress); - in_uint16_le(s, bufsize); - cx = (right - left) + 1; - cy = (bottom - top) + 1; - bmpdata0 = (char*)g_malloc(width * height * Bpp, 0); - if (compress) + int num_updates = 0; + int left = 0; + int top = 0; + int right = 0; + int bottom = 0; + int width = 0; + int height = 0; + int cx = 0; + int cy = 0; + int bpp = 0; + int Bpp = 0; + int compress = 0; + int bufsize = 0; + int size = 0; + int i = 0; + int x = 0; + int y = 0; + char *data = NULL; + char *bmpdata0 = NULL; + char *bmpdata1 = NULL; + + in_uint16_le(s, num_updates); + + for (i = 0; i < num_updates; i++) { - if (compress & 0x400) - { - size = bufsize; - } - else - { - in_uint8s(s, 2); /* pad */ - in_uint16_le(s, size); - in_uint8s(s, 4); /* line_size, final_size */ - } - in_uint8p(s, data, size); - rdp_bitmap_decompress(bmpdata0, width, height, data, size, Bpp); - bmpdata1 = rdp_orders_convert_bitmap(bpp, self->mod->xrdp_bpp, - bmpdata0, width, height, - self->colormap.colors); - self->mod->server_paint_rect(self->mod, left, top, cx, cy, bmpdata1, - width, height, 0, 0); - } - else /* not compressed */ - { - for (y = 0; y < height; y++) - { - data = bmpdata0 + ((height - y) - 1) * (width * Bpp); - if (Bpp == 1) + in_uint16_le(s, left); + in_uint16_le(s, top); + in_uint16_le(s, right); + in_uint16_le(s, bottom); + in_uint16_le(s, width); + in_uint16_le(s, height); + in_uint16_le(s, bpp); + Bpp = (bpp + 7) / 8; + in_uint16_le(s, compress); + in_uint16_le(s, bufsize); + cx = (right - left) + 1; + cy = (bottom - top) + 1; + bmpdata0 = (char *)g_malloc(width * height * Bpp, 0); + + if (compress) { - for (x = 0; x < width; x++) - { - in_uint8(s, data[x]); - } + if (compress & 0x400) + { + size = bufsize; + } + else + { + in_uint8s(s, 2); /* pad */ + in_uint16_le(s, size); + in_uint8s(s, 4); /* line_size, final_size */ + } + + in_uint8p(s, data, size); + rdp_bitmap_decompress(bmpdata0, width, height, data, size, Bpp); + bmpdata1 = rdp_orders_convert_bitmap(bpp, self->mod->xrdp_bpp, + bmpdata0, width, height, + self->colormap.colors); + self->mod->server_paint_rect(self->mod, left, top, cx, cy, bmpdata1, + width, height, 0, 0); } - else if (Bpp == 2) + else /* not compressed */ { - for (x = 0; x < width; x++) - { - in_uint16_le(s, ((tui16*)data)[x]); - } + for (y = 0; y < height; y++) + { + data = bmpdata0 + ((height - y) - 1) * (width * Bpp); + + if (Bpp == 1) + { + for (x = 0; x < width; x++) + { + in_uint8(s, data[x]); + } + } + else if (Bpp == 2) + { + for (x = 0; x < width; x++) + { + in_uint16_le(s, ((tui16 *)data)[x]); + } + } + else if (Bpp == 3) + { + for (x = 0; x < width; x++) + { + in_uint8(s, data[x * 3 + 0]); + in_uint8(s, data[x * 3 + 1]); + in_uint8(s, data[x * 3 + 2]); + } + } + } + + bmpdata1 = rdp_orders_convert_bitmap(bpp, self->mod->xrdp_bpp, + bmpdata0, width, height, + self->colormap.colors); + self->mod->server_paint_rect(self->mod, left, top, cx, cy, bmpdata1, + width, height, 0, 0); } - else if (Bpp == 3) + + if (bmpdata0 != bmpdata1) { - for (x = 0; x < width; x++) - { - in_uint8(s, data[x * 3 + 0]); - in_uint8(s, data[x * 3 + 1]); - in_uint8(s, data[x * 3 + 2]); - } + g_free(bmpdata1); } - } - bmpdata1 = rdp_orders_convert_bitmap(bpp, self->mod->xrdp_bpp, - bmpdata0, width, height, - self->colormap.colors); - self->mod->server_paint_rect(self->mod, left, top, cx, cy, bmpdata1, - width, height, 0, 0); - } - if (bmpdata0 != bmpdata1) - { - g_free(bmpdata1); + + g_free(bmpdata0); } - g_free(bmpdata0); - } } /******************************************************************************/ /* Process a palette update */ static void APP_CC -rdp_rdp_process_palette(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_palette(struct rdp_rdp *self, struct stream *s) { - int i; - int r; - int g; - int b; - - in_uint8s(s, 2); /* pad */ - in_uint16_le(s, self->colormap.ncolors); - in_uint8s(s, 2); /* pad */ - for (i = 0; i < self->colormap.ncolors; i++) - { - in_uint8(s, r); - in_uint8(s, g); - in_uint8(s, b); - self->colormap.colors[i] = (r << 16) | (g << 8) | b; - } - //ui_set_colormap(hmap); + int i; + int r; + int g; + int b; + + in_uint8s(s, 2); /* pad */ + in_uint16_le(s, self->colormap.ncolors); + in_uint8s(s, 2); /* pad */ + + for (i = 0; i < self->colormap.ncolors; i++) + { + in_uint8(s, r); + in_uint8(s, g); + in_uint8(s, b); + self->colormap.colors[i] = (r << 16) | (g << 8) | b; + } + + //ui_set_colormap(hmap); } /******************************************************************************/ /* Process an update PDU */ static int APP_CC -rdp_rdp_process_update_pdu(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_update_pdu(struct rdp_rdp *self, struct stream *s) { - int update_type; - int count; - - in_uint16_le(s, update_type); - self->mod->server_begin_update(self->mod); - switch (update_type) - { - case RDP_UPDATE_ORDERS: - in_uint8s(s, 2); /* pad */ - in_uint16_le(s, count); - in_uint8s(s, 2); /* pad */ - rdp_orders_process_orders(self->orders, s, count); - break; - case RDP_UPDATE_BITMAP: - rdp_rdp_process_bitmap_updates(self, s); - break; - case RDP_UPDATE_PALETTE: - rdp_rdp_process_palette(self, s); - break; - case RDP_UPDATE_SYNCHRONIZE: - break; - default: - break; - } - self->mod->server_end_update(self->mod); - return 0; + int update_type; + int count; + + in_uint16_le(s, update_type); + self->mod->server_begin_update(self->mod); + + switch (update_type) + { + case RDP_UPDATE_ORDERS: + in_uint8s(s, 2); /* pad */ + in_uint16_le(s, count); + in_uint8s(s, 2); /* pad */ + rdp_orders_process_orders(self->orders, s, count); + break; + case RDP_UPDATE_BITMAP: + rdp_rdp_process_bitmap_updates(self, s); + break; + case RDP_UPDATE_PALETTE: + rdp_rdp_process_palette(self, s); + break; + case RDP_UPDATE_SYNCHRONIZE: + break; + default: + break; + } + + self->mod->server_end_update(self->mod); + return 0; } /******************************************************************************/ void APP_CC -rdp_rdp_out_unistr(struct stream* s, char* text) +rdp_rdp_out_unistr(struct stream *s, char *text) { - int i; + int i; - i = 0; - while (text[i] != 0) - { - out_uint8(s, text[i]); + i = 0; + + while (text[i] != 0) + { + out_uint8(s, text[i]); + out_uint8(s, 0); + i++; + } + + out_uint8(s, 0); out_uint8(s, 0); - i++; - } - out_uint8(s, 0); - out_uint8(s, 0); } /******************************************************************************/ int APP_CC -rdp_rdp_send_login_info(struct rdp_rdp* self, int flags) +rdp_rdp_send_login_info(struct rdp_rdp *self, int flags) { - int len_domain; - int len_username; - int len_password; - int len_program; - int len_directory; - int sec_flags; - struct stream* s; - - DEBUG(("in rdp_rdp_send_login_info")); - make_stream(s); - init_stream(s, 8192); - len_domain = 2 * g_strlen(self->mod->domain); - len_username = 2 * g_strlen(self->mod->username); - len_password = 2 * g_strlen(self->mod->password); - len_program = 2 * g_strlen(self->mod->program); - len_directory = 2 * g_strlen(self->mod->directory); - sec_flags = SEC_LOGON_INFO | SEC_ENCRYPT; - if (rdp_sec_init(self->sec_layer, s, sec_flags) != 0) - { - free_stream(s); - DEBUG(("out rdp_rdp_send_login_info error 1")); - return 1; - } - out_uint32_le(s, 0); - out_uint32_le(s, flags); - out_uint16_le(s, len_domain); - out_uint16_le(s, len_username); - out_uint16_le(s, len_password); - out_uint16_le(s, len_program); - out_uint16_le(s, len_directory); - rdp_rdp_out_unistr(s, self->mod->domain); - rdp_rdp_out_unistr(s, self->mod->username); - rdp_rdp_out_unistr(s, self->mod->password); - rdp_rdp_out_unistr(s, self->mod->program); - rdp_rdp_out_unistr(s, self->mod->directory); - s_mark_end(s); - if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0) - { + int len_domain; + int len_username; + int len_password; + int len_program; + int len_directory; + int sec_flags; + struct stream *s; + + DEBUG(("in rdp_rdp_send_login_info")); + make_stream(s); + init_stream(s, 8192); + len_domain = 2 * g_strlen(self->mod->domain); + len_username = 2 * g_strlen(self->mod->username); + len_password = 2 * g_strlen(self->mod->password); + len_program = 2 * g_strlen(self->mod->program); + len_directory = 2 * g_strlen(self->mod->directory); + sec_flags = SEC_LOGON_INFO | SEC_ENCRYPT; + + if (rdp_sec_init(self->sec_layer, s, sec_flags) != 0) + { + free_stream(s); + DEBUG(("out rdp_rdp_send_login_info error 1")); + return 1; + } + + out_uint32_le(s, 0); + out_uint32_le(s, flags); + out_uint16_le(s, len_domain); + out_uint16_le(s, len_username); + out_uint16_le(s, len_password); + out_uint16_le(s, len_program); + out_uint16_le(s, len_directory); + rdp_rdp_out_unistr(s, self->mod->domain); + rdp_rdp_out_unistr(s, self->mod->username); + rdp_rdp_out_unistr(s, self->mod->password); + rdp_rdp_out_unistr(s, self->mod->program); + rdp_rdp_out_unistr(s, self->mod->directory); + s_mark_end(s); + + if (rdp_sec_send(self->sec_layer, s, sec_flags) != 0) + { + free_stream(s); + DEBUG(("out rdp_rdp_send_login_info error 2")); + return 1; + } + free_stream(s); - DEBUG(("out rdp_rdp_send_login_info error 2")); - return 1; - } - free_stream(s); - DEBUG(("out rdp_rdp_send_login_info")); - return 0; + DEBUG(("out rdp_rdp_send_login_info")); + return 0; } /******************************************************************************/ int APP_CC -rdp_rdp_connect(struct rdp_rdp* self, char* ip, char* port) +rdp_rdp_connect(struct rdp_rdp *self, char *ip, char *port) { - int flags; - - DEBUG(("in rdp_rdp_connect")); - flags = RDP_LOGON_NORMAL; - if (g_strlen(self->mod->password) > 0) - { - flags |= RDP_LOGON_AUTO; - } - if (rdp_sec_connect(self->sec_layer, ip, port) != 0) - { - DEBUG(("out rdp_rdp_connect error rdp_sec_connect failed")); - return 1; - } - if (rdp_rdp_send_login_info(self, flags) != 0) - { - DEBUG(("out rdp_rdp_connect error rdp_rdp_send_login_info failed")); - return 1; - } - DEBUG(("out rdp_rdp_connect")); - return 0; + int flags; + + DEBUG(("in rdp_rdp_connect")); + flags = RDP_LOGON_NORMAL; + + if (g_strlen(self->mod->password) > 0) + { + flags |= RDP_LOGON_AUTO; + } + + if (rdp_sec_connect(self->sec_layer, ip, port) != 0) + { + DEBUG(("out rdp_rdp_connect error rdp_sec_connect failed")); + return 1; + } + + if (rdp_rdp_send_login_info(self, flags) != 0) + { + DEBUG(("out rdp_rdp_connect error rdp_rdp_send_login_info failed")); + return 1; + } + + DEBUG(("out rdp_rdp_connect")); + return 0; } /******************************************************************************/ int APP_CC -rdp_rdp_send_input(struct rdp_rdp* self, struct stream* s, +rdp_rdp_send_input(struct rdp_rdp *self, struct stream *s, int time, int message_type, int device_flags, int param1, int param2) { - if (rdp_rdp_init_data(self, s) != 0) - { - return 1; - } - out_uint16_le(s, 1); /* number of events */ - out_uint16_le(s, 0); - out_uint32_le(s, time); - out_uint16_le(s, message_type); - out_uint16_le(s, device_flags); - out_uint16_le(s, param1); - out_uint16_le(s, param2); - s_mark_end(s); - if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_INPUT) != 0) - { - return 1; - } - return 0; + if (rdp_rdp_init_data(self, s) != 0) + { + return 1; + } + + out_uint16_le(s, 1); /* number of events */ + out_uint16_le(s, 0); + out_uint32_le(s, time); + out_uint16_le(s, message_type); + out_uint16_le(s, device_flags); + out_uint16_le(s, param1); + out_uint16_le(s, param2); + s_mark_end(s); + + if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_INPUT) != 0) + { + return 1; + } + + return 0; } /******************************************************************************/ int APP_CC -rdp_rdp_send_invalidate(struct rdp_rdp* self, struct stream* s, +rdp_rdp_send_invalidate(struct rdp_rdp *self, struct stream *s, int left, int top, int width, int height) { - if (rdp_rdp_init_data(self, s) != 0) - { - return 1; - } - out_uint32_le(s, 1); - out_uint16_le(s, left); - out_uint16_le(s, top); - out_uint16_le(s, (left + width) - 1); - out_uint16_le(s, (top + height) - 1); - s_mark_end(s); - if (rdp_rdp_send_data(self, s, 33) != 0) - { - return 1; - } - return 0; + if (rdp_rdp_init_data(self, s) != 0) + { + return 1; + } + + out_uint32_le(s, 1); + out_uint16_le(s, left); + out_uint16_le(s, top); + out_uint16_le(s, (left + width) - 1); + out_uint16_le(s, (top + height) - 1); + s_mark_end(s); + + if (rdp_rdp_send_data(self, s, 33) != 0) + { + return 1; + } + + return 0; } /******************************************************************************/ int APP_CC -rdp_rdp_recv(struct rdp_rdp* self, struct stream* s, int* type) +rdp_rdp_recv(struct rdp_rdp *self, struct stream *s, int *type) { - int len; - int pdu_type; - int chan; - - chan = 0; - DEBUG(("in rdp_rdp_recv")); - if (s->next_packet >= s->end || s->next_packet == 0) - { - if (rdp_sec_recv(self->sec_layer, s, &chan) != 0) + int len; + int pdu_type; + int chan; + + chan = 0; + DEBUG(("in rdp_rdp_recv")); + + if (s->next_packet >= s->end || s->next_packet == 0) + { + if (rdp_sec_recv(self->sec_layer, s, &chan) != 0) + { + DEBUG(("error in rdp_rdp_recv, rdp_sec_recv failed")); + return 1; + } + + s->next_packet = s->p; + } + else { - DEBUG(("error in rdp_rdp_recv, rdp_sec_recv failed")); - return 1; + chan = MCS_GLOBAL_CHANNEL; + s->p = s->next_packet; } - s->next_packet = s->p; - } - else - { - chan = MCS_GLOBAL_CHANNEL; - s->p = s->next_packet; - } - if (chan == MCS_GLOBAL_CHANNEL) - { - in_uint16_le(s, len); - DEBUG(("rdp_rdp_recv got %d len", len)); - if (len == 0x8000) + + if (chan == MCS_GLOBAL_CHANNEL) { - s->next_packet += 8; - DEBUG(("out rdp_rdp_recv")); - return 0; + in_uint16_le(s, len); + DEBUG(("rdp_rdp_recv got %d len", len)); + + if (len == 0x8000) + { + s->next_packet += 8; + DEBUG(("out rdp_rdp_recv")); + return 0; + } + + in_uint16_le(s, pdu_type); + in_uint8s(s, 2); + *type = pdu_type & 0xf; + s->next_packet += len; + } + else + { + /* todo, process channel data */ + DEBUG(("got channel data channel %d", chan)); + s->next_packet = s->end; } - in_uint16_le(s, pdu_type); - in_uint8s(s, 2); - *type = pdu_type & 0xf; - s->next_packet += len; - } - else - { - /* todo, process channel data */ - DEBUG(("got channel data channel %d", chan)); - s->next_packet = s->end; - } - DEBUG(("out rdp_rdp_recv")); - return 0; + + DEBUG(("out rdp_rdp_recv")); + return 0; } /******************************************************************************/ static int APP_CC -rdp_rdp_process_disconnect_pdu(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_disconnect_pdu(struct rdp_rdp *self, struct stream *s) { - return 0; + return 0; } /******************************************************************************/ int APP_CC -rdp_rdp_process_data_pdu(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_data_pdu(struct rdp_rdp *self, struct stream *s) { - int data_pdu_type; - int ctype; - int len; - int rv; - - rv = 0; - in_uint8s(s, 6); /* shareid, pad, streamid */ - in_uint16_le(s, len); - in_uint8(s, data_pdu_type); - in_uint8(s, ctype); - in_uint8s(s, 2); /* clen */ - switch (data_pdu_type) - { - case RDP_DATA_PDU_UPDATE: - rv = rdp_rdp_process_update_pdu(self, s); - break; - case RDP_DATA_PDU_CONTROL: - break; - case RDP_DATA_PDU_SYNCHRONISE: - break; - case RDP_DATA_PDU_POINTER: - rv = rdp_rdp_process_pointer_pdu(self, s); - break; - case RDP_DATA_PDU_PLAY_SOUND: - break; - case RDP_DATA_PDU_LOGON: - break; - case RDP_DATA_PDU_DISCONNECT: - rv = rdp_rdp_process_disconnect_pdu(self, s); - break; - default: - break; - } - return rv; + int data_pdu_type; + int ctype; + int len; + int rv; + + rv = 0; + in_uint8s(s, 6); /* shareid, pad, streamid */ + in_uint16_le(s, len); + in_uint8(s, data_pdu_type); + in_uint8(s, ctype); + in_uint8s(s, 2); /* clen */ + + switch (data_pdu_type) + { + case RDP_DATA_PDU_UPDATE: + rv = rdp_rdp_process_update_pdu(self, s); + break; + case RDP_DATA_PDU_CONTROL: + break; + case RDP_DATA_PDU_SYNCHRONISE: + break; + case RDP_DATA_PDU_POINTER: + rv = rdp_rdp_process_pointer_pdu(self, s); + break; + case RDP_DATA_PDU_PLAY_SOUND: + break; + case RDP_DATA_PDU_LOGON: + break; + case RDP_DATA_PDU_DISCONNECT: + rv = rdp_rdp_process_disconnect_pdu(self, s); + break; + default: + break; + } + + return rv; } /******************************************************************************/ /* Process a bitmap capability set */ static void APP_CC -rdp_rdp_process_general_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_general_caps(struct rdp_rdp *self, struct stream *s) { } /******************************************************************************/ /* Process a bitmap capability set */ static void APP_CC -rdp_rdp_process_bitmap_caps(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_bitmap_caps(struct rdp_rdp *self, struct stream *s) { - int width = 0; - int height = 0; - int bpp = 0; - - in_uint16_le(s, bpp); - in_uint8s(s, 6); - in_uint16_le(s, width); - in_uint16_le(s, height); - self->mod->rdp_bpp = bpp; - /* todo, call reset if needed and use width and height */ + int width = 0; + int height = 0; + int bpp = 0; + + in_uint16_le(s, bpp); + in_uint8s(s, 6); + in_uint16_le(s, width); + in_uint16_le(s, height); + self->mod->rdp_bpp = bpp; + /* todo, call reset if needed and use width and height */ } /******************************************************************************/ /* Process server capabilities */ /* returns error */ static int APP_CC -rdp_rdp_process_server_caps(struct rdp_rdp* self, struct stream* s, int len) +rdp_rdp_process_server_caps(struct rdp_rdp *self, struct stream *s, int len) { - int n = 0; - int ncapsets = 0; - int capset_type = 0; - int capset_length = 0; - char* next = NULL; - char* start = NULL; - - start = s->p; - in_uint16_le(s, ncapsets); - in_uint8s(s, 2); /* pad */ - for (n = 0; n < ncapsets; n++) - { - if (s->p > start + len) + int n = 0; + int ncapsets = 0; + int capset_type = 0; + int capset_length = 0; + char *next = NULL; + char *start = NULL; + + start = s->p; + in_uint16_le(s, ncapsets); + in_uint8s(s, 2); /* pad */ + + for (n = 0; n < ncapsets; n++) { - return 0; - } - in_uint16_le(s, capset_type); - in_uint16_le(s, capset_length); - next = (s->p + capset_length) - 4; - switch (capset_type) - { - case RDP_CAPSET_GENERAL: - rdp_rdp_process_general_caps(self, s); - break; - case RDP_CAPSET_BITMAP: - rdp_rdp_process_bitmap_caps(self, s); - break; - default: - break; + if (s->p > start + len) + { + return 0; + } + + in_uint16_le(s, capset_type); + in_uint16_le(s, capset_length); + next = (s->p + capset_length) - 4; + + switch (capset_type) + { + case RDP_CAPSET_GENERAL: + rdp_rdp_process_general_caps(self, s); + break; + case RDP_CAPSET_BITMAP: + rdp_rdp_process_bitmap_caps(self, s); + break; + default: + break; + } + + s->p = next; } - s->p = next; - } - return 0; + + return 0; } /******************************************************************************/ /* Send a control PDU */ /* returns error */ static int APP_CC -rdp_rdp_send_control(struct rdp_rdp* self, struct stream* s, int action) +rdp_rdp_send_control(struct rdp_rdp *self, struct stream *s, int action) { - if (rdp_rdp_init_data(self, s) != 0) - { - return 1; - } - out_uint16_le(s, action); - out_uint16_le(s, 0); /* userid */ - out_uint32_le(s, 0); /* control id */ - s_mark_end(s); - if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_CONTROL) != 0) - { - return 1; - } - return 0; + if (rdp_rdp_init_data(self, s) != 0) + { + return 1; + } + + out_uint16_le(s, action); + out_uint16_le(s, 0); /* userid */ + out_uint32_le(s, 0); /* control id */ + s_mark_end(s); + + if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_CONTROL) != 0) + { + return 1; + } + + return 0; } /******************************************************************************/ /* Send a synchronisation PDU */ /* returns error */ static int APP_CC -rdp_rdp_send_synchronise(struct rdp_rdp* self, struct stream* s) +rdp_rdp_send_synchronise(struct rdp_rdp *self, struct stream *s) { - if (rdp_rdp_init_data(self, s) != 0) - { - return 1; - } - out_uint16_le(s, 1); /* type */ - out_uint16_le(s, 1002); - s_mark_end(s); - if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_SYNCHRONISE) != 0) - { - return 1; - } - return 0; + if (rdp_rdp_init_data(self, s) != 0) + { + return 1; + } + + out_uint16_le(s, 1); /* type */ + out_uint16_le(s, 1002); + s_mark_end(s); + + if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_SYNCHRONISE) != 0) + { + return 1; + } + + return 0; } /******************************************************************************/ /* Send an (empty) font information PDU */ static int APP_CC -rdp_rdp_send_fonts(struct rdp_rdp* self, struct stream* s, int seq) +rdp_rdp_send_fonts(struct rdp_rdp *self, struct stream *s, int seq) { - if (rdp_rdp_init_data(self, s) != 0) - { - return 1; - } - out_uint16_le(s, 0); /* number of fonts */ - out_uint16_le(s, 0); /* pad? */ - out_uint16_le(s, seq); /* unknown */ - out_uint16_le(s, 0x32); /* entry size */ - s_mark_end(s); - if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_FONT2) != 0) - { - return 1; - } - return 0; + if (rdp_rdp_init_data(self, s) != 0) + { + return 1; + } + + out_uint16_le(s, 0); /* number of fonts */ + out_uint16_le(s, 0); /* pad? */ + out_uint16_le(s, seq); /* unknown */ + out_uint16_le(s, 0x32); /* entry size */ + s_mark_end(s); + + if (rdp_rdp_send_data(self, s, RDP_DATA_PDU_FONT2) != 0) + { + return 1; + } + + return 0; } /******************************************************************************/ /* Respond to a demand active PDU */ int APP_CC -rdp_rdp_process_demand_active(struct rdp_rdp* self, struct stream* s) +rdp_rdp_process_demand_active(struct rdp_rdp *self, struct stream *s) { - int type = 0; - int len_src_descriptor = 0; - int len_combined_caps = 0; - - in_uint32_le(s, self->share_id); - in_uint16_le(s, len_src_descriptor); - in_uint16_le(s, len_combined_caps); - in_uint8s(s, len_src_descriptor); - rdp_rdp_process_server_caps(self, s, len_combined_caps); - rdp_rdp_send_confirm_active(self, s); - rdp_rdp_send_synchronise(self, s); - rdp_rdp_send_control(self, s, RDP_CTL_COOPERATE); - rdp_rdp_send_control(self, s, RDP_CTL_REQUEST_CONTROL); - rdp_rdp_recv(self, s, &type); /* RDP_PDU_SYNCHRONIZE */ - rdp_rdp_recv(self, s, &type); /* RDP_CTL_COOPERATE */ - rdp_rdp_recv(self, s, &type); /* RDP_CTL_GRANT_CONTROL */ - rdp_rdp_send_input(self, s, 0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0); - rdp_rdp_send_fonts(self, s, 1); - rdp_rdp_send_fonts(self, s, 2); - rdp_rdp_recv(self, s, &type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */ - rdp_orders_reset_state(self->orders); - return 0; + int type = 0; + int len_src_descriptor = 0; + int len_combined_caps = 0; + + in_uint32_le(s, self->share_id); + in_uint16_le(s, len_src_descriptor); + in_uint16_le(s, len_combined_caps); + in_uint8s(s, len_src_descriptor); + rdp_rdp_process_server_caps(self, s, len_combined_caps); + rdp_rdp_send_confirm_active(self, s); + rdp_rdp_send_synchronise(self, s); + rdp_rdp_send_control(self, s, RDP_CTL_COOPERATE); + rdp_rdp_send_control(self, s, RDP_CTL_REQUEST_CONTROL); + rdp_rdp_recv(self, s, &type); /* RDP_PDU_SYNCHRONIZE */ + rdp_rdp_recv(self, s, &type); /* RDP_CTL_COOPERATE */ + rdp_rdp_recv(self, s, &type); /* RDP_CTL_GRANT_CONTROL */ + rdp_rdp_send_input(self, s, 0, RDP_INPUT_SYNCHRONIZE, 0, 0, 0); + rdp_rdp_send_fonts(self, s, 1); + rdp_rdp_send_fonts(self, s, 2); + rdp_rdp_recv(self, s, &type); /* RDP_PDU_UNKNOWN 0x28 (Fonts?) */ + rdp_orders_reset_state(self->orders); + return 0; } /******************************************************************************/ int APP_CC -rdp_rec_check_file(struct rdp_rdp* self) +rdp_rec_check_file(struct rdp_rdp *self) { - char file_name[256]; - int index = 0; - int len = 0; - struct stream* s = (struct stream *)NULL; - - g_memset(file_name,0,sizeof(char) * 256); - - if (self->rec_fd == 0) - { - index = 1; - g_sprintf(file_name, "rec%8.8d.rec", index); - while (g_file_exist(file_name)) + char file_name[256]; + int index = 0; + int len = 0; + struct stream *s = (struct stream *)NULL; + + g_memset(file_name, 0, sizeof(char) * 256); + + if (self->rec_fd == 0) { - index++; - if (index >= 9999) - { - return 1; - } - g_sprintf(file_name, "rec%8.8d.rec", index); + index = 1; + g_sprintf(file_name, "rec%8.8d.rec", index); + + while (g_file_exist(file_name)) + { + index++; + + if (index >= 9999) + { + return 1; + } + + g_sprintf(file_name, "rec%8.8d.rec", index); + } + + self->rec_fd = g_file_open(file_name); + make_stream(s); + init_stream(s, 8192); + out_uint8a(s, "XRDPREC1", 8); + out_uint8s(s, 8); + s_mark_end(s); + len = s->end - s->data; + g_file_write(self->rec_fd, s->data, len); + free_stream(s); } - self->rec_fd = g_file_open(file_name); - make_stream(s); - init_stream(s, 8192); - out_uint8a(s, "XRDPREC1", 8); - out_uint8s(s, 8); - s_mark_end(s); - len = s->end - s->data; - g_file_write(self->rec_fd, s->data, len); - free_stream(s); - } - return 0; + + return 0; } /******************************************************************************/ int APP_CC -rdp_rec_write_item(struct rdp_rdp* self, struct stream* s) +rdp_rec_write_item(struct rdp_rdp *self, struct stream *s) { - int len = 0; - int time = 0; - - if (self->rec_fd == 0) - { - return 1; - } - time = g_time1(); - out_uint32_le(s, time); - s_mark_end(s); - len = s->end - s->data; - s_pop_layer(s, iso_hdr); - out_uint32_le(s, len); - g_file_write(self->rec_fd, s->data, len); - return 0; + int len = 0; + int time = 0; + + if (self->rec_fd == 0) + { + return 1; + } + + time = g_time1(); + out_uint32_le(s, time); + s_mark_end(s); + len = s->end - s->data; + s_pop_layer(s, iso_hdr); + out_uint32_le(s, len); + g_file_write(self->rec_fd, s->data, len); + return 0; } diff --git a/rdp/rdp_sec.c b/rdp/rdp_sec.c index 5efab76e..bd0fe349 100644 --- a/rdp/rdp_sec.c +++ b/rdp/rdp_sec.c @@ -1,655 +1,713 @@ -/* - 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. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - librdp secure layer - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * librdp secure layer + */ #include "rdp.h" static char g_pad_54[40] = -{ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 54, 54, 54 }; +{ + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54 +}; static char g_pad_92[48] = -{ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92 }; +{ + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92 +}; /*****************************************************************************/ -struct rdp_sec* APP_CC -rdp_sec_create(struct rdp_rdp* owner) +struct rdp_sec *APP_CC +rdp_sec_create(struct rdp_rdp *owner) { - struct rdp_sec* self; - - self = (struct rdp_sec*)g_malloc(sizeof(struct rdp_sec), 1); - self->rdp_layer = owner; - make_stream(self->client_mcs_data); - init_stream(self->client_mcs_data, 8192); - make_stream(self->server_mcs_data); - init_stream(self->server_mcs_data, 8192); - self->mcs_layer = rdp_mcs_create(self, self->client_mcs_data, - self->server_mcs_data); - if(self->decrypt_rc4_info!=NULL) - { - g_writeln("rdp_sec_create - decrypt_rc4_info already created !!!"); - } - self->decrypt_rc4_info = ssl_rc4_info_create(); - if(self->encrypt_rc4_info!=NULL) - { - g_writeln("rdp_sec_create - encrypt_rc4_info already created !!!"); - } - self->encrypt_rc4_info = ssl_rc4_info_create(); - self->lic_layer = rdp_lic_create(self); - return self; + struct rdp_sec *self; + + self = (struct rdp_sec *)g_malloc(sizeof(struct rdp_sec), 1); + self->rdp_layer = owner; + make_stream(self->client_mcs_data); + init_stream(self->client_mcs_data, 8192); + make_stream(self->server_mcs_data); + init_stream(self->server_mcs_data, 8192); + self->mcs_layer = rdp_mcs_create(self, self->client_mcs_data, + self->server_mcs_data); + + if (self->decrypt_rc4_info != NULL) + { + g_writeln("rdp_sec_create - decrypt_rc4_info already created !!!"); + } + + self->decrypt_rc4_info = ssl_rc4_info_create(); + + if (self->encrypt_rc4_info != NULL) + { + g_writeln("rdp_sec_create - encrypt_rc4_info already created !!!"); + } + + self->encrypt_rc4_info = ssl_rc4_info_create(); + self->lic_layer = rdp_lic_create(self); + return self; } /*****************************************************************************/ void APP_CC -rdp_sec_delete(struct rdp_sec* self) +rdp_sec_delete(struct rdp_sec *self) { - if (self == 0) - { - return; - } - rdp_lic_delete(self->lic_layer); - rdp_mcs_delete(self->mcs_layer); - free_stream(self->client_mcs_data); - free_stream(self->server_mcs_data); - ssl_rc4_info_delete(self->decrypt_rc4_info); - ssl_rc4_info_delete(self->encrypt_rc4_info); - g_free(self); + if (self == 0) + { + return; + } + + rdp_lic_delete(self->lic_layer); + rdp_mcs_delete(self->mcs_layer); + free_stream(self->client_mcs_data); + free_stream(self->server_mcs_data); + ssl_rc4_info_delete(self->decrypt_rc4_info); + ssl_rc4_info_delete(self->encrypt_rc4_info); + g_free(self); } /*****************************************************************************/ /* Reduce key entropy from 64 to 40 bits */ static void APP_CC -rdp_sec_make_40bit(char* key) +rdp_sec_make_40bit(char *key) { - key[0] = 0xd1; - key[1] = 0x26; - key[2] = 0x9e; + key[0] = 0xd1; + key[1] = 0x26; + key[2] = 0x9e; } /*****************************************************************************/ /* returns error */ /* update an encryption key */ static int APP_CC -rdp_sec_update(char* key, char* update_key, int key_len) +rdp_sec_update(char *key, char *update_key, int key_len) { - char shasig[20]; - void* sha1_info; - void* md5_info; - void* rc4_info; - - sha1_info = ssl_sha1_info_create(); - md5_info = ssl_md5_info_create(); - rc4_info = ssl_rc4_info_create(); - ssl_sha1_clear(sha1_info); - ssl_sha1_transform(sha1_info, update_key, key_len); - ssl_sha1_transform(sha1_info, g_pad_54, 40); - ssl_sha1_transform(sha1_info, key, key_len); - ssl_sha1_complete(sha1_info, shasig); - ssl_md5_clear(md5_info); - ssl_md5_transform(md5_info, update_key, key_len); - ssl_md5_transform(md5_info, g_pad_92, 48); - ssl_md5_transform(md5_info, shasig, 20); - ssl_md5_complete(md5_info, key); - ssl_rc4_set_key(rc4_info, key, key_len); - ssl_rc4_crypt(rc4_info, key, key_len); - if (key_len == 8) - { - rdp_sec_make_40bit(key); - } - ssl_sha1_info_delete(sha1_info); - ssl_md5_info_delete(md5_info); - ssl_rc4_info_delete(rc4_info); - return 0; + char shasig[20]; + void *sha1_info; + void *md5_info; + void *rc4_info; + + sha1_info = ssl_sha1_info_create(); + md5_info = ssl_md5_info_create(); + rc4_info = ssl_rc4_info_create(); + ssl_sha1_clear(sha1_info); + ssl_sha1_transform(sha1_info, update_key, key_len); + ssl_sha1_transform(sha1_info, g_pad_54, 40); + ssl_sha1_transform(sha1_info, key, key_len); + ssl_sha1_complete(sha1_info, shasig); + ssl_md5_clear(md5_info); + ssl_md5_transform(md5_info, update_key, key_len); + ssl_md5_transform(md5_info, g_pad_92, 48); + ssl_md5_transform(md5_info, shasig, 20); + ssl_md5_complete(md5_info, key); + ssl_rc4_set_key(rc4_info, key, key_len); + ssl_rc4_crypt(rc4_info, key, key_len); + + if (key_len == 8) + { + rdp_sec_make_40bit(key); + } + + ssl_sha1_info_delete(sha1_info); + ssl_md5_info_delete(md5_info); + ssl_rc4_info_delete(rc4_info); + return 0; } /*****************************************************************************/ static void APP_CC -rdp_sec_decrypt(struct rdp_sec* self, char* data, int len) +rdp_sec_decrypt(struct rdp_sec *self, char *data, int len) { - if (self->decrypt_use_count == 4096) - { - rdp_sec_update(self->decrypt_key, self->decrypt_update_key, - self->rc4_key_len); - ssl_rc4_set_key(self->decrypt_rc4_info, self->decrypt_key, - self->rc4_key_len); - self->decrypt_use_count = 0; - } - ssl_rc4_crypt(self->decrypt_rc4_info, data, len); - self->decrypt_use_count++; + if (self->decrypt_use_count == 4096) + { + rdp_sec_update(self->decrypt_key, self->decrypt_update_key, + self->rc4_key_len); + ssl_rc4_set_key(self->decrypt_rc4_info, self->decrypt_key, + self->rc4_key_len); + self->decrypt_use_count = 0; + } + + ssl_rc4_crypt(self->decrypt_rc4_info, data, len); + self->decrypt_use_count++; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_sec_recv(struct rdp_sec* self, struct stream* s, int* chan) +rdp_sec_recv(struct rdp_sec *self, struct stream *s, int *chan) { - int flags; - - DEBUG((" in rdp_sec_recv")); - if (rdp_mcs_recv(self->mcs_layer, s, chan) != 0) - { - DEBUG((" error in rdp_sec_recv, rdp_mcs_recv failed")); - return 1; - } - in_uint32_le(s, flags); - DEBUG((" rdp_sec_recv flags %8.8x", flags)); - if (flags & SEC_ENCRYPT) /* 0x08 */ - { - in_uint8s(s, 8); /* signature */ - rdp_sec_decrypt(self, s->p, s->end - s->p); - } - if (flags & SEC_LICENCE_NEG) /* 0x80 */ - { - DEBUG((" in rdp_sec_recv, got SEC_LICENCE_NEG")); - rdp_lic_process(self->lic_layer, s); - *chan = 0; - } - DEBUG((" out rdp_sec_recv")); - return 0; + int flags; + + DEBUG((" in rdp_sec_recv")); + + if (rdp_mcs_recv(self->mcs_layer, s, chan) != 0) + { + DEBUG((" error in rdp_sec_recv, rdp_mcs_recv failed")); + return 1; + } + + in_uint32_le(s, flags); + DEBUG((" rdp_sec_recv flags %8.8x", flags)); + + if (flags & SEC_ENCRYPT) /* 0x08 */ + { + in_uint8s(s, 8); /* signature */ + rdp_sec_decrypt(self, s->p, s->end - s->p); + } + + if (flags & SEC_LICENCE_NEG) /* 0x80 */ + { + DEBUG((" in rdp_sec_recv, got SEC_LICENCE_NEG")); + rdp_lic_process(self->lic_layer, s); + *chan = 0; + } + + DEBUG((" out rdp_sec_recv")); + return 0; } /*****************************************************************************/ /* prepare client mcs data to send in mcs layer */ static void APP_CC -rdp_sec_out_mcs_data(struct rdp_sec* self) +rdp_sec_out_mcs_data(struct rdp_sec *self) { - struct stream* s; - int hostlen; - int length; - - s = self->client_mcs_data; - init_stream(s, 512); - self->rdp_layer->mod->hostname[15] = 0; /* limit length to 15 */ - hostlen = 2 * g_strlen(self->rdp_layer->mod->hostname); - length = 158 + 76 + 12 + 4; - /* Generic Conference Control (T.124) ConferenceCreateRequest */ - out_uint16_be(s, 5); - out_uint16_be(s, 0x14); - out_uint8(s, 0x7c); - out_uint16_be(s, 1); - out_uint16_be(s, (length | 0x8000)); /* remaining length */ - out_uint16_be(s, 8); /* length? */ - out_uint16_be(s, 16); - out_uint8(s, 0); - out_uint16_le(s, 0xc001); - out_uint8(s, 0); - out_uint32_le(s, 0x61637544); /* OEM ID: "Duca", as in Ducati. */ - out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */ - /* Client information */ - out_uint16_le(s, SEC_TAG_CLI_INFO); - out_uint16_le(s, 212); /* length */ - out_uint16_le(s, 1); /* RDP version. 1 == RDP4, 4 == RDP5. */ - out_uint16_le(s, 8); - out_uint16_le(s, self->rdp_layer->mod->width); - out_uint16_le(s, self->rdp_layer->mod->height); - out_uint16_le(s, 0xca01); - out_uint16_le(s, 0xaa03); - out_uint32_le(s, self->rdp_layer->mod->keylayout); - out_uint32_le(s, 2600); /* Client build */ - /* Unicode name of client, padded to 32 bytes */ - rdp_rdp_out_unistr(s, self->rdp_layer->mod->hostname); - out_uint8s(s, 30 - hostlen); - out_uint32_le(s, 4); - out_uint32_le(s, 0); - out_uint32_le(s, 12); - out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */ - out_uint16_le(s, 0xca01); /* color depth? */ - out_uint16_le(s, 1); - out_uint32_le(s, 0); - out_uint8(s, self->rdp_layer->mod->rdp_bpp); - out_uint16_le(s, 0x0700); - out_uint8(s, 0); - out_uint32_le(s, 1); - out_uint8s(s, 64); /* End of client info */ - out_uint16_le(s, SEC_TAG_CLI_4); - out_uint16_le(s, 12); - out_uint32_le(s, 9); - out_uint32_le(s, 0); - /* Client encryption settings */ - out_uint16_le(s, SEC_TAG_CLI_CRYPT); - out_uint16_le(s, 12); /* length */ - /* encryption supported, 128-bit supported */ - out_uint32_le(s, 0x3); - out_uint32_le(s, 0); /* Unknown */ - s_mark_end(s); + struct stream *s; + int hostlen; + int length; + + s = self->client_mcs_data; + init_stream(s, 512); + self->rdp_layer->mod->hostname[15] = 0; /* limit length to 15 */ + hostlen = 2 * g_strlen(self->rdp_layer->mod->hostname); + length = 158 + 76 + 12 + 4; + /* Generic Conference Control (T.124) ConferenceCreateRequest */ + out_uint16_be(s, 5); + out_uint16_be(s, 0x14); + out_uint8(s, 0x7c); + out_uint16_be(s, 1); + out_uint16_be(s, (length | 0x8000)); /* remaining length */ + out_uint16_be(s, 8); /* length? */ + out_uint16_be(s, 16); + out_uint8(s, 0); + out_uint16_le(s, 0xc001); + out_uint8(s, 0); + out_uint32_le(s, 0x61637544); /* OEM ID: "Duca", as in Ducati. */ + out_uint16_be(s, ((length - 14) | 0x8000)); /* remaining length */ + /* Client information */ + out_uint16_le(s, SEC_TAG_CLI_INFO); + out_uint16_le(s, 212); /* length */ + out_uint16_le(s, 1); /* RDP version. 1 == RDP4, 4 == RDP5. */ + out_uint16_le(s, 8); + out_uint16_le(s, self->rdp_layer->mod->width); + out_uint16_le(s, self->rdp_layer->mod->height); + out_uint16_le(s, 0xca01); + out_uint16_le(s, 0xaa03); + out_uint32_le(s, self->rdp_layer->mod->keylayout); + out_uint32_le(s, 2600); /* Client build */ + /* Unicode name of client, padded to 32 bytes */ + rdp_rdp_out_unistr(s, self->rdp_layer->mod->hostname); + out_uint8s(s, 30 - hostlen); + out_uint32_le(s, 4); + out_uint32_le(s, 0); + out_uint32_le(s, 12); + out_uint8s(s, 64); /* reserved? 4 + 12 doublewords */ + out_uint16_le(s, 0xca01); /* color depth? */ + out_uint16_le(s, 1); + out_uint32_le(s, 0); + out_uint8(s, self->rdp_layer->mod->rdp_bpp); + out_uint16_le(s, 0x0700); + out_uint8(s, 0); + out_uint32_le(s, 1); + out_uint8s(s, 64); /* End of client info */ + out_uint16_le(s, SEC_TAG_CLI_4); + out_uint16_le(s, 12); + out_uint32_le(s, 9); + out_uint32_le(s, 0); + /* Client encryption settings */ + out_uint16_le(s, SEC_TAG_CLI_CRYPT); + out_uint16_le(s, 12); /* length */ + /* encryption supported, 128-bit supported */ + out_uint32_le(s, 0x3); + out_uint32_le(s, 0); /* Unknown */ + s_mark_end(s); } /*****************************************************************************/ /* Parse a public key structure */ /* returns boolean */ static int APP_CC -rdp_sec_parse_public_key(struct rdp_sec* self, struct stream* s, - char* modulus, char* exponent) +rdp_sec_parse_public_key(struct rdp_sec *self, struct stream *s, + char *modulus, char *exponent) { - int magic; - int modulus_len; + int magic; + int modulus_len; - in_uint32_le(s, magic); - if (magic != SEC_RSA_MAGIC) - { - return 0; - } - in_uint32_le(s, modulus_len); - if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE) - { - return 0; - } - in_uint8s(s, 8); - in_uint8a(s, exponent, SEC_EXPONENT_SIZE); - in_uint8a(s, modulus, SEC_MODULUS_SIZE); - in_uint8s(s, SEC_PADDING_SIZE); - return s_check(s); + in_uint32_le(s, magic); + + if (magic != SEC_RSA_MAGIC) + { + return 0; + } + + in_uint32_le(s, modulus_len); + + if (modulus_len != SEC_MODULUS_SIZE + SEC_PADDING_SIZE) + { + return 0; + } + + in_uint8s(s, 8); + in_uint8a(s, exponent, SEC_EXPONENT_SIZE); + in_uint8a(s, modulus, SEC_MODULUS_SIZE); + in_uint8s(s, SEC_PADDING_SIZE); + return s_check(s); } /*****************************************************************************/ /* Parse a crypto information structure */ /* returns boolean */ static int APP_CC -rdp_sec_parse_crypt_info(struct rdp_sec* self, struct stream* s, - char* modulus, char* exponent) +rdp_sec_parse_crypt_info(struct rdp_sec *self, struct stream *s, + char *modulus, char *exponent) { - int random_len; - int rsa_info_len; - int flags; - int tag; - int length; - char* next_tag; - char* end; - - in_uint32_le(s, self->rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */ - in_uint32_le(s, self->crypt_level); /* 1 = low, 2 = medium, 3 = high */ - if (self->crypt_level == 0) /* no encryption */ - { - return 0; - } - in_uint32_le(s, random_len); - in_uint32_le(s, rsa_info_len); - if (random_len != SEC_RANDOM_SIZE) - { - return 0; - } - in_uint8a(s, self->server_random, random_len); - /* RSA info */ - end = s->p + rsa_info_len; - if (end > s->end) - { - return 0; - } - in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */ - if (flags & 1) - { - in_uint8s(s, 8); /* unknown */ - while (s->p < end) + int random_len; + int rsa_info_len; + int flags; + int tag; + int length; + char *next_tag; + char *end; + + in_uint32_le(s, self->rc4_key_size); /* 1 = 40-bit, 2 = 128-bit */ + in_uint32_le(s, self->crypt_level); /* 1 = low, 2 = medium, 3 = high */ + + if (self->crypt_level == 0) /* no encryption */ { - in_uint16_le(s, tag); - in_uint16_le(s, length); - next_tag = s->p + length; - DEBUG((" rdp_sec_parse_crypt_info tag %d length %d", tag, length)); - switch (tag) - { - case SEC_TAG_PUBKEY: - if (!rdp_sec_parse_public_key(self, s, modulus, exponent)) - { - return 0; - } - break; - case SEC_TAG_KEYSIG: - break; - default: - break; - } - s->p = next_tag; + return 0; } - } - else - { - /* todo */ - return 0; - } - return s_check_end(s); + + in_uint32_le(s, random_len); + in_uint32_le(s, rsa_info_len); + + if (random_len != SEC_RANDOM_SIZE) + { + return 0; + } + + in_uint8a(s, self->server_random, random_len); + /* RSA info */ + end = s->p + rsa_info_len; + + if (end > s->end) + { + return 0; + } + + in_uint32_le(s, flags); /* 1 = RDP4-style, 0x80000002 = X.509 */ + + if (flags & 1) + { + in_uint8s(s, 8); /* unknown */ + + while (s->p < end) + { + in_uint16_le(s, tag); + in_uint16_le(s, length); + next_tag = s->p + length; + DEBUG((" rdp_sec_parse_crypt_info tag %d length %d", tag, length)); + + switch (tag) + { + case SEC_TAG_PUBKEY: + + if (!rdp_sec_parse_public_key(self, s, modulus, exponent)) + { + return 0; + } + + break; + case SEC_TAG_KEYSIG: + break; + default: + break; + } + + s->p = next_tag; + } + } + else + { + /* todo */ + return 0; + } + + return s_check_end(s); } /*****************************************************************************/ static void APP_CC -rdp_sec_rsa_op(char* out, char* in, char* mod, char* exp) +rdp_sec_rsa_op(char *out, char *in, char *mod, char *exp) { - ssl_mod_exp(out, SEC_MODULUS_SIZE, /* 64 */ - in, SEC_RANDOM_SIZE, /* 32 */ - mod, SEC_MODULUS_SIZE, /* 64 */ - exp, SEC_EXPONENT_SIZE); /* 4 */ + ssl_mod_exp(out, SEC_MODULUS_SIZE, /* 64 */ + in, SEC_RANDOM_SIZE, /* 32 */ + mod, SEC_MODULUS_SIZE, /* 64 */ + exp, SEC_EXPONENT_SIZE); /* 4 */ } /*****************************************************************************/ void APP_CC -rdp_sec_hash_48(char* out, char* in, char* salt1, char* salt2, int salt) +rdp_sec_hash_48(char *out, char *in, char *salt1, char *salt2, int salt) { - int i; - void* sha1_info; - void* md5_info; - char pad[4]; - char sha1_sig[20]; - char md5_sig[16]; - - sha1_info = ssl_sha1_info_create(); - md5_info = ssl_md5_info_create(); - for (i = 0; i < 3; i++) - { - g_memset(pad, salt + i, 4); - ssl_sha1_clear(sha1_info); - ssl_sha1_transform(sha1_info, pad, i + 1); - ssl_sha1_transform(sha1_info, in, 48); - ssl_sha1_transform(sha1_info, salt1, 32); - ssl_sha1_transform(sha1_info, salt2, 32); - ssl_sha1_complete(sha1_info, sha1_sig); - ssl_md5_clear(md5_info); - ssl_md5_transform(md5_info, in, 48); - ssl_md5_transform(md5_info, sha1_sig, 20); - ssl_md5_complete(md5_info, md5_sig); - g_memcpy(out + i * 16, md5_sig, 16); - } - ssl_sha1_info_delete(sha1_info); - ssl_md5_info_delete(md5_info); + int i; + void *sha1_info; + void *md5_info; + char pad[4]; + char sha1_sig[20]; + char md5_sig[16]; + + sha1_info = ssl_sha1_info_create(); + md5_info = ssl_md5_info_create(); + + for (i = 0; i < 3; i++) + { + g_memset(pad, salt + i, 4); + ssl_sha1_clear(sha1_info); + ssl_sha1_transform(sha1_info, pad, i + 1); + ssl_sha1_transform(sha1_info, in, 48); + ssl_sha1_transform(sha1_info, salt1, 32); + ssl_sha1_transform(sha1_info, salt2, 32); + ssl_sha1_complete(sha1_info, sha1_sig); + ssl_md5_clear(md5_info); + ssl_md5_transform(md5_info, in, 48); + ssl_md5_transform(md5_info, sha1_sig, 20); + ssl_md5_complete(md5_info, md5_sig); + g_memcpy(out + i * 16, md5_sig, 16); + } + + ssl_sha1_info_delete(sha1_info); + ssl_md5_info_delete(md5_info); } /*****************************************************************************/ void APP_CC -rdp_sec_hash_16(char* out, char* in, char* salt1, char* salt2) +rdp_sec_hash_16(char *out, char *in, char *salt1, char *salt2) { - void* md5_info; - - md5_info = ssl_md5_info_create(); - ssl_md5_clear(md5_info); - ssl_md5_transform(md5_info, in, 16); - ssl_md5_transform(md5_info, salt1, 32); - ssl_md5_transform(md5_info, salt2, 32); - ssl_md5_complete(md5_info, out); - ssl_md5_info_delete(md5_info); + void *md5_info; + + md5_info = ssl_md5_info_create(); + ssl_md5_clear(md5_info); + ssl_md5_transform(md5_info, in, 16); + ssl_md5_transform(md5_info, salt1, 32); + ssl_md5_transform(md5_info, salt2, 32); + ssl_md5_complete(md5_info, out); + ssl_md5_info_delete(md5_info); } /*****************************************************************************/ static int APP_CC -rdp_sec_generate_keys(struct rdp_sec* self) +rdp_sec_generate_keys(struct rdp_sec *self) { - char session_key[48]; - char temp_hash[48]; - char input[48]; - - g_memcpy(input, self->client_random, 24); - g_memcpy(input + 24, self->server_random, 24); - rdp_sec_hash_48(temp_hash, input, self->client_random, - self->server_random, 65); - rdp_sec_hash_48(session_key, temp_hash, self->client_random, - self->server_random, 88); - g_memcpy(self->sign_key, session_key, 16); - rdp_sec_hash_16(self->decrypt_key, session_key + 16, self->client_random, - self->server_random); - rdp_sec_hash_16(self->encrypt_key, session_key + 32, self->client_random, - self->server_random); - DEBUG((" rdp_sec_generate_keys, rc4_key_size is %d", self->rc4_key_size)); - DEBUG((" rdp_sec_generate_keys, crypt_level is %d", self->crypt_level)); - if (self->rc4_key_size == 1) - { - rdp_sec_make_40bit(self->sign_key); - rdp_sec_make_40bit(self->encrypt_key); - rdp_sec_make_40bit(self->decrypt_key); - self->rc4_key_len = 8; - } - else - { - self->rc4_key_len = 16; - } - g_memcpy(self->decrypt_update_key, self->decrypt_key, 16); - g_memcpy(self->encrypt_update_key, self->encrypt_key, 16); - ssl_rc4_set_key(self->decrypt_rc4_info, self->decrypt_key, self->rc4_key_len); - ssl_rc4_set_key(self->encrypt_rc4_info, self->encrypt_key, self->rc4_key_len); - return 0; + char session_key[48]; + char temp_hash[48]; + char input[48]; + + g_memcpy(input, self->client_random, 24); + g_memcpy(input + 24, self->server_random, 24); + rdp_sec_hash_48(temp_hash, input, self->client_random, + self->server_random, 65); + rdp_sec_hash_48(session_key, temp_hash, self->client_random, + self->server_random, 88); + g_memcpy(self->sign_key, session_key, 16); + rdp_sec_hash_16(self->decrypt_key, session_key + 16, self->client_random, + self->server_random); + rdp_sec_hash_16(self->encrypt_key, session_key + 32, self->client_random, + self->server_random); + DEBUG((" rdp_sec_generate_keys, rc4_key_size is %d", self->rc4_key_size)); + DEBUG((" rdp_sec_generate_keys, crypt_level is %d", self->crypt_level)); + + if (self->rc4_key_size == 1) + { + rdp_sec_make_40bit(self->sign_key); + rdp_sec_make_40bit(self->encrypt_key); + rdp_sec_make_40bit(self->decrypt_key); + self->rc4_key_len = 8; + } + else + { + self->rc4_key_len = 16; + } + + g_memcpy(self->decrypt_update_key, self->decrypt_key, 16); + g_memcpy(self->encrypt_update_key, self->encrypt_key, 16); + ssl_rc4_set_key(self->decrypt_rc4_info, self->decrypt_key, self->rc4_key_len); + ssl_rc4_set_key(self->encrypt_rc4_info, self->encrypt_key, self->rc4_key_len); + return 0; } /*****************************************************************************/ /* Process crypto information blob */ static void APP_CC -rdp_sec_process_crypt_info(struct rdp_sec* self, struct stream* s) +rdp_sec_process_crypt_info(struct rdp_sec *self, struct stream *s) { - char modulus[64]; - char exponent[64]; - - g_memset(modulus, 0, sizeof(modulus)); - g_memset(exponent, 0, sizeof(exponent)); - if (!rdp_sec_parse_crypt_info(self, s, modulus, exponent)) - { - DEBUG((" error in rdp_sec_process_crypt_info")); - return; - } - /* Generate a client random, and determine encryption keys */ - g_random(self->client_random, 32); - rdp_sec_rsa_op(self->client_crypt_random, self->client_random, - modulus, exponent); - rdp_sec_generate_keys(self); + char modulus[64]; + char exponent[64]; + + g_memset(modulus, 0, sizeof(modulus)); + g_memset(exponent, 0, sizeof(exponent)); + + if (!rdp_sec_parse_crypt_info(self, s, modulus, exponent)) + { + DEBUG((" error in rdp_sec_process_crypt_info")); + return; + } + + /* Generate a client random, and determine encryption keys */ + g_random(self->client_random, 32); + rdp_sec_rsa_op(self->client_crypt_random, self->client_random, + modulus, exponent); + rdp_sec_generate_keys(self); } /*****************************************************************************/ /* Process connect response data blob */ static void APP_CC -rdp_sec_process_mcs_data(struct rdp_sec* self) +rdp_sec_process_mcs_data(struct rdp_sec *self) { - int tag; - int length; - int len; - char* next_tag; - struct stream* s; - - s = self->server_mcs_data; - s->p = s->data; - in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */ - in_uint8(s, len); - if (len & 0x80) - { + int tag; + int length; + int len; + char *next_tag; + struct stream *s; + + s = self->server_mcs_data; + s->p = s->data; + in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */ in_uint8(s, len); - } - while (s->p < s->end) - { - in_uint16_le(s, tag); - in_uint16_le(s, length); - DEBUG((" rdp_sec_process_mcs_data tag %d length %d", tag, length)); - if (length <= 4) + + if (len & 0x80) { - return; + in_uint8(s, len); } - next_tag = (s->p + length) - 4; - switch (tag) + + while (s->p < s->end) { - case SEC_TAG_SRV_INFO: - //rdp_sec_process_srv_info(self, s); - break; - case SEC_TAG_SRV_CRYPT: - rdp_sec_process_crypt_info(self, s); - break; - case SEC_TAG_SRV_CHANNELS: - break; - default: - break; + in_uint16_le(s, tag); + in_uint16_le(s, length); + DEBUG((" rdp_sec_process_mcs_data tag %d length %d", tag, length)); + + if (length <= 4) + { + return; + } + + next_tag = (s->p + length) - 4; + + switch (tag) + { + case SEC_TAG_SRV_INFO: + //rdp_sec_process_srv_info(self, s); + break; + case SEC_TAG_SRV_CRYPT: + rdp_sec_process_crypt_info(self, s); + break; + case SEC_TAG_SRV_CHANNELS: + break; + default: + break; + } + + s->p = next_tag; } - s->p = next_tag; - } } /*****************************************************************************/ /* Transfer the client random to the server */ /* returns error */ static int APP_CC -rdp_sec_establish_key(struct rdp_sec* self) +rdp_sec_establish_key(struct rdp_sec *self) { - int length; - int flags; - struct stream* s; - - DEBUG((" sending client random")); - make_stream(s); - init_stream(s, 8192); - length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE; - flags = SEC_CLIENT_RANDOM; - if (rdp_sec_init(self, s, flags) != 0) - { - free_stream(s); - return 1; - } - out_uint32_le(s, length); - out_uint8p(s, self->client_crypt_random, SEC_MODULUS_SIZE); - out_uint8s(s, SEC_PADDING_SIZE); - s_mark_end(s); - if (rdp_sec_send(self, s, flags) != 0) - { + int length; + int flags; + struct stream *s; + + DEBUG((" sending client random")); + make_stream(s); + init_stream(s, 8192); + length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE; + flags = SEC_CLIENT_RANDOM; + + if (rdp_sec_init(self, s, flags) != 0) + { + free_stream(s); + return 1; + } + + out_uint32_le(s, length); + out_uint8p(s, self->client_crypt_random, SEC_MODULUS_SIZE); + out_uint8s(s, SEC_PADDING_SIZE); + s_mark_end(s); + + if (rdp_sec_send(self, s, flags) != 0) + { + free_stream(s); + return 1; + } + free_stream(s); - return 1; - } - free_stream(s); - return 0; + return 0; } /*****************************************************************************/ /* Establish a secure connection */ int APP_CC -rdp_sec_connect(struct rdp_sec* self, char* ip, char* port) +rdp_sec_connect(struct rdp_sec *self, char *ip, char *port) { - DEBUG((" in rdp_sec_connect")); - rdp_sec_out_mcs_data(self); - if (rdp_mcs_connect(self->mcs_layer, ip, port) != 0) - { - DEBUG((" out rdp_sec_connect error rdp_mcs_connect failed")); - return 1; - } - rdp_sec_process_mcs_data(self); - if (rdp_sec_establish_key(self) != 0) - { - DEBUG((" out rdp_sec_connect error rdp_sec_establish_key failed")); - return 1; - } - DEBUG((" out rdp_sec_connect")); - return 0; + DEBUG((" in rdp_sec_connect")); + rdp_sec_out_mcs_data(self); + + if (rdp_mcs_connect(self->mcs_layer, ip, port) != 0) + { + DEBUG((" out rdp_sec_connect error rdp_mcs_connect failed")); + return 1; + } + + rdp_sec_process_mcs_data(self); + + if (rdp_sec_establish_key(self) != 0) + { + DEBUG((" out rdp_sec_connect error rdp_sec_establish_key failed")); + return 1; + } + + DEBUG((" out rdp_sec_connect")); + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_sec_init(struct rdp_sec* self, struct stream* s, int flags) +rdp_sec_init(struct rdp_sec *self, struct stream *s, int flags) { - if (rdp_mcs_init(self->mcs_layer, s) != 0) - { - return 1; - } - if (flags & SEC_ENCRYPT) - { - s_push_layer(s, sec_hdr, 12); - } - else - { - s_push_layer(s, sec_hdr, 4); - } - return 0; + if (rdp_mcs_init(self->mcs_layer, s) != 0) + { + return 1; + } + + if (flags & SEC_ENCRYPT) + { + s_push_layer(s, sec_hdr, 12); + } + else + { + s_push_layer(s, sec_hdr, 4); + } + + return 0; } /*****************************************************************************/ /* Output a uint32 into a buffer (little-endian) */ void APP_CC -rdp_sec_buf_out_uint32(char* buffer, int value) +rdp_sec_buf_out_uint32(char *buffer, int value) { - buffer[0] = value & 0xff; - buffer[1] = (value >> 8) & 0xff; - buffer[2] = (value >> 16) & 0xff; - buffer[3] = (value >> 24) & 0xff; + buffer[0] = value & 0xff; + buffer[1] = (value >> 8) & 0xff; + buffer[2] = (value >> 16) & 0xff; + buffer[3] = (value >> 24) & 0xff; } /*****************************************************************************/ /* Generate a MAC hash (5.2.3.1), using a combination of SHA1 and MD5 */ void APP_CC -rdp_sec_sign(char* signature, int siglen, char* session_key, int keylen, - char* data, int datalen) +rdp_sec_sign(char *signature, int siglen, char *session_key, int keylen, + char *data, int datalen) { - char shasig[20]; - char md5sig[16]; - char lenhdr[4]; - void* sha1_context; - void* md5_context; - - rdp_sec_buf_out_uint32(lenhdr, datalen); - sha1_context = ssl_sha1_info_create(); - ssl_sha1_clear(sha1_context); - ssl_sha1_transform(sha1_context, session_key, keylen); - ssl_sha1_transform(sha1_context, g_pad_54, 40); - ssl_sha1_transform(sha1_context, lenhdr, 4); - ssl_sha1_transform(sha1_context, data, datalen); - ssl_sha1_complete(sha1_context, shasig); - ssl_sha1_info_delete(sha1_context); - md5_context = ssl_md5_info_create(); - ssl_md5_clear(md5_context); - ssl_md5_transform(md5_context, session_key, keylen); - ssl_md5_transform(md5_context, g_pad_92, 48); - ssl_md5_transform(md5_context, shasig, 20); - ssl_md5_complete(md5_context, md5sig); - ssl_md5_info_delete(md5_context); - g_memcpy(signature, md5sig, siglen); + char shasig[20]; + char md5sig[16]; + char lenhdr[4]; + void *sha1_context; + void *md5_context; + + rdp_sec_buf_out_uint32(lenhdr, datalen); + sha1_context = ssl_sha1_info_create(); + ssl_sha1_clear(sha1_context); + ssl_sha1_transform(sha1_context, session_key, keylen); + ssl_sha1_transform(sha1_context, g_pad_54, 40); + ssl_sha1_transform(sha1_context, lenhdr, 4); + ssl_sha1_transform(sha1_context, data, datalen); + ssl_sha1_complete(sha1_context, shasig); + ssl_sha1_info_delete(sha1_context); + md5_context = ssl_md5_info_create(); + ssl_md5_clear(md5_context); + ssl_md5_transform(md5_context, session_key, keylen); + ssl_md5_transform(md5_context, g_pad_92, 48); + ssl_md5_transform(md5_context, shasig, 20); + ssl_md5_complete(md5_context, md5sig); + ssl_md5_info_delete(md5_context); + g_memcpy(signature, md5sig, siglen); } /*****************************************************************************/ /* Encrypt data using RC4 */ static void APP_CC -rdp_sec_encrypt(struct rdp_sec* self, char* data, int length) +rdp_sec_encrypt(struct rdp_sec *self, char *data, int length) { - if (self->encrypt_use_count == 4096) - { - rdp_sec_update(self->encrypt_key, self->encrypt_update_key, - self->rc4_key_len); - ssl_rc4_set_key(self->encrypt_rc4_info, self->encrypt_key, - self->rc4_key_len); - self->encrypt_use_count = 0; - } - ssl_rc4_crypt(self->encrypt_rc4_info, data, length); - self->encrypt_use_count++; + if (self->encrypt_use_count == 4096) + { + rdp_sec_update(self->encrypt_key, self->encrypt_update_key, + self->rc4_key_len); + ssl_rc4_set_key(self->encrypt_rc4_info, self->encrypt_key, + self->rc4_key_len); + self->encrypt_use_count = 0; + } + + ssl_rc4_crypt(self->encrypt_rc4_info, data, length); + self->encrypt_use_count++; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_sec_send(struct rdp_sec* self, struct stream* s, int flags) +rdp_sec_send(struct rdp_sec *self, struct stream *s, int flags) { - int datalen; - - DEBUG((" in rdp_sec_send flags %8.8x", flags)); - s_pop_layer(s, sec_hdr); - out_uint32_le(s, flags); - if (flags & SEC_ENCRYPT) - { - datalen = (s->end - s->p) - 8; - rdp_sec_sign(s->p, 8, self->sign_key, self->rc4_key_len, s->p + 8, - datalen); - rdp_sec_encrypt(self, s->p + 8, datalen); - } - if (rdp_mcs_send(self->mcs_layer, s) != 0) - { - DEBUG((" out rdp_sec_send, rdp_mcs_send failed")); - return 1; - } - DEBUG((" out rdp_sec_send")); - return 0; + int datalen; + + DEBUG((" in rdp_sec_send flags %8.8x", flags)); + s_pop_layer(s, sec_hdr); + out_uint32_le(s, flags); + + if (flags & SEC_ENCRYPT) + { + datalen = (s->end - s->p) - 8; + rdp_sec_sign(s->p, 8, self->sign_key, self->rc4_key_len, s->p + 8, + datalen); + rdp_sec_encrypt(self, s->p + 8, datalen); + } + + if (rdp_mcs_send(self->mcs_layer, s) != 0) + { + DEBUG((" out rdp_sec_send, rdp_mcs_send failed")); + return 1; + } + + DEBUG((" out rdp_sec_send")); + return 0; } diff --git a/rdp/rdp_tcp.c b/rdp/rdp_tcp.c index 0f053ff6..f3c990ad 100644 --- a/rdp/rdp_tcp.c +++ b/rdp/rdp_tcp.c @@ -1,178 +1,188 @@ -/* - 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. - - xrdp: A Remote Desktop Protocol server. - Copyright (C) Jay Sorg 2005-2010 - - librdp tcp layer - -*/ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2012 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * librdp tcp layer + */ #include "rdp.h" /*****************************************************************************/ -struct rdp_tcp* APP_CC -rdp_tcp_create(struct rdp_iso* owner) +struct rdp_tcp *APP_CC +rdp_tcp_create(struct rdp_iso *owner) { - struct rdp_tcp* self; + struct rdp_tcp *self; - self = (struct rdp_tcp*)g_malloc(sizeof(struct rdp_tcp), 1); - self->iso_layer = owner; - return self; + self = (struct rdp_tcp *)g_malloc(sizeof(struct rdp_tcp), 1); + self->iso_layer = owner; + return self; } /*****************************************************************************/ void APP_CC -rdp_tcp_delete(struct rdp_tcp* self) +rdp_tcp_delete(struct rdp_tcp *self) { - g_free(self); + g_free(self); } /*****************************************************************************/ /* get out stream ready for data */ /* returns error */ int APP_CC -rdp_tcp_init(struct rdp_tcp* self, struct stream* s) +rdp_tcp_init(struct rdp_tcp *self, struct stream *s) { - init_stream(s, 8192); - return 0; + init_stream(s, 8192); + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_tcp_recv(struct rdp_tcp* self, struct stream* s, int len) +rdp_tcp_recv(struct rdp_tcp *self, struct stream *s, int len) { - int rcvd; - - DEBUG((" in rdp_tcp_recv gota get %d bytes on sck %d", - len, self->sck)); - if (self->sck_closed) - { - DEBUG((" out rdp_tcp_recv error sck closed")); - return 1; - } - init_stream(s, len); - while (len > 0) - { - rcvd = g_tcp_recv(self->sck, s->end, len, 0); - if (rcvd == -1) + int rcvd; + + DEBUG((" in rdp_tcp_recv gota get %d bytes on sck %d", + len, self->sck)); + + if (self->sck_closed) { - if (g_tcp_last_error_would_block(self->sck)) - { - g_tcp_can_recv(self->sck, 10); - } - else - { - self->sck_closed = 1; - DEBUG((" out rdp_tcp_recv error unknown")); + DEBUG((" out rdp_tcp_recv error sck closed")); return 1; - } - } - else if (rcvd == 0) - { - self->sck_closed = 1; - DEBUG((" out rdp_tcp_recv error connection dropped")); - return 1; } - else + + init_stream(s, len); + + while (len > 0) { - s->end += rcvd; - len -= rcvd; + rcvd = g_tcp_recv(self->sck, s->end, len, 0); + + if (rcvd == -1) + { + if (g_tcp_last_error_would_block(self->sck)) + { + g_tcp_can_recv(self->sck, 10); + } + else + { + self->sck_closed = 1; + DEBUG((" out rdp_tcp_recv error unknown")); + return 1; + } + } + else if (rcvd == 0) + { + self->sck_closed = 1; + DEBUG((" out rdp_tcp_recv error connection dropped")); + return 1; + } + else + { + s->end += rcvd; + len -= rcvd; + } } - } - return 0; + + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_tcp_send(struct rdp_tcp* self, struct stream* s) +rdp_tcp_send(struct rdp_tcp *self, struct stream *s) { - int len; - int total; - int sent; - - if (self->sck_closed) - { - DEBUG((" out rdp_tcp_send error sck closed")); - return 1; - } - len = s->end - s->data; - DEBUG((" in rdp_tcp_send gota send %d bytes on sck %d", len, - self->sck)); - total = 0; - while (total < len) - { - sent = g_tcp_send(self->sck, s->data + total, len - total, 0); - if (sent == -1) + int len; + int total; + int sent; + + if (self->sck_closed) { - if (g_tcp_last_error_would_block(self->sck)) - { - g_tcp_can_send(self->sck, 10); - } - else - { - self->sck_closed = 1; - DEBUG((" out rdp_tcp_send error unknown")); + DEBUG((" out rdp_tcp_send error sck closed")); return 1; - } - } - else if (sent == 0) - { - self->sck_closed = 1; - DEBUG((" out rdp_tcp_send error connection dropped")); - return 1; } - else + + len = s->end - s->data; + DEBUG((" in rdp_tcp_send gota send %d bytes on sck %d", len, + self->sck)); + total = 0; + + while (total < len) { - total = total + sent; + sent = g_tcp_send(self->sck, s->data + total, len - total, 0); + + if (sent == -1) + { + if (g_tcp_last_error_would_block(self->sck)) + { + g_tcp_can_send(self->sck, 10); + } + else + { + self->sck_closed = 1; + DEBUG((" out rdp_tcp_send error unknown")); + return 1; + } + } + else if (sent == 0) + { + self->sck_closed = 1; + DEBUG((" out rdp_tcp_send error connection dropped")); + return 1; + } + else + { + total = total + sent; + } } - } - return 0; + + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_tcp_connect(struct rdp_tcp* self, char* ip, char* port) +rdp_tcp_connect(struct rdp_tcp *self, char *ip, char *port) { - DEBUG((" in rdp_tcp_connect ip %s port %s", ip, port)); - self->sck = g_tcp_socket(); - if (g_tcp_connect(self->sck, ip, port) == 0) - { - g_tcp_set_non_blocking(self->sck); - } - else - { - DEBUG((" out rdp_tcp_connect error g_tcp_connect failed")); - return 1; - } - DEBUG((" out rdp_tcp_connect")); - return 0; + DEBUG((" in rdp_tcp_connect ip %s port %s", ip, port)); + self->sck = g_tcp_socket(); + + if (g_tcp_connect(self->sck, ip, port) == 0) + { + g_tcp_set_non_blocking(self->sck); + } + else + { + DEBUG((" out rdp_tcp_connect error g_tcp_connect failed")); + return 1; + } + + DEBUG((" out rdp_tcp_connect")); + return 0; } /*****************************************************************************/ /* returns error */ int APP_CC -rdp_tcp_disconnect(struct rdp_tcp* self) +rdp_tcp_disconnect(struct rdp_tcp *self) { - if (self->sck != 0) - { - g_tcp_close(self->sck); - } - self->sck = 0; - return 0; + if (self->sck != 0) + { + g_tcp_close(self->sck); + } + + self->sck = 0; + return 0; } |
