diff options
154 files changed, 11775 insertions, 3808 deletions
diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..d40734d4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "librfxcodec"] + path = librfxcodec + url = git://github.com/neutrinolabs/librfxcodec diff --git a/common/Makefile.am b/common/Makefile.am index 3d7e8bd1..9feac9fb 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -5,6 +5,8 @@ EXTRA_DIST = \ file.h \ file_loc.h \ list.h \ + list16.h \ + fifo.h \ log.h \ os_calls.h \ os_calls.h \ @@ -15,7 +17,7 @@ EXTRA_DIST = \ trans.h \ xrdp_client_info.h \ xrdp_constants.h \ - xrdp_rail.h + xrdp_rail.h AM_CFLAGS = \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ @@ -31,11 +33,14 @@ libcommon_la_SOURCES = \ d3des.c \ file.c \ list.c \ + list16.c \ + fifo.c \ log.c \ os_calls.c \ ssl_calls.c \ thread_calls.c \ - trans.c + trans.c \ + xrdp_tls.c libcommon_la_LIBADD = \ -lcrypto \ diff --git a/common/arch.h b/common/arch.h index b4eb4719..14ab9d7d 100644 --- a/common/arch.h +++ b/common/arch.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,21 +19,41 @@ #if !defined(ARCH_H) #define ARCH_H -#if !(defined(L_ENDIAN) || defined(B_ENDIAN)) +/* you can define L_ENDIAN or B_ENDIAN and NEED_ALIGN or NO_NEED_ALIGN + in the makefile to override */ + /* check endianess */ +#if !(defined(L_ENDIAN) || defined(B_ENDIAN)) +#if !defined(__BYTE_ORDER) && defined(__linux__) +#include <endian.h> +#endif + +#if defined(BYTE_ORDER) +#if BYTE_ORDER == BIG_ENDIAN +#define B_ENDIAN +#else +#define L_ENDIAN +#endif +#endif + +#if !(defined(L_ENDIAN) || defined(B_ENDIAN)) #if defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || \ defined(__hppa__) #define B_ENDIAN #else #define L_ENDIAN #endif +#endif +#endif + /* check if we need to align data */ +#if !(defined(NEED_ALIGN) || defined(NO_NEED_ALIGN)) #if defined(__sparc__) || defined(__alpha__) || defined(__hppa__) || \ defined(__AIX__) || defined(__PPC__) || defined(__mips__) || \ defined(__ia64__) || defined(__ppc__) || defined(__arm__) #define NEED_ALIGN #elif defined(__x86__) || defined(__x86_64__) || \ - defined(__AMD64__) || defined(_M_IX86) || \ + defined(__AMD64__) || defined(_M_IX86) || defined (_M_AMD64) || \ defined(__i386__) #define NO_NEED_ALIGN #else diff --git a/common/crc16.h b/common/crc16.h new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/common/crc16.h diff --git a/common/defines.h b/common/defines.h index 502a41e8..d87ddae7 100644 --- a/common/defines.h +++ b/common/defines.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2012 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,7 +72,7 @@ (bpp==8?COLOR8(HRED(c),HGREEN(c),HBLUE(c)): \ (bpp==15?COLOR15(HRED(c),HGREEN(c),HBLUE(c)): \ (bpp==16?COLOR16(HRED(c),HGREEN(c),HBLUE(c)): \ - (bpp==24?COLOR24BGR(HRED(c),HGREEN(c),HBLUE(c)):c) \ + (bpp>=24?COLOR24BGR(HRED(c),HGREEN(c),HBLUE(c)):c) \ ) \ ) \ ) \ @@ -101,4 +101,10 @@ /* use crc for bitmap cache lookups */ #define USE_CRC +#define XR_RGB2BGR(a_ulColor) \ + (a_ulColor & 0xFF000000) | \ + ((a_ulColor & 0x00FF0000) >> 16) | \ + (a_ulColor & 0x0000FF00) | \ + ((a_ulColor & 0x000000FF) << 16) + #endif diff --git a/common/fifo.c b/common/fifo.c new file mode 100644 index 00000000..e3f6f3bc --- /dev/null +++ b/common/fifo.c @@ -0,0 +1,169 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2004-2014 + * + * 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. + * + * FIFO implementation to store pointer to data struct + */ + +#include "fifo.h" +#include "os_calls.h" + +/** + * Create new fifo data struct + * + * @return pointer to new FIFO or NULL if system out of memory + *****************************************************************************/ + +FIFO * APP_CC +fifo_create(void) +{ + return (FIFO *) g_malloc(sizeof(FIFO), 1); +} + +/** + * Delete specified FIFO + *****************************************************************************/ + +void APP_CC +fifo_delete(FIFO *self) +{ + USER_DATA *udp; + + if (!self) + return; + + if (!self->head) + { + /* FIFO is empty */ + g_free(self); + return; + } + + if (self->head == self->tail) + { + /* only one item in FIFO */ + if (self->auto_free) + g_free(self->head->item); + + g_free(self->head); + g_free(self); + return; + } + + /* more then one item in FIFO */ + while (self->head) + { + udp = self->head; + + if (self->auto_free) + g_free(udp->item); + + self->head = udp->next; + g_free(udp); + } + + g_free(self); +} + +/** + * Add an item to the specified FIFO + * + * @param self FIFO to operate on + * @param item item to add to specified FIFO + * + * @return 0 on success, -1 on error + *****************************************************************************/ + +int APP_CC +fifo_add_item(FIFO *self, void *item) +{ + USER_DATA *udp; + + if (!self || !item) + return -1; + + if ((udp = (USER_DATA *) g_malloc(sizeof(USER_DATA), 0)) == 0) + return -1; + + udp->item = item; + udp->next = 0; + + /* if fifo is empty, add to head */ + if (!self->head) + { + self->head = udp; + self->tail = udp; + return 0; + } + + /* add to tail */ + self->tail->next = udp; + self->tail = udp; + + return 0; +} + +/** + * Return an item from top of FIFO + * + * @param self FIFO to operate on + * + * @return top item from FIFO or NULL if FIFO is empty + *****************************************************************************/ + +void * APP_CC +fifo_remove_item(FIFO *self) +{ + void *item; + USER_DATA *udp; + + if (!self || !self->head) + return 0; + + if (self->head == self->tail) + { + /* only one item in FIFO */ + item = self->head->item; + g_free(self->head); + self->head = 0; + self->tail = 0; + return item; + } + + /* more then one item in FIFO */ + udp = self->head; + item = self->head->item; + self->head = self->head->next; + g_free(udp); + return item; +} + +/** + * Return FIFO status + * + * @param self FIFO to operate on + * + * @return true if FIFO is empty, false otherwise + *****************************************************************************/ + +int APP_CC +fifo_is_empty(FIFO *self) +{ + if (!self) + return 1; + + return (self->head == 0); +} diff --git a/common/fifo.h b/common/fifo.h new file mode 100644 index 00000000..3d44c453 --- /dev/null +++ b/common/fifo.h @@ -0,0 +1,47 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2004-2014 + * + * 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. + * + * FIFO implementation to store pointer to data struct + */ + +#ifndef _FIFO_H +#define _FIFO_H + +#include "arch.h" + +typedef struct user_data USER_DATA; + +struct user_data +{ + USER_DATA *next; + void *item; +}; + +typedef struct fifo +{ + USER_DATA *head; + USER_DATA *tail; + int auto_free; +} FIFO; + +FIFO * APP_CC fifo_create(void); +void APP_CC fifo_delete(FIFO *self); +int APP_CC fifo_add_item(FIFO *self, void *item); +void * APP_CC fifo_remove_item(FIFO *self); +int APP_CC fifo_is_empty(FIFO *self); + +#endif diff --git a/common/file.c b/common/file.c index f1ba5a87..b51a37cc 100644 --- a/common/file.c +++ b/common/file.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,8 @@ #include "file.h" #include "parse.h" +#define FILE_MAX_LINE_BYTES 2048 + /*****************************************************************************/ /* returns error returns 0 if everything is ok @@ -32,7 +34,7 @@ static int APP_CC l_file_read_sections(int fd, int max_file_size, struct list *names) { struct stream *s; - char text[256]; + char text[FILE_MAX_LINE_BYTES]; char c; int in_it; int in_it_index; @@ -44,7 +46,7 @@ l_file_read_sections(int fd, int max_file_size, struct list *names) g_file_seek(fd, 0); in_it_index = 0; in_it = 0; - g_memset(text, 0, 256); + g_memset(text, 0, FILE_MAX_LINE_BYTES); list_clear(names); make_stream(s); init_stream(s, max_file_size); @@ -67,7 +69,7 @@ l_file_read_sections(int fd, int max_file_size, struct list *names) list_add_item(names, (tbus)g_strdup(text)); in_it = 0; in_it_index = 0; - g_memset(text, 0, 256); + g_memset(text, 0, FILE_MAX_LINE_BYTES); } else if (in_it) { @@ -86,8 +88,9 @@ l_file_read_sections(int fd, int max_file_size, struct list *names) } /*****************************************************************************/ +/* returns error */ static int APP_CC -file_read_line(struct stream *s, char *text) +file_read_line(struct stream *s, char *text, int text_bytes) { int i; int skip_to_end; @@ -108,6 +111,7 @@ file_read_line(struct stream *s, char *text) while (c != 10 && c != 13) { + /* these mean skip the rest of the line */ if (c == '#' || c == '!' || c == ';') { skip_to_end = 1; @@ -117,6 +121,10 @@ file_read_line(struct stream *s, char *text) { text[i] = c; i++; + if (i >= text_bytes) + { + return 1; + } } if (s_check_rem(s, 1)) @@ -214,9 +222,10 @@ l_file_read_section(int fd, int max_file_size, const char *section, struct list *names, struct list *values) { struct stream *s; - char text[512]; - char name[512]; - char value[512]; + char *data; + char *text; + char *name; + char *value; char *lvalue; char c; int in_it; @@ -225,11 +234,16 @@ l_file_read_section(int fd, int max_file_size, const char *section, int index; int file_size; + data = (char *) g_malloc(FILE_MAX_LINE_BYTES * 3, 0); + text = data; + name = text + FILE_MAX_LINE_BYTES; + value = name + FILE_MAX_LINE_BYTES; + file_size = 32 * 1024; /* 32 K file size limit */ g_file_seek(fd, 0); in_it_index = 0; in_it = 0; - g_memset(text, 0, 512); + g_memset(text, 0, FILE_MAX_LINE_BYTES); list_clear(names); list_clear(values); make_stream(s); @@ -249,10 +263,13 @@ l_file_read_section(int fd, int max_file_size, const char *section, in_uint8(s, c); if ((c == '#') || (c == ';')) { - file_read_line(s, text); + if (file_read_line(s, text, FILE_MAX_LINE_BYTES) != 0) + { + break; + } in_it = 0; in_it_index = 0; - g_memset(text, 0, 512); + g_memset(text, 0, FILE_MAX_LINE_BYTES); continue; } if (c == '[') @@ -263,8 +280,8 @@ l_file_read_section(int fd, int max_file_size, const char *section, { if (g_strcasecmp(section, text) == 0) { - file_read_line(s, text); - while (file_read_line(s, text) == 0) + file_read_line(s, text, FILE_MAX_LINE_BYTES); + while (file_read_line(s, text, FILE_MAX_LINE_BYTES) == 0) { if (g_strlen(text) > 0) { @@ -292,21 +309,27 @@ l_file_read_section(int fd, int max_file_size, const char *section, } free_stream(s); + g_free(data); return 0; } in_it = 0; in_it_index = 0; - g_memset(text, 0, 512); + g_memset(text, 0, FILE_MAX_LINE_BYTES); } else if (in_it) { text[in_it_index] = c; in_it_index++; + if (in_it_index >= FILE_MAX_LINE_BYTES) + { + break; + } } } } free_stream(s); + g_free(data); return 1; } @@ -341,7 +364,7 @@ file_by_name_read_sections(const char *file_name, struct list *names) fd = g_file_open(file_name); - if (fd < 1) + if (fd < 0) { return 1; } @@ -382,7 +405,7 @@ file_by_name_read_section(const char *file_name, const char *section, fd = g_file_open(file_name); - if (fd < 1) + if (fd < 0) { return 1; } diff --git a/common/file.h b/common/file.h index cab4304c..ec3bbcb1 100644 --- a/common/file.h +++ b/common/file.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/common/file_loc.h b/common/file_loc.h index c8b3a76f..7389a1ed 100644 --- a/common/file_loc.h +++ b/common/file_loc.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2012 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,4 +41,28 @@ #define XRDP_LIB_PATH "/usr/local/lib/xrdp" #endif +#if !defined(XRDP_LOG_PATH) +#define XRDP_LOG_PATH "/var/log" +#endif + +#if !defined(XRDP_CHANSRV_STR) +#define XRDP_CHANSRV_STR "/tmp/.xrdp/xrdp_chansrv_socket_%d" +#endif + +#if !defined(CHANSRV_PORT_OUT_STR) +#define CHANSRV_PORT_OUT_STR "/tmp/.xrdp/xrdp_chansrv_audio_out_socket_%d" +#endif + +#if !defined(CHANSRV_PORT_IN_STR) +#define CHANSRV_PORT_IN_STR "/tmp/.xrdp/xrdp_chansrv_audio_in_socket_%d" +#endif + +#if !defined(CHANSRV_API_STR) +#define CHANSRV_API_STR "/tmp/.xrdp/xrdpapi_%d" +#endif + +#if !defined(XRDP_X11RDP_STR) +#define XRDP_X11RDP_STR "/tmp/.xrdp/xrdp_display_%d" +#endif + #endif diff --git a/common/list.c b/common/list.c index 2868d767..9fde1f6f 100644 --- a/common/list.c +++ b/common/list.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/common/list.h b/common/list.h index f92cc843..cdc545a0 100644 --- a/common/list.h +++ b/common/list.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,11 +26,11 @@ /* list */ struct list { - tbus* items; - int count; - int alloc_size; - int grow_by; - int auto_free; + tintptr* items; + int count; + int alloc_size; + int grow_by; + int auto_free; }; struct list* APP_CC @@ -38,17 +38,17 @@ list_create(void); void APP_CC list_delete(struct list* self); void APP_CC -list_add_item(struct list* self, tbus item); -tbus APP_CC +list_add_item(struct list* self, tintptr item); +tintptr APP_CC list_get_item(struct list* self, int index); void APP_CC list_clear(struct list* self); int APP_CC -list_index_of(struct list* self, tbus item); +list_index_of(struct list* self, tintptr item); void APP_CC list_remove_item(struct list* self, int index); void APP_CC -list_insert_item(struct list* self, int index, tbus item); +list_insert_item(struct list* self, int index, tintptr item); void APP_CC list_append_list_strdup(struct list* self, struct list* dest, int start_index); void APP_CC diff --git a/common/list16.c b/common/list16.c new file mode 100644 index 00000000..5e5c3d7f --- /dev/null +++ b/common/list16.c @@ -0,0 +1,188 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2014 + * + * 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. + * + * simple list + */ + +#include "arch.h" +#include "os_calls.h" +#include "list16.h" + +/*****************************************************************************/ +struct list16 *APP_CC +list16_create(void) +{ + struct list16 *self; + + self = (struct list16 *)g_malloc(sizeof(struct list16), 0); + list16_init(self); + return self; +} + +/*****************************************************************************/ +void APP_CC +list16_delete(struct list16 *self) +{ + if (self == 0) + { + return; + } + + list16_deinit(self); + g_free(self); +} + +/*****************************************************************************/ +void APP_CC +list16_init(struct list16* self) +{ + g_memset(self, 0, sizeof(struct list16)); + self->max_count = 4; + self->items = self->mitems; +} + +/*****************************************************************************/ +void APP_CC +list16_deinit(struct list16* self) +{ + if (self->items != self->mitems) + { + g_free(self->items); + } +} + +/*****************************************************************************/ +void APP_CC +list16_add_item(struct list16 *self, tui16 item) +{ + tui16 *p; + int i; + + if (self->count >= self->max_count) + { + i = self->max_count; + self->max_count += 4; + p = (tui16 *)g_malloc(sizeof(tui16) * self->max_count, 1); + g_memcpy(p, self->items, sizeof(tui16) * i); + if (self->items != self->mitems) + { + g_free(self->items); + } + self->items = p; + } + + self->items[self->count] = item; + self->count++; +} + +/*****************************************************************************/ +tui16 APP_CC +list16_get_item(struct list16 *self, int index) +{ + if (index < 0 || index >= self->count) + { + return 0; + } + + return self->items[index]; +} + +/*****************************************************************************/ +void APP_CC +list16_clear(struct list16 *self) +{ + if (self->items != self->mitems) + { + g_free(self->items); + } + self->count = 0; + self->max_count = 4; + self->items = self->mitems; +} + +/*****************************************************************************/ +int APP_CC +list16_index_of(struct list16 *self, tui16 item) +{ + int i; + + for (i = 0; i < self->count; i++) + { + if (self->items[i] == item) + { + return i; + } + } + + return -1; +} + +/*****************************************************************************/ +void APP_CC +list16_remove_item(struct list16 *self, int index) +{ + int i; + + if (index >= 0 && index < self->count) + { + for (i = index; i < (self->count - 1); i++) + { + self->items[i] = self->items[i + 1]; + } + + self->count--; + } +} + +/*****************************************************************************/ +void APP_CC +list16_insert_item(struct list16 *self, int index, tui16 item) +{ + tui16 *p; + int i; + + if (index == self->count) + { + list16_add_item(self, item); + return; + } + + if (index >= 0 && index < self->count) + { + self->count++; + + if (self->count > self->max_count) + { + i = self->max_count; + self->max_count += 4; + p = (tui16 *)g_malloc(sizeof(tui16) * self->max_count, 1); + g_memcpy(p, self->items, sizeof(tui16) * i); + if (self->items != self->mitems) + { + g_free(self->items); + } + self->items = p; + } + + for (i = (self->count - 2); i >= index; i--) + { + self->items[i + 1] = self->items[i]; + } + + self->items[index] = item; + } +} diff --git a/common/list16.h b/common/list16.h new file mode 100644 index 00000000..1a328ea7 --- /dev/null +++ b/common/list16.h @@ -0,0 +1,56 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2014 + * + * 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. + * + * simple list + */ + +#if !defined(LIST16_H) +#define LIST16_H + +#include "arch.h" + +/* list */ +struct list16 +{ + tui16* items; + int count; + int max_count; + tui16 mitems[4]; +}; + +struct list16* APP_CC +list16_create(void); +void APP_CC +list16_delete(struct list16* self); +void APP_CC +list16_init(struct list16* self); +void APP_CC +list16_deinit(struct list16* self); +void APP_CC +list16_add_item(struct list16* self, tui16 item); +tui16 APP_CC +list16_get_item(struct list16* self, int index); +void APP_CC +list16_clear(struct list16* self); +int APP_CC +list16_index_of(struct list16* self, tui16 item); +void APP_CC +list16_remove_item(struct list16* self, int index); +void APP_CC +list16_insert_item(struct list16* self, int index, tui16 item); + +#endif diff --git a/common/log.c b/common/log.c index 55353a8f..97053178 100644 --- a/common/log.c +++ b/common/log.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ #include "log.h" /* Here we store the current state and configuration of the log */ -static struct log_config *staticLogConfig = NULL; +static struct log_config *g_staticLogConfig = NULL; /* This file first start with all private functions. In the end of the file the public functions is defined */ @@ -284,6 +284,7 @@ internalReadConfiguration(const char *inFilename, const char *applicationName) if (ret != LOG_STARTUP_OK) { + g_file_close(fd); return ret; } @@ -296,11 +297,12 @@ internalReadConfiguration(const char *inFilename, const char *applicationName) param_v->auto_free = 1; /* read logging config */ - ret = internal_config_read_logging(fd, staticLogConfig, param_n, + ret = internal_config_read_logging(fd, g_staticLogConfig, param_n, param_v, applicationName); if (ret != LOG_STARTUP_OK) { + g_file_close(fd); return ret; } @@ -392,12 +394,12 @@ enum logReturns DEFAULT_CC internalInitAndAllocStruct(void) { enum logReturns ret = LOG_GENERAL_ERROR; - staticLogConfig = g_malloc(sizeof(struct log_config), 1); + g_staticLogConfig = g_malloc(sizeof(struct log_config), 1); - if (staticLogConfig != NULL) + if (g_staticLogConfig != NULL) { - staticLogConfig->fd = -1; - staticLogConfig->enable_syslog = 0; + g_staticLogConfig->fd = -1; + g_staticLogConfig->enable_syslog = 0; ret = LOG_STARTUP_OK; } else @@ -418,7 +420,7 @@ log_start_from_param(const struct log_config *iniParams) { enum logReturns ret = LOG_GENERAL_ERROR; - if (staticLogConfig != NULL) + if (g_staticLogConfig != NULL) { log_message(LOG_LEVEL_ALWAYS, "Log already initialized"); return ret; @@ -440,24 +442,24 @@ log_start_from_param(const struct log_config *iniParams) return ret; } - staticLogConfig->enable_syslog = iniParams->enable_syslog; - staticLogConfig->fd = iniParams->fd; - staticLogConfig->log_file = g_strdup(iniParams->log_file); - staticLogConfig->log_level = iniParams->log_level; - staticLogConfig->log_lock = iniParams->log_lock; - staticLogConfig->log_lock_attr = iniParams->log_lock_attr; - staticLogConfig->program_name = g_strdup(iniParams->program_name); - staticLogConfig->syslog_level = iniParams->syslog_level; - ret = internal_log_start(staticLogConfig); + g_staticLogConfig->enable_syslog = iniParams->enable_syslog; + g_staticLogConfig->fd = iniParams->fd; + g_staticLogConfig->log_file = g_strdup(iniParams->log_file); + g_staticLogConfig->log_level = iniParams->log_level; + g_staticLogConfig->log_lock = iniParams->log_lock; + g_staticLogConfig->log_lock_attr = iniParams->log_lock_attr; + g_staticLogConfig->program_name = g_strdup(iniParams->program_name); + g_staticLogConfig->syslog_level = iniParams->syslog_level; + ret = internal_log_start(g_staticLogConfig); if (ret != LOG_STARTUP_OK) { g_writeln("Could not start log"); - if (staticLogConfig != NULL) + if (g_staticLogConfig != NULL) { - g_free(staticLogConfig); - staticLogConfig = NULL; + g_free(g_staticLogConfig); + g_staticLogConfig = NULL; } } } @@ -487,16 +489,16 @@ log_start(const char *iniFile, const char *applicationName) if (ret == LOG_STARTUP_OK) { - ret = internal_log_start(staticLogConfig); + ret = internal_log_start(g_staticLogConfig); if (ret != LOG_STARTUP_OK) { g_writeln("Could not start log"); - if (staticLogConfig != NULL) + if (g_staticLogConfig != NULL) { - g_free(staticLogConfig); - staticLogConfig = NULL; + g_free(g_staticLogConfig); + g_staticLogConfig = NULL; } } } @@ -517,12 +519,12 @@ enum logReturns DEFAULT_CC log_end(void) { enum logReturns ret = LOG_GENERAL_ERROR; - ret = internal_log_end(staticLogConfig); + ret = internal_log_end(g_staticLogConfig); - if (staticLogConfig != NULL) + if (g_staticLogConfig != NULL) { - g_free(staticLogConfig); - staticLogConfig = NULL; + g_free(g_staticLogConfig); + g_staticLogConfig = NULL; } return ret; @@ -539,13 +541,13 @@ log_message(const enum logLevels lvl, const char *msg, ...) time_t now_t; struct tm *now; - if (staticLogConfig == NULL) + if (g_staticLogConfig == NULL) { g_writeln("The log reference is NULL - log not initialized properly"); return LOG_ERROR_NO_CFG; } - if (0 > staticLogConfig->fd && staticLogConfig->enable_syslog == 0) + if (0 > g_staticLogConfig->fd && g_staticLogConfig->enable_syslog == 0) { return LOG_ERROR_FILE_NOT_OPEN; } @@ -584,7 +586,7 @@ log_message(const enum logLevels lvl, const char *msg, ...) #endif #endif - if (staticLogConfig->enable_syslog && (lvl <= staticLogConfig->syslog_level)) + if (g_staticLogConfig->enable_syslog && (lvl <= g_staticLogConfig->syslog_level)) { /* log to syslog*/ /* %s fix compiler warning 'not a string literal' */ @@ -592,19 +594,19 @@ log_message(const enum logLevels lvl, const char *msg, ...) tc_get_threadid(), buff + 20); } - if (lvl <= staticLogConfig->log_level) + if (lvl <= g_staticLogConfig->log_level) { /* log to console */ g_printf("%s", buff); /* log to application logfile */ #ifdef LOG_ENABLE_THREAD - pthread_mutex_lock(&(staticLogConfig->log_lock)); + pthread_mutex_lock(&(g_staticLogConfig->log_lock)); #endif - if (staticLogConfig->fd > 0) + if (g_staticLogConfig->fd > 0) { - writereply = g_file_write(staticLogConfig->fd, buff, g_strlen(buff)); + writereply = g_file_write(g_staticLogConfig->fd, buff, g_strlen(buff)); if (writereply <= 0) { @@ -613,7 +615,7 @@ log_message(const enum logLevels lvl, const char *msg, ...) } #ifdef LOG_ENABLE_THREAD - pthread_mutex_unlock(&(staticLogConfig->log_lock)); + pthread_mutex_unlock(&(g_staticLogConfig->log_lock)); #endif } @@ -627,11 +629,11 @@ log_message(const enum logLevels lvl, const char *msg, ...) char *DEFAULT_CC getLogFile(char *replybuf, int bufsize) { - if (staticLogConfig) + if (g_staticLogConfig) { - if (staticLogConfig->log_file) + if (g_staticLogConfig->log_file) { - g_strncpy(replybuf, staticLogConfig->log_file, bufsize); + g_strncpy(replybuf, g_staticLogConfig->log_file, bufsize); } else { diff --git a/common/log.h b/common/log.h index 7a38bf38..b95c615a 100644 --- a/common/log.h +++ b/common/log.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,23 +29,23 @@ /* logging levels */ enum logLevels { - LOG_LEVEL_ALWAYS = 0, - LOG_LEVEL_ERROR, - LOG_LEVEL_WARNING, - LOG_LEVEL_INFO, - LOG_LEVEL_DEBUG + LOG_LEVEL_ALWAYS = 0, + LOG_LEVEL_ERROR, + LOG_LEVEL_WARNING, + LOG_LEVEL_INFO, + LOG_LEVEL_DEBUG }; /* startup return values */ enum logReturns { - LOG_STARTUP_OK = 0, - LOG_ERROR_MALLOC, - LOG_ERROR_NULL_FILE, - LOG_ERROR_FILE_OPEN, - LOG_ERROR_NO_CFG, - LOG_ERROR_FILE_NOT_OPEN, - LOG_GENERAL_ERROR + LOG_STARTUP_OK = 0, + LOG_ERROR_MALLOC, + LOG_ERROR_NULL_FILE, + LOG_ERROR_FILE_OPEN, + LOG_ERROR_NO_CFG, + LOG_ERROR_FILE_NOT_OPEN, + LOG_GENERAL_ERROR }; #define SESMAN_CFG_LOGGING "Logging" @@ -65,14 +65,14 @@ enum logReturns struct log_config { - char* program_name; - char* log_file; - int fd; - unsigned int log_level; - int enable_syslog; - unsigned int syslog_level; - pthread_mutex_t log_lock; - pthread_mutexattr_t log_lock_attr; + char *program_name; + char *log_file; + int fd; + unsigned int log_level; + int enable_syslog; + unsigned int syslog_level; + pthread_mutex_t log_lock; + pthread_mutexattr_t log_lock_attr; }; /* internal functions, only used in log.c if this ifdef is defined.*/ @@ -86,7 +86,7 @@ struct log_config * */ enum logReturns DEFAULT_CC -internal_log_start(struct log_config* l_cfg); +internal_log_start(struct log_config *l_cfg); /** * @@ -95,7 +95,7 @@ internal_log_start(struct log_config* l_cfg); * */ enum logReturns DEFAULT_CC -internal_log_end(struct log_config* l_cfg); +internal_log_end(struct log_config *l_cfg); /** * Converts a log level to a string @@ -103,7 +103,7 @@ internal_log_end(struct log_config* l_cfg); * @param str pointer where the string will be stored. */ void DEFAULT_CC -internal_log_lvl2str(const enum logLevels lvl, char* str); +internal_log_lvl2str(const enum logLevels lvl, char *str); /** * @@ -113,7 +113,7 @@ internal_log_lvl2str(const enum logLevels lvl, char* str); * */ enum logLevels DEFAULT_CC -internal_log_text2level(char* s); +internal_log_text2level(char *s); /** * A function that init our struct that holds all state and @@ -133,9 +133,9 @@ internalInitAndAllocStruct(void); * @return */ enum logReturns DEFAULT_CC -internal_config_read_logging(int file, struct log_config* lc, - struct list* param_n, - struct list* param_v, +internal_config_read_logging(int file, struct log_config *lc, + struct list *param_n, + struct list *param_v, const char *applicationName); /*End of internal functions*/ #endif @@ -147,7 +147,7 @@ internal_config_read_logging(int file, struct log_config* lc, * @return LOG_STARTUP_OK on success */ enum logReturns DEFAULT_CC -log_start(const char* iniFile, const char* applicationName); +log_start(const char *iniFile, const char *applicationName); /** * An alternative log_start where the caller gives the params directly. @@ -171,7 +171,7 @@ log_end(void); * @return */ enum logReturns DEFAULT_CC -log_message(const enum logLevels lvl, const char* msg, ...); +log_message(const enum logLevels lvl, const char *msg, ...); /** * @@ -181,7 +181,7 @@ log_message(const enum logLevels lvl, const char* msg, ...); * @return 0 on success, 1 on failure * */ -int APP_CC text2bool(char* s); +int APP_CC text2bool(char *s); /** * This function returns the configured file name for the logfile diff --git a/common/os_calls.c b/common/os_calls.c index 80b2d235..ef057497 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -471,8 +471,11 @@ g_tcp_socket(void) { option_value = 0; option_len = sizeof(option_value); - setsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&option_value, - option_len); + if (setsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&option_value, + option_len) < 0) + { + log_message(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed\n"); + } } } #endif @@ -484,8 +487,11 @@ g_tcp_socket(void) { option_value = 1; option_len = sizeof(option_value); - setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value, - option_len); + if (setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value, + option_len) < 0) + { + log_message(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed\n"); + } } } @@ -498,8 +504,11 @@ g_tcp_socket(void) { option_value = 1024 * 32; option_len = sizeof(option_value); - setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value, - option_len); + if (setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value, + option_len) < 0) + { + log_message(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed\n"); + } } } @@ -768,7 +777,9 @@ g_tcp_local_connect(int sck, const char *port) memset(&s, 0, sizeof(struct sockaddr_un)); s.sun_family = AF_UNIX; - strcpy(s.sun_path, port); + strncpy(s.sun_path, port, sizeof(s.sun_path)); + s.sun_path[sizeof(s.sun_path) - 1] = 0; + return connect(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_un)); #endif } @@ -785,7 +796,10 @@ g_tcp_set_non_blocking(int sck) #else i = fcntl(sck, F_GETFL); i = i | O_NONBLOCK; - fcntl(sck, F_SETFL, i); + if (fcntl(sck, F_SETFL, i) < 0) + { + log_message(LOG_LEVEL_ERROR, "g_tcp_set_non_blocking: fcntl() failed\n"); + } #endif return 0; } @@ -925,7 +939,9 @@ g_tcp_local_bind(int sck, const char *port) memset(&s, 0, sizeof(struct sockaddr_un)); s.sun_family = AF_UNIX; - strcpy(s.sun_path, port); + strncpy(s.sun_path, port, sizeof(s.sun_path)); + s.sun_path[sizeof(s.sun_path) - 1] = 0; + return bind(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_un)); #endif } @@ -1421,7 +1437,12 @@ g_set_wait_obj(tbus obj) return 1; } - sendto(s, "sig", 4, 0, (struct sockaddr *)&sa, sa_size); + if (sendto(s, "sig", 4, 0, (struct sockaddr *)&sa, sa_size) < 0) + { + close(s); + return 1; + } + close(s); return 0; #endif @@ -1934,8 +1955,7 @@ g_mkdir(const char *dirname) #if defined(_WIN32) return 0; #else - mkdir(dirname, S_IRWXU); - return 0; + return mkdir(dirname, S_IRWXU); #endif } @@ -2266,6 +2286,27 @@ g_strncmp(const char *c1, const char *c2, int len) } /*****************************************************************************/ +/* compare up to delim */ +int APP_CC +g_strncmp_d(const char *s1, const char *s2, const char delim, int n) +{ + char c1; + char c2; + + while (n > 0) + { + c1 = *s1++; + c2 = *s2++; + if ((c1 == 0) || (c1 != c2) || (c1 == delim) || (c2 == delim)) + { + return c1 - c2; + } + n--; + } + return c1 - c2; +} + +/*****************************************************************************/ int APP_CC g_strcasecmp(const char *c1, const char *c2) { @@ -2907,8 +2948,12 @@ g_clearenv(void) { #if defined(_WIN32) #else +#if defined(BSD) + environ[0] = 0; +#else environ = 0; #endif +#endif } /*****************************************************************************/ diff --git a/common/os_calls.h b/common/os_calls.h index 06ce8494..1805a6a1 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -115,6 +115,7 @@ char* APP_CC g_strdup(const char* in); char* APP_CC g_strndup(const char* in, const unsigned int maxlen); int APP_CC g_strcmp(const char* c1, const char* c2); int APP_CC g_strncmp(const char* c1, const char* c2, int len); +int APP_CC g_strncmp_d(const char* c1, const char* c2, const char delim, int len); int APP_CC g_strcasecmp(const char* c1, const char* c2); int APP_CC g_strncasecmp(const char* c1, const char* c2, int len); int APP_CC g_atoi(const char* str); diff --git a/common/parse.h b/common/parse.h index 69a57ff8..2ae3927b 100644 --- a/common/parse.h +++ b/common/parse.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,17 +36,17 @@ /* parser state */ struct stream { - char* p; - char* end; - char* data; - int size; - /* offsets of various headers */ - char* iso_hdr; - char* mcs_hdr; - char* sec_hdr; - char* rdp_hdr; - char* channel_hdr; - char* next_packet; + char *p; + char *end; + char *data; + int size; + /* offsets of various headers */ + char *iso_hdr; + char *mcs_hdr; + char *sec_hdr; + char *rdp_hdr; + char *channel_hdr; + char *next_packet; }; /******************************************************************************/ @@ -63,76 +63,77 @@ struct stream /******************************************************************************/ #define make_stream(s) \ - (s) = (struct stream*)g_malloc(sizeof(struct stream), 1) + (s) = (struct stream*)g_malloc(sizeof(struct stream), 1) /******************************************************************************/ #define init_stream(s, v) do \ { \ - if ((v) > (s)->size) \ - { \ - g_free((s)->data); \ - (s)->data = (char*)g_malloc((v), 0); \ - (s)->size = (v); \ - } \ - (s)->p = (s)->data; \ - (s)->end = (s)->data; \ - (s)->next_packet = 0; \ + if ((v) > (s)->size) \ + { \ + g_free((s)->data); \ + (s)->data = (char*)g_malloc((v), 0); \ + (s)->size = (v); \ + } \ + (s)->p = (s)->data; \ + (s)->end = (s)->data; \ + (s)->next_packet = 0; \ } while (0) /******************************************************************************/ #define free_stream(s) do \ { \ - if ((s) != 0) \ - { \ - g_free((s)->data); \ - } \ - g_free((s)); \ + if ((s) != 0) \ + { \ + g_free((s)->data); \ + } \ + g_free((s)); \ } while (0) /******************************************************************************/ #define s_push_layer(s, h, n) do \ { \ - (s)->h = (s)->p; \ - (s)->p += (n); \ + (s)->h = (s)->p; \ + (s)->p += (n); \ } while (0) /******************************************************************************/ #define s_pop_layer(s, h) \ - (s)->p = (s)->h + (s)->p = (s)->h /******************************************************************************/ #define s_mark_end(s) \ - (s)->end = (s)->p + (s)->end = (s)->p #define in_sint8(s, v) do \ { \ - (v) = *((signed char*)((s)->p)); \ - (s)->p++; \ + (v) = *((signed char*)((s)->p)); \ + (s)->p++; \ } while (0) /******************************************************************************/ #define in_uint8(s, v) do \ { \ - (v) = *((unsigned char*)((s)->p)); \ - (s)->p++; \ + (v) = *((unsigned char*)((s)->p)); \ + (s)->p++; \ } while (0) - +/******************************************************************************/ +#define in_uint8_peek(s, v) do { v = *s->p; } while (0) /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) #define in_sint16_le(s, v) do \ { \ - (v) = (signed short) \ - ( \ - (*((unsigned char*)((s)->p + 0)) << 0) | \ - (*((unsigned char*)((s)->p + 1)) << 8) \ - ); \ - (s)->p += 2; \ + (v) = (signed short) \ + ( \ + (*((unsigned char*)((s)->p + 0)) << 0) | \ + (*((unsigned char*)((s)->p + 1)) << 8) \ + ); \ + (s)->p += 2; \ } while (0) #else #define in_sint16_le(s, v) do \ { \ - (v) = *((signed short*)((s)->p)); \ - (s)->p += 2; \ + (v) = *((signed short*)((s)->p)); \ + (s)->p += 2; \ } while (0) #endif @@ -140,49 +141,49 @@ struct stream #if defined(B_ENDIAN) || defined(NEED_ALIGN) #define in_uint16_le(s, v) do \ { \ - (v) = (unsigned short) \ - ( \ - (*((unsigned char*)((s)->p + 0)) << 0) | \ - (*((unsigned char*)((s)->p + 1)) << 8) \ - ); \ - (s)->p += 2; \ + (v) = (unsigned short) \ + ( \ + (*((unsigned char*)((s)->p + 0)) << 0) | \ + (*((unsigned char*)((s)->p + 1)) << 8) \ + ); \ + (s)->p += 2; \ } while (0) #else #define in_uint16_le(s, v) do \ { \ - (v) = *((unsigned short*)((s)->p)); \ - (s)->p += 2; \ + (v) = *((unsigned short*)((s)->p)); \ + (s)->p += 2; \ } while (0) #endif /******************************************************************************/ #define in_uint16_be(s, v) do \ { \ - (v) = *((unsigned char*)((s)->p)); \ - (s)->p++; \ - (v) <<= 8; \ - (v) |= *((unsigned char*)((s)->p)); \ - (s)->p++; \ + (v) = *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ } while (0) /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) #define in_uint32_le(s, v) do \ { \ - (v) = (unsigned int) \ - ( \ - (*((unsigned char*)((s)->p + 0)) << 0) | \ - (*((unsigned char*)((s)->p + 1)) << 8) | \ - (*((unsigned char*)((s)->p + 2)) << 16) | \ - (*((unsigned char*)((s)->p + 3)) << 24) \ - ); \ - (s)->p += 4; \ + (v) = (unsigned int) \ + ( \ + (*((unsigned char*)((s)->p + 0)) << 0) | \ + (*((unsigned char*)((s)->p + 1)) << 8) | \ + (*((unsigned char*)((s)->p + 2)) << 16) | \ + (*((unsigned char*)((s)->p + 3)) << 24) \ + ); \ + (s)->p += 4; \ } while (0) #else #define in_uint32_le(s, v) do \ { \ - (v) = *((unsigned int*)((s)->p)); \ - (s)->p += 4; \ + (v) = *((unsigned int*)((s)->p)); \ + (s)->p += 4; \ } while (0) #endif @@ -190,41 +191,41 @@ struct stream #if defined(B_ENDIAN) || defined(NEED_ALIGN) #define in_uint64_le(s, v) do \ { \ - (v) = (tui64) \ - ( \ - (((tui64)(*((unsigned char*)((s)->p + 0)))) << 0) | \ - (((tui64)(*((unsigned char*)((s)->p + 1)))) << 8) | \ - (((tui64)(*((unsigned char*)((s)->p + 2)))) << 16) | \ - (((tui64)(*((unsigned char*)((s)->p + 3)))) << 24) | \ - (((tui64)(*((unsigned char*)((s)->p + 4)))) << 32) | \ - (((tui64)(*((unsigned char*)((s)->p + 5)))) << 40) | \ - (((tui64)(*((unsigned char*)((s)->p + 6)))) << 48) | \ - (((tui64)(*((unsigned char*)((s)->p + 7)))) << 56) \ - ); \ - (s)->p += 8; \ + (v) = (tui64) \ + ( \ + (((tui64)(*((unsigned char*)((s)->p + 0)))) << 0) | \ + (((tui64)(*((unsigned char*)((s)->p + 1)))) << 8) | \ + (((tui64)(*((unsigned char*)((s)->p + 2)))) << 16) | \ + (((tui64)(*((unsigned char*)((s)->p + 3)))) << 24) | \ + (((tui64)(*((unsigned char*)((s)->p + 4)))) << 32) | \ + (((tui64)(*((unsigned char*)((s)->p + 5)))) << 40) | \ + (((tui64)(*((unsigned char*)((s)->p + 6)))) << 48) | \ + (((tui64)(*((unsigned char*)((s)->p + 7)))) << 56) \ + ); \ + (s)->p += 8; \ } while (0) #else #define in_uint64_le(s, v) do \ { \ - (v) = *((tui64*)((s)->p)); \ - (s)->p += 8; \ + (v) = *((tui64*)((s)->p)); \ + (s)->p += 8; \ } while (0) #endif /******************************************************************************/ #define in_uint32_be(s, v) do \ { \ - (v) = *((unsigned char*)((s)->p)); \ - (s)->p++; \ - (v) <<= 8; \ - (v) |= *((unsigned char*)((s)->p)); \ - (s)->p++; \ - (v) <<= 8; \ - (v) |= *((unsigned char*)((s)->p)); \ - (s)->p++; \ - (v) <<= 8; \ - (v) |= *((unsigned char*)((s)->p)); \ - (s)->p++; \ + (v) = *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ + (v) <<= 8; \ + (v) |= *((unsigned char*)((s)->p)); \ + (s)->p++; \ } while (0) /******************************************************************************/ @@ -238,46 +239,46 @@ struct stream #if defined(B_ENDIAN) || defined(NEED_ALIGN) #define out_uint16_le(s, v) do \ { \ - *((s)->p) = (unsigned char)((v) >> 0); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 8); \ - (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + (s)->p++; \ } while (0) #else #define out_uint16_le(s, v) do \ { \ - *((unsigned short*)((s)->p)) = (unsigned short)(v); \ - (s)->p += 2; \ + *((unsigned short*)((s)->p)) = (unsigned short)(v); \ + (s)->p += 2; \ } while (0) #endif /******************************************************************************/ #define out_uint16_be(s, v) do \ { \ - *((s)->p) = (unsigned char)((v) >> 8); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 0); \ - (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ } while (0) /******************************************************************************/ #if defined(B_ENDIAN) || defined(NEED_ALIGN) #define out_uint32_le(s, v) do \ { \ - *((s)->p) = (unsigned char)((v) >> 0); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 8); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 16); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 24); \ - (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 16); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 24); \ + (s)->p++; \ } while (0) #else #define out_uint32_le(s, v) do \ { \ - *((unsigned int*)((s)->p)) = (v); \ - (s)->p += 4; \ + *((unsigned int*)((s)->p)) = (v); \ + (s)->p += 4; \ } while (0) #endif @@ -285,78 +286,78 @@ struct stream #if defined(B_ENDIAN) || defined(NEED_ALIGN) #define out_uint64_le(s, v) do \ { \ - *((s)->p) = (unsigned char)((v) >> 0); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 8); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 16); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 24); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 32); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 40); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 48); \ - (s)->p++; \ - *((s)->p) = (unsigned char)((v) >> 56); \ - (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 0); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 16); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 24); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 32); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 40); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 48); \ + (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 56); \ + (s)->p++; \ } while (0) #else #define out_uint64_le(s, v) do \ { \ - *((tui64*)((s)->p)) = (v); \ - (s)->p += 8; \ + *((tui64*)((s)->p)) = (v); \ + (s)->p += 8; \ } while (0) #endif /******************************************************************************/ #define out_uint32_be(s, v) do \ { \ - *((s)->p) = (unsigned char)((v) >> 24); \ - s->p++; \ - *((s)->p) = (unsigned char)((v) >> 16); \ - s->p++; \ - *((s)->p) = (unsigned char)((v) >> 8); \ - s->p++; \ - *((s)->p) = (unsigned char)(v); \ - (s)->p++; \ + *((s)->p) = (unsigned char)((v) >> 24); \ + s->p++; \ + *((s)->p) = (unsigned char)((v) >> 16); \ + s->p++; \ + *((s)->p) = (unsigned char)((v) >> 8); \ + s->p++; \ + *((s)->p) = (unsigned char)(v); \ + (s)->p++; \ } while (0) /******************************************************************************/ #define in_uint8p(s, v, n) do \ { \ - (v) = (s)->p; \ - (s)->p += (n); \ + (v) = (s)->p; \ + (s)->p += (n); \ } while (0) /******************************************************************************/ #define in_uint8a(s, v, n) do \ { \ - g_memcpy((v), (s)->p, (n)); \ - (s)->p += (n); \ + g_memcpy((v), (s)->p, (n)); \ + (s)->p += (n); \ } while (0) /******************************************************************************/ #define in_uint8s(s, n) \ - (s)->p += (n) + (s)->p += (n) /******************************************************************************/ #define out_uint8p(s, v, n) do \ { \ - g_memcpy((s)->p, (v), (n)); \ - (s)->p += (n); \ + g_memcpy((s)->p, (v), (n)); \ + (s)->p += (n); \ } while (0) /******************************************************************************/ #define out_uint8a(s, v, n) \ - out_uint8p((s), (v), (n)) + out_uint8p((s), (v), (n)) /******************************************************************************/ #define out_uint8s(s, n) do \ { \ - g_memset((s)->p, 0, (n)); \ - (s)->p += (n); \ + g_memset((s)->p, 0, (n)); \ + (s)->p += (n); \ } while (0) /* diff --git a/common/rail.h b/common/rail.h index deed3a9e..26605cd9 100644 --- a/common/rail.h +++ b/common/rail.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2012 + * Copyright (C) Jay Sorg 2012-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/common/ssl_calls.c b/common/ssl_calls.c index a187edc9..134f5afd 100644 --- a/common/ssl_calls.c +++ b/common/ssl_calls.c @@ -400,7 +400,8 @@ ssl_gen_key_xrdp1(int key_size_in_bits, char *exp, int exp_len, int error; int len; - if ((exp_len != 4) || (mod_len != 64) || (pri_len != 64)) + if ((exp_len != 4) || ((mod_len != 64) && (mod_len != 256)) || + ((pri_len != 64) && (pri_len != 256))) { return 1; } @@ -469,7 +470,8 @@ ssl_gen_key_xrdp1(int key_size_in_bits, char *exp, int exp_len, int error; int len; - if ((exp_len != 4) || (mod_len != 64) || (pri_len != 64)) + if ((exp_len != 4) || ((mod_len != 64) && (mod_len != 256)) || + ((pri_len != 64) && (pri_len != 256))) { return 1; } diff --git a/common/thread_calls.c b/common/thread_calls.c index b571fb62..a68e902a 100644 --- a/common/thread_calls.c +++ b/common/thread_calls.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/common/thread_calls.h b/common/thread_calls.h index 9d2c4a11..2a3122fc 100644 --- a/common/thread_calls.h +++ b/common/thread_calls.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/common/trans.c b/common/trans.c index aced0667..5503ea61 100644 --- a/common/trans.c +++ b/common/trans.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,12 +24,49 @@ #include "parse.h" /*****************************************************************************/ -struct trans *APP_CC +int APP_CC +trans_tls_recv(struct trans *self, void *ptr, int len) +{ + if (self->tls == NULL) + { + return 1; + } + return xrdp_tls_read(self->tls, ptr, len); +} + +/*****************************************************************************/ +int APP_CC +trans_tls_send(struct trans *self, const void *data, int len) +{ + if (self->tls == NULL) + { + return 1; + } + return xrdp_tls_write(self->tls, data, len); +} + +/*****************************************************************************/ +int APP_CC +trans_tcp_recv(struct trans *self, void *ptr, int len) +{ + return g_tcp_recv(self->sck, ptr, len, 0); +} + +/*****************************************************************************/ +int APP_CC +trans_tcp_send(struct trans *self, const void *data, int len) +{ + return g_tcp_send(self->sck, data, len, 0); +} + +/*****************************************************************************/ +struct trans * +APP_CC trans_create(int mode, int in_size, int out_size) { - struct trans *self = (struct trans *)NULL; + struct trans *self = (struct trans *) NULL; - self = (struct trans *)g_malloc(sizeof(struct trans), 1); + self = (struct trans *) g_malloc(sizeof(struct trans), 1); if (self != NULL) { @@ -38,6 +75,10 @@ trans_create(int mode, int in_size, int out_size) make_stream(self->out_s); init_stream(self->out_s, out_size); self->mode = mode; + self->tls = 0; + /* assign tcp calls by default */ + self->trans_recv = trans_tcp_recv; + self->trans_send = trans_tcp_send; } return self; @@ -68,6 +109,11 @@ trans_delete(struct trans *self) g_free(self->listen_filename); } + if (self->tls != 0) + { + xrdp_tls_delete(self->tls); + } + g_free(self); } @@ -92,8 +138,7 @@ trans_get_wait_objs(struct trans *self, tbus *objs, int *count) /*****************************************************************************/ int APP_CC -trans_get_wait_objs_rw(struct trans *self, - tbus *robjs, int *rcount, +trans_get_wait_objs_rw(struct trans *self, tbus *robjs, int *rcount, tbus *wobjs, int *wcount) { if (self == 0) @@ -138,7 +183,7 @@ send_waiting(struct trans *self, int block) if (g_tcp_can_send(self->sck, timeout)) { bytes = (int) (temp_s->end - temp_s->p); - sent = g_tcp_send(self->sck, temp_s->p, bytes, 0); + sent = self->trans_send(self, temp_s->p, bytes); if (sent > 0) { temp_s->p += sent; @@ -174,8 +219,8 @@ send_waiting(struct trans *self, int block) int APP_CC trans_check_wait_objs(struct trans *self) { - tbus in_sck = (tbus)0; - struct trans *in_trans = (struct trans *)NULL; + tbus in_sck = (tbus) 0; + struct trans *in_trans = (struct trans *) NULL; int read_bytes = 0; int to_read = 0; int read_so_far = 0; @@ -224,8 +269,10 @@ trans_check_wait_objs(struct trans *self) in_trans->type1 = TRANS_TYPE_SERVER; in_trans->status = TRANS_STATUS_UP; in_trans->is_term = self->is_term; - g_strncpy(in_trans->addr, self->addr, sizeof(self->addr) - 1); - g_strncpy(in_trans->port, self->port, sizeof(self->port) - 1); + g_strncpy(in_trans->addr, self->addr, + sizeof(self->addr) - 1); + g_strncpy(in_trans->port, self->port, + sizeof(self->port) - 1); if (self->trans_conn_in(self, in_trans) != 0) { @@ -243,12 +290,12 @@ trans_check_wait_objs(struct trans *self) { if (g_tcp_can_recv(self->sck, 0)) { - read_so_far = (int)(self->in_s->end - self->in_s->data); + read_so_far = (int) (self->in_s->end - self->in_s->data); to_read = self->header_size - read_so_far; if (to_read > 0) { - read_bytes = g_tcp_recv(self->sck, self->in_s->end, to_read, 0); + read_bytes = self->trans_recv(self, self->in_s->end, to_read); if (read_bytes == -1) { @@ -275,7 +322,7 @@ trans_check_wait_objs(struct trans *self) } } - read_so_far = (int)(self->in_s->end - self->in_s->data); + read_so_far = (int) (self->in_s->end - self->in_s->data); if (read_so_far == self->header_size) { @@ -299,7 +346,6 @@ trans_check_wait_objs(struct trans *self) return rv; } - /*****************************************************************************/ int APP_CC trans_force_read_s(struct trans *self, struct stream *in_s, int size) @@ -318,7 +364,9 @@ trans_force_read_s(struct trans *self, struct stream *in_s, int size) { return 1; } - rcvd = g_tcp_recv(self->sck, in_s->end, size, 0); + + rcvd = self->trans_recv(self, in_s->end, size); + if (rcvd == -1) { if (g_tcp_last_error_would_block(self->sck)) @@ -380,7 +428,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) return 1; } - size = (int)(out_s->end - out_s->data); + size = (int) (out_s->end - out_s->data); total = 0; if (send_waiting(self, 1) != 0) @@ -391,7 +439,7 @@ trans_force_write_s(struct trans *self, struct stream *out_s) while (total < size) { - sent = g_tcp_send(self->sck, out_s->data + total, size - total, 0); + sent = self->trans_send(self, out_s->data + total, size - total); if (sent == -1) { @@ -455,7 +503,7 @@ trans_write_copy(struct trans *self) } out_s = self->out_s; - size = (int)(out_s->end - out_s->data); + size = (int) (out_s->end - out_s->data); make_stream(wait_s); init_stream(wait_s, size); out_uint8a(wait_s, out_s->data, size); @@ -501,12 +549,18 @@ trans_connect(struct trans *self, const char *server, const char *port, if (self->mode == TRANS_MODE_TCP) /* tcp */ { self->sck = g_tcp_socket(); + if (self->sck < 0) + return 1; + g_tcp_set_non_blocking(self->sck); error = g_tcp_connect(self->sck, server, port); } else if (self->mode == TRANS_MODE_UNIX) /* unix socket */ { self->sck = g_tcp_local_socket(); + if (self->sck < 0) + return 1; + g_tcp_set_non_blocking(self->sck); error = g_tcp_local_connect(self->sck, port); } @@ -537,6 +591,10 @@ trans_connect(struct trans *self, const char *server, const char *port, } /*****************************************************************************/ + +/** + * @return 0 on success, 1 on failure + */ int APP_CC trans_listen_address(struct trans *self, char *port, const char *address) { @@ -548,6 +606,9 @@ trans_listen_address(struct trans *self, char *port, const char *address) if (self->mode == TRANS_MODE_TCP) /* tcp */ { self->sck = g_tcp_socket(); + if (self->sck < 0) + return 1; + g_tcp_set_non_blocking(self->sck); if (g_tcp_bind_address(self->sck, port, address) == 0) @@ -565,7 +626,11 @@ trans_listen_address(struct trans *self, char *port, const char *address) g_free(self->listen_filename); self->listen_filename = 0; g_file_delete(port); + self->sck = g_tcp_local_socket(); + if (self->sck < 0) + return 1; + g_tcp_set_non_blocking(self->sck); if (g_tcp_local_bind(self->sck, port) == 0) @@ -574,7 +639,7 @@ trans_listen_address(struct trans *self, char *port, const char *address) if (g_tcp_listen(self->sck) == 0) { - g_chmod_hex(port, 0xffff); + g_chmod_hex(port, 0x0660); self->status = TRANS_STATUS_UP; /* ok */ self->type1 = TRANS_TYPE_LISTENER; /* listener */ return 0; @@ -593,14 +658,15 @@ trans_listen(struct trans *self, char *port) } /*****************************************************************************/ -struct stream *APP_CC +struct stream * +APP_CC trans_get_in_s(struct trans *self) { - struct stream *rv = (struct stream *)NULL; + struct stream *rv = (struct stream *) NULL; if (self == NULL) { - rv = (struct stream *)NULL; + rv = (struct stream *) NULL; } else { @@ -611,14 +677,15 @@ trans_get_in_s(struct trans *self) } /*****************************************************************************/ -struct stream *APP_CC +struct stream * +APP_CC trans_get_out_s(struct trans *self, int size) { - struct stream *rv = (struct stream *)NULL; + struct stream *rv = (struct stream *) NULL; if (self == NULL) { - rv = (struct stream *)NULL; + rv = (struct stream *) NULL; } else { @@ -628,3 +695,43 @@ trans_get_out_s(struct trans *self, int size) return rv; } +/*****************************************************************************/ +/* returns error */ +int APP_CC +trans_set_tls_mode(struct trans *self, const char *key, const char *cert) +{ + self->tls = xrdp_tls_create(self, key, cert); + if (self->tls == NULL) + { + g_writeln("trans_set_tls_mode: xrdp_tls_create malloc error"); + return 1; + } + + if (xrdp_tls_accept(self->tls) != 0) + { + g_writeln("trans_set_tls_mode: xrdp_tls_accept failed"); + return 1; + } + + /* assign tls functions */ + self->trans_recv = trans_tls_recv; + self->trans_send = trans_tls_send; + + return 0; +} +/*****************************************************************************/ +/* returns error */ +int APP_CC +trans_shutdown_tls_mode(struct trans *self) +{ + if (self->tls != NULL) + { + return xrdp_tls_disconnect(self->tls); + } + + /* assign callback back to tcp cal */ + self->trans_recv = trans_tcp_recv; + self->trans_send = trans_tcp_send; + + return 0; +} diff --git a/common/trans.h b/common/trans.h index c2e5e0df..a169e9cb 100644 --- a/common/trans.h +++ b/common/trans.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,32 +35,59 @@ #define TRANS_STATUS_UP 1 struct trans; /* forward declaration */ +struct xrdp_tls; -typedef int (*ttrans_data_in)(struct trans* self); -typedef int (*ttrans_conn_in)(struct trans* self, struct trans* new_self); -typedef int (*tis_term)(void); +typedef int (DEFAULT_CC *ttrans_data_in)(struct trans* self); +typedef int (DEFAULT_CC *ttrans_conn_in)(struct trans* self, + struct trans* new_self); +typedef int (DEFAULT_CC *tis_term)(void); +typedef int (APP_CC *trans_recv) (struct trans *self, void *ptr, int len); +typedef int (APP_CC *trans_send) (struct trans *self, const void *data, int len); struct trans { - tbus sck; /* socket handle */ - int mode; /* 1 tcp, 2 unix socket */ - int status; - int type1; /* 1 listener 2 server 3 client */ - ttrans_data_in trans_data_in; - ttrans_conn_in trans_conn_in; - void* callback_data; - int header_size; - struct stream* in_s; - struct stream* out_s; - char* listen_filename; - tis_term is_term; /* used to test for exit */ - struct stream* wait_s; - char addr[256]; - char port[256]; - int no_stream_init_on_data_in; - int extra_flags; /* user defined */ + tbus sck; /* socket handle */ + int mode; /* 1 tcp, 2 unix socket */ + int status; + int type1; /* 1 listener 2 server 3 client */ + ttrans_data_in trans_data_in; + ttrans_conn_in trans_conn_in; + void* callback_data; + int header_size; + struct stream* in_s; + struct stream* out_s; + char* listen_filename; + tis_term is_term; /* used to test for exit */ + struct stream* wait_s; + char addr[256]; + char port[256]; + int no_stream_init_on_data_in; + int extra_flags; /* user defined */ + struct xrdp_tls *tls; + trans_recv trans_recv; + trans_send trans_send; }; +/* xrdp_tls */ +struct xrdp_tls +{ + void *ssl; /* SSL * */ + void *ctx; /* SSL_CTX * */ + char *cert; + char *key; + struct trans *trans; +}; + +/* xrdp_tls.c */ +struct xrdp_tls *APP_CC +xrdp_tls_create(struct trans *trans, const char *key, const char *cert); +int APP_CC +xrdp_tls_accept(struct xrdp_tls *self); +int APP_CC +xrdp_tls_disconnect(struct xrdp_tls *self); +void APP_CC +xrdp_tls_delete(struct xrdp_tls *self); + struct trans* APP_CC trans_create(int mode, int in_size, int out_size); void APP_CC @@ -94,5 +121,13 @@ struct stream* APP_CC trans_get_in_s(struct trans* self); struct stream* APP_CC trans_get_out_s(struct trans* self, int size); +int APP_CC +trans_set_tls_mode(struct trans *self, const char *key, const char *cert); +int APP_CC +trans_shutdown_tls_mode(struct trans *self); +int APP_CC +trans_tcp_force_read_s(struct trans *self, struct stream *in_s, int size); +int APP_CC +trans_force_write_s(struct trans *self, struct stream *out_s); #endif diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index 50c9f143..7e906c92 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -106,14 +106,14 @@ struct xrdp_client_info char client_addr[256]; char client_port[256]; - int nego_sec_layer; /* 0, 1, 2 = RDP security layer, TLS , Negotiate */ + int security_layer; /* 0 = rdp, 1 = tls , 2 = hybrid */ int multimon; /* 0 = deny , 1 = allow */ int monitorCount; /* number of monitors detected (max = 16) */ struct monitor_info minfo[16]; /* client monitor data */ int keyboard_type; int keyboard_subtype; - + int png_codec_id; int png_prop_len; char png_prop[64]; @@ -121,6 +121,18 @@ struct xrdp_client_info int mcs_connection_type; int mcs_early_capability_flags; + int max_fastpath_frag_bytes; + int capture_code; + int capture_format; + + char certificate[1024]; + char key_file[1024]; + + /* X11 keyboard layout - inferred from keyboard type/subtype */ + char model[16]; + char layout[16]; + char variant[16]; + }; #endif diff --git a/common/xrdp_constants.h b/common/xrdp_constants.h index ed74fd01..2ee034c3 100644 --- a/common/xrdp_constants.h +++ b/common/xrdp_constants.h @@ -3,7 +3,7 @@ * Miscellaneous protocol constants * * Copyright (C) Matthew Chapman 1999-2008 - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * Copyright (C) Kevin Zhou 2012 * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -161,6 +161,7 @@ #define RDP_INPUT_VIRTKEY 2 #define RDP_INPUT_SCANCODE 4 #define RDP_INPUT_MOUSE 0x8001 +#define RDP_INPUT_MOUSEX 0x8002 /* Device flags */ #define KBD_FLAG_RIGHT 0x0001 @@ -560,6 +561,24 @@ #define RDP_CAPSET_LPOINTER 0x27 #define RDP_CAPLEN_LPOINTER 0x06 +/* fastpath input */ +#define FASTPATH_INPUT_SECURE_CHECKSUM 0x1 +#define FASTPATH_INPUT_ENCRYPTED 0x2 + +#define FASTPATH_INPUT_ACTION_FASTPATH 0x0 +#define FASTPATH_INPUT_ACTION_X224 0x3 + +#define FASTPATH_INPUT_EVENT_SCANCODE 0x0 +#define FASTPATH_INPUT_EVENT_MOUSE 0x1 +#define FASTPATH_INPUT_EVENT_MOUSEX 0x2 +#define FASTPATH_INPUT_EVENT_SYNC 0x3 +#define FASTPATH_INPUT_EVENT_UNICODE 0x4 + +#define FASTPATH_INPUT_KBDFLAGS_RELEASE 0x01 +#define FASTPATH_INPUT_KBDFLAGS_EXTENDED 0x02 + + +/* fastpath output */ #define FASTPATH_OUTPUT_ACTION_FASTPATH 0x0 #define FASTPATH_OUTPUT_ACTION_X224 0x3 diff --git a/common/xrdp_rail.h b/common/xrdp_rail.h index 89cd9f95..b93672be 100644 --- a/common/xrdp_rail.h +++ b/common/xrdp_rail.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2012-2013 + * Copyright (C) Jay Sorg 2012-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,76 +72,76 @@ struct rail_icon_info { - int bpp; - int width; - int height; - int cmap_bytes; - int mask_bytes; - int data_bytes; - char* mask; - char* cmap; - char* data; + int bpp; + int width; + int height; + int cmap_bytes; + int mask_bytes; + int data_bytes; + char *mask; + char *cmap; + char *data; }; struct rail_window_rect { - short left; - short top; - short right; - short bottom; + short left; + short top; + short right; + short bottom; }; struct rail_notify_icon_infotip { - int timeout; - int flags; - char* text; - char* title; + int timeout; + int flags; + char *text; + char *title; }; struct rail_window_state_order { - int owner_window_id; - int style; - int extended_style; - int show_state; - char* title_info; - int client_offset_x; - int client_offset_y; - int client_area_width; - int client_area_height; - int rp_content; - int root_parent_handle; - int window_offset_x; - int window_offset_y; - int window_client_delta_x; - int window_client_delta_y; - int window_width; - int window_height; - int num_window_rects; - struct rail_window_rect* window_rects; - int visible_offset_x; - int visible_offset_y; - int num_visibility_rects; - struct rail_window_rect* visibility_rects; + int owner_window_id; + int style; + int extended_style; + int show_state; + char *title_info; + int client_offset_x; + int client_offset_y; + int client_area_width; + int client_area_height; + int rp_content; + int root_parent_handle; + int window_offset_x; + int window_offset_y; + int window_client_delta_x; + int window_client_delta_y; + int window_width; + int window_height; + int num_window_rects; + struct rail_window_rect *window_rects; + int visible_offset_x; + int visible_offset_y; + int num_visibility_rects; + struct rail_window_rect *visibility_rects; }; struct rail_notify_state_order { - int version; - char* tool_tip; - struct rail_notify_icon_infotip infotip; - int state; - int icon_cache_entry; - int icon_cache_id; - struct rail_icon_info icon_info; + int version; + char *tool_tip; + struct rail_notify_icon_infotip infotip; + int state; + int icon_cache_entry; + int icon_cache_id; + struct rail_icon_info icon_info; }; struct rail_monitored_desktop_order { - int active_window_id; - int num_window_ids; - int* window_ids; + int active_window_id; + int num_window_ids; + int *window_ids; }; #endif diff --git a/common/xrdp_tls.c b/common/xrdp_tls.c new file mode 100644 index 00000000..28f1af55 --- /dev/null +++ b/common/xrdp_tls.c @@ -0,0 +1,269 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Idan Freiberg 2013-2014 + * + * 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. + * + * transport layer security + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <openssl/ssl.h> + +#include "os_calls.h" +#include "trans.h" +#include "ssl_calls.h" + + +/*****************************************************************************/ +struct xrdp_tls * +APP_CC +xrdp_tls_create(struct trans *trans, const char *key, const char *cert) +{ + struct xrdp_tls *self; + self = (struct xrdp_tls *) g_malloc(sizeof(struct xrdp_tls), 1); + + if (self != NULL) + { + self->trans = trans; + self->cert = (char *) cert; + self->key = (char *) key; + } + + return self; +} + +/*****************************************************************************/ +int APP_CC +xrdp_tls_print_error(char *func, SSL *connection, int value) +{ + switch (SSL_get_error(connection, value)) + { + case SSL_ERROR_ZERO_RETURN: + g_writeln("xrdp_tls_print_error: %s: Server closed TLS connection", + func); + return 1; + + case SSL_ERROR_WANT_READ: + g_writeln("xrdp_tls_print_error: SSL_ERROR_WANT_READ"); + return 0; + + case SSL_ERROR_WANT_WRITE: + g_writeln("xrdp_tls_print_error: SSL_ERROR_WANT_WRITE"); + return 0; + + case SSL_ERROR_SYSCALL: + g_writeln("xrdp_tls_print_error: %s: I/O error", func); + return 1; + + case SSL_ERROR_SSL: + g_writeln("xrdp_tls_print_error: %s: Failure in SSL library (protocol error?)", + func); + return 1; + + default: + g_writeln("xrdp_tls_print_error: %s: Unknown error", func); + return 1; + } +} + +/*****************************************************************************/ +int APP_CC +xrdp_tls_accept(struct xrdp_tls *self) +{ + int connection_status; + long options = 0; + + /** + * SSL_OP_NO_SSLv2: + * + * We only want SSLv3 and TLSv1, so disable SSLv2. + * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. + */ + options |= SSL_OP_NO_SSLv2; + +#if defined(SSL_OP_NO_COMPRESSION) + /** + * SSL_OP_NO_COMPRESSION: + * + * The Microsoft RDP server does not advertise support + * for TLS compression, but alternative servers may support it. + * This was observed between early versions of the FreeRDP server + * and the FreeRDP client, and caused major performance issues, + * which is why we're disabling it. + */ + options |= SSL_OP_NO_COMPRESSION; +#endif + + /** + * SSL_OP_TLS_BLOCK_PADDING_BUG: + * + * The Microsoft RDP server does *not* support TLS padding. + * It absolutely needs to be disabled otherwise it won't work. + */ + options |= SSL_OP_TLS_BLOCK_PADDING_BUG; + + /** + * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: + * + * Just like TLS padding, the Microsoft RDP server does not + * support empty fragments. This needs to be disabled. + */ + options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + + self->ctx = SSL_CTX_new(SSLv23_server_method()); + /* set context options */ + SSL_CTX_set_mode(self->ctx, + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | + SSL_MODE_ENABLE_PARTIAL_WRITE); + SSL_CTX_set_options(self->ctx, options); + SSL_CTX_set_read_ahead(self->ctx, 1); + + if (self->ctx == NULL) + { + g_writeln("xrdp_tls_accept: SSL_CTX_new failed"); + return 1; + } + + if (SSL_CTX_use_RSAPrivateKey_file(self->ctx, self->key, SSL_FILETYPE_PEM) + <= 0) + { + g_writeln("xrdp_tls_accept: SSL_CTX_use_RSAPrivateKey_file failed"); + return 1; + } + + self->ssl = SSL_new(self->ctx); + + if (self->ssl == NULL) + { + g_writeln("xrdp_tls_accept: SSL_new failed"); + return 1; + } + + if (SSL_use_certificate_file(self->ssl, self->cert, SSL_FILETYPE_PEM) <= 0) + { + g_writeln("xrdp_tls_accept: SSL_use_certificate_file failed"); + return 1; + } + + if (SSL_set_fd(self->ssl, self->trans->sck) < 1) + { + g_writeln("xrdp_tls_accept: SSL_set_fd failed"); + return 1; + } + + connection_status = SSL_accept(self->ssl); + + if (connection_status <= 0) + { + if (xrdp_tls_print_error("SSL_accept", self->ssl, connection_status)) + { + return 1; + } + } + + g_writeln("xrdp_tls_accept: TLS connection accepted"); + + return 0; +} +/*****************************************************************************/ +int APP_CC +xrdp_tls_disconnect(struct xrdp_tls *self) +{ + int status = SSL_shutdown(self->ssl); + while (status != 1) + { + status = SSL_shutdown(self->ssl); + + if (status <= 0) + { + if (xrdp_tls_print_error("SSL_shutdown", self->ssl, status)) + { + return 1; + } + } + } + return 0; +} +/*****************************************************************************/ +void APP_CC +xrdp_tls_delete(struct xrdp_tls *self) +{ + if (self != NULL) + { + if (self->ssl) + SSL_free(self->ssl); + + if (self->ctx) + SSL_CTX_free(self->ctx); + + g_free(self); + } +} +/*****************************************************************************/ +int APP_CC +xrdp_tls_read(struct xrdp_tls *tls, char *data, int length) +{ + int status; + + status = SSL_read(tls->ssl, data, length); + + switch (SSL_get_error(tls->ssl, status)) + { + case SSL_ERROR_NONE: + break; + + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + status = 0; + break; + + default: + xrdp_tls_print_error("SSL_read", tls->ssl, status); + status = -1; + break; + } + + return status; +} +/*****************************************************************************/ +int APP_CC +xrdp_tls_write(struct xrdp_tls *tls, char *data, int length) +{ + int status; + + status = SSL_write(tls->ssl, data, length); + + switch (SSL_get_error(tls->ssl, status)) + { + case SSL_ERROR_NONE: + break; + + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + status = 0; + break; + + default: + xrdp_tls_print_error("SSL_write", tls->ssl, status); + status = -1; + break; + } + + return status; +} + diff --git a/configure.ac b/configure.ac index 621ce4be..85145cfc 100644 --- a/configure.ac +++ b/configure.ac @@ -40,29 +40,21 @@ AC_ARG_ENABLE(jpeg, AS_HELP_STRING([--enable-jpeg], [jpeg=true], [jpeg=false]) AM_CONDITIONAL(XRDP_JPEG, [test x$jpeg = xtrue]) AC_ARG_ENABLE(tjpeg, AS_HELP_STRING([--enable-tjpeg], - [Build turbo jpeg module(assumes /opt/libjpeg-turbo) (default: no)]), + [Build turbo jpeg module (default: no)]), [tjpeg=true], [tjpeg=false]) AM_CONDITIONAL(XRDP_TJPEG, [test x$tjpeg = xtrue]) - -AC_ARG_ENABLE(simplesound, AS_HELP_STRING([--enable-simplesound], - [Build simple pulse audio interface (default: no)]), - [simplesound=true], [simplesound=false]) -AM_CONDITIONAL(XRDP_SIMPLESOUND, [test x$simplesound = xtrue]) - AC_ARG_ENABLE(fuse, AS_HELP_STRING([--enable-fuse], [Build fuse(clipboard file / drive redir) (default: no)]), [fuse=true], [fuse=false]) AM_CONDITIONAL(XRDP_FUSE, [test x$fuse = xtrue]) - -AC_ARG_ENABLE(loadpulsemodules, AS_HELP_STRING([--enable-loadpulsemodules], - [Build code to load pulse audio modules (default: no)]), - [loadpulsemodules=true], [loadpulsemodules=false]) -AM_CONDITIONAL(XRDP_LOAD_PULSE_MODULES, [test x$loadpulsemodules = xtrue]) - AC_ARG_ENABLE(xrdpvr, AS_HELP_STRING([--enable-xrdpvr], [Build xrdpvr module (default: no)]), [xrdpvr=true], [xrdpvr=false]) AM_CONDITIONAL(XRDP_XRDPVR, [test x$xrdpvr = xtrue]) +AC_ARG_ENABLE(rfxcodec, AS_HELP_STRING([--enable-rfxcodec], + [Build using librfxcodec (default: no)]), + [rfxcodec=true], [rfxcodec=false]) +AM_CONDITIONAL(XRDP_RFXCODEC, [test x$rfxcodec = xtrue]) AM_CONDITIONAL(GOT_PREFIX, test "x${prefix}" != "xNONE"]) @@ -113,18 +105,34 @@ then [#define _FILE_OFFSET_BITS 64]) fi -# checking for libpulse -if ! test -z "$enable_loadpulsemodules" +# checking for TurboJPEG +if ! test -z "$enable_tjpeg" then - AC_CHECK_HEADER([pulse/util.h], [], - [AC_MSG_ERROR([please install libpulse-dev or libpulse-devel])]) -fi +if test ! -z "$TURBOJPEG_PATH" +then + # env var TURBOJPEG_PATH has been defined, use that + AC_CHECK_HEADER([$TURBOJPEG_PATH/include/turbojpeg.h], [], + [AC_MSG_ERROR([could not find TurboJPEG in dir specified by env variable TURBOJPEG_PATH ($TURBOJPEG_PATH)])]) -# checking for libpulse libpulse-simple -if ! test -z "$enable_simplesound" + AC_SUBST(TurboJpegIncDir, ["-I$TURBOJPEG_PATH/include"]) + AC_SUBST(TurboJpegLibDir, ["-L$TURBOJPEG_PATH/lib -Wl,-rpath -Wl,$TURBOJPEG_PATH/lib"]) +elif test -e /opt/libjpeg-turbo/lib64 +then + # TurboJPEG has been installed to /opt on a 64 bit m/c + AC_SUBST(TurboJpegIncDir, ["-I/opt/libjpeg-turbo/include"]) + AC_SUBST(TurboJpegLibDir, ["-L/opt/libjpeg-turbo/lib64 -Wl,-rpath -Wl,/opt/libjpeg-turbo/lib64"]) +elif test -e /opt/libjpeg-turbo/lib32 then - AC_CHECK_HEADER([pulse/simple.h], [], - [AC_MSG_ERROR([please install libpulse-dev or libpulse-devel])]) + # TurboJPEG has been installed to /opt on a 32 bit m/c + AC_SUBST(TurboJpegIncDir, ["-I/opt/libjpeg-turbo/include"]) + AC_SUBST(TurboJpegLibDir, ["-L/opt/libjpeg-turbo/lib32 -Wl,-rpath -Wl,/opt/libjpeg-turbo/lib32"]) +else + # check in default location + AC_CHECK_HEADER([/usr/include/turbojpeg.h], [], + [AC_MSG_ERROR([please install TurboJPEG ])]) + AC_SUBST(TurboJpegIncDir, [""]) + AC_SUBST(TurboJpegLibDir, [""]) +fi fi # checking for Xlib, Xfixes @@ -133,6 +141,9 @@ AC_CHECK_HEADER([X11/Xlib.h], [], AC_CHECK_HEADER([X11/extensions/Xfixes.h], [], [AC_MSG_ERROR([please install libx11-dev and libxfixes-dev or libXfixes-devel])], [#include <X11/Xlib.h>]) +AC_CHECK_HEADER([X11/extensions/Xrandr.h], [], + [AC_MSG_ERROR([please install libxrandr-dev or libXrandr-devel])], + [#include <X11/Xlib.h>]) libdir="${libdir}/xrdp"; if test "x${prefix}" = "xNONE" ; then @@ -158,8 +169,9 @@ AC_CONFIG_FILES([Makefile docs/man/Makefile instfiles/Makefile instfiles/pam.d/Makefile - instfiles/init.d/Makefile - instfiles/default/Makefile + instfiles/init.d/Makefile + instfiles/default/Makefile + instfiles/pulse/Makefile genkeymap/Makefile xrdpapi/Makefile xrdpvr/Makefile diff --git a/docs/man/sesman.ini.5 b/docs/man/sesman.ini.5 index 84beafb4..a1ba3a50 100644 --- a/docs/man/sesman.ini.5 +++ b/docs/man/sesman.ini.5 @@ -116,6 +116,31 @@ Sets the time(in seconds) limit before a disconnected session is killed. If set to \fI0\fR, automatic killing is disabled. .br +.TP +\fBPolicy\fR=\fI[Default|UBD|UBI|UBC|UBDI|UBDC]\fR +Session allocation policy. By Default, a new session is created +for the combination <User,BitPerPixel> when using Xrdp, and +for the combination <User,BitPerPixel,DisplaySize> when using Xvnc. +This behaviour can be changed by setting session policy to: +.br + +.br +\fBUBD\fR - session per <User,BitPerPixel,DisplaySize> +.br +\fBUBI\fR - session per <User,BitPerPixel,IPAddr> +.br +\fBUBC\fR - session per <User,BitPerPixel,Connection> +.br +\fBUBDI\fR - session per <User,BitPerPixel,DisplaySize,IPAddr> +.br +\fBUBDC\fR - session per <User,BitPerPixel,DisplaySize,Connection> +.br + +.br +Note that the criteria <User,BitPerPixel> can not be turned off +and <DisplaySize> will always be checkt when for Xvnc connections. +.br + .SH "SECURITY" The following parameters can be used in the \fB[Sessions]\fR section: diff --git a/docs/man/xrdp.ini.5 b/docs/man/xrdp.ini.5 index 7b32a9f0..131c0796 100644 --- a/docs/man/xrdp.ini.5 +++ b/docs/man/xrdp.ini.5 @@ -54,7 +54,7 @@ If set to \fB0\fR, \fBfalse\fR or \fBno\fR this option disables all channels \fB See section \fBCHANNELS\fP below for more fine grained options. .TP -\fBcrypt_level\fP=\fIlow|medium|high\fP +\fBcrypt_level\fP=\fIlow|medium|high|fips\fP .\" <http://blogs.msdn.com/b/openspecification/archive/2011/12/08/encryption-negotiation-in-rdp-connection.aspx> RDP connection are controlled by two encryption settings: \fIEncryption Level\fP and \fIEncryption Method\fP. The only supported \fIEncryption Method\fP is \fB40BIT_ENCRYPTION\fP, \fB128BIT_ENCRYPTION\fP and \fB56BIT_ENCRYPTION\fP are currently not supported. @@ -70,6 +70,10 @@ All data sent between the client and the server is protected by encryption based .TP .B high All data sent between the client and server is protected by encryption based on the server's maximum key strength. +.TP +.B fips +All data sent between the client and server is protected using Federal Information Processing Standard 140-1 validated encryption methods. +.I This level is required for Windows clients (mstsc.exe) if the client's group policy enforces FIPS-compliance mode. .RE .TP diff --git a/genkeymap/genkeymap.c b/genkeymap/genkeymap.c index 46513513..91ec9e89 100644 --- a/genkeymap/genkeymap.c +++ b/genkeymap/genkeymap.c @@ -45,8 +45,8 @@ int main(int argc, char **argv) char text[256]; char *displayname = NULL; char *outfname; - char *sections[5] = {"noshift", "shift", "altgr", "capslock", "shiftcapslock"}; - int states[5] = {0, 1, 0x80, 2, 3}; + char *sections[6] = {"noshift", "shift", "altgr", "shiftaltgr", "capslock", "shiftcapslock"}; + int states[6] = {0, 1, 0x80, 0x81, 2, 3}; int i; int idx; int char_count; @@ -94,7 +94,7 @@ int main(int argc, char **argv) e.display = dpy; e.same_screen = True; - for (idx = 0; idx < 5; idx++) /* Sections and states */ + for (idx = 0; idx < 6; idx++) /* Sections and states */ { fprintf(outf, "[%s]\n", sections[idx]); e.state = states[idx]; diff --git a/genkeymap/readme.txt b/genkeymap/readme.txt index 0cfeb2e9..d9df684d 100644 --- a/genkeymap/readme.txt +++ b/genkeymap/readme.txt @@ -1,35 +1,42 @@ +Creating a new keymap file. +--------------------------- -crating a new keymap file. - -The names of the files are +The names of the files are of the format; km-xxxx.ini -where the xxx is replaces ny the hex number of the layout of interest. +where the xxxx is replaced by the hex number of the layout of interest. + +The files have 6 sections; -The files have 5 section +[noshift], [shift], [altgr], [shiftaltgr], [capslock], [shiftcapslock] -[noshift], [shift], [altgr], [capslock], [shiftcapslock] +In each section there are multiple lines for each key. -In each section there are multiple lines for each key -An example line looks like +An example line looks like; Key10=49:49 In this line, 10 is the X11 scancode, the first 49 is the keysym value, the second 49 if the unicode value of the key. This is the definition for the 'noshift' '1' key on a en-us keyboard. In this case, the keysym -and the unicode value are the same. Here is an example where they are -not. -This is the definition for the backspace key. +and the unicode value are the same. + +Here is an example where they are not; + +This is the definition for the backspace key; Key22=65288:8 -And this is the star on the keypad +And this is the star on the keypad; Key63=65450:42 -To create a new file run xrdp-genkeymap filename +To create a new file run "xrdp-genkeymap <filename>" + +Example: ./xrdp-genkeymap /etc/xrdp/km-0409.ini -Example ./xrdp-genkeymap /etc/xrdp/km-0409.ini +Note: You need to have enough rights to be able to write to the +/etc/xrdp directory. -Note: You need to have rights to the /etc/xrdp directory. +Alternatively, create the keymap file in a directory of your choice, then +copy or move it over to /etc/xrdp using sudo/su. diff --git a/instfiles/Makefile.am b/instfiles/Makefile.am index b7fa3b9b..b1c0ebd0 100644 --- a/instfiles/Makefile.am +++ b/instfiles/Makefile.am @@ -5,7 +5,8 @@ xrdp.service SUBDIRS = \ pam.d \ init.d \ - default + default \ + pulse if HAVE_SYSTEMD systemdsystemunit_DATA = \ diff --git a/instfiles/pulse/Makefile.am b/instfiles/pulse/Makefile.am new file mode 100644 index 00000000..fcd9ee4b --- /dev/null +++ b/instfiles/pulse/Makefile.am @@ -0,0 +1,3 @@ +EXTRA_DIST = default.pa +pulsedir=$(sysconfdir)/xrdp/pulse +pulse_DATA = default.pa diff --git a/instfiles/pulse/default.pa b/instfiles/pulse/default.pa new file mode 100644 index 00000000..38e9f790 --- /dev/null +++ b/instfiles/pulse/default.pa @@ -0,0 +1,7 @@ +.nofail +.fail +load-module module-augment-properties +load-module module-xrdp-sink +load-module module-xrdp-source +load-module module-always-sink +load-module module-native-protocol-unix diff --git a/keygen/keygen.c b/keygen/keygen.c index d1495011..8b40071f 100644 --- a/keygen/keygen.c +++ b/keygen/keygen.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2012 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,19 +31,25 @@ #include "list.h" #include "file.h" -#define MY_KEY_SIZE 512 +/* this is the signature size in bytes */ +#define TSSK_KEY_LENGTH 64 + +/* default to 512 bit key size, can set changed, set */ +static int g_key_size_bits = 512; static tui8 g_exponent[4] = { 0x01, 0x00, 0x01, 0x00 }; +/* 4 bytes public exponent */ static tui8 g_ppk_e[4] = { 0x5B, 0x7B, 0x88, 0xC0 }; -static tui8 g_ppk_n[72] = +/* 64 byte modulus */ +static tui8 g_ppk_n[72] = /* 64 bytes + 8 bytes pad */ { 0x3D, 0x3A, 0x5E, 0xBD, 0x72, 0x43, 0x3E, 0xC9, 0x4D, 0xBB, 0xC1, 0x1E, 0x4A, 0xBA, 0x5F, 0xCB, @@ -56,7 +62,8 @@ static tui8 g_ppk_n[72] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static tui8 g_ppk_d[108] = +/* 64 bytes private exponent */ +static tui8 g_ppk_d[108] = /* 64 bytes + 44 bytes pad */ { 0x87, 0xA7, 0x19, 0x32, 0xDA, 0x11, 0x87, 0x55, 0x58, 0x00, 0x16, 0x16, 0x25, 0x65, 0x68, 0xF8, @@ -74,40 +81,115 @@ static tui8 g_ppk_d[108] = 0x00, 0x00, 0x00, 0x00 }; -static tui8 g_testkey[176] = +/* 512 bit proprietary certificate + dwVersion 0 4 bytes always 0x00000001 + dwSigAlgId 4 4 bytes always 0x00000001 + dwKeyAlgId 8 4 bytes always 0x00000001 + wPublicKeyBlobType 12 2 bytes always 0x0006 + wPublicKeyBlobLen 14 2 bytes 0x005C 92 bytes + magic 16 4 bytes always 0x31415352 + keylen 20 4 bytes 0x0048 72 bytes + bitlen 24 4 bytes 0x0200 512 bits + datalen 28 4 bytes 0x003F 63 bytes + pubExp 32 4 bytes 0x00010001 + modulus 36 72 bytes + wSignatureBlobType 108 2 bytes always 0x0008 + wSignatureBlobLen 110 2 bytes 0x0048 72 bytes + SignatureBlob 112 72 bytes */ + +static tui8 g_testkey512[184] = /* 512 bit test key */ { - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* 0 */ 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x5c, 0x00, 0x52, 0x53, 0x41, 0x31, 0x48, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x01, 0x00, 0x79, 0x6f, 0xb4, 0xdf, + 0x01, 0x00, 0x01, 0x00, 0x79, 0x6f, 0xb4, 0xdf, /* 32 */ 0xa6, 0x95, 0xb9, 0xa9, 0x61, 0xe3, 0xc4, 0x5e, 0xff, 0x6b, 0xd8, 0x81, 0x8a, 0x12, 0x4a, 0x93, 0x42, 0x97, 0x18, 0x93, 0xac, 0xd1, 0x3a, 0x38, - 0x3c, 0x68, 0x50, 0x19, 0x31, 0xb6, 0x84, 0x51, + 0x3c, 0x68, 0x50, 0x19, 0x31, 0xb6, 0x84, 0x51, /* 64 */ 0x79, 0xfb, 0x1c, 0xe7, 0xe3, 0x99, 0x20, 0xc7, 0x84, 0xdf, 0xd1, 0xaa, 0xb5, 0x15, 0xef, 0x47, 0x7e, 0xfc, 0x88, 0xeb, 0x29, 0xc3, 0x27, 0x5a, - 0x35, 0xf8, 0xfd, 0xaa, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x48, 0x00, + 0x35, 0xf8, 0xfd, 0xaa, 0x00, 0x00, 0x00, 0x00, /* 96 */ + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x48, 0x00, 0x32, 0x3b, 0xde, 0x6f, 0x18, 0x97, 0x1e, 0xc3, 0x6b, 0x2b, 0x2d, 0xe4, 0xfc, 0x2d, 0xa2, 0x8e, - 0x32, 0x3c, 0xf3, 0x1b, 0x24, 0x90, 0x57, 0x4d, + 0x32, 0x3c, 0xf3, 0x1b, 0x24, 0x90, 0x57, 0x4d, /* 128 */ 0x8e, 0xe4, 0x69, 0xfc, 0x16, 0x8d, 0x41, 0x92, 0x78, 0xc7, 0x9c, 0xb4, 0x26, 0xff, 0xe8, 0x3e, 0xa1, 0x8a, 0xf5, 0x57, 0xc0, 0x7f, 0x3e, 0x21, - 0x17, 0x32, 0x30, 0x6f, 0x79, 0xe1, 0x36, 0xcd, - 0xb6, 0x8e, 0xbe, 0x57, 0x57, 0xd2, 0xa9, 0x36 + 0x17, 0x32, 0x30, 0x6f, 0x79, 0xe1, 0x36, 0xcd, /* 160 */ + 0xb6, 0x8e, 0xbe, 0x57, 0x57, 0xd2, 0xa9, 0x36, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -/* this is the installed signature */ -char inst_pub_sig[] = "0x6a,0x41,0xb1,0x43,0xcf,0x47,0x6f,0xf1,0xe6,0xcc,0xa1,\ -0x72,0x97,0xd9,0xe1,0x85,0x15,0xb3,0xc2,0x39,0xa0,0xa6,0x26,0x1a,0xb6,\ -0x49,0x01,0xfa,0xa6,0xda,0x60,0xd7,0x45,0xf7,0x2c,0xee,0xe4,0x8e,0x64,\ -0x2e,0x37,0x49,0xf0,0x4c,0x94,0x6f,0x08,0xf5,0x63,0x4c,0x56,0x29,0x55,\ -0x5a,0x63,0x41,0x2c,0x20,0x65,0x95,0x99,0xb1,0x15,0x7c"; - +/* 2048 bit proprietary certificate + dwVersion 0 4 bytes always 0x00000001 + dwSigAlgId 4 4 bytes always 0x00000001 + dwKeyAlgId 8 4 bytes always 0x00000001 + wPublicKeyBlobType 12 2 bytes always 0x0006 + wPublicKeyBlobLen 14 2 bytes 0x011C 284 bytes + magic 16 4 bytes always 0x31415352 + keylen 20 4 bytes 0x0108 264 bytes + bitlen 24 4 bytes 0x0800 2048 bits + datalen 28 4 bytes 0x00FF 255 bytes + pubExp 32 4 bytes 0x00010001 + modulus 36 264 bytes + wSignatureBlobType 300 2 bytes always 0x0008 + wSignatureBlobLen 302 2 bytes 0x0048 72 bytes + SignatureBlob 304 72 bytes */ + +static tui8 g_testkey2048[376] = /* 2048 bit test key */ +{ + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* 0 */ + 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x1c, 0x01, + 0x52, 0x53, 0x41, 0x31, 0x08, 0x01, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x13, 0x77, 0x6d, 0xd8, /* 32 */ + 0x7b, 0x6e, 0x6f, 0xb4, 0x27, 0x6d, 0x70, 0x3a, + 0x97, 0x5f, 0xcb, 0x50, 0x9b, 0x13, 0x6b, 0xc7, + 0xba, 0xdf, 0x73, 0x54, 0x17, 0x35, 0xf0, 0x09, + 0x9e, 0x9d, 0x0b, 0x6a, 0x2c, 0x9f, 0xd1, 0x0c, /* 64 */ + 0xc6, 0x47, 0x83, 0xde, 0xca, 0x90, 0x20, 0xac, + 0x70, 0x63, 0x9b, 0xb7, 0x49, 0x07, 0x0b, 0xf5, + 0xf2, 0x38, 0x2a, 0x40, 0xff, 0xf1, 0xba, 0x97, + 0x79, 0x3e, 0xd4, 0xd1, 0xf3, 0x41, 0x0f, 0x91, /* 96 */ + 0xfe, 0x1a, 0x86, 0xf4, 0x1b, 0xef, 0xcc, 0x29, + 0xa3, 0x35, 0x6f, 0x60, 0xfa, 0x98, 0x53, 0x51, + 0x80, 0x57, 0x15, 0x2f, 0xe1, 0x8b, 0xd7, 0x86, + 0x15, 0x2d, 0xb5, 0xec, 0x7a, 0xdd, 0xc5, 0x1d, /* 128 */ + 0x1b, 0x88, 0x53, 0x67, 0x86, 0xe1, 0x6e, 0xcd, + 0x4e, 0x2e, 0xfd, 0xd2, 0x49, 0x04, 0xfb, 0x1d, + 0x95, 0xf0, 0xe9, 0x7f, 0x97, 0xa3, 0x1b, 0xb2, + 0x92, 0x2e, 0x62, 0x2a, 0x96, 0xd4, 0xea, 0x18, /* 160 */ + 0x8e, 0x99, 0x41, 0xea, 0x83, 0xb5, 0xf1, 0x0e, + 0xea, 0x53, 0x70, 0x99, 0xd7, 0x9e, 0x0c, 0x65, + 0x2b, 0xf4, 0xdc, 0x0e, 0xe7, 0x9e, 0xce, 0x04, + 0x25, 0x01, 0x88, 0xc4, 0xc1, 0xd2, 0xa4, 0x18, /* 192 */ + 0xc2, 0x8a, 0x52, 0x0f, 0x01, 0xb2, 0x71, 0x30, + 0x44, 0x3f, 0x5b, 0x11, 0x2e, 0xe7, 0x53, 0xa0, + 0xc8, 0x1f, 0x77, 0xaf, 0xb5, 0xbb, 0xaf, 0x12, + 0xe8, 0x19, 0x0c, 0xf6, 0x1f, 0xa8, 0x3e, 0x11, /* 224 */ + 0x34, 0xe4, 0xac, 0x1c, 0x1c, 0x00, 0xbb, 0xb9, + 0x2f, 0xbb, 0x81, 0x76, 0x4e, 0x46, 0xda, 0x73, + 0x00, 0x82, 0x71, 0xa4, 0x62, 0xc3, 0xd4, 0x3f, + 0xda, 0x34, 0x54, 0x27, 0xe3, 0xd0, 0x3a, 0x73, /* 256 */ + 0x2f, 0x99, 0xc4, 0x91, 0x56, 0x12, 0x98, 0xa8, + 0x3b, 0x8d, 0x61, 0x83, 0x62, 0xb7, 0x20, 0x61, + 0x4d, 0xc9, 0x41, 0xd1, 0x40, 0x02, 0x11, 0x4b, + 0x63, 0x46, 0xc7, 0xc1, 0x00, 0x00, 0x00, 0x00, /* 288 */ + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x48, 0x00, + 0x00, 0x50, 0xb7, 0x75, 0xf3, 0x77, 0x99, 0xb2, + 0xd3, 0xdd, 0xcd, 0x83, 0x6e, 0xdb, 0x0a, 0x29, + 0x88, 0x05, 0xb5, 0x8a, 0x49, 0xd5, 0xa8, 0x5a, /* 320 */ + 0xc3, 0xb7, 0x18, 0xc2, 0x3c, 0x1e, 0xde, 0xd3, + 0x8f, 0xdd, 0x21, 0x27, 0x84, 0xa0, 0xc8, 0x8d, + 0x65, 0xce, 0x5d, 0x3d, 0x46, 0x65, 0x88, 0xfc, + 0x35, 0x0a, 0x04, 0xa0, 0xda, 0xc1, 0xab, 0xbf, /* 352 */ + 0xcd, 0xf1, 0x7e, 0x71, 0x7b, 0xf8, 0x4a, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; /*****************************************************************************/ static int APP_CC @@ -115,7 +197,7 @@ out_params(void) { g_writeln(""); g_writeln("xrdp rsa key gen utility examples"); - g_writeln(" xrdp-keygen xrdp ['path and file name' | auto]"); + g_writeln(" xrdp-keygen xrdp ['path and file name' | auto] [512 or 2048]"); g_writeln(" xrdp-keygen test"); g_writeln(""); return 0; @@ -131,37 +213,70 @@ sign_key(char *e_data, int e_len, char *n_data, int n_len, char *md5_final; void *md5; - if ((e_len != 4) || (n_len != 64) || (sign_len != 64)) + if ((e_len != 4) || ((n_len != 64) && (n_len != 256)) || (sign_len != 64)) { return 1; } - key = (char *)g_malloc(176, 0); - md5_final = (char *)g_malloc(64, 0); - md5 = ssl_md5_info_create(); - /* copy the test key */ - g_memcpy(key, g_testkey, 176); - /* replace e and n */ - g_memcpy(key + 32, e_data, 4); - g_memcpy(key + 36, n_data, 64); - ssl_md5_clear(md5); - /* the first 108 bytes */ - ssl_md5_transform(md5, key, 108); - /* set the whole thing with 0xff */ - g_memset(md5_final, 0xff, 64); - /* digest 16 bytes */ - ssl_md5_complete(md5, md5_final); - /* set non 0xff array items */ - md5_final[16] = 0; - md5_final[62] = 1; - md5_final[63] = 0; - /* encrypt */ - ssl_mod_exp(sign_data, 64, md5_final, 64, (char *)g_ppk_n, 64, - (char *)g_ppk_d, 64); - /* cleanup */ - ssl_md5_info_delete(md5); - g_free(key); - g_free(md5_final); + if (n_len == 64) + { + key = (char *)g_malloc(184, 0); + md5_final = (char *)g_malloc(64, 0); + md5 = ssl_md5_info_create(); + /* copy the test key */ + g_memcpy(key, g_testkey512, 184); + /* replace e and n */ + g_memcpy(key + 32, e_data, e_len); + g_memcpy(key + 36, n_data, n_len); + ssl_md5_clear(md5); + /* the first 108 bytes */ + ssl_md5_transform(md5, key, 108); + /* set the whole thing with 0xff */ + g_memset(md5_final, 0xff, 64); + /* digest 16 bytes */ + ssl_md5_complete(md5, md5_final); + /* set non 0xff array items */ + md5_final[16] = 0; + md5_final[62] = 1; + md5_final[63] = 0; + /* encrypt */ + ssl_mod_exp(sign_data, sign_len, md5_final, 64, (char *)g_ppk_n, 64, + (char *)g_ppk_d, 64); + /* cleanup */ + ssl_md5_info_delete(md5); + g_free(key); + g_free(md5_final); + } + else if (n_len == 256) + { + key = (char *)g_malloc(376, 0); + md5_final = (char *)g_malloc(64, 0); + md5 = ssl_md5_info_create(); + /* copy the test key */ + g_memcpy(key, g_testkey2048, 376); + /* replace e and n */ + g_memcpy(key + 32, e_data, e_len); + g_memcpy(key + 36, n_data, n_len); + ssl_md5_clear(md5); + /* the first 300 bytes */ + ssl_md5_transform(md5, key, 300); + /* set the whole thing with 0xff */ + g_memset(md5_final, 0xff, 64); + /* digest 16 bytes */ + ssl_md5_complete(md5, md5_final); + /* set non 0xff array items */ + md5_final[16] = 0; + md5_final[62] = 1; + md5_final[63] = 0; + /* encrypt */ + ssl_mod_exp(sign_data, sign_len, md5_final, 64, (char *)g_ppk_n, 64, + (char *)g_ppk_d, 64); + /* cleanup */ + ssl_md5_info_delete(md5); + g_free(key); + g_free(md5_final); + } + return 0; } @@ -249,11 +364,12 @@ save_all(char *e_data, int e_len, char *n_data, int n_len, fd = g_file_open(filename); - if (fd > 0) + if (fd != -1) { if (g_file_write(fd, "[keys]\n", 7) == -1) { g_writeln("problem writing to %s, maybe no rights", filename); + g_file_close(fd); return 1; } @@ -287,21 +403,21 @@ key_gen(const char *path_and_file_name) int error; e_data = (char *)g_exponent; - n_data = (char *)g_malloc(64, 0); - d_data = (char *)g_malloc(64, 0); + n_data = (char *)g_malloc(256, 0); + d_data = (char *)g_malloc(256, 0); sign_data = (char *)g_malloc(64, 0); e_len = 4; - n_len = 64; - d_len = 64; + n_len = g_key_size_bits / 8; + d_len = n_len; sign_len = 64; error = 0; g_writeln(""); - g_writeln("Generating %d bit rsa key...", MY_KEY_SIZE); + g_writeln("Generating %d bit rsa key...", g_key_size_bits); g_writeln(""); if (error == 0) { - error = ssl_gen_key_xrdp1(MY_KEY_SIZE, e_data, e_len, n_data, n_len, + error = ssl_gen_key_xrdp1(g_key_size_bits, e_data, e_len, n_data, n_len, d_data, d_len); if (error != 0) @@ -340,84 +456,58 @@ key_gen(const char *path_and_file_name) } /*****************************************************************************/ -/* returns boolean */ static int APP_CC -key_gen_run_it(void) +key_gen_auto(void) { - int fd; - int index; - int rv; - struct list *names; - struct list *values; - char *name; - char *value; - - if (!g_file_exist("/etc/xrdp/rsakeys.ini")) - { - return 1; - } - - if (g_file_get_size("/etc/xrdp/rsakeys.ini") < 10) - { - return 1; - } - - fd = g_file_open("/etc/xrdp/rsakeys.ini"); - - if (fd < 0) - { - return 1; - } - - rv = 0; - names = list_create(); - names->auto_free = 1; - values = list_create(); - values->auto_free = 1; - - if (file_read_section(fd, "keys", names, values) == 0) - { - for (index = 0; index < names->count; index++) - { - name = (char *)list_get_item(names, index); - value = (char *)list_get_item(values, index); - - if (g_strcasecmp(name, "pub_sig") == 0) - { - if (g_strcasecmp(value, inst_pub_sig) == 0) - { - rv = 1; - } - } - } - } - else - { - g_writeln("error reading keys section of rsakeys.ini"); - } - - list_delete(names); - list_delete(values); - g_file_close(fd); - return rv; + return key_gen("/etc/xrdp/rsakeys.ini"); } /*****************************************************************************/ static int APP_CC -key_gen_auto(void) +key_test512(void) { - if (key_gen_run_it()) - { - return key_gen("/etc/xrdp/rsakeys.ini"); - } + char *md5_final; + char *sig; + void *md5; - g_writeln("xrdp-keygen does not need to run"); + md5_final = (char *)g_malloc(64, 0); + sig = (char *)g_malloc(64, 0); + md5 = ssl_md5_info_create(); + g_writeln("original key is:"); + g_hexdump((char *)g_testkey512, 184); + g_writeln("original exponent is:"); + g_hexdump((char *)g_testkey512 + 32, 4); + g_writeln("original modulus is:"); + g_hexdump((char *)g_testkey512 + 36, 64); + g_writeln("original signature is:"); + g_hexdump((char *)g_testkey512 + 112, 64); + ssl_md5_clear(md5); + ssl_md5_transform(md5, (char *)g_testkey512, 108); + g_memset(md5_final, 0xff, 64); + ssl_md5_complete(md5, md5_final); + g_writeln("md5 hash of first 108 bytes of this key is:"); + g_hexdump(md5_final, 16); + md5_final[16] = 0; + md5_final[62] = 1; + md5_final[63] = 0; + ssl_mod_exp(sig, 64, md5_final, 64, (char *)g_ppk_n, 64, (char *)g_ppk_d, 64); + g_writeln("produced signature(this should match original " + "signature above) is:"); + g_hexdump(sig, 64); + g_memset(md5_final, 0, 64); + ssl_mod_exp(md5_final, 64, (char *)g_testkey512 + 112, 64, (char *)g_ppk_n, 64, + (char *)g_ppk_e, 4); + g_writeln("decrypted hash of first 108 bytes of this key is:"); + g_hexdump(md5_final, 64); + ssl_md5_info_delete(md5); + g_free(md5_final); + g_free(sig); return 0; } /*****************************************************************************/ static int APP_CC -key_test(void) +key_test2048(void) { char *md5_final; char *sig; @@ -427,28 +517,28 @@ key_test(void) sig = (char *)g_malloc(64, 0); md5 = ssl_md5_info_create(); g_writeln("original key is:"); - g_hexdump((char *)g_testkey, 176); + g_hexdump((char *)g_testkey2048, 376); g_writeln("original exponent is:"); - g_hexdump((char *)g_testkey + 32, 4); + g_hexdump((char *)g_testkey2048 + 32, 4); g_writeln("original modulus is:"); - g_hexdump((char *)g_testkey + 36, 64); + g_hexdump((char *)g_testkey2048 + 36, 256); g_writeln("original signature is:"); - g_hexdump((char *)g_testkey + 112, 64); + g_hexdump((char *)g_testkey2048 + 304, 64); ssl_md5_clear(md5); - ssl_md5_transform(md5, (char *)g_testkey, 108); + ssl_md5_transform(md5, (char *)g_testkey2048, 300); g_memset(md5_final, 0xff, 64); ssl_md5_complete(md5, md5_final); - g_writeln("md5 hash of first 108 bytes of this key is:"); + g_writeln("md5 hash of first 300 bytes of this key is:"); g_hexdump(md5_final, 16); md5_final[16] = 0; md5_final[62] = 1; md5_final[63] = 0; ssl_mod_exp(sig, 64, md5_final, 64, (char *)g_ppk_n, 64, (char *)g_ppk_d, 64); - g_writeln("produced signature(this should match original \ -signature above) is:"); + g_writeln("produced signature(this should match original " + "signature above) is:"); g_hexdump(sig, 64); g_memset(md5_final, 0, 64); - ssl_mod_exp(md5_final, 64, (char *)g_testkey + 112, 64, (char *)g_ppk_n, 64, + ssl_mod_exp(md5_final, 64, (char *)g_testkey2048 + 304, 64, (char *)g_ppk_n, 64, (char *)g_ppk_e, 4); g_writeln("decrypted hash of first 108 bytes of this key is:"); g_hexdump(md5_final, 64); @@ -468,6 +558,15 @@ main(int argc, char **argv) { if (argc > 2) { + if (argc > 3) + { + g_key_size_bits = g_atoi(argv[3]); + if ((g_key_size_bits != 512) && (g_key_size_bits != 2048)) + { + out_params(); + return 0; + } + } if (g_strcasecmp(argv[2], "auto") == 0) { if (g_getuid() != 0) @@ -490,7 +589,13 @@ main(int argc, char **argv) } else if (g_strcasecmp(argv[1], "test") == 0) { - return key_test(); + g_writeln(""); + g_writeln("testing 512 bit key"); + key_test512(); + g_writeln(""); + g_writeln("testing 2048 bit key"); + key_test2048(); + return 0; } } diff --git a/librfxcodec b/librfxcodec new file mode 160000 +Subproject de6a45cba607b902da704304fa3de8ddd3d1523 diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am index e83fce10..bd37cad4 100644 --- a/libxrdp/Makefile.am +++ b/libxrdp/Makefile.am @@ -18,8 +18,8 @@ endif if XRDP_TJPEG EXTRA_DEFINES += -DXRDP_JPEG -DXRDP_TJPEG -EXTRA_INCLUDES += -I/opt/libjpeg-turbo/include -EXTRA_FLAGS += -L/opt/libjpeg-turbo/lib -Wl,-rpath -Wl,/opt/libjpeg-turbo/lib +EXTRA_INCLUDES += @TurboJpegIncDir@ +EXTRA_FLAGS += @TurboJpegLibDir@ EXTRA_LIBS += -lturbojpeg else if XRDP_JPEG @@ -59,7 +59,9 @@ libxrdp_la_SOURCES = \ xrdp_bitmap32_compress.c \ xrdp_jpeg_compress.c \ xrdp_orders_rail.c \ - xrdp_mppc_enc.c + xrdp_mppc_enc.c \ + xrdp_fastpath.c \ + xrdp_caps.c libxrdp_la_LDFLAGS = \ $(EXTRA_FLAGS) diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c index 7ab1f914..df755f2b 100644 --- a/libxrdp/libxrdp.c +++ b/libxrdp/libxrdp.c @@ -21,6 +21,12 @@ #include "libxrdp.h" #include "xrdp_orders_rail.h" +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) + /******************************************************************************/ struct xrdp_session *EXPORT_CC libxrdp_init(tbus id, struct trans *trans) @@ -29,6 +35,7 @@ libxrdp_init(tbus id, struct trans *trans) session = (struct xrdp_session *)g_malloc(sizeof(struct xrdp_session), 1); session->id = id; + session->trans = trans; session->rdp = xrdp_rdp_create(session, trans); session->orders = xrdp_orders_create(session, (struct xrdp_rdp *)session->rdp); session->client_info = &(((struct xrdp_rdp *)session->rdp)->client_info); @@ -61,7 +68,103 @@ libxrdp_disconnect(struct xrdp_session *session) int EXPORT_CC libxrdp_process_incomming(struct xrdp_session *session) { - return xrdp_rdp_incoming((struct xrdp_rdp *)session->rdp); + int rv; + + rv = xrdp_rdp_incoming((struct xrdp_rdp *)(session->rdp)); + return rv; +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_get_pdu_bytes(const char *aheader) +{ + int rv; + const tui8 *header; + + rv = -1; + header = (const tui8 *) aheader; + + if (header[0] == 0x03) + { + /* TPKT */ + rv = (header[2] << 8) | header[3]; + } + else if (header[0] == 0x30) + { + /* TSRequest (NLA) */ + if (header[1] & 0x80) + { + if ((header[1] & ~(0x80)) == 1) + { + rv = header[2]; + rv += 3; + } + else if ((header[1] & ~(0x80)) == 2) + { + rv = (header[2] << 8) | header[3]; + rv += 4; + } + else + { + g_writeln("libxrdp_get_pdu_bytes: error TSRequest!"); + return -1; + } + } + else + { + rv = header[1]; + rv += 2; + } + } + else + { + /* Fast-Path */ + if (header[1] & 0x80) + { + rv = ((header[1] & 0x7F) << 8) | header[2]; + } + else + { + rv = header[1]; + } + } + return rv; +} + +/******************************************************************************/ +/* only used durring connection */ +struct stream * APP_CC +libxrdp_force_read(struct trans* trans) +{ + int bytes; + struct stream *s; + + s = trans->in_s; + init_stream(s, 32 * 1024); + + if (trans_force_read(trans, 4) != 0) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + bytes = libxrdp_get_pdu_bytes(s->data); + if (bytes < 1) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + if (bytes > 32 * 1024) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + + if (trans_force_read(trans, bytes - 4) != 0) + { + g_writeln("libxrdp_force_read: error"); + return 0; + } + return s; } /******************************************************************************/ @@ -73,9 +176,15 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) int code; int term; int dead_lock_counter; + int do_read; struct xrdp_rdp *rdp; - struct stream *ls; + do_read = s == 0; + if (do_read && session->up_and_running) + { + g_writeln("libxrdp_process_data: error logic"); + return 1; + } if (session->in_process_data != 0) { g_writeln("libxrdp_process_data: error reentry"); @@ -83,14 +192,6 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) } session->in_process_data++; - ls = 0; - if (s == 0) - { - make_stream(ls); - init_stream(ls, 8192 * 4); - s = ls; - } - term = 0; cont = 1; rv = 0; @@ -105,13 +206,36 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) if (session->is_term()) { term = 1; + break; } } code = 0; + if (do_read) + { + if (s == 0) + { + s = libxrdp_force_read(session->trans); + } + else + { + if ((s->next_packet == 0) || (s->next_packet >= s->end)) + { + s = libxrdp_force_read(session->trans); + } + } + if (s == 0) + { + g_writeln("libxrdp_process_data: libxrdp_force_read failed"); + rv = 1; + break; + } + } + if (xrdp_rdp_recv(rdp, s, &code) != 0) { + g_writeln("libxrdp_process_data: xrdp_rdp_recv failed"); rv = 1; break; } @@ -121,39 +245,33 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) switch (code) { case -1: - xrdp_rdp_send_demand_active(rdp); - - /* send Monitor Layout PDU for multimon */ - if (session->client_info->monitorCount > 0 && - session->client_info->multimon == 1) - { - DEBUG(("sending monitor layout pdu")); - if (xrdp_rdp_send_monitorlayout(rdp) != 0) - { - g_writeln("xrdp_rdp_send_monitorlayout: error"); - } - } - + xrdp_caps_send_demand_active(rdp); session->up_and_running = 0; break; case 0: dead_lock_counter++; break; case RDP_PDU_CONFIRM_ACTIVE: /* 3 */ - xrdp_rdp_process_confirm_active(rdp, s); + xrdp_caps_process_confirm_active(rdp, s); break; case RDP_PDU_DATA: /* 7 */ - if (xrdp_rdp_process_data(rdp, s) != 0) { DEBUG(("libxrdp_process_data returned non zero")); cont = 0; term = 1; } - + break; + case 2: /* FASTPATH_INPUT_EVENT */ + if (xrdp_fastpath_process_input_event(rdp->sec_layer->fastpath_layer, s) != 0) + { + DEBUG(("libxrdp_process_data returned non zero")); + cont = 0; + term = 1; + } break; default: - g_writeln("unknown in libxrdp_process_data"); + g_writeln("unknown in libxrdp_process_data: code= %d", code); dead_lock_counter++; break; } @@ -169,16 +287,10 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s) if (cont) { - cont = (s->next_packet != 0) && - (s->next_packet < s->end); + cont = (s->next_packet != 0) && (s->next_packet < s->end); } } - if (s == ls) - { - free_stream(s); - } - session->in_process_data--; return rv; @@ -198,11 +310,27 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette) } DEBUG(("libxrdp_send_palette sending palette")); + /* clear orders */ libxrdp_orders_force_send(session); make_stream(s); init_stream(s, 8192); - xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + LLOGLN(10, ("libxrdp_send_palette: fastpath")); + if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) + { + free_stream(s); + return 1; + } + } + else { + LLOGLN(10, ("libxrdp_send_palette: slowpath")); + xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + } + + /* TS_UPDATE_PALETTE_DATA */ out_uint16_le(s, RDP_UPDATE_PALETTE); out_uint16_le(s, 0); out_uint16_le(s, 256); /* # of colors */ @@ -217,8 +345,22 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette) } s_mark_end(s); - xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_UPDATE); + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_PALETTE) != 0) + { + free_stream(s); + return 1; + } + } + else + { + xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, + RDP_DATA_PDU_UPDATE); + } free_stream(s); + /* send the orders palette too */ libxrdp_orders_init(session); libxrdp_orders_send_palette(session, palette, 0); @@ -482,20 +624,46 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, } make_stream(s); init_stream(s, 8192); - xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); - if ((session->client_info->pointer_flags & 1) == 0) + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ { - out_uint16_le(s, RDP_POINTER_COLOR); - out_uint16_le(s, 0); /* pad */ - data_bytes = 3072; + LLOGLN(10, ("libxrdp_send_pointer: fastpath")); + if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) + { + free_stream(s); + return 1; + } + + if ((session->client_info->pointer_flags & 1) == 0) + { + data_bytes = 3072; + } + else + { + data_bytes = ((bpp + 7) / 8) * 32 * 32; + out_uint16_le(s, bpp); + } } - else + else /* slowpath */ { - out_uint16_le(s, RDP_POINTER_POINTER); - out_uint16_le(s, 0); /* pad */ - out_uint16_le(s, bpp); - data_bytes = ((bpp + 7) / 8) * 32 * 32; + LLOGLN(10, ("libxrdp_send_pointer: slowpath")); + xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + if ((session->client_info->pointer_flags & 1) == 0) + { + out_uint16_le(s, RDP_POINTER_COLOR); + out_uint16_le(s, 0); /* pad */ + data_bytes = 3072; + } + else + { + out_uint16_le(s, RDP_POINTER_POINTER); + out_uint16_le(s, 0); /* pad */ + out_uint16_le(s, bpp); + data_bytes = ((bpp + 7) / 8) * 32 * 32; + } } + + out_uint16_le(s, cache_idx); /* cache_idx */ out_uint16_le(s, x); out_uint16_le(s, y); @@ -506,7 +674,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, switch (bpp) { - case 15: + //case 15: /* coverity: this is logically dead code */ case 16: p16 = (tui16 *) data; for (i = 0; i < 32; i++) @@ -547,9 +715,34 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, } out_uint8a(s, mask, 128); /* mask */ + out_uint8(s, 0); /* pad */ s_mark_end(s); - xrdp_rdp_send_data((struct xrdp_rdp *)(session->rdp), s, - RDP_DATA_PDU_POINTER); + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + if ((session->client_info->pointer_flags & 1) == 0) + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_COLOR) != 0) + { + free_stream(s); + return 1; + } + } + else + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_POINTER) != 0) + { + free_stream(s); + return 1; + } + } + } + else + { + xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, + RDP_DATA_PDU_POINTER); + } free_stream(s); return 0; } @@ -563,12 +756,41 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx) DEBUG(("libxrdp_set_pointer sending cursor index")); make_stream(s); init_stream(s, 8192); - xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); - out_uint16_le(s, RDP_POINTER_CACHED); - out_uint16_le(s, 0); /* pad */ + + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + LLOGLN(10, ("libxrdp_send_pointer: fastpath")); + if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0) + { + return 1; + } + } + else + { + LLOGLN(10, ("libxrdp_send_pointer: slowpath")); + xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s); + out_uint16_le(s, RDP_POINTER_CACHED); + out_uint16_le(s, 0); /* pad */ + } + out_uint16_le(s, cache_idx); /* cache_idx */ s_mark_end(s); - xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_POINTER); + + if (session->client_info->use_fast_path & 1) /* fastpath output supported */ + { + if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s, + FASTPATH_UPDATETYPE_CACHED) != 0) + { + free_stream(s); + return 1; + } + } + else + { + xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, + RDP_DATA_PDU_POINTER); + } free_stream(s); return 0; } @@ -782,7 +1004,7 @@ libxrdp_reset(struct xrdp_session *session, } /* this should do the resizing */ - if (xrdp_rdp_send_demand_active((struct xrdp_rdp *)session->rdp) != 0) + if (xrdp_caps_send_demand_active((struct xrdp_rdp *)session->rdp) != 0) { return 1; } @@ -1079,3 +1301,91 @@ libxrdp_monitored_desktop(struct xrdp_session *session, orders = (struct xrdp_orders *)(session->orders); return xrdp_orders_send_monitored_desktop(orders, mdo, flags); } + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_codec_jpeg_compress(struct xrdp_session *session, + int format, char *inp_data, + int width, int height, + int stride, int x, int y, + int cx, int cy, int quality, + char *out_data, int *io_len) +{ + struct xrdp_orders *orders; + void* jpeg_han; + + orders = (struct xrdp_orders *)(session->orders); + jpeg_han = orders->jpeg_han; + return xrdp_codec_jpeg_compress(jpeg_han, format, inp_data, + width, height, stride, x, y, + cx, cy, quality, out_data, io_len); +} + +/*****************************************************************************/ +int EXPORT_CC +libxrdp_fastpath_send_surface(struct xrdp_session *session, + char* data_pad, int pad_bytes, + int data_bytes, + int destLeft, int destTop, + int destRight, int destBottom, int bpp, + int codecID, int width, int height) +{ + struct stream ls; + struct stream *s; + struct xrdp_rdp *rdp; + int rv; + int sec_bytes; + int rdp_bytes; + int max_bytes; + int cmd_bytes; + + LLOGLN(10, ("libxrdp_fastpath_init:")); + if ((session->client_info->use_fast_path & 1) == 0) + { + return 1; + } + max_bytes = session->client_info->max_fastpath_frag_bytes; + if (max_bytes < 32 * 1024) + { + max_bytes = 32 * 1024; + } + rdp = (struct xrdp_rdp *) (session->rdp); + rdp_bytes = xrdp_rdp_get_fastpath_bytes(rdp); + sec_bytes = xrdp_sec_get_fastpath_bytes(rdp->sec_layer); + cmd_bytes = 10 + 12; + if (data_bytes + rdp_bytes + sec_bytes + cmd_bytes > max_bytes) + { + return 1; + } + if (sec_bytes + rdp_bytes + cmd_bytes > pad_bytes) + { + return 1; + } + g_memset(&ls, 0, sizeof(ls)); + s = &ls; + s->data = (data_pad + pad_bytes) - (rdp_bytes + sec_bytes + cmd_bytes); + s->sec_hdr = s->data; + s->rdp_hdr = s->sec_hdr + sec_bytes; + s->end = data_pad + pad_bytes + data_bytes; + s->p = s->data + (rdp_bytes + sec_bytes); + /* TS_SURFCMD_SET_SURF_BITS */ + out_uint16_le(s, 0x0001); /* CMDTYPE_SET_SURFACE_BITS */ + out_uint16_le(s, destLeft); + out_uint16_le(s, destTop); + out_uint16_le(s, destRight); + out_uint16_le(s, destBottom); + /* TS_ BITMAP_DATA_EX */ + out_uint8(s, bpp); + out_uint8(s, 0); + out_uint8(s, 0); + out_uint8(s, codecID); + out_uint16_le(s, width); + out_uint16_le(s, height); + out_uint32_le(s, data_bytes); + /* 4 = FASTPATH_UPDATETYPE_SURFCMDS */ + if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0) + { + return 1; + } + return 0; +} diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h index d9e5e6d1..0bda9f45 100644 --- a/libxrdp/libxrdp.h +++ b/libxrdp/libxrdp.h @@ -37,33 +37,46 @@ #include "file_loc.h" #include "xrdp_client_info.h" + /* iso */ struct xrdp_iso { - struct xrdp_mcs* mcs_layer; /* owner */ - int requestedProtocol; - int selectedProtocol; - struct trans* trans; + struct xrdp_mcs *mcs_layer; /* owner */ + int rdpNegData; /* bool */ + int requestedProtocol; + int selectedProtocol; + int failureCode; + struct trans *trans; }; /* used in mcs */ struct mcs_channel_item { - char name[16]; - int flags; - int chanid; + char name[16]; + int flags; + int chanid; }; /* mcs */ struct xrdp_mcs { - struct xrdp_sec* sec_layer; /* owner */ - struct xrdp_iso* iso_layer; - int userid; - int chanid; - struct stream* client_mcs_data; - struct stream* server_mcs_data; - struct list* channel_list; + struct xrdp_sec *sec_layer; /* owner */ + struct xrdp_iso *iso_layer; + int userid; + int chanid; + struct stream *client_mcs_data; + struct stream *server_mcs_data; + struct list *channel_list; +}; + +/* fastpath */ +struct xrdp_fastpath +{ + struct xrdp_sec *sec_layer; /* owner */ + struct trans *trans; + struct xrdp_session *session; + int numEvents; + int secFlags; }; /* Encryption Methods */ @@ -80,177 +93,181 @@ struct xrdp_mcs #define CRYPT_LEVEL_HIGH 0x00000003 #define CRYPT_LEVEL_FIPS 0x00000004 + /* sec */ struct xrdp_sec { - struct xrdp_rdp* rdp_layer; /* owner */ - struct xrdp_mcs* mcs_layer; - struct xrdp_channel* chan_layer; - char server_random[32]; - char client_random[64]; - char client_crypt_random[72]; - struct stream client_mcs_data; - struct stream server_mcs_data; - int decrypt_use_count; - int encrypt_use_count; - char decrypt_key[16]; - char encrypt_key[16]; - char decrypt_update_key[16]; - char encrypt_update_key[16]; - int crypt_method; - int rc4_key_len; /* 8 = 40 bit, 16 = 128 bit */ - int crypt_level; - char sign_key[16]; - void* decrypt_rc4_info; - void* encrypt_rc4_info; - char pub_exp[4]; - char pub_mod[64]; - char pub_sig[64]; - char pri_exp[64]; - int channel_code; - int multimon; - char fips_encrypt_key[24]; - char fips_decrypt_key[24]; - char fips_sign_key[20]; - void* encrypt_fips_info; - void* decrypt_fips_info; - void* sign_fips_info; + struct xrdp_rdp *rdp_layer; /* owner */ + struct xrdp_mcs *mcs_layer; + struct xrdp_fastpath *fastpath_layer; + struct xrdp_channel *chan_layer; + char server_random[32]; + char client_random[256]; + char client_crypt_random[256 + 8]; /* 64 + 8, 256 + 8 */ + struct stream client_mcs_data; + struct stream server_mcs_data; + int decrypt_use_count; + int encrypt_use_count; + char decrypt_key[16]; + char encrypt_key[16]; + char decrypt_update_key[16]; + char encrypt_update_key[16]; + int crypt_method; + int rc4_key_len; /* 8 = 40 bit, 16 = 128 bit */ + int crypt_level; + char sign_key[16]; + void *decrypt_rc4_info; + void *encrypt_rc4_info; + char pub_exp[4]; + char pub_mod[256]; + char pub_sig[64]; + char pri_exp[256]; + int rsa_key_bytes; /* 64 or 256 , 0 = no rdp security */ + char fips_encrypt_key[24]; + char fips_decrypt_key[24]; + char fips_sign_key[20]; + void *encrypt_fips_info; + void *decrypt_fips_info; + void *sign_fips_info; }; /* channel */ struct xrdp_channel { - struct xrdp_sec* sec_layer; - struct xrdp_mcs* mcs_layer; + struct xrdp_sec *sec_layer; + struct xrdp_mcs *mcs_layer; }; /* rdp */ struct xrdp_rdp { - struct xrdp_session* session; - struct xrdp_sec* sec_layer; - int share_id; - int mcs_channel; - struct xrdp_client_info client_info; - struct xrdp_mppc_enc* mppc_enc; - void* rfx_enc; + struct xrdp_session *session; + struct xrdp_sec *sec_layer; + int share_id; + int mcs_channel; + struct xrdp_client_info client_info; + struct xrdp_mppc_enc *mppc_enc; + void *rfx_enc; }; /* state */ struct xrdp_orders_state { - int last_order; /* last order sent */ - - int clip_left; /* RDP_ORDER_BOUNDS, RDP_ORDER_LASTBOUNDS */ - int clip_top; - int clip_right; - int clip_bottom; - - int rect_x; /* RDP_ORDER_RECT */ - int rect_y; - int rect_cx; - int rect_cy; - int rect_color; - - int scr_blt_x; /* RDP_ORDER_SCREENBLT */ - int scr_blt_y; - int scr_blt_cx; - int scr_blt_cy; - int scr_blt_rop; - int scr_blt_srcx; - int scr_blt_srcy; - - int pat_blt_x; /* RDP_ORDER_PATBLT */ - int pat_blt_y; - int pat_blt_cx; - int pat_blt_cy; - int pat_blt_rop; - int pat_blt_bg_color; - int pat_blt_fg_color; - struct xrdp_brush pat_blt_brush; - - int dest_blt_x; /* RDP_ORDER_DESTBLT */ - int dest_blt_y; - int dest_blt_cx; - int dest_blt_cy; - int dest_blt_rop; - - int line_mix_mode; /* RDP_ORDER_LINE */ - int line_startx; - int line_starty; - int line_endx; - int line_endy; - int line_bg_color; - int line_rop; - struct xrdp_pen line_pen; - - int mem_blt_color_table; /* RDP_ORDER_MEMBLT */ - int mem_blt_cache_id; - int mem_blt_x; - int mem_blt_y; - int mem_blt_cx; - int mem_blt_cy; - int mem_blt_rop; - int mem_blt_srcx; - int mem_blt_srcy; - int mem_blt_cache_idx; - - int text_font; /* RDP_ORDER_TEXT2 */ - int text_flags; - int text_unknown; - int text_mixmode; - int text_fg_color; - int text_bg_color; - int text_clip_left; - int text_clip_top; - int text_clip_right; - int text_clip_bottom; - int text_box_left; - int text_box_top; - int text_box_right; - int text_box_bottom; - int text_x; - int text_y; - int text_len; - char* text_data; - - int com_blt_srcidx; /* RDP_ORDER_COMPOSITE */ /* 2 */ - int com_blt_srcformat; /* 2 */ - int com_blt_srcwidth; /* 2 */ - int com_blt_srcrepeat; /* 1 */ - int com_blt_srctransform[10]; /* 40 */ - int com_blt_mskflags; /* 1 */ - int com_blt_mskidx; /* 2 */ - int com_blt_mskformat; /* 2 */ - int com_blt_mskwidth; /* 2 */ - int com_blt_mskrepeat; /* 1 */ - int com_blt_op; /* 1 */ - int com_blt_srcx; /* 2 */ - int com_blt_srcy; /* 2 */ - int com_blt_mskx; /* 2 */ - int com_blt_msky; /* 2 */ - int com_blt_dstx; /* 2 */ - int com_blt_dsty; /* 2 */ - int com_blt_width; /* 2 */ - int com_blt_height; /* 2 */ - int com_blt_dstformat; /* 2 */ + int last_order; /* last order sent */ + + int clip_left; /* RDP_ORDER_BOUNDS, RDP_ORDER_LASTBOUNDS */ + int clip_top; + int clip_right; + int clip_bottom; + + int rect_x; /* RDP_ORDER_RECT */ + int rect_y; + int rect_cx; + int rect_cy; + int rect_color; + + int scr_blt_x; /* RDP_ORDER_SCREENBLT */ + int scr_blt_y; + int scr_blt_cx; + int scr_blt_cy; + int scr_blt_rop; + int scr_blt_srcx; + int scr_blt_srcy; + + int pat_blt_x; /* RDP_ORDER_PATBLT */ + int pat_blt_y; + int pat_blt_cx; + int pat_blt_cy; + int pat_blt_rop; + int pat_blt_bg_color; + int pat_blt_fg_color; + struct xrdp_brush pat_blt_brush; + + int dest_blt_x; /* RDP_ORDER_DESTBLT */ + int dest_blt_y; + int dest_blt_cx; + int dest_blt_cy; + int dest_blt_rop; + + int line_mix_mode; /* RDP_ORDER_LINE */ + int line_startx; + int line_starty; + int line_endx; + int line_endy; + int line_bg_color; + int line_rop; + struct xrdp_pen line_pen; + + int mem_blt_color_table; /* RDP_ORDER_MEMBLT */ + int mem_blt_cache_id; + int mem_blt_x; + int mem_blt_y; + int mem_blt_cx; + int mem_blt_cy; + int mem_blt_rop; + int mem_blt_srcx; + int mem_blt_srcy; + int mem_blt_cache_idx; + + int text_font; /* RDP_ORDER_TEXT2 */ + int text_flags; + int text_unknown; + int text_mixmode; + int text_fg_color; + int text_bg_color; + int text_clip_left; + int text_clip_top; + int text_clip_right; + int text_clip_bottom; + int text_box_left; + int text_box_top; + int text_box_right; + int text_box_bottom; + int text_x; + int text_y; + int text_len; + char *text_data; + + int com_blt_srcidx; /* RDP_ORDER_COMPOSITE */ /* 2 */ + int com_blt_srcformat; /* 2 */ + int com_blt_srcwidth; /* 2 */ + int com_blt_srcrepeat; /* 1 */ + int com_blt_srctransform[10]; /* 40 */ + int com_blt_mskflags; /* 1 */ + int com_blt_mskidx; /* 2 */ + int com_blt_mskformat; /* 2 */ + int com_blt_mskwidth; /* 2 */ + int com_blt_mskrepeat; /* 1 */ + int com_blt_op; /* 1 */ + int com_blt_srcx; /* 2 */ + int com_blt_srcy; /* 2 */ + int com_blt_mskx; /* 2 */ + int com_blt_msky; /* 2 */ + int com_blt_dstx; /* 2 */ + int com_blt_dsty; /* 2 */ + int com_blt_width; /* 2 */ + int com_blt_height; /* 2 */ + int com_blt_dstformat; /* 2 */ }; /* orders */ struct xrdp_orders { - struct stream* out_s; - struct xrdp_rdp* rdp_layer; - struct xrdp_session* session; - struct xrdp_wm* wm; - - char* order_count_ptr; /* pointer to count, set when sending */ - int order_count; - int order_level; /* inc for every call to xrdp_orders_init */ - struct xrdp_orders_state orders_state; - void* jpeg_han; - int rfx_min_pixel; + struct stream *out_s; + struct xrdp_rdp *rdp_layer; + struct xrdp_session *session; + struct xrdp_wm *wm; + + char *order_count_ptr; /* pointer to count, set when sending */ + int order_count; + int order_level; /* inc for every call to xrdp_orders_init */ + struct xrdp_orders_state orders_state; + void *jpeg_han; + int rfx_min_pixel; + /* shared */ + struct stream *s; + struct stream *temp_s; }; #define PROTO_RDP_40 1 @@ -258,19 +275,20 @@ struct xrdp_orders struct xrdp_mppc_enc { - int protocol_type; /* PROTO_RDP_40, PROTO_RDP_50 etc */ - char *historyBuffer; /* contains uncompressed data */ - char *outputBuffer; /* contains compressed data */ - char *outputBufferPlus; - int historyOffset; /* next free slot in historyBuffer */ - int buf_len; /* length of historyBuffer, protocol dependant */ - int bytes_in_opb; /* compressed bytes available in outputBuffer */ - int flags; /* PACKET_COMPRESSED, PACKET_AT_FRONT, PACKET_FLUSHED etc */ - int flagsHold; - int first_pkt; /* this is the first pkt passing through enc */ - tui16 *hash_table; + int protocol_type; /* PROTO_RDP_40, PROTO_RDP_50 etc */ + char *historyBuffer; /* contains uncompressed data */ + char *outputBuffer; /* contains compressed data */ + char *outputBufferPlus; + int historyOffset; /* next free slot in historyBuffer */ + int buf_len; /* length of historyBuffer, protocol dependant */ + int bytes_in_opb; /* compressed bytes available in outputBuffer */ + int flags; /* PACKET_COMPRESSED, PACKET_AT_FRONT, PACKET_FLUSHED etc */ + int flagsHold; + int first_pkt; /* this is the first pkt passing through enc */ + tui16 *hash_table; }; + int APP_CC compress_rdp(struct xrdp_mppc_enc *enc, tui8 *srcData, int len); struct xrdp_mppc_enc * APP_CC @@ -279,217 +297,225 @@ void APP_CC mppc_enc_free(struct xrdp_mppc_enc *enc); /* xrdp_tcp.c */ -struct xrdp_tcp* APP_CC -xrdp_tcp_create(struct xrdp_iso* owner, struct trans* trans); +struct xrdp_tcp * APP_CC +xrdp_tcp_create(struct xrdp_iso *owner, struct trans *trans); void APP_CC -xrdp_tcp_delete(struct xrdp_tcp* self); +xrdp_tcp_delete(struct xrdp_tcp *self); int APP_CC -xrdp_tcp_init(struct xrdp_tcp* self, struct stream* s); +xrdp_tcp_init(struct xrdp_tcp *self, struct stream *s); int APP_CC -xrdp_tcp_recv(struct xrdp_tcp* self, struct stream* s, int len); +xrdp_tcp_recv(struct xrdp_tcp *self, struct stream *s, int len); int APP_CC -xrdp_tcp_send(struct xrdp_tcp* self, struct stream* s); +xrdp_tcp_send(struct xrdp_tcp *self, struct stream *s); /* xrdp_iso.c */ -struct xrdp_iso* APP_CC -xrdp_iso_create(struct xrdp_mcs* owner, struct trans* trans); +struct xrdp_iso * APP_CC +xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans); void APP_CC -xrdp_iso_delete(struct xrdp_iso* self); +xrdp_iso_delete(struct xrdp_iso *self); +int APP_CC +xrdp_iso_init(struct xrdp_iso *self, struct stream *s); int APP_CC -xrdp_iso_init(struct xrdp_iso* self, struct stream* s); +xrdp_iso_recv(struct xrdp_iso *self, struct stream *s); int APP_CC -xrdp_iso_recv(struct xrdp_iso* self, struct stream* s); +xrdp_iso_send(struct xrdp_iso *self, struct stream *s); int APP_CC -xrdp_iso_send(struct xrdp_iso* self, struct stream* s); +xrdp_iso_incoming(struct xrdp_iso *self); int APP_CC -xrdp_iso_incoming(struct xrdp_iso* self); +xrdp_iso_detect_tpkt(struct xrdp_iso *self, struct stream *s); /* xrdp_mcs.c */ -struct xrdp_mcs* APP_CC -xrdp_mcs_create(struct xrdp_sec* owner, struct trans* trans, - struct stream* client_mcs_data, - struct stream* server_mcs_data); +struct xrdp_mcs * APP_CC +xrdp_mcs_create(struct xrdp_sec *owner, struct trans *trans, + struct stream *client_mcs_data, + struct stream *server_mcs_data); void APP_CC -xrdp_mcs_delete(struct xrdp_mcs* self); +xrdp_mcs_delete(struct xrdp_mcs *self); int APP_CC -xrdp_mcs_init(struct xrdp_mcs* self, struct stream* s); +xrdp_mcs_init(struct xrdp_mcs *self, struct stream *s); int APP_CC -xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan); +xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan); int APP_CC -xrdp_mcs_send(struct xrdp_mcs* self, struct stream* s, int chan); +xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan); int APP_CC -xrdp_mcs_incoming(struct xrdp_mcs* self); +xrdp_mcs_incoming(struct xrdp_mcs *self); int APP_CC -xrdp_mcs_disconnect(struct xrdp_mcs* self); +xrdp_mcs_disconnect(struct xrdp_mcs *self); /* xrdp_sec.c */ -struct xrdp_sec* APP_CC -xrdp_sec_create(struct xrdp_rdp* owner, struct trans* trans, int crypt_level, - int channel_code, int multimon); +struct xrdp_sec *APP_CC +xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans); void APP_CC -xrdp_sec_delete(struct xrdp_sec* self); +xrdp_sec_delete(struct xrdp_sec *self); +int APP_CC +xrdp_sec_init(struct xrdp_sec *self, struct stream *s); +int APP_CC +xrdp_sec_get_fastpath_bytes(struct xrdp_sec *self); +int APP_CC +xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s); int APP_CC -xrdp_sec_init(struct xrdp_sec* self, struct stream* s); +xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s); int APP_CC -xrdp_sec_recv(struct xrdp_sec* self, struct stream* s, int* chan); +xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s); int APP_CC -xrdp_sec_send(struct xrdp_sec* self, struct stream* s, int chan); +xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan); int APP_CC -xrdp_sec_process_mcs_data(struct xrdp_sec* self); +xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan); int APP_CC -xrdp_sec_out_mcs_data(struct xrdp_sec* self); +xrdp_sec_process_mcs_data(struct xrdp_sec *self); int APP_CC -xrdp_sec_incoming(struct xrdp_sec* self); +xrdp_sec_incoming(struct xrdp_sec *self); int APP_CC -xrdp_sec_disconnect(struct xrdp_sec* self); +xrdp_sec_disconnect(struct xrdp_sec *self); /* xrdp_rdp.c */ -struct xrdp_rdp* APP_CC -xrdp_rdp_create(struct xrdp_session* session, struct trans* trans); +struct xrdp_rdp * APP_CC +xrdp_rdp_create(struct xrdp_session *session, struct trans *trans); void APP_CC -xrdp_rdp_delete(struct xrdp_rdp* self); +xrdp_rdp_delete(struct xrdp_rdp *self); int APP_CC -xrdp_rdp_init(struct xrdp_rdp* self, struct stream* s); +xrdp_rdp_init(struct xrdp_rdp *self, struct stream *s); int APP_CC -xrdp_rdp_init_data(struct xrdp_rdp* self, struct stream* s); +xrdp_rdp_init_data(struct xrdp_rdp *self, struct stream *s); int APP_CC -xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code); +xrdp_rdp_get_fastpath_bytes(struct xrdp_rdp *self); int APP_CC -xrdp_rdp_send(struct xrdp_rdp* self, struct stream* s, int pdu_type); +xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s); int APP_CC -xrdp_rdp_send_data(struct xrdp_rdp* self, struct stream* s, - int data_pdu_type); +xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code); int APP_CC -xrdp_rdp_send_data_update_sync(struct xrdp_rdp* self); +xrdp_rdp_send(struct xrdp_rdp *self, struct stream *s, int pdu_type); int APP_CC -xrdp_rdp_incoming(struct xrdp_rdp* self); +xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, + int data_pdu_type); int APP_CC -xrdp_rdp_send_demand_active(struct xrdp_rdp* self); +xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, + int data_pdu_type); int APP_CC -xrdp_rdp_send_monitorlayout(struct xrdp_rdp* self); +xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self); int APP_CC -xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s); +xrdp_rdp_incoming(struct xrdp_rdp *self); int APP_CC -xrdp_rdp_process_data(struct xrdp_rdp* self, struct stream* s); +xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s); int APP_CC -xrdp_rdp_disconnect(struct xrdp_rdp* self); +xrdp_rdp_disconnect(struct xrdp_rdp *self); int APP_CC -xrdp_rdp_send_deactive(struct xrdp_rdp* self); +xrdp_rdp_send_deactive(struct xrdp_rdp *self); /* xrdp_orders.c */ -struct xrdp_orders* APP_CC -xrdp_orders_create(struct xrdp_session* session, - struct xrdp_rdp* rdp_layer); +struct xrdp_orders * APP_CC +xrdp_orders_create(struct xrdp_session *session, + struct xrdp_rdp *rdp_layer); void APP_CC -xrdp_orders_delete(struct xrdp_orders* self); +xrdp_orders_delete(struct xrdp_orders *self); int APP_CC -xrdp_orders_reset(struct xrdp_orders* self); +xrdp_orders_reset(struct xrdp_orders *self); int APP_CC -xrdp_orders_init(struct xrdp_orders* self); +xrdp_orders_init(struct xrdp_orders *self); int APP_CC -xrdp_orders_send(struct xrdp_orders* self); +xrdp_orders_send(struct xrdp_orders *self); int APP_CC -xrdp_orders_force_send(struct xrdp_orders* self); +xrdp_orders_force_send(struct xrdp_orders *self); int APP_CC -xrdp_orders_check(struct xrdp_orders* self, int max_size); +xrdp_orders_check(struct xrdp_orders *self, int max_size); int APP_CC -xrdp_orders_rect(struct xrdp_orders* self, int x, int y, int cx, int cy, - int color, struct xrdp_rect* rect); +xrdp_orders_rect(struct xrdp_orders *self, int x, int y, int cx, int cy, + int color, struct xrdp_rect *rect); int APP_CC -xrdp_orders_screen_blt(struct xrdp_orders* self, int x, int y, +xrdp_orders_screen_blt(struct xrdp_orders *self, int x, int y, int cx, int cy, int srcx, int srcy, - int rop, struct xrdp_rect* rect); + int rop, struct xrdp_rect *rect); int APP_CC -xrdp_orders_pat_blt(struct xrdp_orders* self, int x, int y, +xrdp_orders_pat_blt(struct xrdp_orders *self, int x, int y, int cx, int cy, int rop, int bg_color, - int fg_color, struct xrdp_brush* brush, - struct xrdp_rect* rect); + int fg_color, struct xrdp_brush *brush, + struct xrdp_rect *rect); int APP_CC -xrdp_orders_dest_blt(struct xrdp_orders* self, int x, int y, +xrdp_orders_dest_blt(struct xrdp_orders *self, int x, int y, int cx, int cy, int rop, - struct xrdp_rect* rect); + struct xrdp_rect *rect); int APP_CC -xrdp_orders_line(struct xrdp_orders* self, int mix_mode, +xrdp_orders_line(struct xrdp_orders *self, int mix_mode, int startx, int starty, int endx, int endy, int rop, int bg_color, - struct xrdp_pen* pen, - struct xrdp_rect* rect); + struct xrdp_pen *pen, + struct xrdp_rect *rect); int APP_CC -xrdp_orders_mem_blt(struct xrdp_orders* self, int cache_id, +xrdp_orders_mem_blt(struct xrdp_orders *self, int cache_id, int color_table, int x, int y, int cx, int cy, int rop, int srcx, int srcy, - int cache_idx, struct xrdp_rect* rect); + int cache_idx, struct xrdp_rect *rect); int APP_CC -xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, +xrdp_orders_composite_blt(struct xrdp_orders *self, int srcidx, int srcformat, int srcwidth, - int srcrepeat, int* srctransform, int mskflags, + int srcrepeat, int *srctransform, int mskflags, int mskidx, int mskformat, int mskwidth, int mskrepeat, int op, int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat, - struct xrdp_rect* rect); + struct xrdp_rect *rect); int APP_CC -xrdp_orders_text(struct xrdp_orders* self, +xrdp_orders_text(struct xrdp_orders *self, int font, int flags, int mixmode, int fg_color, int bg_color, int clip_left, int clip_top, int clip_right, int clip_bottom, int box_left, int box_top, int box_right, int box_bottom, - int x, int y, char* data, int data_len, - struct xrdp_rect* rect); + int x, int y, char *data, int data_len, + struct xrdp_rect *rect); int APP_CC -xrdp_orders_send_palette(struct xrdp_orders* self, int* palette, +xrdp_orders_send_palette(struct xrdp_orders *self, int *palette, int cache_id); int APP_CC -xrdp_orders_send_raw_bitmap(struct xrdp_orders* self, - int width, int height, int bpp, char* data, +xrdp_orders_send_raw_bitmap(struct xrdp_orders *self, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int APP_CC -xrdp_orders_send_bitmap(struct xrdp_orders* self, - int width, int height, int bpp, char* data, +xrdp_orders_send_bitmap(struct xrdp_orders *self, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int APP_CC -xrdp_orders_send_font(struct xrdp_orders* self, - struct xrdp_font_char* font_char, +xrdp_orders_send_font(struct xrdp_orders *self, + struct xrdp_font_char *font_char, int font_index, int char_index); int APP_CC -xrdp_orders_send_raw_bitmap2(struct xrdp_orders* self, - int width, int height, int bpp, char* data, +xrdp_orders_send_raw_bitmap2(struct xrdp_orders *self, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int APP_CC -xrdp_orders_send_bitmap2(struct xrdp_orders* self, - int width, int height, int bpp, char* data, +xrdp_orders_send_bitmap2(struct xrdp_orders *self, + int width, int height, int bpp, char *data, int cache_id, int cache_idx, int hints); int APP_CC -xrdp_orders_send_bitmap3(struct xrdp_orders* self, - int width, int height, int bpp, char* data, +xrdp_orders_send_bitmap3(struct xrdp_orders *self, + int width, int height, int bpp, char *data, int cache_id, int cache_idx, int hints); int APP_CC -xrdp_orders_send_brush(struct xrdp_orders* self, int width, int height, - int bpp, int type, int size, char* data, int cache_id); +xrdp_orders_send_brush(struct xrdp_orders *self, int width, int height, + int bpp, int type, int size, char *data, int cache_id); int APP_CC -xrdp_orders_send_create_os_surface(struct xrdp_orders* self, int id, +xrdp_orders_send_create_os_surface(struct xrdp_orders *self, int id, int width, int height, - struct list* del_list); + struct list *del_list); int APP_CC -xrdp_orders_send_switch_os_surface(struct xrdp_orders* self, int id); +xrdp_orders_send_switch_os_surface(struct xrdp_orders *self, int id); /* xrdp_bitmap_compress.c */ int APP_CC -xrdp_bitmap_compress(char* in_data, int width, int height, - struct stream* s, int bpp, int byte_limit, - int start_line, struct stream* temp_s, +xrdp_bitmap_compress(char *in_data, int width, int height, + struct stream *s, int bpp, int byte_limit, + int start_line, struct stream *temp_s, int e); int APP_CC -xrdp_bitmap32_compress(char* in_data, int width, int height, - struct stream* s, int bpp, int byte_limit, - int start_line, struct stream* temp_s, - int e); +xrdp_bitmap32_compress(char *in_data, int width, int height, + struct stream *s, int bpp, int byte_limit, + int start_line, struct stream *temp_s, + int e, int flags); int APP_CC -xrdp_jpeg_compress(void *handle, char* in_data, int width, int height, - struct stream* s, int bpp, int byte_limit, - int start_line, struct stream* temp_s, +xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, + struct stream *s, int bpp, int byte_limit, + int start_line, struct stream *temp_s, int e, int quality); int APP_CC @@ -516,16 +542,35 @@ xrdp_jpeg_deinit(void *handle); /* xrdp_channel.c */ struct xrdp_channel* APP_CC -xrdp_channel_create(struct xrdp_sec* owner, struct xrdp_mcs* mcs_layer); +xrdp_channel_create(struct xrdp_sec *owner, struct xrdp_mcs *mcs_layer); void APP_CC -xrdp_channel_delete(struct xrdp_channel* self); +xrdp_channel_delete(struct xrdp_channel *self); int APP_CC -xrdp_channel_init(struct xrdp_channel* self, struct stream* s); +xrdp_channel_init(struct xrdp_channel *self, struct stream *s); int APP_CC -xrdp_channel_send(struct xrdp_channel* self, struct stream* s, int channel_id, +xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id, int total_data_len, int flags); int APP_CC -xrdp_channel_process(struct xrdp_channel* self, struct stream* s, +xrdp_channel_process(struct xrdp_channel *self, struct stream *s, int chanid); +/* xrdp_fastpath.c */ +struct xrdp_fastpath *APP_CC +xrdp_fastpath_create(struct xrdp_sec *owner, struct trans *trans); +void APP_CC +xrdp_fastpath_delete(struct xrdp_fastpath *self); +int APP_CC +xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s); +int APP_CC +xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, struct stream *s); +int APP_CC +xrdp_fastpath_init(struct xrdp_fastpath *self, struct stream *s); +int APP_CC +xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s); + +/* xrdp_caps.c */ +int APP_CC +xrdp_caps_send_demand_active(struct xrdp_rdp *self); +int APP_CC +xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s); #endif diff --git a/libxrdp/libxrdpinc.h b/libxrdp/libxrdpinc.h index d322eafa..2262f66f 100644 --- a/libxrdp/libxrdpinc.h +++ b/libxrdp/libxrdpinc.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,202 +27,220 @@ struct xrdp_brush { - int x_orgin; - int y_orgin; - int style; - char pattern[8]; + int x_orgin; + int y_orgin; + int style; + char pattern[8]; }; struct xrdp_pen { - int style; - int width; - int color; + int style; + int width; + int color; }; /* 2.2.2.2.1.2.5.1 Cache Glyph Data (TS_CACHE_GLYPH_DATA) */ struct xrdp_font_char { - int offset; /* x */ - int baseline; /* y */ - int width; /* cx */ - int height; /* cy */ - int incby; - int bpp; - char* data; + int offset; /* x */ + int baseline; /* y */ + int width; /* cx */ + int height; /* cy */ + int incby; + int bpp; + char *data; }; struct xrdp_rect { - int left; - int top; - int right; - int bottom; + int left; + int top; + int right; + int bottom; }; struct xrdp_session { - long id; - struct trans* trans; - int (*callback)(long id, int msg, long param1, long param2, long param3, - long param4); - void* rdp; - void* orders; - struct xrdp_client_info* client_info; - int up_and_running; - int (*is_term)(void); - int in_process_data; /* inc / dec libxrdp_process_data calls */ + tintptr id; + struct trans *trans; + int (*callback)(tintptr id, int msg, tintptr param1, tintptr param2, + tintptr param3, tintptr param4); + void *rdp; + void *orders; + struct xrdp_client_info *client_info; + int up_and_running; + int (*is_term)(void); + int in_process_data; /* inc / dec libxrdp_process_data calls */ }; -struct xrdp_session* DEFAULT_CC -libxrdp_init(tbus id, struct trans* trans); +struct xrdp_session * DEFAULT_CC +libxrdp_init(tbus id, struct trans *trans); int DEFAULT_CC -libxrdp_exit(struct xrdp_session* session); +libxrdp_exit(struct xrdp_session *session); int DEFAULT_CC -libxrdp_disconnect(struct xrdp_session* session); +libxrdp_disconnect(struct xrdp_session *session); int DEFAULT_CC -libxrdp_process_incomming(struct xrdp_session* session); +libxrdp_process_incomming(struct xrdp_session *session); +int EXPORT_CC +libxrdp_get_pdu_bytes(const char *aheader); +struct stream * APP_CC +libxrdp_force_read(struct trans *trans); int DEFAULT_CC -libxrdp_process_data(struct xrdp_session* session, struct stream *s); +libxrdp_process_data(struct xrdp_session *session, struct stream *s); int DEFAULT_CC -libxrdp_send_palette(struct xrdp_session* session, int* palette); +libxrdp_send_palette(struct xrdp_session *session, int *palette); int DEFAULT_CC -libxrdp_send_bell(struct xrdp_session* session); +libxrdp_send_bell(struct xrdp_session *session); int DEFAULT_CC -libxrdp_send_bitmap(struct xrdp_session* session, int width, int height, - int bpp, char* data, int x, int y, int cx, int cy); +libxrdp_send_bitmap(struct xrdp_session *session, int width, int height, + int bpp, char *data, int x, int y, int cx, int cy); int DEFAULT_CC -libxrdp_send_pointer(struct xrdp_session* session, int cache_idx, - char* data, char* mask, int x, int y, int bpp); +libxrdp_send_pointer(struct xrdp_session *session, int cache_idx, + char *data, char *mask, int x, int y, int bpp); int DEFAULT_CC -libxrdp_set_pointer(struct xrdp_session* session, int cache_idx); +libxrdp_set_pointer(struct xrdp_session *session, int cache_idx); int DEFAULT_CC -libxrdp_orders_init(struct xrdp_session* session); +libxrdp_orders_init(struct xrdp_session *session); int DEFAULT_CC -libxrdp_orders_send(struct xrdp_session* session); +libxrdp_orders_send(struct xrdp_session *session); int DEFAULT_CC -libxrdp_orders_force_send(struct xrdp_session* session); +libxrdp_orders_force_send(struct xrdp_session *session); int DEFAULT_CC -libxrdp_orders_rect(struct xrdp_session* session, int x, int y, - int cx, int cy, int color, struct xrdp_rect* rect); +libxrdp_orders_rect(struct xrdp_session *session, int x, int y, + int cx, int cy, int color, struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_screen_blt(struct xrdp_session* session, int x, int y, +libxrdp_orders_screen_blt(struct xrdp_session *session, int x, int y, int cx, int cy, int srcx, int srcy, - int rop, struct xrdp_rect* rect); + int rop, struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_pat_blt(struct xrdp_session* session, int x, int y, +libxrdp_orders_pat_blt(struct xrdp_session *session, int x, int y, int cx, int cy, int rop, int bg_color, - int fg_color, struct xrdp_brush* brush, - struct xrdp_rect* rect); + int fg_color, struct xrdp_brush *brush, + struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_dest_blt(struct xrdp_session* session, int x, int y, +libxrdp_orders_dest_blt(struct xrdp_session *session, int x, int y, int cx, int cy, int rop, - struct xrdp_rect* rect); + struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_line(struct xrdp_session* session, int mix_mode, +libxrdp_orders_line(struct xrdp_session *session, int mix_mode, int startx, int starty, int endx, int endy, int rop, int bg_color, - struct xrdp_pen* pen, - struct xrdp_rect* rect); + struct xrdp_pen *pen, + struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_mem_blt(struct xrdp_session* session, int cache_id, +libxrdp_orders_mem_blt(struct xrdp_session *session, int cache_id, int color_table, int x, int y, int cx, int cy, int rop, int srcx, int srcy, - int cache_idx, struct xrdp_rect* rect); + int cache_idx, struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_composite_blt(struct xrdp_session* session, int srcidx, +libxrdp_orders_composite_blt(struct xrdp_session *session, int srcidx, int srcformat, int srcwidth, int srcrepeat, - int* srctransform, int mskflags, + int *srctransform, int mskflags, int mskidx, int mskformat, int mskwidth, int mskrepeat, int op, int srcx, int srcy, int mskx, int msky, int dstx, int dsty, int width, int height, int dstformat, - struct xrdp_rect* rect); + struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_text(struct xrdp_session* session, +libxrdp_orders_text(struct xrdp_session *session, int font, int flags, int mixmode, int fg_color, int bg_color, int clip_left, int clip_top, int clip_right, int clip_bottom, int box_left, int box_top, int box_right, int box_bottom, - int x, int y, char* data, int data_len, - struct xrdp_rect* rect); + int x, int y, char *data, int data_len, + struct xrdp_rect *rect); int DEFAULT_CC -libxrdp_orders_send_palette(struct xrdp_session* session, int* palette, +libxrdp_orders_send_palette(struct xrdp_session *session, int *palette, int cache_id); int DEFAULT_CC -libxrdp_orders_send_raw_bitmap(struct xrdp_session* session, - int width, int height, int bpp, char* data, +libxrdp_orders_send_raw_bitmap(struct xrdp_session *session, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int DEFAULT_CC -libxrdp_orders_send_bitmap(struct xrdp_session* session, - int width, int height, int bpp, char* data, +libxrdp_orders_send_bitmap(struct xrdp_session *session, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int DEFAULT_CC -libxrdp_orders_send_font(struct xrdp_session* session, - struct xrdp_font_char* font_char, +libxrdp_orders_send_font(struct xrdp_session *session, + struct xrdp_font_char *font_char, int font_index, int char_index); int DEFAULT_CC -libxrdp_reset(struct xrdp_session* session, +libxrdp_reset(struct xrdp_session *session, int width, int height, int bpp); int DEFAULT_CC -libxrdp_orders_send_raw_bitmap2(struct xrdp_session* session, - int width, int height, int bpp, char* data, +libxrdp_orders_send_raw_bitmap2(struct xrdp_session *session, + int width, int height, int bpp, char *data, int cache_id, int cache_idx); int DEFAULT_CC -libxrdp_orders_send_bitmap2(struct xrdp_session* session, - int width, int height, int bpp, char* data, +libxrdp_orders_send_bitmap2(struct xrdp_session *session, + int width, int height, int bpp, char *data, int cache_id, int cache_idx, int hints); int DEFAULT_CC -libxrdp_orders_send_bitmap3(struct xrdp_session* session, - int width, int height, int bpp, char* data, +libxrdp_orders_send_bitmap3(struct xrdp_session *session, + int width, int height, int bpp, char *data, int cache_id, int cache_idx, int hints); int DEFAULT_CC -libxrdp_query_channel(struct xrdp_session* session, int index, - char* channel_name, int* channel_flags); +libxrdp_query_channel(struct xrdp_session *session, int index, + char *channel_name, int *channel_flags); int DEFAULT_CC -libxrdp_get_channel_id(struct xrdp_session* session, char* name); +libxrdp_get_channel_id(struct xrdp_session *session, char *name); int DEFAULT_CC -libxrdp_send_to_channel(struct xrdp_session* session, int channel_id, - char* data, int data_len, +libxrdp_send_to_channel(struct xrdp_session *session, int channel_id, + char *data, int data_len, int total_data_len, int flags); int DEFAULT_CC -libxrdp_orders_send_brush(struct xrdp_session* session, +libxrdp_orders_send_brush(struct xrdp_session *session, int width, int height, int bpp, int type, - int size, char* data, int cache_id); + int size, char *data, int cache_id); int DEFAULT_CC -libxrdp_orders_send_create_os_surface(struct xrdp_session* session, int id, +libxrdp_orders_send_create_os_surface(struct xrdp_session *session, int id, int width, int height, - struct list* del_list); + struct list *del_list); int DEFAULT_CC -libxrdp_orders_send_switch_os_surface(struct xrdp_session* session, int id); +libxrdp_orders_send_switch_os_surface(struct xrdp_session *session, int id); int DEFAULT_CC -libxrdp_window_new_update(struct xrdp_session* session, int window_id, - struct rail_window_state_order* window_state, +libxrdp_window_new_update(struct xrdp_session *session, int window_id, + struct rail_window_state_order *window_state, int flags); int DEFAULT_CC -libxrdp_window_delete(struct xrdp_session* session, int window_id); +libxrdp_window_delete(struct xrdp_session *session, int window_id); int DEFAULT_CC -libxrdp_window_icon(struct xrdp_session* session, int window_id, +libxrdp_window_icon(struct xrdp_session *session, int window_id, int cache_entry, int cache_id, - struct rail_icon_info* icon_info, int flags); + struct rail_icon_info *icon_info, int flags); int DEFAULT_CC -libxrdp_window_cached_icon(struct xrdp_session* session, int window_id, +libxrdp_window_cached_icon(struct xrdp_session *session, int window_id, int cache_entry, int cache_id, int flags); int DEFAULT_CC -libxrdp_notify_new_update(struct xrdp_session* session, +libxrdp_notify_new_update(struct xrdp_session *session, int window_id, int notify_id, - struct rail_notify_state_order* notify_state, + struct rail_notify_state_order *notify_state, int flags); int DEFAULT_CC -libxrdp_notify_delete(struct xrdp_session* session, +libxrdp_notify_delete(struct xrdp_session *session, int window_id, int notify_id); int DEFAULT_CC -libxrdp_monitored_desktop(struct xrdp_session* session, - struct rail_monitored_desktop_order* mdo, +libxrdp_monitored_desktop(struct xrdp_session *session, + struct rail_monitored_desktop_order *mdo, int flags); +int DEFAULT_CC +libxrdp_codec_jpeg_compress(struct xrdp_session *session, + int format, char *inp_data, + int width, int height, + int stride, int x, int y, + int cx, int cy, int quality, + char *out_data, int *io_len); +int DEFAULT_CC +libxrdp_fastpath_send_surface(struct xrdp_session *session, + char *data_pad, int pad_bytes, + int data_bytes, + int destLeft, int dst_Top, + int destRight, int destBottom, int bpp, + int codecID, int width, int height); #endif diff --git a/libxrdp/xrdp_bitmap32_compress.c b/libxrdp/xrdp_bitmap32_compress.c index b681d040..083c4409 100644 --- a/libxrdp/xrdp_bitmap32_compress.c +++ b/libxrdp/xrdp_bitmap32_compress.c @@ -19,14 +19,518 @@ * 32 bpp compression */ +/* +RDP 6.0 Bitmap Compression +http://msdn.microsoft.com/en-us/library/cc241877.aspx +*/ + #include "libxrdp.h" +#define FLAGS_RLE 0x10 +#define FLAGS_NOALPHA 0x20 + +#define LLOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LLOG_LEVEL) { g_writeln _args ; } } while (0) +#define LHEXDUMP(_level, _args) \ + do { if (_level < LLOG_LEVEL) { g_hexdump _args ; } } while (0) + +/*****************************************************************************/ +/* split RGB */ +static int APP_CC +fsplit3(char *in_data, int start_line, int width, int e, + char *r_data, char *g_data, char *b_data) +{ +#if defined(L_ENDIAN) + int rp; + int gp; + int bp; +#endif + int index; + int out_index; + int pixel; + int cy; + int *ptr32; + + cy = 0; + out_index = 0; + while (start_line >= 0) + { + ptr32 = (int *) (in_data + start_line * width * 4); + index = 0; +#if defined(L_ENDIAN) + while (index + 4 <= width) + { + pixel = *ptr32; + ptr32++; + rp = (pixel >> 16) & 0x000000ff; + gp = (pixel >> 8) & 0x000000ff; + bp = (pixel >> 0) & 0x000000ff; + pixel = *ptr32; + ptr32++; + rp |= (pixel >> 8) & 0x0000ff00; + gp |= (pixel << 0) & 0x0000ff00; + bp |= (pixel << 8) & 0x0000ff00; + pixel = *ptr32; + ptr32++; + rp |= (pixel >> 0) & 0x00ff0000; + gp |= (pixel << 8) & 0x00ff0000; + bp |= (pixel << 16) & 0x00ff0000; + pixel = *ptr32; + ptr32++; + rp |= (pixel << 8) & 0xff000000; + gp |= (pixel << 16) & 0xff000000; + bp |= (pixel << 24) & 0xff000000; + *((int*)(r_data + out_index)) = rp; + *((int*)(g_data + out_index)) = gp; + *((int*)(b_data + out_index)) = bp; + out_index += 4; + index += 4; + } +#endif + while (index < width) + { + pixel = *ptr32; + ptr32++; + r_data[out_index] = pixel >> 16; + g_data[out_index] = pixel >> 8; + b_data[out_index] = pixel >> 0; + out_index++; + index++; + } + for (index = 0; index < e; index++) + { + r_data[out_index] = r_data[out_index - 1]; + g_data[out_index] = g_data[out_index - 1]; + b_data[out_index] = b_data[out_index - 1]; + out_index++; + } + start_line--; + cy++; + if (out_index > 64 * 64) + { + break; + } + } + return cy; +} + /*****************************************************************************/ +/* split ARGB */ +static int APP_CC +fsplit4(char *in_data, int start_line, int width, int e, + char *a_data, char *r_data, char *g_data, char *b_data) +{ +#if defined(L_ENDIAN) + int ap; + int rp; + int gp; + int bp; +#endif + int index; + int out_index; + int pixel; + int cy; + int *ptr32; + + cy = 0; + out_index = 0; + while (start_line >= 0) + { + ptr32 = (int *) (in_data + start_line * width * 4); + index = 0; +#if defined(L_ENDIAN) + while (index + 4 <= width) + { + pixel = *ptr32; + ptr32++; + ap = (pixel >> 24) & 0x000000ff; + rp = (pixel >> 16) & 0x000000ff; + gp = (pixel >> 8) & 0x000000ff; + bp = (pixel >> 0) & 0x000000ff; + pixel = *ptr32; + ptr32++; + ap |= (pixel >> 16) & 0x0000ff00; + rp |= (pixel >> 8) & 0x0000ff00; + gp |= (pixel << 0) & 0x0000ff00; + bp |= (pixel << 8) & 0x0000ff00; + pixel = *ptr32; + ptr32++; + ap |= (pixel >> 8) & 0x00ff0000; + rp |= (pixel >> 0) & 0x00ff0000; + gp |= (pixel << 8) & 0x00ff0000; + bp |= (pixel << 16) & 0x00ff0000; + pixel = *ptr32; + ptr32++; + ap |= (pixel << 0) & 0xff000000; + rp |= (pixel << 8) & 0xff000000; + gp |= (pixel << 16) & 0xff000000; + bp |= (pixel << 24) & 0xff000000; + *((int*)(a_data + out_index)) = ap; + *((int*)(r_data + out_index)) = rp; + *((int*)(g_data + out_index)) = gp; + *((int*)(b_data + out_index)) = bp; + out_index += 4; + index += 4; + } +#endif + while (index < width) + { + pixel = *ptr32; + ptr32++; + a_data[out_index] = pixel >> 24; + r_data[out_index] = pixel >> 16; + g_data[out_index] = pixel >> 8; + b_data[out_index] = pixel >> 0; + out_index++; + index++; + } + for (index = 0; index < e; index++) + { + a_data[out_index] = a_data[out_index - 1]; + r_data[out_index] = r_data[out_index - 1]; + g_data[out_index] = g_data[out_index - 1]; + b_data[out_index] = b_data[out_index - 1]; + out_index++; + } + start_line--; + cy++; + if (out_index > 64 * 64) + { + break; + } + } + return cy; +} + +/*****************************************************************************/ +#define DELTA_ONE \ +do { \ + delta = src8[cx] - src8[0]; \ + is_neg = (delta >> 7) & 1; \ + dst8[cx] = (((delta ^ -is_neg) + is_neg) << 1) - is_neg; \ + src8++; \ + dst8++; \ +} while (0) + +/*****************************************************************************/ +static int APP_CC +fdelta(char *in_plane, char *out_plane, int cx, int cy) +{ + char delta; + char is_neg; + char *src8; + char *dst8; + char *src8_end; + + g_memcpy(out_plane, in_plane, cx); + src8 = in_plane; + dst8 = out_plane; + src8_end = src8 + (cx * cy - cx); + while (src8 + 8 <= src8_end) + { + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + DELTA_ONE; + } + while (src8 < src8_end) + { + DELTA_ONE; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +fout(int collen, int replen, char *colptr, struct stream *s) +{ + int code; + int lcollen; + int lreplen; + int cont; + + LLOGLN(10, ("fout: collen %d replen %d", collen, replen)); + cont = collen > 13; + while (cont) + { + lcollen = collen; + if (lcollen > 15) + { + lcollen = 15; + } + code = lcollen << 4; + out_uint8(s, code); + out_uint8a(s, colptr, lcollen); + colptr += lcollen; + collen -= lcollen; + cont = collen > 13; + } + cont = (collen > 0) || (replen > 0); + while (cont) + { + lreplen = replen; + if ((collen == 0) && (lreplen > 15)) + { + /* big run */ + if (lreplen > 47) + { + lreplen = 47; + } + LLOGLN(10, ("fout: big run lreplen %d", lreplen)); + replen -= lreplen; + code = ((lreplen & 0xF) << 4) | ((lreplen & 0xF0) >> 4); + out_uint8(s, code); + colptr += lreplen; + } + else + { + if (lreplen > 15) + { + lreplen = 15; + } + replen -= lreplen; + if (lreplen < 3) + { + collen += lreplen; + lreplen = 0; + } + code = (collen << 4) | lreplen; + out_uint8(s, code); + out_uint8a(s, colptr, collen); + colptr += collen + lreplen; + collen = 0; + } + cont = replen > 0; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +fpack(char *plane, int cx, int cy, struct stream *s) +{ + char *ptr8; + char *colptr; + char *lend; + char *holdp; + int jndex; + int collen; + int replen; + + LLOGLN(10, ("fpack:")); + holdp = s->p; + for (jndex = 0; jndex < cy; jndex++) + { + LLOGLN(10, ("line start line %d cx %d cy %d", jndex, cx, cy)); + ptr8 = plane + jndex * cx; + LHEXDUMP(10, (ptr8, cx)); + lend = ptr8 + (cx - 1); + colptr = ptr8; + if (colptr[0] == 0) + { + collen = 0; + replen = 1; + } + else + { + collen = 1; + replen = 0; + } + while (ptr8 < lend) + { + if (ptr8[0] == ptr8[1]) + { + replen++; + } + else + { + if (replen > 0) + { + if (replen < 3) + { + collen += replen + 1; + replen = 0; + } + else + { + fout(collen, replen, colptr, s); + colptr = ptr8 + 1; + replen = 0; + collen = 1; + } + } + else + { + collen++; + } + } + ptr8++; + } + /* end of line */ + fout(collen, replen, colptr, s); + } + return (int) (s->p - holdp); +} + +/*****************************************************************************/ +static int APP_CC +foutraw3(struct stream *s, int bytes, int header, + char *r_data, char *g_data, char *b_data) +{ + out_uint8(s, header); + out_uint8a(s, r_data, bytes); + out_uint8a(s, g_data, bytes); + out_uint8a(s, b_data, bytes); + /* pad if no RLE */ + out_uint8(s, 0x00); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +foutraw4(struct stream *s, int bytes, int header, + char *a_data, char *r_data, char *g_data, char *b_data) +{ + out_uint8(s, header); + out_uint8a(s, a_data, bytes); + out_uint8a(s, r_data, bytes); + out_uint8a(s, g_data, bytes); + out_uint8a(s, b_data, bytes); + /* pad if no RLE */ + out_uint8(s, 0x00); + return 0; +} + +/*****************************************************************************/ +/* returns the number of lines compressed */ int APP_CC xrdp_bitmap32_compress(char *in_data, int width, int height, struct stream *s, int bpp, int byte_limit, int start_line, struct stream *temp_s, - int e) + int e, int flags) { - return 0; + char *a_data; + char *r_data; + char *g_data; + char *b_data; + char *sa_data; + char *sr_data; + char *sg_data; + char *sb_data; + int a_bytes; + int r_bytes; + int g_bytes; + int b_bytes; + int cx; + int cy; + int max_bytes; + int total_bytes; + int header; + + LLOGLN(10, ("xrdp_bitmap32_compress:")); + max_bytes = 4 * 1024; + /* need max 8, 4K planes for work */ + if (max_bytes * 8 > temp_s->size) + { + return 0; + } + header = flags & 0xFF; + cx = width + e; + sa_data = temp_s->data; + sr_data = sa_data + max_bytes; + sg_data = sr_data + max_bytes; + sb_data = sg_data + max_bytes; + a_data = sb_data + max_bytes; + r_data = a_data + max_bytes; + g_data = r_data + max_bytes; + b_data = g_data + max_bytes; + + if (header & FLAGS_NOALPHA) + { + cy = fsplit3(in_data, start_line, width, e, + sr_data, sg_data, sb_data); + if (header & FLAGS_RLE) + { + fdelta(sr_data, r_data, cx, cy); + fdelta(sg_data, g_data, cx, cy); + fdelta(sb_data, b_data, cx, cy); + out_uint8(s, header); + r_bytes = fpack(r_data, cx, cy, s); + g_bytes = fpack(g_data, cx, cy, s); + b_bytes = fpack(b_data, cx, cy, s); + total_bytes = r_bytes + g_bytes + b_bytes; + if (1 + total_bytes > byte_limit) + { + /* failed */ + LLOGLN(0, ("xrdp_bitmap32_compress: too big, rgb " + "bytes %d %d %d total_bytes %d cx %d cy %d " + "byte_limit %d", r_bytes, g_bytes, b_bytes, + total_bytes, cx, cy, byte_limit)); + return 0; + } + max_bytes = cx * cy * 3; + if (total_bytes > max_bytes) + { + /* raw is better */ + LLOGLN(10, ("xrdp_bitmap32_compress: too big, rgb " + "bytes %d %d %d total_bytes %d cx %d cy %d " + "max_bytes %d", r_bytes, g_bytes, b_bytes, + total_bytes, cx, cy, max_bytes)); + init_stream(s, 0); + foutraw3(s, cx * cy, FLAGS_NOALPHA, sr_data, sg_data, sb_data); + } + } + else + { + foutraw3(s, cx * cy, FLAGS_NOALPHA, sr_data, sg_data, sb_data); + } + } + else + { + cy = fsplit4(in_data, start_line, width, e, + sa_data, sr_data, sg_data, sb_data); + if (header & FLAGS_RLE) + { + fdelta(sa_data, a_data, cx, cy); + fdelta(sr_data, r_data, cx, cy); + fdelta(sg_data, g_data, cx, cy); + fdelta(sb_data, b_data, cx, cy); + out_uint8(s, header); + a_bytes = fpack(a_data, cx, cy, s); + r_bytes = fpack(r_data, cx, cy, s); + g_bytes = fpack(g_data, cx, cy, s); + b_bytes = fpack(b_data, cx, cy, s); + max_bytes = cx * cy * 4; + total_bytes = a_bytes + r_bytes + g_bytes + b_bytes; + if (1 + total_bytes > byte_limit) + { + /* failed */ + LLOGLN(0, ("xrdp_bitmap32_compress: too big, argb " + "bytes %d %d %d %d total_bytes %d cx %d cy %d " + "byte_limit %d", a_bytes, r_bytes, g_bytes, b_bytes, + total_bytes, cx, cy, byte_limit)); + return 0; + } + if (total_bytes > max_bytes) + { + /* raw is better */ + LLOGLN(10, ("xrdp_bitmap32_compress: too big, argb " + "bytes %d %d %d %d total_bytes %d cx %d cy %d " + "max_bytes %d", a_bytes, r_bytes, g_bytes, b_bytes, + total_bytes, cx, cy, max_bytes)); + init_stream(s, 0); + foutraw4(s, cx * cy, 0, sa_data, sr_data, sg_data, sb_data); + } + } + else + { + foutraw4(s, cx * cy, 0, sa_data, sr_data, sg_data, sb_data); + } + } + return cy; } diff --git a/libxrdp/xrdp_caps.c b/libxrdp/xrdp_caps.c new file mode 100644 index 00000000..a5883a01 --- /dev/null +++ b/libxrdp/xrdp_caps.c @@ -0,0 +1,916 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2014 + * Copyright (C) Idan Freiberg 2004-2014 + * + * 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. + * + * RDP Capability Sets + */ + +#include "libxrdp.h" + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_send_monitorlayout(struct xrdp_rdp *self) +{ + struct stream *s; + int i; + + make_stream(s); + init_stream(s, 8192); + + if (xrdp_rdp_init_data(self, s) != 0) + { + free_stream(s); + return 1; + } + + out_uint32_le(s, self->client_info.monitorCount); /* monitorCount (4 bytes) */ + + /* TODO: validate for allowed monitors in terminal server (maybe by config?) */ + for (i = 0; i < self->client_info.monitorCount; i++) + { + out_uint32_le(s, self->client_info.minfo[i].left); + out_uint32_le(s, self->client_info.minfo[i].top); + out_uint32_le(s, self->client_info.minfo[i].right); + out_uint32_le(s, self->client_info.minfo[i].bottom); + out_uint32_le(s, self->client_info.minfo[i].is_primary); + } + + s_mark_end(s); + + if (xrdp_rdp_send_data(self, s, 0x37) != 0) + { + free_stream(s); + return 1; + } + + free_stream(s); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int extraFlags; + int client_does_fastpath_output; + + if (len < 10 + 2) + { + g_writeln("xrdp_caps_process_general: error"); + return 1; + } + in_uint8s(s, 10); + in_uint16_le(s, extraFlags); + /* use_compact_packets is pretty much 'use rdp5' */ + self->client_info.use_compact_packets = (extraFlags != 0); + /* op2 is a boolean to use compact bitmap headers in bitmap cache */ + /* set it to same as 'use rdp5' boolean */ + self->client_info.op2 = self->client_info.use_compact_packets; + /* FASTPATH_OUTPUT_SUPPORTED 0x0001 */ + client_does_fastpath_output = extraFlags & FASTPATH_OUTPUT_SUPPORTED; + if ((self->client_info.use_fast_path & 1) && !client_does_fastpath_output) + { + /* server supports fast path output and client does not, turn it off */ + self->client_info.use_fast_path &= ~1; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int i; + char order_caps[32]; + int ex_flags; + int cap_flags; + + DEBUG(("order capabilities")); + if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4) + { + g_writeln("xrdp_caps_process_order: error"); + return 1; + } + in_uint8s(s, 20); /* Terminal desc, pad */ + in_uint8s(s, 2); /* Cache X granularity */ + in_uint8s(s, 2); /* Cache Y granularity */ + in_uint8s(s, 2); /* Pad */ + in_uint8s(s, 2); /* Max order level */ + in_uint8s(s, 2); /* Number of fonts */ + in_uint16_le(s, cap_flags); /* Capability flags */ + in_uint8a(s, order_caps, 32); /* Orders supported */ + g_memcpy(self->client_info.orders, order_caps, 32); + DEBUG(("dest blt-0 %d", order_caps[0])); + DEBUG(("pat blt-1 %d", order_caps[1])); + DEBUG(("screen blt-2 %d", order_caps[2])); + DEBUG(("memblt-3-13 %d %d", order_caps[3], order_caps[13])); + DEBUG(("triblt-4-14 %d %d", order_caps[4], order_caps[14])); + DEBUG(("line-8 %d", order_caps[8])); + DEBUG(("line-9 %d", order_caps[9])); + DEBUG(("rect-10 %d", order_caps[10])); + DEBUG(("desksave-11 %d", order_caps[11])); + DEBUG(("polygon-20 %d", order_caps[20])); + DEBUG(("polygon2-21 %d", order_caps[21])); + DEBUG(("polyline-22 %d", order_caps[22])); + DEBUG(("ellipse-25 %d", order_caps[25])); + DEBUG(("ellipse2-26 %d", order_caps[26])); + DEBUG(("text2-27 %d", order_caps[27])); + DEBUG(("order_caps dump")); +#if defined(XRDP_DEBUG) + g_hexdump(order_caps, 32); +#endif + in_uint8s(s, 2); /* Text capability flags */ + /* read extended order support flags */ + in_uint16_le(s, ex_flags); /* Ex flags */ + + if (cap_flags & 0x80) /* ORDER_FLAGS_EXTRA_SUPPORT */ + { + self->client_info.order_flags_ex = ex_flags; + if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT) + { + g_writeln("xrdp_caps_process_order: bitmap cache v3 supported"); + self->client_info.bitmap_cache_version |= 4; + } + } + in_uint8s(s, 4); /* Pad */ + + in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */ + self->client_info.desktop_cache = i; + DEBUG(("desktop cache size %d", i)); + in_uint8s(s, 4); /* Unknown */ + in_uint8s(s, 4); /* Unknown */ + return 0; +} + +/*****************************************************************************/ +/* get the bitmap cache size */ +static int APP_CC +xrdp_caps_process_bmpcache(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int i; + + if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2) + { + g_writeln("xrdp_caps_process_bmpcache: error"); + return 1; + } + self->client_info.bitmap_cache_version |= 1; + in_uint8s(s, 24); + /* cache 1 */ + in_uint16_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache1_entries = i; + in_uint16_le(s, self->client_info.cache1_size); + /* cache 2 */ + in_uint16_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache2_entries = i; + in_uint16_le(s, self->client_info.cache2_size); + /* caceh 3 */ + in_uint16_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache3_entries = i; + in_uint16_le(s, self->client_info.cache3_size); + DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries, + self->client_info.cache1_size)); + DEBUG(("cache2 entries %d size %d", self->client_info.cache2_entries, + self->client_info.cache2_size)); + DEBUG(("cache3 entries %d size %d", self->client_info.cache3_entries, + self->client_info.cache3_size)); + return 0; +} + +/*****************************************************************************/ +/* get the bitmap cache size */ +static int APP_CC +xrdp_caps_process_bmpcache2(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int Bpp = 0; + int i = 0; + + if (len < 2 + 2 + 4 + 4 + 4) + { + g_writeln("xrdp_caps_process_bmpcache2: error"); + return 1; + } + self->client_info.bitmap_cache_version |= 2; + Bpp = (self->client_info.bpp + 7) / 8; + in_uint16_le(s, i); /* cache flags */ + self->client_info.bitmap_cache_persist_enable = i; + in_uint8s(s, 2); /* number of caches in set, 3 */ + in_uint32_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache1_entries = i; + self->client_info.cache1_size = 256 * Bpp; + in_uint32_le(s, i); + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache2_entries = i; + self->client_info.cache2_size = 1024 * Bpp; + in_uint32_le(s, i); + i = i & 0x7fffffff; + i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); + i = MAX(i, 0); + self->client_info.cache3_entries = i; + self->client_info.cache3_size = 4096 * Bpp; + DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries, + self->client_info.cache1_size)); + DEBUG(("cache2 entries %d size %d", self->client_info.cache2_entries, + self->client_info.cache2_size)); + DEBUG(("cache3 entries %d size %d", self->client_info.cache3_entries, + self->client_info.cache3_size)); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int codec_id; + + if (len < 1) + { + g_writeln("xrdp_caps_process_cache_v3_codec_id: error"); + return 1; + } + in_uint8(s, codec_id); + g_writeln("xrdp_caps_process_cache_v3_codec_id: cache_v3_codec_id %d", + codec_id); + self->client_info.v3_codec_id = codec_id; + return 0; +} + +/*****************************************************************************/ +/* get the number of client cursor cache */ +static int APP_CC +xrdp_caps_process_pointer(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int i; + int colorPointerFlag; + int no_new_cursor; + + if (len < 2 + 2 + 2) + { + g_writeln("xrdp_caps_process_pointer: error"); + return 1; + } + no_new_cursor = self->client_info.pointer_flags & 2; + in_uint16_le(s, colorPointerFlag); + self->client_info.pointer_flags = colorPointerFlag; + in_uint16_le(s, i); + i = MIN(i, 32); + self->client_info.pointer_cache_entries = i; + if (colorPointerFlag & 1) + { + g_writeln("xrdp_caps_process_pointer: client supports " + "new(color) cursor"); + in_uint16_le(s, i); + i = MIN(i, 32); + self->client_info.pointer_cache_entries = i; + } + else + { + g_writeln("xrdp_caps_process_pointer: client does not support " + "new(color) cursor"); + } + if (no_new_cursor) + { + g_writeln("xrdp_caps_process_pointer: new(color) cursor is " + "disabled by config"); + self->client_info.pointer_flags = 0; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_input(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int inputFlags; + int client_does_fastpath_input; + + in_uint16_le(s, inputFlags); + client_does_fastpath_input = (inputFlags & INPUT_FLAG_FASTPATH_INPUT) || + (inputFlags & INPUT_FLAG_FASTPATH_INPUT2); + if ((self->client_info.use_fast_path & 2) && !client_does_fastpath_input) + { + self->client_info.use_fast_path &= ~2; + } + return 0; +} + +/*****************************************************************************/ +/* get the type of client brush cache */ +int APP_CC +xrdp_caps_process_brushcache(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int code; + + if (len < 4) + { + g_writeln("xrdp_caps_process_brushcache: error"); + return 1; + } + in_uint32_le(s, code); + self->client_info.brush_cache_code = code; + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_caps_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int i32; + + if (len < 4 + 2 + 2) + { + g_writeln("xrdp_caps_process_offscreen_bmpcache: error"); + return 1; + } + in_uint32_le(s, i32); + self->client_info.offscreen_support_level = i32; + in_uint16_le(s, i32); + self->client_info.offscreen_cache_size = i32 * 1024; + in_uint16_le(s, i32); + self->client_info.offscreen_cache_entries = i32; + g_writeln("xrdp_process_offscreen_bmpcache: support level %d " + "cache size %d MB cache entries %d", + self->client_info.offscreen_support_level, + self->client_info.offscreen_cache_size, + self->client_info.offscreen_cache_entries); + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_caps_process_rail(struct xrdp_rdp *self, struct stream *s, int len) +{ + int i32; + + if (len < 4) + { + g_writeln("xrdp_caps_process_rail: error"); + return 1; + } + in_uint32_le(s, i32); + self->client_info.rail_support_level = i32; + g_writeln("xrdp_process_capset_rail: rail_support_level %d", + self->client_info.rail_support_level); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_window(struct xrdp_rdp *self, struct stream *s, int len) +{ + int i32; + + if (len < 4 + 1 + 2) + { + g_writeln("xrdp_caps_process_window: error"); + return 1; + } + in_uint32_le(s, i32); + self->client_info.wnd_support_level = i32; + in_uint8(s, i32); + self->client_info.wnd_num_icon_caches = i32; + in_uint16_le(s, i32); + self->client_info.wnd_num_icon_cache_entries = i32; + g_writeln("xrdp_process_capset_window wnd_support_level %d " + "wnd_num_icon_caches %d wnd_num_icon_cache_entries %d", + self->client_info.wnd_support_level, + self->client_info.wnd_num_icon_caches, + self->client_info.wnd_num_icon_cache_entries); + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len) +{ + int codec_id; + int codec_count; + int index; + int codec_properties_length; + int i1; + char *codec_guid; + char *next_guid; + + if (len < 1) + { + g_writeln("xrdp_caps_process_codecs: error"); + return 1; + } + in_uint8(s, codec_count); + len--; + + for (index = 0; index < codec_count; index++) + { + codec_guid = s->p; + if (len < 16 + 1 + 2) + { + g_writeln("xrdp_caps_process_codecs: error"); + return 1; + } + in_uint8s(s, 16); + in_uint8(s, codec_id); + in_uint16_le(s, codec_properties_length); + len -= 16 + 1 + 2; + if (len < codec_properties_length) + { + g_writeln("xrdp_caps_process_codecs: error"); + return 1; + } + len -= codec_properties_length; + next_guid = s->p + codec_properties_length; + + if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0) + { + g_writeln("xrdp_caps_process_codecs: nscodec codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.ns_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.ns_prop, s->p, i1); + self->client_info.ns_prop_len = i1; + } + else if (g_memcmp(codec_guid, XR_CODEC_GUID_REMOTEFX, 16) == 0) + { + g_writeln("xrdp_caps_process_codecs: rfx codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.rfx_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.rfx_prop, s->p, i1); + self->client_info.rfx_prop_len = i1; + } + else if (g_memcmp(codec_guid, XR_CODEC_GUID_JPEG, 16) == 0) + { + g_writeln("xrdp_caps_process_codecs: jpeg codec id %d prop len %d", + codec_id, codec_properties_length); + self->client_info.jpeg_codec_id = codec_id; + i1 = MIN(64, codec_properties_length); + g_memcpy(self->client_info.jpeg_prop, s->p, i1); + self->client_info.jpeg_prop_len = i1; + /* make sure that requested quality is between 0 to 100 */ + if (self->client_info.jpeg_prop[0] < 0 || self->client_info.jpeg_prop[0] > 100) + { + g_writeln(" Warning: the requested jpeg quality (%d) is invalid," + " falling back to default", self->client_info.jpeg_prop[0]); + self->client_info.jpeg_prop[0] = 75; /* use default */ + } + g_writeln(" jpeg quality set to %d", self->client_info.jpeg_prop[0]); + } + else + { + g_writeln("xrdp_caps_process_codecs: unknown codec id %d", codec_id); + } + + s->p = next_guid; + } + + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_caps_process_multifragmetupdate(struct xrdp_rdp *self, struct stream *s, + int len) +{ + int MaxRequestSize; + + in_uint32_le(s, MaxRequestSize); + self->client_info.max_fastpath_frag_bytes = MaxRequestSize; + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s) +{ + int cap_len; + int source_len; + int num_caps; + int index; + int type; + int len; + char *p; + + DEBUG(("in xrdp_caps_process_confirm_active")); + in_uint8s(s, 4); /* rdp_shareid */ + in_uint8s(s, 2); /* userid */ + in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */ + in_uint16_le(s, cap_len); + in_uint8s(s, source_len); + in_uint16_le(s, num_caps); + in_uint8s(s, 2); /* pad */ + + for (index = 0; index < num_caps; index++) + { + p = s->p; + if (!s_check_rem(s, 4)) + { + g_writeln("xrdp_caps_process_confirm_active: error 1"); + return 1; + } + in_uint16_le(s, type); + in_uint16_le(s, len); + if ((len < 4) || !s_check_rem(s, len - 4)) + { + g_writeln("xrdp_caps_process_confirm_active: error len %d", len, s->end - s->p); + return 1; + } + len -= 4; + switch (type) + { + case RDP_CAPSET_GENERAL: /* 1 */ + DEBUG(("RDP_CAPSET_GENERAL")); + xrdp_caps_process_general(self, s, len); + break; + case RDP_CAPSET_BITMAP: /* 2 */ + DEBUG(("RDP_CAPSET_BITMAP")); + break; + case RDP_CAPSET_ORDER: /* 3 */ + DEBUG(("RDP_CAPSET_ORDER")); + xrdp_caps_process_order(self, s, len); + break; + case RDP_CAPSET_BMPCACHE: /* 4 */ + DEBUG(("RDP_CAPSET_BMPCACHE")); + xrdp_caps_process_bmpcache(self, s, len); + break; + case RDP_CAPSET_CONTROL: /* 5 */ + DEBUG(("RDP_CAPSET_CONTROL")); + break; + case 6: + xrdp_caps_process_cache_v3_codec_id(self, s, len); + break; + case RDP_CAPSET_ACTIVATE: /* 7 */ + DEBUG(("RDP_CAPSET_ACTIVATE")); + break; + case RDP_CAPSET_POINTER: /* 8 */ + DEBUG(("RDP_CAPSET_POINTER")); + xrdp_caps_process_pointer(self, s, len); + break; + case RDP_CAPSET_SHARE: /* 9 */ + DEBUG(("RDP_CAPSET_SHARE")); + break; + case RDP_CAPSET_COLCACHE: /* 10 */ + DEBUG(("RDP_CAPSET_COLCACHE")); + break; + case 12: /* 12 */ + DEBUG(("--12")); + break; + case 13: /* 13 */ + xrdp_caps_process_input(self, s, len); + break; + case 14: /* 14 */ + DEBUG(("--14")); + break; + case RDP_CAPSET_BRUSHCACHE: /* 15 */ + xrdp_caps_process_brushcache(self, s, len); + break; + case 16: /* 16 */ + DEBUG(("--16")); + break; + case 17: /* 17 */ + DEBUG(("CAPSET_TYPE_OFFSCREEN_CACHE")); + xrdp_caps_process_offscreen_bmpcache(self, s, len); + break; + case RDP_CAPSET_BMPCACHE2: /* 19 */ + DEBUG(("RDP_CAPSET_BMPCACHE2")); + xrdp_caps_process_bmpcache2(self, s, len); + break; + case 20: /* 20 */ + DEBUG(("--20")); + break; + case 21: /* 21 */ + DEBUG(("--21")); + break; + case 22: /* 22 */ + DEBUG(("--22")); + break; + case 0x0017: /* 23 CAPSETTYPE_RAIL */ + xrdp_caps_process_rail(self, s, len); + break; + case 0x0018: /* 24 CAPSETTYPE_WINDOW */ + xrdp_caps_process_window(self, s, len); + break; + case 0x001A: /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */ + xrdp_caps_process_multifragmetupdate(self, s, len); + break; + case RDP_CAPSET_BMPCODECS: /* 0x1d(29) */ + xrdp_caps_process_codecs(self, s, len); + break; + default: + g_writeln("unknown in xrdp_caps_process_confirm_active %d", type); + break; + } + + s->p = p + len + 4; + } + + DEBUG(("out xrdp_caps_process_confirm_active")); + return 0; +} +/*****************************************************************************/ +int APP_CC +xrdp_caps_send_demand_active(struct xrdp_rdp *self) +{ + struct stream *s; + int caps_count; + int caps_size; + int codec_caps_count; + int codec_caps_size; + int flags; + char *caps_count_ptr; + char *caps_size_ptr; + char *caps_ptr; + char *codec_caps_count_ptr; + char *codec_caps_size_ptr; + + make_stream(s); + init_stream(s, 8192); + + DEBUG(("in xrdp_caps_send_demand_active")); + + if (xrdp_rdp_init(self, s) != 0) + { + free_stream(s); + return 1; + } + + caps_count = 0; + out_uint32_le(s, self->share_id); + out_uint16_le(s, 4); /* 4 chars for RDP\0 */ + /* 2 bytes size after num caps, set later */ + caps_size_ptr = s->p; + out_uint8s(s, 2); + out_uint8a(s, "RDP", 4); + /* 4 byte num caps, set later */ + caps_count_ptr = s->p; + out_uint8s(s, 4); + caps_ptr = s->p; + + /* Output share capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_SHARE); + out_uint16_le(s, RDP_CAPLEN_SHARE); + out_uint16_le(s, self->mcs_channel); + out_uint16_be(s, 0xb5e2); /* 0x73e1 */ + + /* Output general capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_GENERAL); /* 1 */ + out_uint16_le(s, RDP_CAPLEN_GENERAL); /* 24(0x18) */ + 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 */ + /* NO_BITMAP_COMPRESSION_HDR 0x0400 + FASTPATH_OUTPUT_SUPPORTED 0x0001 */ + if (self->client_info.use_fast_path & 1) + { + out_uint16_le(s, 0x401); + } + else + { + out_uint16_le(s, 0x400); + } + 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 */ + + /* Output bitmap capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_BITMAP); /* 2 */ + out_uint16_le(s, RDP_CAPLEN_BITMAP); /* 28(0x1c) */ + out_uint16_le(s, self->client_info.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, self->client_info.width); /* width */ + out_uint16_le(s, self->client_info.height); /* height */ + out_uint16_le(s, 0); /* Pad */ + out_uint16_le(s, 1); /* Allow resize */ + out_uint16_le(s, 1); /* bitmap compression */ + out_uint16_le(s, 0); /* unknown */ + out_uint16_le(s, 0); /* unknown */ + out_uint16_le(s, 0); /* pad */ + + /* Output font capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_FONT); /* 14 */ + out_uint16_le(s, RDP_CAPLEN_FONT); /* 4 */ + + /* Output order capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_ORDER); /* 3 */ + out_uint16_le(s, RDP_CAPLEN_ORDER); /* 88(0x58) */ + out_uint8s(s, 16); + out_uint32_be(s, 0x40420f00); + 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, 0x2f); /* Number of fonts */ + out_uint16_le(s, 0x22); /* Capability flags */ + /* caps */ + out_uint8(s, 1); /* NEG_DSTBLT_INDEX 0x00 0 */ + out_uint8(s, 1); /* NEG_PATBLT_INDEX 0x01 1 */ + out_uint8(s, 1); /* NEG_SCRBLT_INDEX 0x02 2 */ + out_uint8(s, 1); /* NEG_MEMBLT_INDEX 0x03 3 */ + out_uint8(s, 0); /* NEG_MEM3BLT_INDEX 0x04 4 */ + out_uint8(s, 0); /* NEG_ATEXTOUT_INDEX 0x05 5 */ + out_uint8(s, 0); /* NEG_AEXTTEXTOUT_INDEX 0x06 6 */ + out_uint8(s, 0); /* NEG_DRAWNINEGRID_INDEX 0x07 7 */ + out_uint8(s, 1); /* NEG_LINETO_INDEX 0x08 8 */ + out_uint8(s, 0); /* NEG_MULTI_DRAWNINEGRID_INDEX 0x09 9 */ + out_uint8(s, 1); /* NEG_OPAQUE_RECT_INDEX 0x0A 10 */ + out_uint8(s, 0); /* NEG_SAVEBITMAP_INDEX 0x0B 11 */ + out_uint8(s, 0); /* NEG_WTEXTOUT_INDEX 0x0C 12 */ + out_uint8(s, 0); /* NEG_MEMBLT_V2_INDEX 0x0D 13 */ + out_uint8(s, 0); /* NEG_MEM3BLT_V2_INDEX 0x0E 14 */ + out_uint8(s, 0); /* NEG_MULTIDSTBLT_INDEX 0x0F 15 */ + out_uint8(s, 0); /* NEG_MULTIPATBLT_INDEX 0x10 16 */ + out_uint8(s, 0); /* NEG_MULTISCRBLT_INDEX 0x11 17 */ + out_uint8(s, 1); /* NEG_MULTIOPAQUERECT_INDEX 0x12 18 */ + out_uint8(s, 0); /* NEG_FAST_INDEX_INDEX 0x13 19 */ + out_uint8(s, 0); /* NEG_POLYGON_SC_INDEX 0x14 20 */ + out_uint8(s, 0); /* NEG_POLYGON_CB_INDEX 0x15 21 */ + out_uint8(s, 0); /* NEG_POLYLINE_INDEX 0x16 22 */ + out_uint8(s, 0); /* unused 0x17 23 */ + out_uint8(s, 0); /* NEG_FAST_GLYPH_INDEX 0x18 24 */ + out_uint8(s, 0); /* NEG_ELLIPSE_SC_INDEX 0x19 25 */ + out_uint8(s, 0); /* NEG_ELLIPSE_CB_INDEX 0x1A 26 */ + out_uint8(s, 1); /* NEG_GLYPH_INDEX_INDEX 0x1B 27 */ + out_uint8(s, 0); /* NEG_GLYPH_WEXTTEXTOUT_INDEX 0x1C 28 */ + out_uint8(s, 0); /* NEG_GLYPH_WLONGTEXTOUT_INDEX 0x1D 29 */ + out_uint8(s, 0); /* NEG_GLYPH_WLONGEXTTEXTOUT_INDEX 0x1E 30 */ + out_uint8(s, 0); /* unused 0x1F 31 */ + out_uint16_le(s, 0x6a1); + /* declare support of bitmap cache rev3 */ + out_uint16_le(s, XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT); + out_uint32_le(s, 0x0f4240); /* desk save */ + out_uint32_le(s, 0x0f4240); /* desk save */ + out_uint32_le(s, 1); /* ? */ + out_uint32_le(s, 0); /* ? */ + + /* Output bmpcodecs capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_BMPCODECS); + codec_caps_size_ptr = s->p; + out_uint8s(s, 2); /* cap len set later */ + codec_caps_count = 0; + codec_caps_count_ptr = s->p; + out_uint8s(s, 1); /* bitmapCodecCount set later */ + /* nscodec */ + codec_caps_count++; + out_uint8a(s, XR_CODEC_GUID_NSCODEC, 16); + out_uint8(s, 1); /* codec id, must be 1 */ + out_uint16_le(s, 3); + out_uint8(s, 0x01); /* fAllowDynamicFidelity */ + out_uint8(s, 0x01); /* fAllowSubsampling */ + out_uint8(s, 0x03); /* colorLossLevel */ + /* remotefx */ + codec_caps_count++; + out_uint8a(s, XR_CODEC_GUID_REMOTEFX, 16); + out_uint8(s, 0); /* codec id, client sets */ + out_uint16_le(s, 256); + out_uint8s(s, 256); + /* jpeg */ + codec_caps_count++; + out_uint8a(s, XR_CODEC_GUID_JPEG, 16); + out_uint8(s, 0); /* codec id, client sets */ + out_uint16_le(s, 1); /* ext length */ + out_uint8(s, 75); + /* calculate and set size and count */ + codec_caps_size = (int)(s->p - codec_caps_size_ptr); + codec_caps_size += 2; /* 2 bytes for RDP_CAPSET_BMPCODECS above */ + codec_caps_size_ptr[0] = codec_caps_size; + codec_caps_size_ptr[1] = codec_caps_size >> 8; + codec_caps_count_ptr[0] = codec_caps_count; + + /* Output color cache capability set */ + caps_count++; + 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 */ + + /* Output pointer capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_POINTER); + out_uint16_le(s, RDP_CAPLEN_POINTER); + out_uint16_le(s, 1); /* Colour pointer */ + out_uint16_le(s, 0x19); /* Cache size */ + out_uint16_le(s, 0x19); /* Cache size */ + + /* Output input capability set */ + caps_count++; + out_uint16_le(s, RDP_CAPSET_INPUT); /* 13(0xd) */ + out_uint16_le(s, RDP_CAPLEN_INPUT); /* 88(0x58) */ + + /* INPUT_FLAG_SCANCODES 0x0001 + INPUT_FLAG_MOUSEX 0x0004 + INPUT_FLAG_FASTPATH_INPUT 0x0008 + INPUT_FLAG_FASTPATH_INPUT2 0x0020 */ + flags = 0x0001 | 0x0004; + if (self->client_info.use_fast_path & 2) + { + /* 0x0008 INPUT_FLAG_FASTPATH_INPUT */ + /* 0x0020 INPUT_FLAG_FASTPATH_INPUT2 */ + flags |= 0x0008 | 0x0020; + } + out_uint16_le(s, flags); + out_uint8s(s, 82); + + /* Remote Programs Capability Set */ + caps_count++; + out_uint16_le(s, 0x0017); /* CAPSETTYPE_RAIL */ + out_uint16_le(s, 8); + out_uint32_le(s, 3); /* TS_RAIL_LEVEL_SUPPORTED + TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */ + + /* Window List Capability Set */ + caps_count++; + out_uint16_le(s, 0x0018); /* CAPSETTYPE_WINDOW */ + out_uint16_le(s, 11); + out_uint32_le(s, 2); /* TS_WINDOW_LEVEL_SUPPORTED_EX */ + out_uint8(s, 3); /* NumIconCaches */ + out_uint16_le(s, 12); /* NumIconCacheEntries */ + + /* 6 - bitmap cache v3 codecid */ + caps_count++; + out_uint16_le(s, 0x0006); + out_uint16_le(s, 5); + out_uint8(s, 0); /* client sets */ + + if (self->client_info.use_fast_path & 1) /* fastpath output on */ + { + caps_count++; + out_uint16_le(s, 0x001A); /* 26 CAPSETTYPE_MULTIFRAGMENTUPDATE */ + out_uint16_le(s, 8); + out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */ + } + + out_uint8s(s, 4); /* pad */ + + s_mark_end(s); + + caps_size = (int)(s->end - caps_ptr); + caps_size_ptr[0] = caps_size; + caps_size_ptr[1] = caps_size >> 8; + + caps_count_ptr[0] = caps_count; + caps_count_ptr[1] = caps_count >> 8; + caps_count_ptr[2] = caps_count >> 16; + caps_count_ptr[3] = caps_count >> 24; + + if (xrdp_rdp_send(self, s, RDP_PDU_DEMAND_ACTIVE) != 0) + { + free_stream(s); + return 1; + } + DEBUG(("out (1) xrdp_caps_send_demand_active")); + + /* send Monitor Layout PDU for dual monitor */ + if (self->client_info.monitorCount > 0 && + self->client_info.multimon == 1) + { + DEBUG(("xrdp_caps_send_demand_active: sending monitor layout pdu")); + if (xrdp_caps_send_monitorlayout(self) != 0) + { + g_writeln("xrdp_caps_send_demand_active: error sending monitor layout pdu"); + } + } + + free_stream(s); + return 0; +} diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c index 198b876b..7d3909d5 100644 --- a/libxrdp/xrdp_channel.c +++ b/libxrdp/xrdp_channel.c @@ -105,10 +105,21 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id, s_pop_layer(s, channel_hdr); out_uint32_le(s, total_data_len); - if (channel->flags & XR_CHANNEL_OPTION_SHOW_PROTOCOL) - { - flags |= CHANNEL_FLAG_SHOW_PROTOCOL; - } + /* + * According to 2.2.1.3.4.1 Channel Definition Structure (CHANNEL_DEF): + * CHANNEL_OPTION_SHOW_PROTOCOL 0x00200000 + * The value of this flag MUST be ignored by the server. The + * visibility of the Channel PDU Header (section 2.2.6.1.1) is + * determined by the CHANNEL_FLAG_SHOW_PROTOCOL + * (0x00000010) flag as defined in the flags field (section + * 2.2.6.1.1). + * + * That's flag makes MSTSC crash when using RAIL channel. + */ +// if (channel->flags & XR_CHANNEL_OPTION_SHOW_PROTOCOL) +// { +// flags |= CHANNEL_FLAG_SHOW_PROTOCOL; +// } out_uint32_le(s, flags); diff --git a/libxrdp/xrdp_fastpath.c b/libxrdp/xrdp_fastpath.c index 10f844e5..f84f5ae1 100644 --- a/libxrdp/xrdp_fastpath.c +++ b/libxrdp/xrdp_fastpath.c @@ -1,8 +1,8 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2012-2013 - * Copyright (C) Kevin Zhou 2012 + * Copyright (C) Jay Sorg 2012-2014 + * Copyright (C) Idan Freiberg 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,16 +21,16 @@ /*****************************************************************************/ struct xrdp_fastpath *APP_CC -xrdp_fastpath_create(struct xrdp_session *session) +xrdp_fastpath_create(struct xrdp_sec *owner, struct trans *trans) { struct xrdp_fastpath *self; + DEBUG((" in xrdp_fastpath_create")); self = (struct xrdp_fastpath *)g_malloc(sizeof(struct xrdp_fastpath), 1); - self->tcp_layer = - ((struct xrdp_rdp *)session->rdp)->sec_layer-> - mcs_layer->iso_layer->tcp_layer; - make_stream(self->out_s); - init_stream(self->out_s, FASTPATH_MAX_PACKET_SIZE); + self->sec_layer = owner; + self->trans = trans; + self->session = owner->rdp_layer->session; + DEBUG((" out xrdp_fastpath_create")); return self; } @@ -42,8 +42,6 @@ xrdp_fastpath_delete(struct xrdp_fastpath *self) { return; } - - free_stream(self->out_s); g_free(self); } @@ -55,155 +53,306 @@ xrdp_fastpath_reset(struct xrdp_fastpath *self) return 0; } +/*****************************************************************************/ int APP_CC -xrdp_fastpath_init(struct xrdp_fastpath *self) +xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s) { + int fp_hdr; + int len = 0; /* unused */ + int byte; + char *holdp; + + DEBUG((" in xrdp_fastpath_recv")); + holdp = s->p; + if (!s_check_rem(s, 2)) + { + return 1; + } + in_uint8(s, fp_hdr); /* fpInputHeader (1 byte) */ + in_uint8(s, byte); /* length 1 (1 byte) */ + + self->numEvents = (fp_hdr & 0x3C) >> 2; + self->secFlags = (fp_hdr & 0xC0) >> 6; + + if (byte & 0x80) + { + byte &= ~(0x80); + len = (byte << 8); + + if (!s_check_rem(s, 1)) + { + return 1; + } + in_uint8(s, byte); /* length 2 (1 byte) */ + + len += byte; + } + else + { + len = byte; + } + s->next_packet = holdp + len; + DEBUG((" out xrdp_fastpath_recv")); return 0; } /*****************************************************************************/ +/* no fragmenation */ int APP_CC -xrdp_fastpath_send_update_pdu(struct xrdp_fastpath *self, tui8 updateCode, - struct stream *s) +xrdp_fastpath_init(struct xrdp_fastpath *self, struct stream *s) { - tui16 len; - tui16 maxLen; - tui32 payloadLeft; - tui8 fragment; - struct stream *s_send; - int compression; - int i; - int i32; + int bytes; - compression = 0; - s_send = self->out_s; - maxLen = FASTPATH_MAX_PACKET_SIZE - 6; /* 6 bytes for header */ - payloadLeft = (s->end - s->data); + bytes = self->session->client_info->max_fastpath_frag_bytes; + if (bytes < 32 * 1024) + { + bytes = 32 * 1024; + } + init_stream(s, bytes); + return 0; +} - for (i = 0; payloadLeft > 0; i++) +/*****************************************************************************/ +/* no fragmenation */ +int APP_CC +xrdp_fastpath_send(struct xrdp_fastpath *self, struct stream *s) +{ + if (trans_force_write_s(self->trans, s) != 0) { - if (payloadLeft > maxLen) - { - len = maxLen; - } - else - { - len = payloadLeft; - } + return 1; + } + return 0; +} - payloadLeft -= len; +/*****************************************************************************/ +/* FASTPATH_INPUT_EVENT_SCANCODE */ +int APP_CC +xrdp_fastpath_process_EVENT_SCANCODE(struct xrdp_fastpath *self, + int eventFlags, struct stream *s) +{ + int flags; + int code; + flags = 0; - if (payloadLeft == 0) - { - fragment = i ? FASTPATH_FRAGMENT_LAST : FASTPATH_FRAGMENT_SINGLE; - } - else - { - fragment = i ? FASTPATH_FRAGMENT_NEXT : FASTPATH_FRAGMENT_FIRST; - } + if (!s_check_rem(s, 1)) + { + return 1; + } + in_uint8(s, code); /* keyCode (1 byte) */ - init_stream(s_send, 0); - out_uint8(s_send, 0); /* fOutputHeader */ - i32 = ((len + 6) >> 8) | 0x80; - out_uint8(s_send, i32); /* use 2 bytes for length even length < 128 ??? */ - i32 = (len + 6) & 0xff; - out_uint8(s_send, i32); - i32 = (updateCode & 0x0f) | ((fragment & 0x03) << 4) | - ((compression & 0x03) << 6); - out_uint8(s_send, i32); - out_uint16_le(s_send, len); - s_copy(s_send, s, len); - s_mark_end(s_send); - - if (xrdp_tcp_send(self->tcp_layer, s_send) != 0) - { - return 1; - } + if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE)) + { + flags |= KBD_FLAG_UP; + } + else + { + flags |= KBD_FLAG_DOWN; } + if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_EXTENDED)) + flags |= KBD_FLAG_EXT; + + if (self->session->callback != 0) + { + /* msg_type can be + RDP_INPUT_SYNCHRONIZE - 0 + RDP_INPUT_SCANCODE - 4 + RDP_INPUT_MOUSE - 0x8001 + RDP_INPUT_MOUSEX - 0x8002 */ + /* call to xrdp_wm.c : callback */ + self->session->callback(self->session->id, RDP_INPUT_SCANCODE, code, 0, + flags, 0); + } return 0; } /*****************************************************************************/ -int -xrdp_fastpath_process_update(struct xrdp_fastpath *self, tui8 updateCode, - tui32 size, struct stream *s) +/* FASTPATH_INPUT_EVENT_MOUSE */ +int APP_CC +xrdp_fastpath_process_EVENT_MOUSE(struct xrdp_fastpath *self, int eventFlags, + struct stream *s) { - switch (updateCode) - { - case FASTPATH_UPDATETYPE_ORDERS: - case FASTPATH_UPDATETYPE_BITMAP: - case FASTPATH_UPDATETYPE_PALETTE: - case FASTPATH_UPDATETYPE_SYNCHRONIZE: - case FASTPATH_UPDATETYPE_SURFCMDS: - case FASTPATH_UPDATETYPE_PTR_NULL: - case FASTPATH_UPDATETYPE_PTR_DEFAULT: - case FASTPATH_UPDATETYPE_PTR_POSITION: - case FASTPATH_UPDATETYPE_COLOR: - case FASTPATH_UPDATETYPE_CACHED: - case FASTPATH_UPDATETYPE_POINTER: - break; - default: - g_writeln("xrdp_fastpath_process_update: unknown updateCode 0x%X", - updateCode); - break; + int pointerFlags; + int xPos; + int yPos; + + /* eventFlags MUST be zeroed out */ + if (eventFlags != 0) + { + return 1; + } + + if (!s_check_rem(s, 2 + 2 + 2)) + { + return 1; } + in_uint16_le(s, pointerFlags); /* pointerFlags (2 bytes) */ + in_uint16_le(s, xPos); /* xPos (2 bytes) */ + in_uint16_le(s, yPos); /* yPos (2 bytes) */ + if (self->session->callback != 0) + { + /* msg_type can be + RDP_INPUT_SYNCHRONIZE - 0 + RDP_INPUT_SCANCODE - 4 + RDP_INPUT_MOUSE - 0x8001 + RDP_INPUT_MOUSEX - 0x8002 */ + /* call to xrdp_wm.c : callback */ + self->session->callback(self->session->id, RDP_INPUT_MOUSE, + xPos, yPos, pointerFlags, 0); + } return 0; } /*****************************************************************************/ +/* FASTPATH_INPUT_EVENT_MOUSEX */ int APP_CC -xrdp_fastpath_process_data(struct xrdp_fastpath *self, struct stream *s, - tui8 header) +xrdp_fastpath_process_EVENT_MOUSEX(struct xrdp_fastpath *self, + int eventFlags, struct stream *s) { - tui8 encryptionFlags; - tui8 numberEvents; - tui8 length2; - tui8 updateHeader; - tui8 updateCode; - tui8 updateFrag; - tui8 updateComp; - tui16 length; - tui32 size; - - encryptionFlags = (header & 0xc0) >> 6; - numberEvents = (header & 0x3c) >> 2; - xrdp_tcp_recv(self->tcp_layer, s, 1); - in_uint8(s, length); - - if (length & 0x80) - { - xrdp_tcp_recv(self->tcp_layer, s, 1); - in_uint8(s, length2); - length = (length & 0x7f) << 8 + length2 - 3; + int pointerFlags; + int xPos; + int yPos; + + /* eventFlags MUST be zeroed out */ + if (eventFlags != 0) + { + return 1; } - else + + if (!s_check_rem(s, 2 + 2 + 2)) { - length -= 2; + return 1; } + in_uint16_le(s, pointerFlags); /* pointerFlags (2 bytes) */ + in_uint16_le(s, xPos); /* xPos (2 bytes) */ + in_uint16_le(s, yPos); /* yPos (2 bytes) */ - xrdp_tcp_recv(self->tcp_layer, s, length); + if (self->session->callback != 0) + { + /* msg_type can be + RDP_INPUT_SYNCHRONIZE - 0 + RDP_INPUT_SCANCODE - 4 + RDP_INPUT_MOUSE - 0x8001 + RDP_INPUT_MOUSEX - 0x8002 */ + /* call to xrdp_wm.c : callback */ + self->session->callback(self->session->id, RDP_INPUT_MOUSEX, + xPos, yPos, pointerFlags, 0); + } + return 0; +} - if (encryptionFlags != 0) +/*****************************************************************************/ +/* FASTPATH_INPUT_EVENT_SYNC */ +int APP_CC +xrdp_fastpath_process_EVENT_SYNC(struct xrdp_fastpath *self, int eventCode, + int eventFlags, struct stream *s) +{ + /* + * The eventCode bitfield (3 bits in size) MUST be set to + * FASTPATH_INPUT_EVENT_SYNC (3). + * The eventFlags bitfield (5 bits in size) contains flags + * indicating the "on" + * status of the keyboard toggle keys. + */ + if (self->session->callback != 0) { - /* TODO decryption ...*/ + /* msg_type can be + RDP_INPUT_SYNCHRONIZE - 0 + RDP_INPUT_SCANCODE - 4 + RDP_INPUT_MOUSE - 0x8001 + RDP_INPUT_MOUSEX - 0x8002 */ + /* call to xrdp_wm.c : callback */ + self->session->callback(self->session->id, RDP_INPUT_SYNCHRONIZE, + eventCode, 0, eventFlags, 0); } + return 0; +} + +/*****************************************************************************/ +/* FASTPATH_INPUT_EVENT_UNICODE */ +int APP_CC +xrdp_fastpath_process_EVENT_UNICODE(struct xrdp_fastpath *self, + int eventFlags, struct stream *s) +{ + if (!s_check_rem(s, 2)) + { + return 1; + } + in_uint8s(s, 2); + return 0; +} - /* parse updateHeader */ - in_uint8(s, updateHeader); - updateCode = (updateHeader & 0x0f); - updateFrag = (updateHeader & 0x30) >> 4; - updateComp = (updateHeader & 0xc0) >> 6; +/*****************************************************************************/ +/* FASTPATH_INPUT_EVENT */ +int APP_CC +xrdp_fastpath_process_input_event(struct xrdp_fastpath *self, struct stream *s) +{ + int i; + int eventHeader; + int eventCode; + int eventFlags; - if (updateFrag && updateComp) + /* process fastpath input events */ + for (i = 0; i < self->numEvents; i++) { - /* TODO */ - g_writeln("xrdp_fastpath_process_data: updateFrag=%d, updateComp=%d", - updateFrag, updateComp); - return 1; - } + if (!s_check_rem(s, 1)) + { + return 1; + } + in_uint8(s, eventHeader); + + eventFlags = (eventHeader & 0x1F); + eventCode = (eventHeader >> 5); + + switch (eventCode) + { + case FASTPATH_INPUT_EVENT_SCANCODE: + if (xrdp_fastpath_process_EVENT_SCANCODE(self, + eventFlags, + s) != 0) + { + return 1; + } + break; - in_uint16_le(s, size); - return xrdp_fastpath_process_update(self, updateCode, size, s); + case FASTPATH_INPUT_EVENT_MOUSE: + if (xrdp_fastpath_process_EVENT_MOUSE(self, + eventFlags, + s) != 0) + { + return 1; + } + break; + case FASTPATH_INPUT_EVENT_MOUSEX: + if (xrdp_fastpath_process_EVENT_MOUSEX(self, + eventFlags, + s) != 0) + { + return 1; + } + break; + case FASTPATH_INPUT_EVENT_SYNC: + if (xrdp_fastpath_process_EVENT_SYNC(self, eventCode, + eventFlags, + s) != 0) + { + return 1; + } + break; + case FASTPATH_INPUT_EVENT_UNICODE: + if (xrdp_fastpath_process_EVENT_UNICODE(self, + eventFlags, + s) != 0) + { + return 1; + } + break; + default: + g_writeln("xrdp_fastpath_process_input_event: unknown " + "eventCode %d", eventCode); + break; + } + } + return 0; } diff --git a/libxrdp/xrdp_iso.c b/libxrdp/xrdp_iso.c index 31c279b5..ee490839 100644 --- a/libxrdp/xrdp_iso.c +++ b/libxrdp/xrdp_iso.c @@ -1,8 +1,8 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 - * Copyright (C) Idan Freiberg 2013 + * Copyright (C) Jay Sorg 2004-2014 + * Copyright (C) Idan Freiberg 2013-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,13 +22,14 @@ #include "libxrdp.h" /*****************************************************************************/ -struct xrdp_iso *APP_CC +struct xrdp_iso * +APP_CC xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans) { struct xrdp_iso *self; DEBUG((" in xrdp_iso_create")); - self = (struct xrdp_iso *)g_malloc(sizeof(struct xrdp_iso), 1); + self = (struct xrdp_iso *) g_malloc(sizeof(struct xrdp_iso), 1); self->mcs_layer = owner; self->trans = trans; DEBUG((" out xrdp_iso_create")); @@ -50,37 +51,33 @@ xrdp_iso_delete(struct xrdp_iso *self) /*****************************************************************************/ /* returns error */ static int APP_CC -xrdp_iso_recv_rdpnegreq(struct xrdp_iso *self, struct stream *s) +xrdp_iso_process_rdpNegReq(struct xrdp_iso *self, struct stream *s) { int flags; int len; - DEBUG((" in xrdp_iso_recv_rdpnegreq")); - in_uint8(s, flags); - if (flags != 0x0) + if (flags != 0x0 && flags != 0x8 && flags != 0x1) { - DEBUG((" xrdp_iso_recv_rdpnegreq: flags: %x",flags)); + DEBUG(("xrdp_iso_process_rdpNegReq: error, flags: %x",flags)); return 1; } in_uint16_le(s, len); - if (len != 8) // fixed length + if (len != 8) { - DEBUG((" xrdp_iso_recv_rdpnegreq: length: %x",len)); + DEBUG(("xrdp_iso_process_rdpNegReq: error, length: %x",len)); return 1; } in_uint32_le(s, self->requestedProtocol); + if (self->requestedProtocol > 0xb) + { + DEBUG(("xrdp_iso_process_rdpNegReq: error, requestedProtocol: %x", + self->requestedProtocol)); + return 1; + } - //TODO: think of protocol verification logic -// if (requestedProtocol != PROTOCOL_RDP || PROTOCOL_SSL || PROTOCOL_HYBRID || PROTOCOL_HYBRID_EX) -// { -// DEBUG((" xrdp_iso_recv_rdpnegreq: wrong requestedProtocol: %x",requestedProtocol)); -// return 1; -// } - - DEBUG((" out xrdp_iso_recv_rdpnegreq")); return 0; } /*****************************************************************************/ @@ -88,29 +85,23 @@ xrdp_iso_recv_rdpnegreq(struct xrdp_iso *self, struct stream *s) static int APP_CC xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len) { - int ver; // TPKT Version - int plen; // TPKT PacketLength - int do_read; - - *code = 0; // X.224 Packet Type - *len = 0; // X.224 Length Indicator + int ver; // tpkt ver + int plen; // tpkt len - /* early in connection sequence, iso needs to do a force read */ - do_read = s != self->trans->in_s; + *code = 0; // x.244 type + *len = 0; // X.224 len indicator - if (do_read) + if (s != self->trans->in_s) { - init_stream(s, 4); - if (trans_force_read_s(self->trans, s, 4) != 0) - { - return 1; - } + g_writeln("xrdp_iso_recv_msg error logic"); } in_uint8(s, ver); if (ver != 3) { + g_writeln("xrdp_iso_recv_msg: bad ver"); + g_hexdump(s->data, 4); return 1; } @@ -122,15 +113,6 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len) return 1; } - if (do_read) - { - init_stream(s, plen - 4); - if (trans_force_read_s(self->trans, s, plen - 4) != 0) - { - return 1; - } - } - if (!s_check_rem(s, 2)) { return 1; @@ -184,120 +166,70 @@ xrdp_iso_recv(struct xrdp_iso *self, struct stream *s) DEBUG((" out xrdp_iso_recv")); return 0; } - /*****************************************************************************/ static int APP_CC -xrdp_iso_send_rdpnegrsp(struct xrdp_iso *self, struct stream *s, int code) +xrdp_iso_send_cc(struct xrdp_iso *self) { - init_stream(s, 8192 * 4); /* 32 KB */ + struct stream *s; + char *holdp; + char *len_ptr; + char *len_indicator_ptr; + int len; + int len_indicator; - /* TPKT HEADER - 4 bytes */ - out_uint8(s, 3); /* version */ - out_uint8(s, 0); /* RESERVED */ - if (self->selectedProtocol != -1) - { - out_uint16_be(s, 19); /* length */ //rdp negotiation happens. - } - else - { - out_uint16_be(s, 11); /* length */ //rdp negotiation doesn't happen. - } - /* ISO LAYER - X.224 - 7 bytes*/ - if (self->selectedProtocol != -1) - { - out_uint8(s, 14); /* length */ - } - else - { - out_uint8(s, 6); /* length */ - } - out_uint8(s, code); /* SHOULD BE 0xD for CC */ + make_stream(s); + init_stream(s, 8192); + + holdp = s->p; + /* tpkt */ + out_uint8(s, 3); /* version */ + out_uint8(s, 0); /* pad */ + len_ptr = s->p; + out_uint16_be(s, 0); /* length, set later */ + /* iso */ + len_indicator_ptr = s->p; + out_uint8(s, 0); /* length indicator, set later */ + out_uint8(s, ISO_PDU_CC); /* Connection Confirm PDU */ out_uint16_be(s, 0); out_uint16_be(s, 0x1234); out_uint8(s, 0); - if (self->selectedProtocol != -1) + /* rdpNegData */ + if (self->rdpNegData) { - /* RDP_NEG_RSP - 8 bytes*/ - out_uint8(s, RDP_NEG_RSP); - out_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ - out_uint16_le(s, 8); /* fixed length */ - out_uint32_le(s, self->selectedProtocol); /* selected protocol */ + if (self->failureCode) + { + out_uint8(s, RDP_NEG_FAILURE); + out_uint8(s, 0); /* no flags */ + out_uint16_le(s, 8); /* must be 8 */ + out_uint32_le(s, self->failureCode); /* failure code */ + } + else + { + out_uint8(s, RDP_NEG_RSP); + //TODO: hardcoded flags + out_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */ + out_uint16_le(s, 8); /* must be 8 */ + out_uint32_le(s, self->selectedProtocol); /* selected protocol */ + } } s_mark_end(s); - if (trans_force_write_s(self->trans, s) != 0) - { - return 1; - } - - return 0; -} -/*****************************************************************************/ -static int APP_CC -xrdp_iso_send_rdpnegfailure(struct xrdp_iso *self, struct stream *s, int code, int failureCode) -{ - init_stream(s, 8192 * 4); /* 32 KB */ - - /* TPKT HEADER - 4 bytes */ - out_uint8(s, 3); /* version */ - out_uint8(s, 0); /* RESERVED */ - out_uint16_be(s, 19); /* length */ - /* ISO LAYER - X.224 - 7 bytes*/ - out_uint8(s, 14); /* length */ - out_uint8(s, code); /* SHOULD BE 0xD for CC */ - out_uint16_be(s, 0); - out_uint16_be(s, 0x1234); - out_uint8(s, 0); - /* RDP_NEG_FAILURE - 8 bytes*/ - out_uint8(s, RDP_NEG_FAILURE); - out_uint8(s, 0); /* no flags available */ - out_uint16_le(s, 8); /* fixed length */ - out_uint32_le(s, failureCode); /* failure code */ - s_mark_end(s); + len = (int) (s->end - holdp); + len_indicator = (int) (s->end - len_indicator_ptr) - 1; + len_ptr[0] = len >> 8; + len_ptr[1] = len; + len_indicator_ptr[0] = len_indicator; if (trans_force_write_s(self->trans, s) != 0) { + free_stream(s); return 1; } - return 0; -} - -/*****************************************************************************/ -static int APP_CC -xrdp_iso_send_nego(struct xrdp_iso *self) -{ - struct stream *s; - - make_stream(s); - init_stream(s, 8192); - - //TODO: negotiation logic here. - if (self->requestedProtocol != PROTOCOL_RDP) - { - // Send RDP_NEG_FAILURE back to client - if (xrdp_iso_send_rdpnegfailure(self, s, ISO_PDU_CC, - SSL_NOT_ALLOWED_BY_SERVER) != 0) - { - free_stream(s); - return 1; - } - } - else - { - self->selectedProtocol = PROTOCOL_RDP; - // Send RDP_NEG_RSP back to client - if (xrdp_iso_send_rdpnegrsp(self, s, ISO_PDU_CC) != 0) - { - free_stream(s); - return 1; - } - } free_stream(s); return 0; } - /*****************************************************************************/ /* returns error */ int APP_CC @@ -311,26 +243,26 @@ xrdp_iso_incoming(struct xrdp_iso *self) char *pend; struct stream *s; - make_stream(s); - init_stream(s, 8192); DEBUG((" in xrdp_iso_incoming")); + s = libxrdp_force_read(self->trans); + if (s == 0) + { + return 1; + } + if (xrdp_iso_recv_msg(self, s, &code, &len) != 0) { - DEBUG((" in xrdp_iso_recv_msg error!!")); - free_stream(s); + g_writeln("xrdp_iso_incoming: xrdp_iso_recv_msg returned non zero"); return 1; } if ((code != ISO_PDU_CR) || (len < 6)) { - free_stream(s); return 1; } - self->selectedProtocol = -1; - self->requestedProtocol = PROTOCOL_RDP; - + /* process connection request */ pend = s->p + (len - 6); cookie_index = 0; while (s->p < pend) @@ -341,9 +273,10 @@ xrdp_iso_incoming(struct xrdp_iso *self) default: break; case RDP_NEG_REQ: /* rdpNegReq 1 */ - if (xrdp_iso_recv_rdpnegreq(self, s) != 0) + self->rdpNegData = 1; + if (xrdp_iso_process_rdpNegReq(self, s) != 0) { - free_stream(s); + g_writeln("xrdp_iso_incoming: xrdp_iso_process_rdpNegReq returned non zero"); return 1; } break; @@ -369,14 +302,87 @@ xrdp_iso_incoming(struct xrdp_iso *self) } } - if (xrdp_iso_send_nego(self) != 0) + int serverSecurityLayer = self->mcs_layer->sec_layer->rdp_layer->client_info.security_layer; + /* security layer negotiation */ + if (self->rdpNegData) { - free_stream(s); + self->selectedProtocol = PROTOCOL_RDP; /* set default security layer */ + + switch (serverSecurityLayer) + { + case (PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_HYBRID_EX): + /* server supports tls+hybrid+hybrid_ex */ + if (self->requestedProtocol == (PROTOCOL_SSL | PROTOCOL_HYBRID + | PROTOCOL_HYBRID_EX)) + { + /* client supports tls+hybrid+hybrid_ex */ + self->selectedProtocol = PROTOCOL_SSL; //TODO: change + } + else + { + self->failureCode = SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER; + } + break; + case (PROTOCOL_SSL | PROTOCOL_HYBRID): + /* server supports tls+hybrid */ + if (self->requestedProtocol == (PROTOCOL_SSL | PROTOCOL_HYBRID)) + { + /* client supports tls+hybrid */ + self->selectedProtocol = PROTOCOL_SSL; //TODO: change + } + else + { + self->failureCode = HYBRID_REQUIRED_BY_SERVER; + } + break; + case PROTOCOL_SSL: + /* server supports tls */ + if (self->requestedProtocol & PROTOCOL_SSL) //TODO + { + /* client supports tls */ + self->selectedProtocol = PROTOCOL_SSL; + } + else + { + self->failureCode = SSL_REQUIRED_BY_SERVER; + } + break; + case PROTOCOL_RDP: + /* server supports rdp */ + if (self->requestedProtocol == PROTOCOL_RDP) + { + /* client supports rdp */ + self->selectedProtocol = PROTOCOL_RDP; + } + else + { + self->failureCode = SSL_NOT_ALLOWED_BY_SERVER; + } + break; + default: + /* unsupported protocol */ + g_writeln("xrdp_iso_incoming: unsupported protocol %d", + self->requestedProtocol); + self->failureCode = INCONSISTENT_FLAGS; //TODO: ? + } + } + else if (self->requestedProtocol != serverSecurityLayer) + { + /* enforce server security */ + return 1; + } + + /* set things for tls connection */ + + + /* send connection confirm back to client */ + if (xrdp_iso_send_cc(self) != 0) + { + g_writeln("xrdp_iso_incoming: xrdp_iso_send_cc returned non zero"); return 1; } DEBUG((" out xrdp_iso_incoming")); - free_stream(s); return 0; } @@ -399,7 +405,7 @@ xrdp_iso_send(struct xrdp_iso *self, struct stream *s) DEBUG((" in xrdp_iso_send")); s_pop_layer(s, iso_hdr); - len = (int)(s->end - s->p); + len = (int) (s->end - s->p); out_uint8(s, 3); out_uint8(s, 0); out_uint16_be(s, len); diff --git a/libxrdp/xrdp_jpeg_compress.c b/libxrdp/xrdp_jpeg_compress.c index 334cc2e3..e4ce64fe 100644 --- a/libxrdp/xrdp_jpeg_compress.c +++ b/libxrdp/xrdp_jpeg_compress.c @@ -120,10 +120,11 @@ xrdp_codec_jpeg_compress(void *handle, /* len of compressed data */ ) { - tjhandle tj_han; - int error; - int bpp; - char *src_ptr; + tjhandle tj_han; + int error; + int bpp; + char *src_ptr; + unsigned long lio_len; /* * note: for now we assume that format is always XBGR and ignore format @@ -143,7 +144,21 @@ xrdp_codec_jpeg_compress(void *handle, /* start of inner rect in inp_data */ src_ptr = inp_data + (y * stride + x * bpp); + lio_len = *io_len; /* compress inner rect */ + + /* notes + * TJPF_RGB no works, zero bytes + * TJPF_BGR no works, not zero but no open + * TJPF_RGBX no works, zero bytes + * TJPF_BGRX no works, off scaled image + * TJPF_XBGR works + * TJPF_XRGB no works, zero bytes + * TJPF_RGBA no works, zero bytes + * TJPF_BGRA no works, zero bytes + * TJPF_ABGR no works, zero bytes + * TJPF_ARGB no works, zero bytes */ + error = tjCompress(tj_han, /* opaque handle */ src_ptr, /* source buf */ cx, /* width of area to compress */ @@ -151,11 +166,12 @@ xrdp_codec_jpeg_compress(void *handle, cy, /* height of area to compress */ TJPF_XBGR, /* pixel size */ out_data, /* dest buf */ - io_len, /* inner_buf length & compressed_size */ + &lio_len, /* inner_buf length & compressed_size */ TJSAMP_420, /* jpeg sub sample */ quality, /* jpeg quality */ 0 /* flags */ ); + *io_len = lio_len; return height; } @@ -382,6 +398,15 @@ xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, } /*****************************************************************************/ +int APP_CC +xrdp_codec_jpeg_compress(void *handle, int format, char *inp_data, int width, + int height, int stride, int x, int y, int cx, int cy, + int quality, char *out_data, int *io_len) +{ + return 0; +} + +/*****************************************************************************/ void *APP_CC xrdp_jpeg_init(void) { @@ -408,6 +433,15 @@ xrdp_jpeg_compress(void *handle, char *in_data, int width, int height, } /*****************************************************************************/ +int APP_CC +xrdp_codec_jpeg_compress(void *handle, int format, char *inp_data, int width, + int height, int stride, int x, int y, int cx, int cy, + int quality, char *out_data, int *io_len) +{ + return 0; +} + +/*****************************************************************************/ void *APP_CC xrdp_jpeg_init(void) { diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index 9dcb5b51..716ad13f 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -122,14 +122,14 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) int len; int userid; int chanid; - DEBUG((" in xrdp_mcs_recv")); while (1) { if (xrdp_iso_recv(self->iso_layer, s) != 0) { - DEBUG((" out xrdp_mcs_recv xrdp_iso_recv returned non zero")); + DEBUG((" out xrdp_mcs_recv, xrdp_iso_recv return non zero")); + g_writeln("xrdp_mcs_recv: xrdp_iso_recv failed"); return 1; } @@ -151,12 +151,7 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) /* this is channels getting added from the client */ if (appid == MCS_CJRQ) { - if (s == self->iso_layer->trans->in_s) - { - /* this should not happen */ - g_writeln("xrdp_mcs_recv: error, MCS_CJRQ at wrong time"); - return 1; - } + if (!s_check_rem(s, 4)) { return 1; @@ -171,6 +166,14 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan) { log_message(LOG_LEVEL_ERROR,"Non handled error from xrdp_mcs_send_cjcf") ; } + + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + g_writeln("xrdp_mcs_recv: libxrdp_force_read failed"); + return 1; + } + continue; } @@ -322,30 +325,29 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) int len; struct stream *s; - make_stream(s); - init_stream(s, 16 * 1024); + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_ber_parse_header(self, s, MCS_CONNECT_INITIAL, &len) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { - free_stream(s); return 1; } if ((len < 0) || !s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -353,13 +355,11 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { - free_stream(s); return 1; } if ((len < 0) || !s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -367,13 +367,11 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0) { - free_stream(s); return 1; } if ((len < 0) || !s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -381,38 +379,32 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (xrdp_mcs_parse_domain_params(self, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_parse_domain_params(self, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_parse_domain_params(self, s) != 0) { - free_stream(s); return 1; } if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0) { - free_stream(s); return 1; } /* mcs data can not be zero length */ if ((len <= 0) || (len > 16 * 1024)) { - free_stream(s); return 1; } if (!s_check_rem(s, len)) { - free_stream(s); return 1; } @@ -424,12 +416,10 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self) if (s_check_end(s)) { - free_stream(s); return 0; } else { - free_stream(s); return 1; } } @@ -443,18 +433,20 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) struct stream *s; DEBUG((" in xrdp_mcs_recv_edrq")); - make_stream(s); - init_stream(s, 8192); + + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } - + if (!s_check_rem(s, 1)) { - free_stream(s); return 1; } @@ -462,13 +454,11 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) if ((opcode >> 2) != MCS_EDRQ) { - free_stream(s); return 1; } if (!s_check_rem(s, 4)) { - free_stream(s); return 1; } @@ -479,7 +469,6 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) { if (!s_check_rem(s, 2)) { - free_stream(s); return 1; } in_uint16_be(s, self->userid); @@ -487,11 +476,9 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self) if (!(s_check_end(s))) { - free_stream(s); return 1; } - free_stream(s); DEBUG((" out xrdp_mcs_recv_edrq")); return 0; } @@ -505,18 +492,20 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) struct stream *s; DEBUG((" in xrdp_mcs_recv_aurq")); - make_stream(s); - init_stream(s, 8192); + + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } if (!s_check_rem(s, 1)) { - free_stream(s); return 1; } @@ -524,7 +513,6 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) if ((opcode >> 2) != MCS_AURQ) { - free_stream(s); return 1; } @@ -532,7 +520,6 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) { if (!s_check_rem(s, 2)) { - free_stream(s); return 1; } in_uint16_be(s, self->userid); @@ -540,11 +527,9 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self) if (!(s_check_end(s))) { - free_stream(s); return 1; } - free_stream(s); DEBUG((" out xrdp_mcs_recv_aurq")); return 0; } @@ -592,18 +577,19 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) int opcode; struct stream *s; - make_stream(s); - init_stream(s, 8192); + s = libxrdp_force_read(self->iso_layer->trans); + if (s == 0) + { + return 1; + } if (xrdp_iso_recv(self->iso_layer, s) != 0) { - free_stream(s); return 1; } if (!s_check_rem(s, 1)) { - free_stream(s); return 1; } @@ -611,13 +597,11 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) if ((opcode >> 2) != MCS_CJRQ) { - free_stream(s); return 1; } if (!s_check_rem(s, 4)) { - free_stream(s); return 1; } @@ -627,7 +611,6 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) { if (!s_check_rem(s, 2)) { - free_stream(s); return 1; } in_uint8s(s, 2); @@ -635,11 +618,9 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) if (!(s_check_end(s))) { - free_stream(s); return 1; } - free_stream(s); return 0; } @@ -725,7 +706,163 @@ xrdp_mcs_out_domain_params(struct xrdp_mcs *self, struct stream *s, xrdp_mcs_ber_out_int8(self, s, 2); return 0; } +/*****************************************************************************/ +/* prepare server gcc data to send in mcs response msg */ +int APP_CC +xrdp_mcs_out_gcc_data(struct xrdp_sec *self) +{ + struct stream *s; + int num_channels_even; + int num_channels; + int index; + int channel; + int gcc_size; + char* gcc_size_ptr; + char* ud_ptr; + + num_channels = self->mcs_layer->channel_list->count; + num_channels_even = num_channels + (num_channels & 1); + s = &(self->server_mcs_data); + init_stream(s, 8192); + out_uint16_be(s, 5); /* AsnBerObjectIdentifier */ + out_uint16_be(s, 0x14); + out_uint8(s, 0x7c); + out_uint16_be(s, 1); /* -- */ + out_uint8(s, 0x2a); /* ConnectPDULen */ + out_uint8(s, 0x14); + out_uint8(s, 0x76); + out_uint8(s, 0x0a); + out_uint8(s, 1); + out_uint8(s, 1); + out_uint8(s, 0); + out_uint16_le(s, 0xc001); + out_uint8(s, 0); + out_uint8(s, 0x4d); /* M */ + out_uint8(s, 0x63); /* c */ + out_uint8(s, 0x44); /* D */ + out_uint8(s, 0x6e); /* n */ + /* GCC Response Total Length - 2 bytes , set later */ + gcc_size_ptr = s->p; /* RDPGCCUserDataResponseLength */ + out_uint8s(s, 2); + ud_ptr = s->p; /* User Data */ + out_uint16_le(s, SEC_TAG_SRV_INFO); + if (self->mcs_layer->iso_layer->rdpNegData) + { + out_uint16_le(s, 12); /* len */ + } + else + { + out_uint16_le(s, 8); /* len */ + } + out_uint8(s, 4); /* 4 = rdp5 1 = rdp4 */ + out_uint8(s, 0); + out_uint8(s, 8); + out_uint8(s, 0); + if (self->mcs_layer->iso_layer->rdpNegData) + { + /* ReqeustedProtocol */ + out_uint32_le(s, self->mcs_layer->iso_layer->requestedProtocol); + } + out_uint16_le(s, SEC_TAG_SRV_CHANNELS); + out_uint16_le(s, 8 + (num_channels_even * 2)); /* len */ + out_uint16_le(s, MCS_GLOBAL_CHANNEL); /* 1003, 0x03eb main channel */ + out_uint16_le(s, num_channels); /* number of other channels */ + + for (index = 0; index < num_channels_even; index++) + { + if (index < num_channels) + { + channel = MCS_GLOBAL_CHANNEL + (index + 1); + out_uint16_le(s, channel); + } + else + { + out_uint16_le(s, 0); + } + } + + if (self->rsa_key_bytes == 64) + { + g_writeln("xrdp_sec_out_mcs_data: using 512 bit RSA key"); + out_uint16_le(s, SEC_TAG_SRV_CRYPT); + out_uint16_le(s, 0x00ec); /* len is 236 */ + out_uint32_le(s, self->crypt_method); + out_uint32_le(s, self->crypt_level); + out_uint32_le(s, 32); /* 32 bytes random len */ + out_uint32_le(s, 0xb8); /* 184 bytes rsa info(certificate) len */ + out_uint8a(s, self->server_random, 32); + /* here to end is certificate */ + /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */ + /* TermService\Parameters\Certificate */ + out_uint32_le(s, 1); + out_uint32_le(s, 1); + out_uint32_le(s, 1); + out_uint16_le(s, SEC_TAG_PUBKEY); /* 0x0006 */ + out_uint16_le(s, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */ + out_uint32_le(s, SEC_RSA_MAGIC); /* 0x31415352 'RSA1' */ + out_uint32_le(s, 0x0048); /* 72 bytes modulus len */ + out_uint32_be(s, 0x00020000); /* bit len */ + out_uint32_be(s, 0x3f000000); /* data len */ + out_uint8a(s, self->pub_exp, 4); /* pub exp */ + out_uint8a(s, self->pub_mod, 64); /* pub mod */ + out_uint8s(s, 8); /* pad */ + out_uint16_le(s, SEC_TAG_KEYSIG); /* 0x0008 */ + out_uint16_le(s, 72); /* len */ + out_uint8a(s, self->pub_sig, 64); /* pub sig */ + out_uint8s(s, 8); /* pad */ + } + else if (self->rsa_key_bytes == 256) + { + g_writeln("xrdp_sec_out_mcs_data: using 2048 bit RSA key"); + out_uint16_le(s, SEC_TAG_SRV_CRYPT); + out_uint16_le(s, 0x01ac); /* len is 428 */ + out_uint32_le(s, self->crypt_method); + out_uint32_le(s, self->crypt_level); + out_uint32_le(s, 32); /* 32 bytes random len */ + out_uint32_le(s, 0x178); /* 376 bytes rsa info(certificate) len */ + out_uint8a(s, self->server_random, 32); + /* here to end is certificate */ + /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */ + /* TermService\Parameters\Certificate */ + out_uint32_le(s, 1); + out_uint32_le(s, 1); + out_uint32_le(s, 1); + out_uint16_le(s, SEC_TAG_PUBKEY); /* 0x0006 */ + out_uint16_le(s, 0x011c); /* 284 bytes length of SEC_TAG_PUBKEY */ + out_uint32_le(s, SEC_RSA_MAGIC); /* 0x31415352 'RSA1' */ + out_uint32_le(s, 0x0108); /* 264 bytes modulus len */ + out_uint32_be(s, 0x00080000); /* bit len */ + out_uint32_be(s, 0xff000000); /* data len */ + out_uint8a(s, self->pub_exp, 4); /* pub exp */ + out_uint8a(s, self->pub_mod, 256); /* pub mod */ + out_uint8s(s, 8); /* pad */ + out_uint16_le(s, SEC_TAG_KEYSIG); /* 0x0008 */ + out_uint16_le(s, 72); /* len */ + out_uint8a(s, self->pub_sig, 64); /* pub sig */ + out_uint8s(s, 8); /* pad */ + } + else if (self->rsa_key_bytes == 0) /* no security */ + { + g_writeln("xrdp_sec_out_mcs_data: using no security"); + out_uint16_le(s, SEC_TAG_SRV_CRYPT); + out_uint16_le(s, 12); /* len is 12 */ + out_uint32_le(s, self->crypt_method); + out_uint32_le(s, self->crypt_level); + } + else + { + g_writeln("xrdp_sec_out_mcs_data: error"); + } + /* end certificate */ + s_mark_end(s); + + gcc_size = (int)(s->end - ud_ptr) | 0x8000; + gcc_size_ptr[0] = gcc_size >> 8; + gcc_size_ptr[1] = gcc_size; + + return 0; +} /*****************************************************************************/ /* returns error */ static int APP_CC @@ -737,9 +874,11 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self) DEBUG((" in xrdp_mcs_send_connect_response")); make_stream(s); init_stream(s, 8192); - data_len = self->server_mcs_data->end - self->server_mcs_data->data; + data_len = (int) (self->server_mcs_data->end - self->server_mcs_data->data); xrdp_iso_init(self->iso_layer, s); - xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, data_len + 38); + //TODO: we should calculate the whole length include MCS_CONNECT_RESPONSE + xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, + data_len > 0x80 ? data_len + 38 : data_len + 36); xrdp_mcs_ber_out_header(self, s, BER_TAG_RESULT, 1); out_uint8(s, 0); xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1); @@ -767,13 +906,9 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self) int APP_CC xrdp_mcs_incoming(struct xrdp_mcs *self) { + int i; DEBUG((" in xrdp_mcs_incoming")); - if (xrdp_iso_incoming(self->iso_layer) != 0) - { - return 1; - } - if (xrdp_mcs_recv_connect_initial(self) != 0) { return 1; @@ -785,8 +920,7 @@ xrdp_mcs_incoming(struct xrdp_mcs *self) return 1; } - /* in xrdp_sec.c */ - if (xrdp_sec_out_mcs_data(self->sec_layer) != 0) + if (xrdp_mcs_out_gcc_data(self->sec_layer) != 0) { return 1; } @@ -811,25 +945,18 @@ xrdp_mcs_incoming(struct xrdp_mcs *self) return 1; } - if (xrdp_mcs_recv_cjrq(self) != 0) - { - return 1; - } - - if (xrdp_mcs_send_cjcf(self, self->userid, - self->userid + MCS_USERCHANNEL_BASE) != 0) - { - return 1; - } - - if (xrdp_mcs_recv_cjrq(self) != 0) + for (i = 0; i < self->channel_list->count + 2; i++) { - return 1; - } + if (xrdp_mcs_recv_cjrq(self) != 0) + { + return 1; + } - if (xrdp_mcs_send_cjcf(self, self->userid, MCS_GLOBAL_CHANNEL) != 0) - { - return 1; + if (xrdp_mcs_send_cjcf(self, self->userid, + self->userid + MCS_USERCHANNEL_BASE + i) != 0) + { + return 1; + } } DEBUG((" out xrdp_mcs_incoming")); @@ -895,7 +1022,7 @@ xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan) if (len > 8192 * 2) { - g_writeln("error in xrdp_mcs_send, size too bog, its %d", len); + g_writeln("error in xrdp_mcs_send, size too big, its %d", len); } //if (len > max_len) @@ -958,6 +1085,7 @@ close_rdp_socket(struct xrdp_mcs *self) { if (self->iso_layer->trans != 0) { + trans_shutdown_tls_mode(self->iso_layer->trans); g_tcp_close(self->iso_layer->trans->sck); self->iso_layer->trans->sck = 0 ; g_writeln("xrdp_mcs_disconnect - socket closed"); diff --git a/libxrdp/xrdp_mppc_enc.c b/libxrdp/xrdp_mppc_enc.c index 15125d54..ff6caf4d 100644 --- a/libxrdp/xrdp_mppc_enc.c +++ b/libxrdp/xrdp_mppc_enc.c @@ -456,7 +456,7 @@ mppc_enc_new(int protocol_type) return 0; } - enc->first_pkt = 1; + enc->flagsHold = PACKET_AT_FRONT; enc->historyBuffer = (char *) g_malloc(enc->buf_len, 1); if (enc->historyBuffer == 0) @@ -574,20 +574,13 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) g_memset(outputBuffer, 0, len); enc->flags = PACKET_COMPR_TYPE_64K; - if (enc->first_pkt) - { - enc->first_pkt = 0; - enc->flagsHold |= PACKET_AT_FRONT; - } - - if ((enc->historyOffset + len) >= enc->buf_len) + if ((enc->historyOffset + len) >= enc->buf_len - 3) { /* historyBuffer cannot hold srcData - rewind it */ enc->historyOffset = 0; g_memset(hash_table, 0, enc->buf_len * 2); g_memset(enc->historyBuffer, 0, enc->buf_len); // added - enc->first_pkt = 0; - enc->flagsHold |= PACKET_AT_FRONT; + enc->flagsHold |= PACKET_AT_FRONT | PACKET_FLUSHED; } /* point to next free byte in historyBuffer */ @@ -602,7 +595,7 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) ctr = copy_offset = lom = 0; /* if we are at start of history buffer, do not attempt to compress */ - /* first 2 bytes,because minimum LoM is 3 */ + /* first 2 bytes, because minimum LoM is 3 */ if (historyOffset == 0) { /* encode first two bytes as literals */ @@ -970,40 +963,6 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) ctr++; } - /* if bits_left == 8, opb_index has already been incremented */ - if ((bits_left == 8) && (opb_index > len)) - { - /* compressed data longer than uncompressed data */ - /* give up */ - enc->historyOffset = 0; - g_memset(hash_table, 0, enc->buf_len * 2); - g_memset(enc->historyBuffer, 0, enc->buf_len); - enc->flagsHold |= PACKET_FLUSHED; - enc->first_pkt = 1; - - g_memcpy(enc->outputBuffer, srcData, len); - enc->bytes_in_opb = len; - enc->flags = 0x81; - - return 1; - } - else if (opb_index + 1 > len) - { - /* compressed data longer than uncompressed data */ - /* give up */ - enc->historyOffset = 0; - g_memset(hash_table, 0, enc->buf_len * 2); - g_memset(enc->historyBuffer, 0, enc->buf_len); - enc->flagsHold |= PACKET_FLUSHED; - enc->first_pkt = 1; - - g_memcpy(enc->outputBuffer, srcData, len); - enc->bytes_in_opb = len; - enc->flags = 0x81; - - return 1; - } - /* if bits_left != 8, increment opb_index, which is zero indexed */ if (bits_left != 8) { @@ -1012,24 +971,21 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len) if (opb_index > len) { + /* compressed data longer than uncompressed data */ /* give up */ enc->historyOffset = 0; g_memset(hash_table, 0, enc->buf_len * 2); g_memset(enc->historyBuffer, 0, enc->buf_len); - enc->flagsHold |= PACKET_FLUSHED; - enc->first_pkt = 1; - - g_memcpy(enc->outputBuffer, srcData, len); - enc->bytes_in_opb = len; - enc->flags = 0x81; - - return 1; + enc->flagsHold |= PACKET_AT_FRONT | PACKET_FLUSHED; + return 0; } + enc->flags |= PACKET_COMPRESSED; enc->bytes_in_opb = opb_index; enc->flags |= enc->flagsHold; enc->flagsHold = 0; + DLOG(("\n")); //g_writeln("compression ratio: %f", (float) len / (float) enc->bytes_in_opb); diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c index 317e1135..7d969514 100644 --- a/libxrdp/xrdp_orders.c +++ b/libxrdp/xrdp_orders.c @@ -34,6 +34,8 @@ } \ } +#define MAX_ORDERS_SIZE (16 * 1024 - 256) + /*****************************************************************************/ struct xrdp_orders *APP_CC xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer) @@ -44,7 +46,7 @@ xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer) self->session = session; self->rdp_layer = rdp_layer; make_stream(self->out_s); - init_stream(self->out_s, 16384); + init_stream(self->out_s, 32 * 1024); self->orders_state.clip_right = 1; /* silly rdp right clip */ self->orders_state.clip_bottom = 1; /* silly rdp bottom clip */ self->jpeg_han = xrdp_jpeg_init(); @@ -53,6 +55,8 @@ xrdp_orders_create(struct xrdp_session *session, struct xrdp_rdp *rdp_layer) { self->rfx_min_pixel = 64 * 32; } + make_stream(self->s); + make_stream(self->temp_s); return self; } @@ -64,9 +68,10 @@ xrdp_orders_delete(struct xrdp_orders *self) { return; } - xrdp_jpeg_deinit(self->jpeg_han); free_stream(self->out_s); + free_stream(self->s); + free_stream(self->temp_s); g_free(self->orders_state.text_data); g_free(self); } @@ -81,7 +86,6 @@ xrdp_orders_reset(struct xrdp_orders *self) { return 1; } - g_free(self->orders_state.text_data); g_memset(&(self->orders_state), 0, sizeof(self->orders_state)); self->order_count_ptr = 0; @@ -98,24 +102,33 @@ int APP_CC xrdp_orders_init(struct xrdp_orders *self) { self->order_level++; - if (self->order_level == 1) { self->order_count = 0; - - /* is this big enough */ - if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0) + if (self->rdp_layer->client_info.use_fast_path & 1) { - return 1; + LLOGLN(10, ("xrdp_orders_init: fastpath")); + if (xrdp_rdp_init_fastpath(self->rdp_layer, self->out_s) != 0) + { + return 1; + } + self->order_count_ptr = self->out_s->p; + out_uint8s(self->out_s, 2); /* number of orders, set later */ + } + else + { + LLOGLN(10, ("xrdp_orders_init: slowpath")); + if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0) + { + return 1; + } + out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); + out_uint8s(self->out_s, 2); /* pad */ + self->order_count_ptr = self->out_s->p; + out_uint8s(self->out_s, 2); /* number of orders, set later */ + out_uint8s(self->out_s, 2); /* pad */ } - - out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); - out_uint8s(self->out_s, 2); /* pad */ - self->order_count_ptr = self->out_s->p; - out_uint8s(self->out_s, 2); /* number of orders, set later */ - out_uint8s(self->out_s, 2); /* pad */ } - return 0; } @@ -127,11 +140,9 @@ xrdp_orders_send(struct xrdp_orders *self) int rv; rv = 0; - if (self->order_level > 0) { self->order_level--; - if ((self->order_level == 0) && (self->order_count > 0)) { s_mark_end(self->out_s); @@ -139,15 +150,24 @@ xrdp_orders_send(struct xrdp_orders *self) self->order_count_ptr[0] = self->order_count; self->order_count_ptr[1] = self->order_count >> 8; self->order_count = 0; - - if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, - RDP_DATA_PDU_UPDATE) != 0) + if (self->rdp_layer->client_info.use_fast_path & 1) + { + if (xrdp_rdp_send_fastpath(self->rdp_layer, + self->out_s, 0) != 0) + { + rv = 1; + } + } + else { - rv = 1; + if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, + RDP_DATA_PDU_UPDATE) != 0) + { + rv = 1; + } } } } - return rv; } @@ -160,21 +180,29 @@ xrdp_orders_force_send(struct xrdp_orders *self) { return 1; } - if ((self->order_level > 0) && (self->order_count > 0)) { s_mark_end(self->out_s); DEBUG(("xrdp_orders_force_send sending %d orders", self->order_count)); self->order_count_ptr[0] = self->order_count; self->order_count_ptr[1] = self->order_count >> 8; - - if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, - RDP_DATA_PDU_UPDATE) != 0) + if (self->rdp_layer->client_info.use_fast_path & 1) { - return 1; + if (xrdp_rdp_send_fastpath(self->rdp_layer, + self->out_s, FASTPATH_UPDATETYPE_ORDERS) != 0) + { + return 1; + } + } + else + { + if (xrdp_rdp_send_data(self->rdp_layer, self->out_s, + RDP_DATA_PDU_UPDATE) != 0) + { + return 1; + } } } - self->order_count = 0; self->order_level = 0; return 0; @@ -190,14 +218,7 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size) int size; int max_packet_size; - if (self->rdp_layer->client_info.bpp == 8) - { - max_packet_size = 8000; - } - else - { - max_packet_size = 16000; - } + max_packet_size = MAX_ORDERS_SIZE; if (self->order_level < 1) { @@ -1632,7 +1653,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, int present; char* present_ptr; char* order_flags_ptr; - + if (xrdp_orders_check(self, 80) != 0) { return 1; @@ -1653,9 +1674,9 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, order_flags |= RDP_ORDER_BOUNDS; if (xrdp_orders_last_bounds(self, rect)) { - + order_flags |= RDP_ORDER_LASTBOUNDS; - + } } } @@ -1699,21 +1720,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, { xrdp_orders_out_bounds(self, rect); } - + if (srcidx != self->orders_state.com_blt_srcidx) { present |= 0x000001; out_uint16_le(self->out_s, srcidx); self->orders_state.com_blt_srcidx = srcidx; } - + if (srcformat != self->orders_state.com_blt_srcformat) { present |= 0x000002; out_uint32_le(self->out_s, srcformat); self->orders_state.com_blt_srcformat = srcformat; } - + if (srcwidth != self->orders_state.com_blt_srcwidth) { present |= 0x000004; @@ -1727,14 +1748,14 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_srcwidth = srcwidth; } - + if (srcrepeat != self->orders_state.com_blt_srcrepeat) { present |= 0x000008; out_uint8(self->out_s, srcrepeat); self->orders_state.com_blt_srcrepeat = srcrepeat; } - + if (srctransform != 0) { if (srctransform[0] != self->orders_state.com_blt_srctransform[0]) @@ -1768,21 +1789,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, self->orders_state.com_blt_srctransform[0] = 0; } } - + if (mskflags != self->orders_state.com_blt_mskflags) { present |= 0x000040; out_uint8(self->out_s, mskflags); self->orders_state.com_blt_mskflags = mskflags; } - + if (mskidx != self->orders_state.com_blt_mskidx) { present |= 0x000080; out_uint16_le(self->out_s, mskidx); self->orders_state.com_blt_mskidx = mskidx; } - + if (mskformat != self->orders_state.com_blt_mskformat) { present |= 0x000100; @@ -1803,21 +1824,21 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_mskwidth = mskwidth; } - + if (mskrepeat != self->orders_state.com_blt_mskrepeat) { present |= 0x000400; out_uint8(self->out_s, mskrepeat); self->orders_state.com_blt_mskrepeat = mskrepeat; } - + if (op != self->orders_state.com_blt_op) { present |= 0x000800; out_uint8(self->out_s, op); self->orders_state.com_blt_op = op; } - + if (srcx != self->orders_state.com_blt_srcx) { present |= 0x001000; @@ -1831,7 +1852,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_srcx = srcx; } - + if (srcy != self->orders_state.com_blt_srcy) { present |= 0x002000; @@ -1845,7 +1866,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_srcy = srcy; } - + if (mskx != self->orders_state.com_blt_mskx) { present |= 0x004000; @@ -1859,7 +1880,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_mskx = mskx; } - + if (msky != self->orders_state.com_blt_msky) { present |= 0x008000; @@ -1873,7 +1894,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_msky = msky; } - + if (dstx != self->orders_state.com_blt_dstx) { present |= 0x010000; @@ -1887,7 +1908,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_dstx = dstx; } - + if (dsty != self->orders_state.com_blt_dsty) { present |= 0x020000; @@ -1901,7 +1922,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_dsty = dsty; } - + if (width != self->orders_state.com_blt_width) { present |= 0x040000; @@ -1915,7 +1936,7 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, } self->orders_state.com_blt_width = width; } - + if (height != self->orders_state.com_blt_height) { present |= 0x080000; @@ -1936,11 +1957,11 @@ xrdp_orders_composite_blt(struct xrdp_orders* self, int srcidx, int srcformat, out_uint32_le(self->out_s, dstformat); self->orders_state.com_blt_dstformat = dstformat; } - + xrdp_order_pack_small_or_tiny(self, order_flags_ptr, order_flags, - + present_ptr, present, 3); - + return 0; } @@ -2304,19 +2325,26 @@ xrdp_orders_send_bitmap(struct xrdp_orders *self, e = 4 - e; } - make_stream(s); - init_stream(s, 16384); - make_stream(temp_s); - init_stream(temp_s, 16384); + s = self->s; + init_stream(s, 16384 * 2); + temp_s = self->temp_s; + init_stream(temp_s, 16384 * 2); p = s->p; i = height; - lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, - i - 1, temp_s, e); + if (bpp > 24) + { + lines_sending = xrdp_bitmap32_compress(data, width, height, s, + bpp, 16384, + i - 1, temp_s, e, 0x10); + } + else + { + lines_sending = xrdp_bitmap_compress(data, width, height, s, bpp, 16384, + i - 1, temp_s, e); + } if (lines_sending != height) { - free_stream(s); - free_stream(temp_s); g_writeln("error in xrdp_orders_send_bitmap, lines_sending(%d) != \ height(%d)", lines_sending, height); return 1; @@ -2364,8 +2392,6 @@ height(%d)", lines_sending, height); } out_uint8a(self->out_s, s->data, bufsize); - free_stream(s); - free_stream(temp_s); return 0; } @@ -2564,16 +2590,17 @@ xrdp_orders_send_bitmap2(struct xrdp_orders *self, e = 4 - e; } - make_stream(s); - init_stream(s, 16384); - make_stream(temp_s); - init_stream(temp_s, 16384); + s = self->s; + init_stream(s, 16384 * 2); + temp_s = self->temp_s; + init_stream(temp_s, 16384 * 2); p = s->p; i = height; if (bpp > 24) { - lines_sending = xrdp_bitmap32_compress(data, width, height, s, bpp, 16384, - i - 1, temp_s, e); + lines_sending = xrdp_bitmap32_compress(data, width, height, s, + bpp, 16384, + i - 1, temp_s, e, 0x10); } else { @@ -2583,8 +2610,6 @@ xrdp_orders_send_bitmap2(struct xrdp_orders *self, if (lines_sending != height) { - free_stream(s); - free_stream(temp_s); g_writeln("error in xrdp_orders_send_bitmap2, lines_sending(%d) != \ height(%d)", lines_sending, height); return 1; @@ -2613,8 +2638,6 @@ height(%d)", lines_sending, height); i = cache_idx & 0xff; out_uint8(self->out_s, i); out_uint8a(self->out_s, s->data, bufsize); - free_stream(s); - free_stream(temp_s); return 0; } diff --git a/libxrdp/xrdp_orders_rail.h b/libxrdp/xrdp_orders_rail.h index 8f5b402f..475b8f17 100644 --- a/libxrdp/xrdp_orders_rail.h +++ b/libxrdp/xrdp_orders_rail.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2012 + * Copyright (C) Jay Sorg 2012-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,31 +20,31 @@ #define _XRDP_ORDERS_RAIL_H int APP_CC -xrdp_orders_send_window_delete(struct xrdp_orders* self, int window_id); +xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id); int APP_CC -xrdp_orders_send_window_cached_icon(struct xrdp_orders* self, +xrdp_orders_send_window_cached_icon(struct xrdp_orders *self, int window_id, int cache_entry, int cache_id, int flags); int APP_CC -xrdp_orders_send_window_icon(struct xrdp_orders* self, +xrdp_orders_send_window_icon(struct xrdp_orders *self, int window_id, int cache_entry, int cache_id, - struct rail_icon_info* icon_info, + struct rail_icon_info *icon_info, int flags); int APP_CC -xrdp_orders_send_window_new_update(struct xrdp_orders* self, int window_id, - struct rail_window_state_order* window_state, +xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id, + struct rail_window_state_order *window_state, int flags); int APP_CC -xrdp_orders_send_notify_delete(struct xrdp_orders* self, int window_id, +xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id, int notify_id); int APP_CC -xrdp_orders_send_notify_new_update(struct xrdp_orders* self, +xrdp_orders_send_notify_new_update(struct xrdp_orders *self, int window_id, int notify_id, - struct rail_notify_state_order* notify_state, + struct rail_notify_state_order *notify_state, int flags); int APP_CC -xrdp_orders_send_monitored_desktop(struct xrdp_orders* self, - struct rail_monitored_desktop_order* mdo, +xrdp_orders_send_monitored_desktop(struct xrdp_orders *self, + struct rail_monitored_desktop_order *mdo, int flags); #endif diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index ec882f4e..4fc83ae8 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -26,6 +26,14 @@ #include <freerdp/constants.h> #endif +#define LOG_LEVEL 1 +#define LLOG(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) + +#define FASTPATH_FRAG_SIZE (16 * 1024 - 128) + /*****************************************************************************/ static int APP_CC xrdp_rdp_read_config(struct xrdp_client_info *client_info) @@ -68,7 +76,11 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) } else if (g_strcasecmp(item, "crypt_level") == 0) { - if (g_strcasecmp(value, "low") == 0) + if (g_strcasecmp(value, "none") == 0) + { + client_info->crypt_level = 0; + } + else if (g_strcasecmp(value, "low") == 0) { client_info->crypt_level = 1; } @@ -123,6 +135,85 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) { client_info->require_credentials = g_text2bool(value); } + else if (g_strcasecmp(item, "use_fastpath") == 0) + { + if (g_strcasecmp(value, "output") == 0) + { + client_info->use_fast_path = 1; + } + else if (g_strcasecmp(value, "input") == 0) + { + client_info->use_fast_path = 2; + } + else if (g_strcasecmp(value, "both") == 0) + { + client_info->use_fast_path = 3; + } + else if (g_strcasecmp(value, "none") == 0) + { + client_info->use_fast_path = 0; + } + else + { + log_message(LOG_LEVEL_ALWAYS,"Warning: Your configured fastpath level is" + "undefined, fastpath will not be used"); + client_info->use_fast_path = 0; + } + } + else if (g_strcasecmp(item, "security_layer") == 0) + { + if (g_strcasecmp(value, "rdp") == 0) + { + client_info->security_layer = PROTOCOL_RDP; + } + else if (g_strcasecmp(value, "tls") == 0) + { + client_info->security_layer = PROTOCOL_SSL; + } + else if (g_strcasecmp(value, "hybrid") == 0) + { + client_info->security_layer = PROTOCOL_SSL | PROTOCOL_HYBRID; + } + else + { + log_message(LOG_LEVEL_ALWAYS,"Warning: Your configured security layer is" + "undefined, xrdp will negotiate client compatible"); + client_info->security_layer = PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_HYBRID_EX; + } + } + else if (g_strcasecmp(item, "certificate") == 0) + { + g_memset(client_info->certificate, 0, sizeof(char) * 1024); + if (value[0] != '/') + { + /* default certificate path */ + g_snprintf(client_info->certificate, 1023, "%s/cert.pem", XRDP_CFG_PATH); + log_message(LOG_LEVEL_ALWAYS,"WARNING: Invalid x.509 certificate path defined, " + "default path will be used: %s", client_info->certificate); + } + else + { + /* use user defined certificate */ + g_strncpy(client_info->certificate, value, 1023); + } + } + else if (g_strcasecmp(item, "key_file") == 0) + { + g_memset(client_info->key_file, 0, sizeof(char) * 1024); + if (value[0] != '/') + { + /* default key_file path */ + g_snprintf(client_info->key_file, 1023, "%s/key.pem", XRDP_CFG_PATH); + log_message(LOG_LEVEL_ALWAYS,"WARNING: Invalid x.509 certificate path defined, " + "default path will be used: %s", client_info->key_file); + } + else + { + /* use user defined key_file */ + g_strncpy(client_info->key_file, value, 1023); + } + } + } list_delete(items); @@ -198,10 +289,7 @@ xrdp_rdp_create(struct xrdp_session *session, struct trans *trans) /* read ini settings */ xrdp_rdp_read_config(&self->client_info); /* create sec layer */ - self->sec_layer = xrdp_sec_create(self, trans, - self->client_info.crypt_level, - self->client_info.channel_code, - self->client_info.multimon); + self->sec_layer = xrdp_sec_create(self, trans); /* default 8 bit v1 color bitmap cache entries and size */ self->client_info.cache1_entries = 600; self->client_info.cache1_size = 256; @@ -266,7 +354,7 @@ xrdp_rdp_init_data(struct xrdp_rdp *self, struct stream *s) } /*****************************************************************************/ -/* returns erros */ +/* returns error */ int APP_CC xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) { @@ -274,11 +362,26 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) int len = 0; int pdu_code = 0; int chan = 0; + const tui8 *header; DEBUG(("in xrdp_rdp_recv")); - if (s->next_packet == 0 || s->next_packet >= s->end) { + /* check for fastpath first */ + header = (const tui8 *) (s->p); + if ((header[0] != 0x3) && (header[0] != 0x3c)) + { + if (xrdp_sec_recv_fastpath(self->sec_layer, s) != 0) + { + return 1; + } + /* next_packet gets set in xrdp_sec_recv_fastpath */ + *code = 2; // special code for fastpath input + DEBUG(("out (fastpath) xrdp_rdp_recv")); + return 0; + } + + /* not fastpath, do tpkt */ chan = 0; error = xrdp_sec_recv(self->sec_layer, s, &chan); @@ -293,6 +396,7 @@ xrdp_rdp_recv(struct xrdp_rdp *self, struct stream *s, int *code) if (error != 0) { DEBUG(("out xrdp_rdp_recv error")); + g_writeln("xrdp_rdp_recv: xrdp_sec_recv failed"); return 1; } @@ -433,7 +537,9 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, } else { - g_writeln("mppc_encode not ok: type %d flags %d", mppc_enc->protocol_type, mppc_enc->flags); + LLOGLN(10, ("xrdp_rdp_send_data: mppc_encode not ok " + "type %d flags %d", mppc_enc->protocol_type, + mppc_enc->flags)); } } @@ -459,841 +565,241 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s, } /*****************************************************************************/ +/* returns the fastpath rdp byte count */ int APP_CC -xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) +xrdp_rdp_get_fastpath_bytes(struct xrdp_rdp *self) { - struct stream *s = (struct stream *)NULL; - - make_stream(s); - init_stream(s, 8192); - DEBUG(("in xrdp_rdp_send_data_update_sync")); - - if (xrdp_rdp_init_data(self, s) != 0) + if (self->client_info.rdp_compression) { - DEBUG(("out xrdp_rdp_send_data_update_sync error")); - free_stream(s); - return 1; + return 4; } - - out_uint16_le(s, RDP_UPDATE_SYNCHRONIZE); - out_uint8s(s, 2); - s_mark_end(s); - - if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_UPDATE) != 0) - { - DEBUG(("out xrdp_rdp_send_data_update_sync error")); - free_stream(s); - return 1; - } - - DEBUG(("out xrdp_rdp_send_data_update_sync")); - free_stream(s); - return 0; + return 3; } /*****************************************************************************/ int APP_CC -xrdp_rdp_incoming(struct xrdp_rdp *self) +xrdp_rdp_init_fastpath(struct xrdp_rdp *self, struct stream *s) { - DEBUG(("in xrdp_rdp_incoming")); - - if (xrdp_sec_incoming(self->sec_layer) != 0) + if (xrdp_sec_init_fastpath(self->sec_layer, s) != 0) { return 1; } - self->mcs_channel = self->sec_layer->mcs_layer->userid + - MCS_USERCHANNEL_BASE; - DEBUG(("out xrdp_rdp_incoming mcs channel %d", self->mcs_channel)); - g_strncpy(self->client_info.client_addr, - self->sec_layer->mcs_layer->iso_layer->trans->addr, - sizeof(self->client_info.client_addr) - 1); - g_strncpy(self->client_info.client_port, - self->sec_layer->mcs_layer->iso_layer->trans->port, - sizeof(self->client_info.client_port) - 1); - return 0; -} - -/*****************************************************************************/ -int APP_CC -xrdp_rdp_send_demand_active(struct xrdp_rdp *self) -{ - struct stream *s; - int caps_count; - int caps_size; - int codec_caps_count; - int codec_caps_size; - int flags; - char *caps_count_ptr; - char *caps_size_ptr; - char *caps_ptr; - char *codec_caps_count_ptr; - char *codec_caps_size_ptr; - - make_stream(s); - init_stream(s, 8192); - - if (xrdp_rdp_init(self, s) != 0) - { - free_stream(s); - return 1; - } - - caps_count = 0; - out_uint32_le(s, self->share_id); - out_uint16_le(s, 4); /* 4 chars for RDP\0 */ - /* 2 bytes size after num caps, set later */ - caps_size_ptr = s->p; - out_uint8s(s, 2); - out_uint8a(s, "RDP", 4); - /* 4 byte num caps, set later */ - caps_count_ptr = s->p; - out_uint8s(s, 4); - caps_ptr = s->p; - - /* Output share capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_SHARE); - out_uint16_le(s, RDP_CAPLEN_SHARE); - out_uint16_le(s, self->mcs_channel); - out_uint16_be(s, 0xb5e2); /* 0x73e1 */ - - /* Output general capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_GENERAL); /* 1 */ - out_uint16_le(s, RDP_CAPLEN_GENERAL); /* 24(0x18) */ - 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 */ - /* NO_BITMAP_COMPRESSION_HDR 0x0400 - FASTPATH_OUTPUT_SUPPORTED 0x0001 */ - if (self->client_info.use_fast_path & 1) + if (self->client_info.rdp_compression) { - out_uint16_le(s, 0x401); + s_push_layer(s, rdp_hdr, 4); } else { - out_uint16_le(s, 0x400); + s_push_layer(s, rdp_hdr, 3); } - 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 */ - - /* Output bitmap capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_BITMAP); /* 2 */ - out_uint16_le(s, RDP_CAPLEN_BITMAP); /* 28(0x1c) */ - out_uint16_le(s, self->client_info.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, self->client_info.width); /* width */ - out_uint16_le(s, self->client_info.height); /* height */ - out_uint16_le(s, 0); /* Pad */ - out_uint16_le(s, 1); /* Allow resize */ - out_uint16_le(s, 1); /* bitmap compression */ - out_uint16_le(s, 0); /* unknown */ - out_uint16_le(s, 0); /* unknown */ - out_uint16_le(s, 0); /* pad */ - - /* Output font capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_FONT); /* 14 */ - out_uint16_le(s, RDP_CAPLEN_FONT); /* 4 */ - - /* Output order capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_ORDER); /* 3 */ - out_uint16_le(s, RDP_CAPLEN_ORDER); /* 88(0x58) */ - out_uint8s(s, 16); - out_uint32_be(s, 0x40420f00); - 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, 0x2f); /* Number of fonts */ - out_uint16_le(s, 0x22); /* Capability flags */ - /* caps */ - out_uint8(s, 1); /* NEG_DSTBLT_INDEX 0x00 0 */ - out_uint8(s, 1); /* NEG_PATBLT_INDEX 0x01 1 */ - out_uint8(s, 1); /* NEG_SCRBLT_INDEX 0x02 2 */ - out_uint8(s, 1); /* NEG_MEMBLT_INDEX 0x03 3 */ - out_uint8(s, 0); /* NEG_MEM3BLT_INDEX 0x04 4 */ - out_uint8(s, 0); /* NEG_ATEXTOUT_INDEX 0x05 5 */ - out_uint8(s, 0); /* NEG_AEXTTEXTOUT_INDEX 0x06 6 */ - out_uint8(s, 0); /* NEG_DRAWNINEGRID_INDEX 0x07 7 */ - out_uint8(s, 1); /* NEG_LINETO_INDEX 0x08 8 */ - out_uint8(s, 0); /* NEG_MULTI_DRAWNINEGRID_INDEX 0x09 9 */ - out_uint8(s, 1); /* NEG_OPAQUE_RECT_INDEX 0x0A 10 */ - out_uint8(s, 0); /* NEG_SAVEBITMAP_INDEX 0x0B 11 */ - out_uint8(s, 0); /* NEG_WTEXTOUT_INDEX 0x0C 12 */ - out_uint8(s, 0); /* NEG_MEMBLT_V2_INDEX 0x0D 13 */ - out_uint8(s, 0); /* NEG_MEM3BLT_V2_INDEX 0x0E 14 */ - out_uint8(s, 0); /* NEG_MULTIDSTBLT_INDEX 0x0F 15 */ - out_uint8(s, 0); /* NEG_MULTIPATBLT_INDEX 0x10 16 */ - out_uint8(s, 0); /* NEG_MULTISCRBLT_INDEX 0x11 17 */ - out_uint8(s, 1); /* NEG_MULTIOPAQUERECT_INDEX 0x12 18 */ - out_uint8(s, 0); /* NEG_FAST_INDEX_INDEX 0x13 19 */ - out_uint8(s, 0); /* NEG_POLYGON_SC_INDEX 0x14 20 */ - out_uint8(s, 0); /* NEG_POLYGON_CB_INDEX 0x15 21 */ - out_uint8(s, 0); /* NEG_POLYLINE_INDEX 0x16 22 */ - out_uint8(s, 0); /* unused 0x17 23 */ - out_uint8(s, 0); /* NEG_FAST_GLYPH_INDEX 0x18 24 */ - out_uint8(s, 0); /* NEG_ELLIPSE_SC_INDEX 0x19 25 */ - out_uint8(s, 0); /* NEG_ELLIPSE_CB_INDEX 0x1A 26 */ - out_uint8(s, 1); /* NEG_GLYPH_INDEX_INDEX 0x1B 27 */ - out_uint8(s, 0); /* NEG_GLYPH_WEXTTEXTOUT_INDEX 0x1C 28 */ - out_uint8(s, 0); /* NEG_GLYPH_WLONGTEXTOUT_INDEX 0x1D 29 */ - out_uint8(s, 0); /* NEG_GLYPH_WLONGEXTTEXTOUT_INDEX 0x1E 30 */ - out_uint8(s, 0); /* unused 0x1F 31 */ - out_uint16_le(s, 0x6a1); - /* declare support of bitmap cache rev3 */ - out_uint16_le(s, XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT); - out_uint32_le(s, 0x0f4240); /* desk save */ - out_uint32_le(s, 0x0f4240); /* desk save */ - out_uint32_le(s, 1); /* ? */ - out_uint32_le(s, 0); /* ? */ - - /* Output bmpcodecs capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_BMPCODECS); - codec_caps_size_ptr = s->p; - out_uint8s(s, 2); /* cap len set later */ - codec_caps_count = 0; - codec_caps_count_ptr = s->p; - out_uint8s(s, 1); /* bitmapCodecCount set later */ - /* nscodec */ - codec_caps_count++; - out_uint8a(s, XR_CODEC_GUID_NSCODEC, 16); - out_uint8(s, 1); /* codec id, must be 1 */ - out_uint16_le(s, 3); - out_uint8(s, 0x01); /* fAllowDynamicFidelity */ - out_uint8(s, 0x01); /* fAllowSubsampling */ - out_uint8(s, 0x03); /* colorLossLevel */ - /* remotefx */ - codec_caps_count++; - out_uint8a(s, XR_CODEC_GUID_REMOTEFX, 16); - out_uint8(s, 0); /* codec id, client sets */ - out_uint16_le(s, 256); - out_uint8s(s, 256); - /* jpeg */ - codec_caps_count++; - out_uint8a(s, XR_CODEC_GUID_JPEG, 16); - out_uint8(s, 0); /* codec id, client sets */ - out_uint16_le(s, 1); /* ext length */ - out_uint8(s, 75); - /* calculate and set size and count */ - codec_caps_size = (int)(s->p - codec_caps_size_ptr); - codec_caps_size += 2; /* 2 bytes for RDP_CAPSET_BMPCODECS above */ - codec_caps_size_ptr[0] = codec_caps_size; - codec_caps_size_ptr[1] = codec_caps_size >> 8; - codec_caps_count_ptr[0] = codec_caps_count; - - /* Output color cache capability set */ - caps_count++; - 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 */ - - /* Output pointer capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_POINTER); - out_uint16_le(s, RDP_CAPLEN_POINTER); - out_uint16_le(s, 1); /* Colour pointer */ - out_uint16_le(s, 0x19); /* Cache size */ - out_uint16_le(s, 0x19); /* Cache size */ - - /* Output input capability set */ - caps_count++; - out_uint16_le(s, RDP_CAPSET_INPUT); /* 13(0xd) */ - out_uint16_le(s, RDP_CAPLEN_INPUT); /* 88(0x58) */ - - /* INPUT_FLAG_SCANCODES 0x0001 - INPUT_FLAG_MOUSEX 0x0004 - INPUT_FLAG_FASTPATH_INPUT 0x0008 - INPUT_FLAG_FASTPATH_INPUT2 0x0020 */ - flags = 0x0001 | 0x0004; - if (self->client_info.use_fast_path & 2) - flags |= 0x0008 | 0x0020; - out_uint16_le(s, flags); - out_uint8s(s, 82); - - /* Remote Programs Capability Set */ - caps_count++; - out_uint16_le(s, 0x0017); /* CAPSETTYPE_RAIL */ - out_uint16_le(s, 8); - out_uint32_le(s, 3); /* TS_RAIL_LEVEL_SUPPORTED - TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */ - - /* Window List Capability Set */ - caps_count++; - out_uint16_le(s, 0x0018); /* CAPSETTYPE_WINDOW */ - out_uint16_le(s, 11); - out_uint32_le(s, 2); /* TS_WINDOW_LEVEL_SUPPORTED_EX */ - out_uint8(s, 3); /* NumIconCaches */ - out_uint16_le(s, 12); /* NumIconCacheEntries */ - - /* 6 - bitmap cache v3 codecid */ - caps_count++; - out_uint16_le(s, 0x0006); - out_uint16_le(s, 5); - out_uint8(s, 0); /* client sets */ - - out_uint8s(s, 4); /* pad */ - - s_mark_end(s); - - caps_size = (int)(s->end - caps_ptr); - caps_size_ptr[0] = caps_size; - caps_size_ptr[1] = caps_size >> 8; - - caps_count_ptr[0] = caps_count; - caps_count_ptr[1] = caps_count >> 8; - caps_count_ptr[2] = caps_count >> 16; - caps_count_ptr[3] = caps_count >> 24; - - if (xrdp_rdp_send(self, s, RDP_PDU_DEMAND_ACTIVE) != 0) - { - free_stream(s); - return 1; - } - - free_stream(s); return 0; } /*****************************************************************************/ -static int APP_CC -xrdp_process_capset_general(struct xrdp_rdp *self, struct stream *s, - int len) +/* returns error */ +/* 2.2.9.1.2.1 Fast-Path Update (TS_FP_UPDATE) + * http://msdn.microsoft.com/en-us/library/cc240622.aspx */ +int APP_CC +xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s, + int data_pdu_type) { - int i; + int updateHeader; + int updateCode; + int fragmentation; + int compression; + int comp_type; + int comp_len; + int no_comp_len; + int send_len; + int cont; + int header_bytes; + int sec_bytes; + int to_comp_len; + int sec_offset; + int rdp_offset; + struct stream frag_s; + struct stream comp_s; + struct stream send_s; + struct xrdp_mppc_enc *mppc_enc; - if (len < 10 + 2) + LLOGLN(10, ("xrdp_rdp_send_fastpath:")); + s_pop_layer(s, rdp_hdr); + updateCode = data_pdu_type; + if (self->client_info.rdp_compression) { - g_writeln("xrdp_process_capset_general: error"); - return 1; + compression = 2; + header_bytes = 4; } - in_uint8s(s, 10); - in_uint16_le(s, i); - /* use_compact_packets is pretty much 'use rdp5' */ - self->client_info.use_compact_packets = (i != 0); - /* op2 is a boolean to use compact bitmap headers in bitmap cache */ - /* set it to same as 'use rdp5' boolean */ - self->client_info.op2 = self->client_info.use_compact_packets; - return 0; -} - -/*****************************************************************************/ -static int APP_CC -xrdp_process_capset_order(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int i; - char order_caps[32]; - int ex_flags; - int cap_flags; - - DEBUG(("order capabilities")); - if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4) + else { - g_writeln("xrdp_process_capset_order: error"); - return 1; + compression = 0; + header_bytes = 3; } - in_uint8s(s, 20); /* Terminal desc, pad */ - in_uint8s(s, 2); /* Cache X granularity */ - in_uint8s(s, 2); /* Cache Y granularity */ - in_uint8s(s, 2); /* Pad */ - in_uint8s(s, 2); /* Max order level */ - in_uint8s(s, 2); /* Number of fonts */ - in_uint16_le(s, cap_flags); /* Capability flags */ - in_uint8a(s, order_caps, 32); /* Orders supported */ - g_memcpy(self->client_info.orders, order_caps, 32); - DEBUG(("dest blt-0 %d", order_caps[0])); - DEBUG(("pat blt-1 %d", order_caps[1])); - DEBUG(("screen blt-2 %d", order_caps[2])); - DEBUG(("memblt-3-13 %d %d", order_caps[3], order_caps[13])); - DEBUG(("triblt-4-14 %d %d", order_caps[4], order_caps[14])); - DEBUG(("line-8 %d", order_caps[8])); - DEBUG(("line-9 %d", order_caps[9])); - DEBUG(("rect-10 %d", order_caps[10])); - DEBUG(("desksave-11 %d", order_caps[11])); - DEBUG(("polygon-20 %d", order_caps[20])); - DEBUG(("polygon2-21 %d", order_caps[21])); - DEBUG(("polyline-22 %d", order_caps[22])); - DEBUG(("ellipse-25 %d", order_caps[25])); - DEBUG(("ellipse2-26 %d", order_caps[26])); - DEBUG(("text2-27 %d", order_caps[27])); - DEBUG(("order_caps dump")); -#if defined(XRDP_DEBUG) - g_hexdump(order_caps, 32); -#endif - in_uint8s(s, 2); /* Text capability flags */ - /* read extended order support flags */ - in_uint16_le(s, ex_flags); /* Ex flags */ - - if (cap_flags & 0x80) /* ORDER_FLAGS_EXTRA_SUPPORT */ + sec_bytes = xrdp_sec_get_fastpath_bytes(self->sec_layer); + fragmentation = 0; + frag_s = *s; + sec_offset = (int)(frag_s.sec_hdr - frag_s.data); + rdp_offset = (int)(frag_s.rdp_hdr - frag_s.data); + cont = 1; + while (cont) { - self->client_info.order_flags_ex = ex_flags; - if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT) + comp_type = 0; + send_s = frag_s; + no_comp_len = (int)(frag_s.end - frag_s.p); + if (no_comp_len > FASTPATH_FRAG_SIZE) { - g_writeln("xrdp_process_capset_order: bitmap cache v3 supported"); - self->client_info.bitmap_cache_version |= 4; + no_comp_len = FASTPATH_FRAG_SIZE; + if (fragmentation == 0) + { + fragmentation = 2; /* FASTPATH_FRAGMENT_FIRST */ + } + else if (fragmentation == 2) + { + fragmentation = 3; /* FASTPATH_FRAGMENT_NEXT */ + } } + else + { + if (fragmentation != 0) + { + fragmentation = 1; /* FASTPATH_FRAGMENT_LAST */ + } + } + send_len = no_comp_len; + LLOGLN(10, ("xrdp_rdp_send_fastpath: no_comp_len %d fragmentation %d", + no_comp_len, fragmentation)); + if ((compression != 0) && (no_comp_len > header_bytes + 16)) + { + to_comp_len = no_comp_len - header_bytes; + mppc_enc = self->mppc_enc; + if (compress_rdp(mppc_enc, (tui8 *)(frag_s.p + header_bytes), + to_comp_len)) + { + comp_len = mppc_enc->bytes_in_opb + header_bytes; + LLOGLN(10, ("xrdp_rdp_send_fastpath: no_comp_len %d " + "comp_len %d", no_comp_len, comp_len)); + send_len = comp_len; + comp_type = mppc_enc->flags; + /* outputBuffer has 64 bytes preceding it */ + g_memset(&comp_s, 0, sizeof(comp_s)); + comp_s.data = mppc_enc->outputBuffer - + (rdp_offset + header_bytes); + comp_s.p = comp_s.data + rdp_offset; + comp_s.end = comp_s.p + send_len; + comp_s.size = send_len; + comp_s.sec_hdr = comp_s.data + sec_offset; + comp_s.rdp_hdr = comp_s.data + rdp_offset; + send_s = comp_s; + } + else + { + LLOGLN(10, ("xrdp_rdp_send_fastpath: mppc_encode not ok " + "type %d flags %d", mppc_enc->protocol_type, + mppc_enc->flags)); + } + } + updateHeader = (updateCode & 15) | + ((fragmentation & 3) << 4) | + ((compression & 3) << 6); + out_uint8(&send_s, updateHeader); + if (compression != 0) + { + out_uint8(&send_s, comp_type); + } + send_len -= header_bytes; + out_uint16_le(&send_s, send_len); + send_s.end = send_s.p + send_len; + if (xrdp_sec_send_fastpath(self->sec_layer, &send_s) != 0) + { + LLOGLN(0, ("xrdp_rdp_send_fastpath: xrdp_fastpath_send failed")); + return 1; + } + frag_s.p += no_comp_len; + cont = frag_s.p < frag_s.end; + frag_s.p -= header_bytes; + frag_s.sec_hdr = frag_s.p - sec_bytes; + frag_s.data = frag_s.sec_hdr; } - in_uint8s(s, 4); /* Pad */ - - in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */ - self->client_info.desktop_cache = i; - DEBUG(("desktop cache size %d", i)); - in_uint8s(s, 4); /* Unknown */ - in_uint8s(s, 4); /* Unknown */ - return 0; -} - -/*****************************************************************************/ -/* get the bitmap cache size */ -static int APP_CC -xrdp_process_capset_bmpcache(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int i; - - if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2) - { - g_writeln("xrdp_process_capset_bmpcache: error"); - return 1; - } - self->client_info.bitmap_cache_version |= 1; - in_uint8s(s, 24); - /* cache 1 */ - in_uint16_le(s, i); - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache1_entries = i; - in_uint16_le(s, self->client_info.cache1_size); - /* cache 2 */ - in_uint16_le(s, i); - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache2_entries = i; - in_uint16_le(s, self->client_info.cache2_size); - /* caceh 3 */ - in_uint16_le(s, i); - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache3_entries = i; - in_uint16_le(s, self->client_info.cache3_size); - DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries, - self->client_info.cache1_size)); - DEBUG(("cache2 entries %d size %d", self->client_info.cache2_entries, - self->client_info.cache2_size)); - DEBUG(("cache3 entries %d size %d", self->client_info.cache3_entries, - self->client_info.cache3_size)); - return 0; -} - -/*****************************************************************************/ -/* get the bitmap cache size */ -static int APP_CC -xrdp_process_capset_bmpcache2(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int Bpp = 0; - int i = 0; - - if (len < 2 + 2 + 4 + 4 + 4) - { - g_writeln("xrdp_process_capset_bmpcache2: error"); - return 1; - } - self->client_info.bitmap_cache_version |= 2; - Bpp = (self->client_info.bpp + 7) / 8; - in_uint16_le(s, i); /* cache flags */ - self->client_info.bitmap_cache_persist_enable = i; - in_uint8s(s, 2); /* number of caches in set, 3 */ - in_uint32_le(s, i); - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache1_entries = i; - self->client_info.cache1_size = 256 * Bpp; - in_uint32_le(s, i); - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache2_entries = i; - self->client_info.cache2_size = 1024 * Bpp; - in_uint32_le(s, i); - i = i & 0x7fffffff; - i = MIN(i, XRDP_MAX_BITMAP_CACHE_IDX); - i = MAX(i, 0); - self->client_info.cache3_entries = i; - self->client_info.cache3_size = 4096 * Bpp; - DEBUG(("cache1 entries %d size %d", self->client_info.cache1_entries, - self->client_info.cache1_size)); - DEBUG(("cache2 entries %d size %d", self->client_info.cache2_entries, - self->client_info.cache2_size)); - DEBUG(("cache3 entries %d size %d", self->client_info.cache3_entries, - self->client_info.cache3_size)); - return 0; -} - -/*****************************************************************************/ -static int -xrdp_process_capset_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int codec_id; - - if (len < 1) - { - g_writeln("xrdp_process_capset_cache_v3_codec_id: error"); - return 1; - } - in_uint8(s, codec_id); - g_writeln("xrdp_process_capset_cache_v3_codec_id: cache_v3_codec_id %d", - codec_id); - self->client_info.v3_codec_id = codec_id; - return 0; -} - -/*****************************************************************************/ -/* get the number of client cursor cache */ -static int APP_CC -xrdp_process_capset_pointercache(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int i; - int colorPointerFlag; - int no_new_cursor; - - if (len < 2 + 2 + 2) - { - g_writeln("xrdp_process_capset_pointercache: error"); - return 1; - } - no_new_cursor = self->client_info.pointer_flags & 2; - in_uint16_le(s, colorPointerFlag); - self->client_info.pointer_flags = colorPointerFlag; - in_uint16_le(s, i); - i = MIN(i, 32); - self->client_info.pointer_cache_entries = i; - if (colorPointerFlag & 1) - { - g_writeln("xrdp_process_capset_pointercache: client supports " - "new(color) cursor"); - in_uint16_le(s, i); - i = MIN(i, 32); - self->client_info.pointer_cache_entries = i; - } - else - { - g_writeln("xrdp_process_capset_pointercache: client does not support " - "new(color) cursor"); - } - if (no_new_cursor) - { - g_writeln("xrdp_process_capset_pointercache: new(color) cursor is " - "disabled by config"); - self->client_info.pointer_flags = 0; - } - return 0; -} - -/*****************************************************************************/ -/* get the type of client brush cache */ -static int APP_CC -xrdp_process_capset_brushcache(struct xrdp_rdp *self, struct stream *s, - int len) -{ - int code; - - if (len < 4) - { - g_writeln("xrdp_process_capset_brushcache: error"); - return 1; - } - in_uint32_le(s, code); - self->client_info.brush_cache_code = code; return 0; } /*****************************************************************************/ -static int APP_CC -xrdp_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s, - int len) +int APP_CC +xrdp_rdp_send_data_update_sync(struct xrdp_rdp *self) { - int i32; - - if (len < 4 + 2 + 2) - { - g_writeln("xrdp_process_offscreen_bmpcache: error"); - return 1; - } - in_uint32_le(s, i32); - self->client_info.offscreen_support_level = i32; - in_uint16_le(s, i32); - self->client_info.offscreen_cache_size = i32 * 1024; - in_uint16_le(s, i32); - self->client_info.offscreen_cache_entries = i32; - g_writeln("xrdp_process_offscreen_bmpcache: support level %d " - "cache size %d MB cache entries %d", - self->client_info.offscreen_support_level, - self->client_info.offscreen_cache_size, - self->client_info.offscreen_cache_entries); - return 0; -} + struct stream *s = (struct stream *)NULL; -/*****************************************************************************/ -static int APP_CC -xrdp_process_capset_rail(struct xrdp_rdp *self, struct stream *s, int len) -{ - int i32; + make_stream(s); + init_stream(s, 8192); + DEBUG(("in xrdp_rdp_send_data_update_sync")); - if (len < 4) + if (self->client_info.use_fast_path & 1) /* fastpath output supported */ { - g_writeln("xrdp_process_capset_rail: error"); - return 1; + LLOGLN(10, ("xrdp_rdp_send_data_update_sync: fastpath")); + if (xrdp_rdp_init_fastpath(self, s) != 0) + { + free_stream(s); + return 1; + } } - in_uint32_le(s, i32); - self->client_info.rail_support_level = i32; - g_writeln("xrdp_process_capset_rail: rail_support_level %d", - self->client_info.rail_support_level); - return 0; -} - -/*****************************************************************************/ -static int APP_CC -xrdp_process_capset_window(struct xrdp_rdp *self, struct stream *s, int len) -{ - int i32; - - if (len < 4 + 1 + 2) + else /* slowpath */ { - g_writeln("xrdp_process_capset_window: error"); - return 1; + if (xrdp_rdp_init_data(self, s) != 0) + { + DEBUG(("out xrdp_rdp_send_data_update_sync error")); + free_stream(s); + return 1; + } + out_uint16_le(s, RDP_UPDATE_SYNCHRONIZE); } - in_uint32_le(s, i32); - self->client_info.wnd_support_level = i32; - in_uint8(s, i32); - self->client_info.wnd_num_icon_caches = i32; - in_uint16_le(s, i32); - self->client_info.wnd_num_icon_cache_entries = i32; - g_writeln("xrdp_process_capset_window wnd_support_level %d " - "wnd_num_icon_caches %d wnd_num_icon_cache_entries %d", - self->client_info.wnd_support_level, - self->client_info.wnd_num_icon_caches, - self->client_info.wnd_num_icon_cache_entries); - return 0; -} - -/*****************************************************************************/ -static int APP_CC -xrdp_process_capset_codecs(struct xrdp_rdp *self, struct stream *s, int len) -{ - int codec_id; - int codec_count; - int index; - int codec_properties_length; - int i1; - char *codec_guid; - char *next_guid; - if (len < 1) - { - g_writeln("xrdp_process_capset_codecs: error"); - return 1; - } - in_uint8(s, codec_count); - len--; + out_uint16_le(s, 0); /* pad */ + s_mark_end(s); - for (index = 0; index < codec_count; index++) + if (self->client_info.use_fast_path & 1) /* fastpath output supported */ { - codec_guid = s->p; - if (len < 16 + 1 + 2) + if (xrdp_rdp_send_fastpath(self, s, + FASTPATH_UPDATETYPE_SYNCHRONIZE) != 0) { - g_writeln("xrdp_process_capset_codecs: error"); + free_stream(s); return 1; } - in_uint8s(s, 16); - in_uint8(s, codec_id); - in_uint16_le(s, codec_properties_length); - len -= 16 + 1 + 2; - if (len < codec_properties_length) + } + else /* slowpath */ + { + if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_UPDATE) != 0) { - g_writeln("xrdp_process_capset_codecs: error"); + DEBUG(("out xrdp_rdp_send_data_update_sync error")); + free_stream(s); return 1; } - len -= codec_properties_length; - next_guid = s->p + codec_properties_length; - - if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0) - { - g_writeln("xrdp_process_capset_codecs: nscodec codec id %d prop len %d", - codec_id, codec_properties_length); - self->client_info.ns_codec_id = codec_id; - i1 = MIN(64, codec_properties_length); - g_memcpy(self->client_info.ns_prop, s->p, i1); - self->client_info.ns_prop_len = i1; - } - else if (g_memcmp(codec_guid, XR_CODEC_GUID_REMOTEFX, 16) == 0) - { - g_writeln("xrdp_process_capset_codecs: rfx codec id %d prop len %d", - codec_id, codec_properties_length); - self->client_info.rfx_codec_id = codec_id; - i1 = MIN(64, codec_properties_length); - g_memcpy(self->client_info.rfx_prop, s->p, i1); - self->client_info.rfx_prop_len = i1; - } - else if (g_memcmp(codec_guid, XR_CODEC_GUID_JPEG, 16) == 0) - { - g_writeln("xrdp_process_capset_codecs: jpeg codec id %d prop len %d", - codec_id, codec_properties_length); - self->client_info.jpeg_codec_id = codec_id; - i1 = MIN(64, codec_properties_length); - g_memcpy(self->client_info.jpeg_prop, s->p, i1); - self->client_info.jpeg_prop_len = i1; - g_writeln(" jpeg quality %d", self->client_info.jpeg_prop[0]); - } - else - { - g_writeln("xrdp_process_capset_codecs: unknown codec id %d", codec_id); - } - - s->p = next_guid; } + + DEBUG(("out xrdp_rdp_send_data_update_sync")); + free_stream(s); return 0; } /*****************************************************************************/ int APP_CC -xrdp_rdp_process_confirm_active(struct xrdp_rdp *self, struct stream *s) +xrdp_rdp_incoming(struct xrdp_rdp *self) { - int cap_len; - int source_len; - int num_caps; - int index; - int type; - int len; - char *p; - - DEBUG(("in xrdp_rdp_process_confirm_active")); - in_uint8s(s, 4); /* rdp_shareid */ - in_uint8s(s, 2); /* userid */ - in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */ - in_uint16_le(s, cap_len); - in_uint8s(s, source_len); - in_uint16_le(s, num_caps); - in_uint8s(s, 2); /* pad */ + DEBUG(("in xrdp_rdp_incoming")); - for (index = 0; index < num_caps; index++) + if (xrdp_sec_incoming(self->sec_layer) != 0) { - p = s->p; - if (!s_check_rem(s, 4)) - { - g_writeln("xrdp_rdp_process_confirm_active: error 1"); - return 1; - } - in_uint16_le(s, type); - in_uint16_le(s, len); - if ((len < 4) || !s_check_rem(s, len - 4)) - { - g_writeln("xrdp_rdp_process_confirm_active: error len %d", len, s->end - s->p); - return 1; - } - len -= 4; - switch (type) - { - case RDP_CAPSET_GENERAL: /* 1 */ - DEBUG(("RDP_CAPSET_GENERAL")); - xrdp_process_capset_general(self, s, len); - break; - case RDP_CAPSET_BITMAP: /* 2 */ - DEBUG(("RDP_CAPSET_BITMAP")); - break; - case RDP_CAPSET_ORDER: /* 3 */ - DEBUG(("RDP_CAPSET_ORDER")); - xrdp_process_capset_order(self, s, len); - break; - case RDP_CAPSET_BMPCACHE: /* 4 */ - DEBUG(("RDP_CAPSET_BMPCACHE")); - xrdp_process_capset_bmpcache(self, s, len); - break; - case RDP_CAPSET_CONTROL: /* 5 */ - DEBUG(("RDP_CAPSET_CONTROL")); - break; - case 6: - xrdp_process_capset_cache_v3_codec_id(self, s, len); - break; - case RDP_CAPSET_ACTIVATE: /* 7 */ - DEBUG(("RDP_CAPSET_ACTIVATE")); - break; - case RDP_CAPSET_POINTER: /* 8 */ - DEBUG(("RDP_CAPSET_POINTER")); - xrdp_process_capset_pointercache(self, s, len); - break; - case RDP_CAPSET_SHARE: /* 9 */ - DEBUG(("RDP_CAPSET_SHARE")); - break; - case RDP_CAPSET_COLCACHE: /* 10 */ - DEBUG(("RDP_CAPSET_COLCACHE")); - break; - case 12: /* 12 */ - DEBUG(("--12")); - break; - case 13: /* 13 */ - DEBUG(("--13")); - break; - case 14: /* 14 */ - DEBUG(("--14")); - break; - case RDP_CAPSET_BRUSHCACHE: /* 15 */ - xrdp_process_capset_brushcache(self, s, len); - break; - case 16: /* 16 */ - DEBUG(("--16")); - break; - case 17: /* 17 */ - DEBUG(("CAPSET_TYPE_OFFSCREEN_CACHE")); - xrdp_process_offscreen_bmpcache(self, s, len); - break; - case RDP_CAPSET_BMPCACHE2: /* 19 */ - DEBUG(("RDP_CAPSET_BMPCACHE2")); - xrdp_process_capset_bmpcache2(self, s, len); - break; - case 20: /* 20 */ - DEBUG(("--20")); - break; - case 21: /* 21 */ - DEBUG(("--21")); - break; - case 22: /* 22 */ - DEBUG(("--22")); - break; - case 0x0017: /* 23 CAPSETTYPE_RAIL */ - xrdp_process_capset_rail(self, s, len); - break; - case 0x0018: /* 24 CAPSETTYPE_WINDOW */ - xrdp_process_capset_window(self, s, len); - break; - case 26: /* 26 */ - DEBUG(("--26")); - break; - case RDP_CAPSET_BMPCODECS: /* 0x1d(29) */ - xrdp_process_capset_codecs(self, s, len); - break; - default: - g_writeln("unknown in xrdp_rdp_process_confirm_active %d", type); - break; - } - - s->p = p + len + 4; + return 1; } - - DEBUG(("out xrdp_rdp_process_confirm_active")); + self->mcs_channel = self->sec_layer->mcs_layer->userid + + MCS_USERCHANNEL_BASE; + DEBUG(("out xrdp_rdp_incoming mcs channel %d", self->mcs_channel)); + g_strncpy(self->client_info.client_addr, + self->sec_layer->mcs_layer->iso_layer->trans->addr, + sizeof(self->client_info.client_addr) - 1); + g_strncpy(self->client_info.client_port, + self->sec_layer->mcs_layer->iso_layer->trans->port, + sizeof(self->client_info.client_port) - 1); return 0; } @@ -1371,8 +877,8 @@ xrdp_rdp_send_synchronise(struct xrdp_rdp *self) return 1; } - out_uint16_le(s, 1); - out_uint16_le(s, 1002); + out_uint16_le(s, 1); /* messageType (2 bytes) */ + out_uint16_le(s, 1002); /* targetUser (2 bytes) */ s_mark_end(s); if (xrdp_rdp_send_data(self, s, RDP_DATA_PDU_SYNCHRONISE) != 0) @@ -1511,45 +1017,7 @@ xrdp_rdp_send_fontmap(struct xrdp_rdp *self) free_stream(s); return 0; } -/*****************************************************************************/ -int APP_CC -xrdp_rdp_send_monitorlayout(struct xrdp_rdp *self) -{ - struct stream *s; - int i; - make_stream(s); - init_stream(s, 8192); - - if (xrdp_rdp_init_data(self, s) != 0) - { - free_stream(s); - return 1; - } - - out_uint32_le(s, self->client_info.monitorCount); /* MonitorCount */ - - /* TODO: validate for allowed monitors in terminal server (maybe by config?) */ - for (i = 0; i < self->client_info.monitorCount; i++) - { - out_uint32_le(s, self->client_info.minfo[i].left); - out_uint32_le(s, self->client_info.minfo[i].top); - out_uint32_le(s, self->client_info.minfo[i].right); - out_uint32_le(s, self->client_info.minfo[i].bottom); - out_uint32_le(s, self->client_info.minfo[i].is_primary); - } - - s_mark_end(s); - - if (xrdp_rdp_send_data(self, s, 0x37) != 0) - { - free_stream(s); - return 1; - } - - free_stream(s); - return 0; -} /*****************************************************************************/ static int APP_CC xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s) @@ -1694,7 +1162,6 @@ xrdp_rdp_process_data(struct xrdp_rdp *self, struct stream *s) return 0; } - /*****************************************************************************/ int APP_CC xrdp_rdp_disconnect(struct xrdp_rdp *self) diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index a4fe8c5a..63957a45 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -26,6 +26,8 @@ do { if (_level < LOG_LEVEL) { g_write _args ; } } while (0) #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { g_writeln _args ; } } while (0) +#define LHEXDUMP(_level, _args) \ + do { if (_level < LOG_LEVEL) { g_hexdump _args ; } } while (0) /* some compilers need unsigned char to avoid warnings */ static tui8 g_pad_54[40] = @@ -183,6 +185,8 @@ static const tui8 g_fips_ivec[8] = 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; +static int is_security_header_present = 1; /* next packet should contain security header? */ + /*****************************************************************************/ static void APP_CC hex_str_to_bin(char *in, char *out, int out_len) @@ -219,85 +223,251 @@ hex_str_to_bin(char *in, char *out, int out_len) } /*****************************************************************************/ -struct xrdp_sec *APP_CC -xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans, int crypt_level, - int channel_code, int multimon) +static void APP_CC +xrdp_load_keyboard_layout(struct xrdp_client_info *client_info) { - struct xrdp_sec *self; + int fd; + int index = 0; + int bytes; + struct list *names = (struct list *)NULL; + struct list *items = (struct list *)NULL; + struct list *values = (struct list *)NULL; + char *item = (char *)NULL; + char *value = (char *)NULL; + char *q = (char *)NULL; + char keyboard_cfg_file[256] = { 0 }; + char rdp_layout[256] = { 0 }; + + LLOGLN(0, ("xrdp_load_keyboard_layout:")); + /* infer model/variant */ + /* TODO specify different X11 keyboard models/variants */ + g_memset(client_info->model, 0, sizeof(client_info->model)); + g_memset(client_info->variant, 0, sizeof(client_info->variant)); + g_strncpy(client_info->layout, "us", sizeof(client_info->layout) - 1); + if (client_info->keyboard_subtype == 3) + { + /* macintosh keyboard */ + bytes = sizeof(client_info->variant); + g_strncpy(client_info->variant, "mac", bytes - 1); + } + else if (client_info->keyboard_subtype == 0) + { + /* default - standard subtype */ + client_info->keyboard_subtype = 1; + } + + g_snprintf(keyboard_cfg_file, 255, "%s/xrdp_keyboard.ini", XRDP_CFG_PATH); + LLOGLN(10, ("keyboard_cfg_file %s", keyboard_cfg_file)); + + fd = g_file_open(keyboard_cfg_file); + + if (fd > 0) + { + int section_found = -1; + char section_rdp_layouts[256] = { 0 }; + char section_layouts_map[256] = { 0 }; + + names = list_create(); + names->auto_free = 1; + items = list_create(); + items->auto_free = 1; + values = list_create(); + values->auto_free = 1; + + file_read_sections(fd, names); + for (index = 0; index < names->count; index++) + { + q = (char *)list_get_item(names, index); + if (g_strncasecmp("default", q, 8) != 0) + { + int i; - DEBUG((" in xrdp_sec_create")); - self = (struct xrdp_sec *)g_malloc(sizeof(struct xrdp_sec), 1); - self->rdp_layer = owner; - self->crypt_method = CRYPT_METHOD_NONE; - self->crypt_level = CRYPT_LEVEL_NONE; - switch (crypt_level) - { - case 1: /* low */ - self->crypt_method = CRYPT_METHOD_40BIT; - self->crypt_level = CRYPT_LEVEL_LOW; - break; - case 2: /* medium */ - self->crypt_method = CRYPT_METHOD_40BIT; - self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE; - break; - case 3: /* high */ - self->crypt_method = CRYPT_METHOD_128BIT; - self->crypt_level = CRYPT_LEVEL_HIGH; - break; - case 4: /* fips */ - self->crypt_method = CRYPT_METHOD_FIPS; - self->crypt_level = CRYPT_LEVEL_FIPS; - break; - default: - g_writeln("Fatal : Illegal crypt_level"); - break ; - } + file_read_section(fd, q, items, values); - self->channel_code = channel_code; - self->multimon = multimon; + for (i = 0; i < items->count; i++) + { + item = (char *)list_get_item(items, i); + value = (char *)list_get_item(values, i); + LLOGLN(10, ("xrdp_load_keyboard_layout: item %s value %s", + item, value)); + if (g_strcasecmp(item, "keyboard_type") == 0) + { + int v = g_atoi(value); + if (v == client_info->keyboard_type) + { + section_found = index; + } + } + else if (g_strcasecmp(item, "keyboard_subtype") == 0) + { + int v = g_atoi(value); + if (v != client_info->keyboard_subtype && + section_found == index) + { + section_found = -1; + break; + } + } + else if (g_strcasecmp(item, "rdp_layouts") == 0) + { + if (section_found != -1 && section_found == index) + { + g_strncpy(section_rdp_layouts, value, 255); + } + } + else if (g_strcasecmp(item, "layouts_map") == 0) + { + if (section_found != -1 && section_found == index) + { + g_strncpy(section_layouts_map, value, 255); + } + } + else if (g_strcasecmp(item, "model") == 0) + { + if (section_found != -1 && section_found == index) + { + bytes = sizeof(client_info->model); + g_memset(client_info->model, 0, bytes); + g_strncpy(client_info->model, value, bytes - 1); + } + } + else if (g_strcasecmp(item, "variant") == 0) + { + if (section_found != -1 && section_found == index) + { + bytes = sizeof(client_info->variant); + g_memset(client_info->variant, 0, bytes); + g_strncpy(client_info->variant, value, bytes - 1); + } + } + else + { + /* + * mixing items from different sections will result in + * skipping over current section. + */ + LLOGLN(10, ("xrdp_load_keyboard_layout: skipping " + "configuration item - %s, continuing to next " + "section", item)); + break; + } + } - if (self->decrypt_rc4_info != NULL) - { - g_writeln("xrdp_sec_create - decrypt_rc4_info already created !!!"); - } + list_clear(items); + list_clear(values); + } + } + + if (section_found == -1) + { + g_memset(section_rdp_layouts, 0, sizeof(char) * 256); + g_memset(section_layouts_map, 0, sizeof(char) * 256); + // read default section + file_read_section(fd, "default", items, values); + for (index = 0; index < items->count; index++) + { + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + if (g_strcasecmp(item, "rdp_layouts") == 0) + { + g_strncpy(section_rdp_layouts, value, 255); + } + else if (g_strcasecmp(item, "layouts_map") == 0) + { + g_strncpy(section_layouts_map, value, 255); + } + } + list_clear(items); + list_clear(values); + } - self->decrypt_rc4_info = ssl_rc4_info_create(); + /* load the map */ + file_read_section(fd, section_rdp_layouts, items, values); + for (index = 0; index < items->count; index++) + { + int rdp_layout_id; + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + rdp_layout_id = g_htoi(value); + if (rdp_layout_id == client_info->keylayout) + { + g_strncpy(rdp_layout, item, 255); + break; + } + } + list_clear(items); + list_clear(values); + file_read_section(fd, section_layouts_map, items, values); + for (index = 0; index < items->count; index++) + { + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + if (g_strcasecmp(item, rdp_layout) == 0) + { + bytes = sizeof(client_info->layout); + g_strncpy(client_info->layout, value, bytes - 1); + break; + } + } - if (self->encrypt_rc4_info != NULL) + list_delete(names); + list_delete(items); + list_delete(values); + + LLOGLN(0, ("xrdp_load_keyboard_layout: model [%s] variant [%s] " + "layout [%s]", client_info->model, client_info->variant, + client_info->layout)); + g_file_close(fd); + } + else { - g_writeln("xrdp_sec_create - encrypt_rc4_info already created !!!"); + LLOGLN(0, ("xrdp_load_keyboard_layout: error opening %d", + keyboard_cfg_file)); } +} + +/*****************************************************************************/ +struct xrdp_sec *APP_CC +xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans) +{ + struct xrdp_sec *self; - self->encrypt_rc4_info = ssl_rc4_info_create(); - self->mcs_layer = xrdp_mcs_create(self, trans, &self->client_mcs_data, - &self->server_mcs_data); - self->chan_layer = xrdp_channel_create(self, self->mcs_layer); - DEBUG((" out xrdp_sec_create")); - return self; + DEBUG((" in xrdp_sec_create")); + self = (struct xrdp_sec *) g_malloc(sizeof(struct xrdp_sec), 1); + self->rdp_layer = owner; + self->crypt_method = CRYPT_METHOD_NONE; /* set later */ + self->crypt_level = CRYPT_LEVEL_NONE; + self->mcs_layer = xrdp_mcs_create(self, trans, &(self->client_mcs_data), + &(self->server_mcs_data)); + self->fastpath_layer = xrdp_fastpath_create(self, trans); + self->chan_layer = xrdp_channel_create(self, self->mcs_layer); + DEBUG((" out xrdp_sec_create")); + + return self; } /*****************************************************************************/ void APP_CC -xrdp_sec_delete(struct xrdp_sec *self) -{ - if (self == 0) - { - g_writeln("xrdp_sec_delete: indata is null"); - return; - } - - xrdp_channel_delete(self->chan_layer); - xrdp_mcs_delete(self->mcs_layer); - ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */ - ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */ - ssl_des3_info_delete(self->decrypt_fips_info); - ssl_des3_info_delete(self->encrypt_fips_info); - ssl_hmac_info_delete(self->sign_fips_info); - g_free(self->client_mcs_data.data); - g_free(self->server_mcs_data.data); - /* Crypto information must always be cleared */ - g_memset(self, 0, sizeof(struct xrdp_sec)); - g_free(self); +xrdp_sec_delete(struct xrdp_sec *self) { + + if (self == 0) { + g_writeln("xrdp_sec_delete: indata is null"); + return; + } + + xrdp_channel_delete(self->chan_layer); + xrdp_mcs_delete(self->mcs_layer); + xrdp_fastpath_delete(self->fastpath_layer); + ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */ + ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */ + ssl_des3_info_delete(self->decrypt_fips_info); + ssl_des3_info_delete(self->encrypt_fips_info); + ssl_hmac_info_delete(self->sign_fips_info); + g_free(self->client_mcs_data.data); + g_free(self->server_mcs_data.data); + /* Crypto information must always be cleared */ + g_memset(self, 0, sizeof(struct xrdp_sec)); + g_free(self); } /*****************************************************************************/ @@ -320,7 +490,7 @@ xrdp_sec_init(struct xrdp_sec *self, struct stream *s) } else { - s_push_layer(s, sec_hdr, 4); +// s_push_layer(s, sec_hdr, 4); } return 0; @@ -766,9 +936,12 @@ xrdp_sec_send_media_lic_response(struct xrdp_sec *self) /*****************************************************************************/ static void APP_CC -xrdp_sec_rsa_op(char *out, char *in, char *mod, char *exp) +xrdp_sec_rsa_op(struct xrdp_sec *self, char *out, char *in, int in_bytes, + char *mod, char *exp) { - ssl_mod_exp(out, 64, in, 64, mod, 64, exp, 64); + ssl_mod_exp(out, self->rsa_key_bytes, in, in_bytes, + mod, self->rsa_key_bytes, + exp, self->rsa_key_bytes); } /*****************************************************************************/ @@ -952,6 +1125,68 @@ xrdp_sec_establish_keys(struct xrdp_sec *self) /*****************************************************************************/ /* returns error */ int APP_CC +xrdp_sec_recv_fastpath(struct xrdp_sec *self, struct stream *s) +{ + int ver; + int len; + int pad; + + LLOGLN(10, ("xrdp_sec_recv_fastpath:")); + if (xrdp_fastpath_recv(self->fastpath_layer, s) != 0) + { + return 1; + } + + if (self->fastpath_layer->secFlags & FASTPATH_INPUT_ENCRYPTED) + { + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + if (!s_check_rem(s, 12)) + { + return 1; + } + in_uint16_le(s, len); + in_uint8(s, ver); /* length (2 bytes) */ + if (len != 0x10) /* length MUST set to 0x10 */ + { + return 1; + } + in_uint8(s, pad); + LLOGLN(10, ("xrdp_sec_recv_fastpath: len %d ver %d pad %d", len, ver, pad)); + in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */ + LLOGLN(10, ("xrdp_sec_recv_fastpath: data len %d", (int)(s->end - s->p))); + xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); + s->end -= pad; + } + else + { + if (!s_check_rem(s, 8)) + { + return 1; + } + in_uint8s(s, 8); /* dataSignature (8 bytes), skip for now */ + xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); + } + } + + if (self->fastpath_layer->numEvents == 0) + { + /** + * If numberEvents is not provided in fpInputHeader, it will be provided + * as one additional byte here. + */ + if (!s_check_rem(s, 8)) + { + return 1; + } + in_uint8(s, self->fastpath_layer->numEvents); /* numEvents (1 byte) (optional) */ + } + + return 0; +} +/*****************************************************************************/ +/* returns error */ +int APP_CC xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) { int flags; @@ -963,7 +1198,8 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) if (xrdp_mcs_recv(self->mcs_layer, s, chan) != 0) { - DEBUG((" out xrdp_sec_recv error")); + DEBUG((" out xrdp_sec_recv : error")); + g_writeln("xrdp_sec_recv: xrdp_mcs_recv failed"); return 1; } @@ -971,6 +1207,13 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) { return 1; } + + + if (!is_security_header_present) + { + return 0; + } + in_uint32_le(s, flags); DEBUG((" in xrdp_sec_recv flags $%x", flags)); @@ -995,7 +1238,7 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) xrdp_sec_fips_decrypt(self, s->p, (int)(s->end - s->p)); s->end -= pad; } - else + else if (self->crypt_level > CRYPT_LEVEL_NONE) { if (!s_check_rem(s, 8)) { @@ -1008,19 +1251,31 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) if (flags & SEC_CLIENT_RANDOM) /* 0x01 */ { - if (!s_check_rem(s, 4 + 64)) + if (!s_check_rem(s, 4)) { return 1; } in_uint32_le(s, len); - in_uint8a(s, self->client_crypt_random, 64); - xrdp_sec_rsa_op(self->client_random, self->client_crypt_random, - self->pub_mod, self->pri_exp); + /* 512, 2048 bit */ + if ((len != 64 + 8) && (len != 256 + 8)) + { + return 1; + } + if (!s_check_rem(s, len - 8)) + { + return 1; + } + in_uint8a(s, self->client_crypt_random, len - 8); + xrdp_sec_rsa_op(self, self->client_random, self->client_crypt_random, + len - 8, self->pub_mod, self->pri_exp); + LLOGLN(10, ("xrdp_sec_recv: client random - len %d", len)); + LHEXDUMP(10, (self->client_random, 256)); + LHEXDUMP(10, (self->client_crypt_random, len - 8)); if (self->crypt_level == CRYPT_LEVEL_FIPS) { xrdp_sec_fips_establish_keys(self); } - else + else if (self->crypt_method != CRYPT_METHOD_NONE) { xrdp_sec_establish_keys(self); } @@ -1068,6 +1323,12 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) return 1; } + if (self->crypt_level == CRYPT_LEVEL_NONE + && self->crypt_method == CRYPT_METHOD_NONE) + { + is_security_header_present = 0; /* in tls mode, no more security header from now on */ + } + DEBUG((" out xrdp_sec_recv")); return -1; /* special error that means send demand active */ } @@ -1170,7 +1431,7 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) } else { - out_uint32_le(s, 0); +// out_uint32_le(s, 0); } if (xrdp_mcs_send(self->mcs_layer, s, chan) != 0) @@ -1183,6 +1444,120 @@ xrdp_sec_send(struct xrdp_sec *self, struct stream *s, int chan) } /*****************************************************************************/ +/* returns the fastpath sec byte count */ +int APP_CC +xrdp_sec_get_fastpath_bytes(struct xrdp_sec *self) +{ + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + return 3 + 4 + 8; + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) + { + return 3 + 8; + } + return 3; +} + +/*****************************************************************************/ +/* returns error */ +int APP_CC +xrdp_sec_init_fastpath(struct xrdp_sec *self, struct stream *s) +{ + if (xrdp_fastpath_init(self->fastpath_layer, s) != 0) + { + return 1; + } + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + s_push_layer(s, sec_hdr, 3 + 4 + 8); + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) + { + s_push_layer(s, sec_hdr, 3 + 8); + } + else + { + s_push_layer(s, sec_hdr, 3); + } + return 0; +} + +/*****************************************************************************/ +/* returns error */ +/* 2.2.9.1.2 Server Fast-Path Update PDU (TS_FP_UPDATE_PDU) + * http://msdn.microsoft.com/en-us/library/cc240621.aspx */ +int APP_CC +xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s) +{ + int secFlags; + int fpOutputHeader; + int datalen; + int pdulen; + int pad; + int error; + char save[8]; + + LLOGLN(10, ("xrdp_sec_send_fastpath:")); + error = 0; + s_pop_layer(s, sec_hdr); + if (self->crypt_level == CRYPT_LEVEL_FIPS) + { + LLOGLN(10, ("xrdp_sec_send_fastpath: fips")); + pdulen = (int)(s->end - s->p); + datalen = pdulen - 15; + pad = (8 - (datalen % 8)) & 7; + secFlags = 0x2; + fpOutputHeader = secFlags << 6; + out_uint8(s, fpOutputHeader); + pdulen += pad; + pdulen |= 0x8000; + out_uint16_be(s, pdulen); + out_uint16_le(s, 16); /* crypto header size */ + out_uint8(s, 1); /* fips version */ + s->end += pad; + out_uint8(s, pad); /* fips pad */ + xrdp_sec_fips_sign(self, s->p, 8, s->p + 8, datalen); + g_memcpy(save, s->p + 8 + datalen, pad); + g_memset(s->p + 8 + datalen, 0, pad); + xrdp_sec_fips_encrypt(self, s->p + 8, datalen + pad); + error = xrdp_fastpath_send(self->fastpath_layer, s); + g_memcpy(s->p + 8 + datalen, save, pad); + } + else if (self->crypt_level > CRYPT_LEVEL_LOW) + { + LLOGLN(10, ("xrdp_sec_send_fastpath: crypt")); + pdulen = (int)(s->end - s->p); + datalen = pdulen - 11; + secFlags = 0x2; + fpOutputHeader = secFlags << 6; + out_uint8(s, fpOutputHeader); + pdulen |= 0x8000; + out_uint16_be(s, pdulen); + xrdp_sec_sign(self, s->p, 8, s->p + 8, datalen); + xrdp_sec_encrypt(self, s->p + 8, datalen); + error = xrdp_fastpath_send(self->fastpath_layer, s); + } + else + { + LLOGLN(10, ("xrdp_sec_send_fastpath: no crypt")); + pdulen = (int)(s->end - s->p); + LLOGLN(10, ("xrdp_sec_send_fastpath: pdulen %d", pdulen)); + secFlags = 0x0; + fpOutputHeader = secFlags << 6; + out_uint8(s, fpOutputHeader); + pdulen |= 0x8000; + out_uint16_be(s, pdulen); + error = xrdp_fastpath_send(self->fastpath_layer, s); + } + if (error != 0) + { + return 1; + } + return 0; +} + +/*****************************************************************************/ /* http://msdn.microsoft.com/en-us/library/cc240510.aspx 2.2.1.3.2 Client Core Data (TS_UD_CS_CORE) */ static int APP_CC @@ -1404,10 +1779,23 @@ xrdp_sec_process_mcs_data_CS_SECURITY(struct xrdp_sec *self, struct stream* s) found = 1; } } - if (found == 0) + if ((found == 0) && + (self->crypt_level == CRYPT_LEVEL_NONE)) { - g_writeln(" no security"); + if (crypt_method == CRYPT_METHOD_NONE) + { + g_writeln(" client and server support none crypt, using " + "none crypt"); + self->crypt_method = CRYPT_METHOD_NONE; + self->crypt_level = CRYPT_LEVEL_NONE; + found = 1; + } } +// if (found == 0) +// { +// g_writeln(" can not find client / server agreed encryption method"); +// return 1; +// } return 0; } @@ -1420,11 +1808,15 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) int num_channels; int index; struct mcs_channel_item *channel_item; + struct xrdp_client_info *client_info = (struct xrdp_client_info *)NULL; + + client_info = &(self->rdp_layer->client_info); + - DEBUG(("processing channels, channel_code is %d", self->channel_code)); + DEBUG(("processing channels, channel_code is %d", client_info->channel_code)); /* this is an option set in xrdp.ini */ - if (self->channel_code != 1) /* are channels on? */ + if (client_info->channel_code != 1) /* are channels on? */ { g_writeln("Processing channel data from client - The channel is off"); return 0; @@ -1444,16 +1836,19 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s) for (index = 0; index < num_channels; index++) { + struct mcs_channel_item *channel_item; + channel_item = (struct mcs_channel_item *) g_malloc(sizeof(struct mcs_channel_item), 1); if (!s_check_rem(s, 12)) { + g_free(channel_item); return 1; } in_uint8a(s, channel_item->name, 8); in_uint32_le(s, channel_item->flags); channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1); - list_add_item(self->mcs_layer->channel_list, (tintptr)channel_item); + list_add_item(self->mcs_layer->channel_list, (tintptr) channel_item); DEBUG(("got channel flags %8.8x name %s", channel_item->flags, channel_item->name)); } @@ -1473,9 +1868,9 @@ xrdp_sec_process_mcs_data_monitors(struct xrdp_sec *self, struct stream *s) client_info = &(self->rdp_layer->client_info); - DEBUG(("processing monitors data, allow_multimon is %d", self->multimon)); + DEBUG(("processing monitors data, allow_multimon is %d", client_info->multimon)); /* this is an option set in xrdp.ini */ - if (self->multimon != 1) /* are multi-monitors allowed ? */ + if (client_info->multimon != 1) /* are multi-monitors allowed ? */ { DEBUG(("[INFO] xrdp_sec_process_mcs_data_monitors: multimon is not " "allowed, skipping")); @@ -1617,113 +2012,6 @@ xrdp_sec_process_mcs_data(struct xrdp_sec *self) } /*****************************************************************************/ -/* prepare server mcs data to send in mcs layer */ -int APP_CC -xrdp_sec_out_mcs_data(struct xrdp_sec *self) -{ - struct stream *s; - int num_channels_even; - int num_channels; - int index; - int channel; - - num_channels = self->mcs_layer->channel_list->count; - num_channels_even = num_channels + (num_channels & 1); - s = &self->server_mcs_data; - init_stream(s, 512); - out_uint16_be(s, 5); - out_uint16_be(s, 0x14); - out_uint8(s, 0x7c); - out_uint16_be(s, 1); - out_uint8(s, 0x2a); - out_uint8(s, 0x14); - out_uint8(s, 0x76); - out_uint8(s, 0x0a); - out_uint8(s, 1); - out_uint8(s, 1); - out_uint8(s, 0); - out_uint16_le(s, 0xc001); - out_uint8(s, 0); - out_uint8(s, 0x4d); /* M */ - out_uint8(s, 0x63); /* c */ - out_uint8(s, 0x44); /* D */ - out_uint8(s, 0x6e); /* n */ - if (self->mcs_layer->iso_layer->selectedProtocol != -1) - { // Check for RDPNEGDATA availability - out_uint16_be(s, 0x80fc + (num_channels_even * 2) + 4); - } - else - { - out_uint16_be(s, 0x80fc + (num_channels_even * 2)); - } - out_uint16_le(s, SEC_TAG_SRV_INFO); - if (self->mcs_layer->iso_layer->selectedProtocol != -1) - { - out_uint16_le(s, 12); /* len */ - } - else - { - out_uint16_le(s, 8); /* len */ - } - out_uint8(s, 4); /* 4 = rdp5 1 = rdp4 */ - out_uint8(s, 0); - out_uint8(s, 8); - out_uint8(s, 0); - if (self->mcs_layer->iso_layer->selectedProtocol != -1) - { - /* clientReqeustedProtocol */ - out_uint32_le(s, self->mcs_layer->iso_layer->selectedProtocol); - } - out_uint16_le(s, SEC_TAG_SRV_CHANNELS); - out_uint16_le(s, 8 + (num_channels_even * 2)); /* len */ - out_uint16_le(s, MCS_GLOBAL_CHANNEL); /* 1003, 0x03eb main channel */ - out_uint16_le(s, num_channels); /* number of other channels */ - - for (index = 0; index < num_channels_even; index++) - { - if (index < num_channels) - { - channel = MCS_GLOBAL_CHANNEL + (index + 1); - out_uint16_le(s, channel); - } - else - { - out_uint16_le(s, 0); - } - } - - out_uint16_le(s, SEC_TAG_SRV_CRYPT); - out_uint16_le(s, 0x00ec); /* len is 236 */ - out_uint32_le(s, self->crypt_method); - out_uint32_le(s, self->crypt_level); - out_uint32_le(s, 32); /* 32 bytes random len */ - out_uint32_le(s, 0xb8); /* 184 bytes rsa info(certificate) len */ - out_uint8a(s, self->server_random, 32); - /* here to end is certificate */ - /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */ - /* TermService\Parameters\Certificate */ - out_uint32_le(s, 1); - out_uint32_le(s, 1); - out_uint32_le(s, 1); - out_uint16_le(s, SEC_TAG_PUBKEY); - out_uint16_le(s, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */ - out_uint32_le(s, SEC_RSA_MAGIC); - out_uint32_le(s, 0x48); /* 72 bytes modulus len */ - out_uint32_be(s, 0x00020000); - out_uint32_be(s, 0x3f000000); - out_uint8a(s, self->pub_exp, 4); /* pub exp */ - out_uint8a(s, self->pub_mod, 64); /* pub mod */ - out_uint8s(s, 8); /* pad */ - out_uint16_le(s, SEC_TAG_KEYSIG); - out_uint16_le(s, 72); /* len */ - out_uint8a(s, self->pub_sig, 64); /* pub sig */ - out_uint8s(s, 8); /* pad */ - /* end certificate */ - s_mark_end(s); - return 0; -} - -/*****************************************************************************/ /* process the mcs client data we received from the mcs layer */ static int APP_CC xrdp_sec_in_mcs_data(struct xrdp_sec *self) @@ -1782,67 +2070,166 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self) in_uint8s(s, 79); in_uint32_le(s, client_info->keyboard_type); in_uint32_le(s, client_info->keyboard_subtype); + xrdp_load_keyboard_layout(client_info); s->p = s->data; return 0; } /*****************************************************************************/ +/* returns error */ +int APP_CC +xrdp_sec_init_rdp_security(struct xrdp_sec *self) +{ + switch (self->rdp_layer->client_info.crypt_level) + { + case 0: /* none */ + self->crypt_method = CRYPT_METHOD_NONE; + self->crypt_level = CRYPT_LEVEL_NONE; + break; + case 1: /* low */ + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_LOW; + break; + case 2: /* medium */ + self->crypt_method = CRYPT_METHOD_40BIT; + self->crypt_level = CRYPT_LEVEL_CLIENT_COMPATIBLE; + break; + case 3: /* high */ + self->crypt_method = CRYPT_METHOD_128BIT; + self->crypt_level = CRYPT_LEVEL_HIGH; + break; + case 4: /* fips */ + self->crypt_method = CRYPT_METHOD_FIPS; + self->crypt_level = CRYPT_LEVEL_FIPS; + break; + default: + g_writeln("Fatal : Illegal crypt_level"); + break ; + } + + if (self->decrypt_rc4_info != NULL) + { + g_writeln("xrdp_sec_init_rdp_security: decrypt_rc4_info already created !!!"); + } + else + { + self->decrypt_rc4_info = ssl_rc4_info_create(); + } + + if (self->encrypt_rc4_info != NULL) + { + g_writeln("xrdp_sec_init_rdp_security: encrypt_rc4_info already created !!!"); + } + else + { + self->encrypt_rc4_info = ssl_rc4_info_create(); + } + + return 0; +} + +/*****************************************************************************/ int APP_CC xrdp_sec_incoming(struct xrdp_sec *self) { struct list *items = NULL; struct list *values = NULL; + struct xrdp_iso *iso; int index = 0; char *item = NULL; char *value = NULL; char key_file[256]; - LLOGLN(10, ("xrdp_sec_incoming:")); - g_memset(key_file, 0, sizeof(char) * 256); - DEBUG((" in xrdp_sec_incoming")); - g_random(self->server_random, 32); - items = list_create(); - items->auto_free = 1; - values = list_create(); - values->auto_free = 1; - g_snprintf(key_file, 255, "%s/rsakeys.ini", XRDP_CFG_PATH); - - if (file_by_name_read_section(key_file, "keys", items, values) != 0) - { - /* this is a show stopper */ - log_message(LOG_LEVEL_ALWAYS, "XRDP cannot read file: %s " - "(check permissions)", key_file); - list_delete(items); - list_delete(values); + DEBUG((" in xrdp_sec_incoming:")); + iso = self->mcs_layer->iso_layer; + + /* negotiate security layer */ + if (xrdp_iso_incoming(iso) != 0) + { + DEBUG(("xrdp_sec_incoming: xrdp_iso_incoming failed")); return 1; } - for (index = 0; index < items->count; index++) + /* initialize selected security layer */ + if (iso->requestedProtocol > PROTOCOL_RDP) { - item = (char *)list_get_item(items, index); - value = (char *)list_get_item(values, index); + /* init tls security */ + DEBUG((" in xrdp_sec_incoming: init tls security")); - if (g_strcasecmp(item, "pub_exp") == 0) + if (trans_set_tls_mode(self->mcs_layer->iso_layer->trans, + self->rdp_layer->client_info.key_file, + self->rdp_layer->client_info.certificate) != 0) { - hex_str_to_bin(value, self->pub_exp, 4); - } - else if (g_strcasecmp(item, "pub_mod") == 0) - { - hex_str_to_bin(value, self->pub_mod, 64); + g_writeln("xrdp_sec_incoming: trans_set_tls_mode failed"); + return 1; } - else if (g_strcasecmp(item, "pub_sig") == 0) + + self->crypt_level = CRYPT_LEVEL_NONE; + self->crypt_method = CRYPT_METHOD_NONE; + self->rsa_key_bytes = 0; + + } + else + { + /* init rdp security */ + DEBUG((" in xrdp_sec_incoming: init rdp security")); + if (xrdp_sec_init_rdp_security(self) != 0) { - hex_str_to_bin(value, self->pub_sig, 64); + DEBUG(("xrdp_sec_incoming: xrdp_sec_init_rdp_security failed")); + return 1; } - else if (g_strcasecmp(item, "pri_exp") == 0) + if (self->crypt_method != CRYPT_METHOD_NONE) { - hex_str_to_bin(value, self->pri_exp, 64); + g_memset(key_file, 0, sizeof(char) * 256); + g_random(self->server_random, 32); + items = list_create(); + items->auto_free = 1; + values = list_create(); + values->auto_free = 1; + g_snprintf(key_file, 255, "%s/rsakeys.ini", XRDP_CFG_PATH); + + if (file_by_name_read_section(key_file, "keys", items, values) != 0) + { + /* this is a show stopper */ + log_message(LOG_LEVEL_ALWAYS, "XRDP cannot read file: %s " + "(check permissions)", key_file); + list_delete(items); + list_delete(values); + return 1; + } + + for (index = 0; index < items->count; index++) + { + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + + if (g_strcasecmp(item, "pub_exp") == 0) + { + hex_str_to_bin(value, self->pub_exp, 4); + } + else if (g_strcasecmp(item, "pub_mod") == 0) + { + self->rsa_key_bytes = (g_strlen(value) + 1) / 5; + g_writeln("pub_mod bytes %d", self->rsa_key_bytes); + hex_str_to_bin(value, self->pub_mod, self->rsa_key_bytes); + } + else if (g_strcasecmp(item, "pub_sig") == 0) + { + hex_str_to_bin(value, self->pub_sig, 64); + } + else if (g_strcasecmp(item, "pri_exp") == 0) + { + self->rsa_key_bytes = (g_strlen(value) + 1) / 5; + g_writeln("pri_exp %d", self->rsa_key_bytes); + hex_str_to_bin(value, self->pri_exp, self->rsa_key_bytes); + } + } + list_delete(items); + list_delete(values); } } - list_delete(items); - list_delete(values); - + /* negotiate mcs layer */ if (xrdp_mcs_incoming(self->mcs_layer) != 0) { return 1; @@ -1861,6 +2248,7 @@ xrdp_sec_incoming(struct xrdp_sec *self) { return 1; } + LLOGLN(10, ("xrdp_sec_incoming: out")); return 0; } diff --git a/neutrinordp/xrdp-neutrinordp.c b/neutrinordp/xrdp-neutrinordp.c index 96502000..6c8b17ac 100644 --- a/neutrinordp/xrdp-neutrinordp.c +++ b/neutrinordp/xrdp-neutrinordp.c @@ -275,11 +275,13 @@ lxrdp_event(struct mod *mod, int msg, long param1, long param2, case 107: /* wheel up */ flags = PTR_FLAGS_WHEEL | 0x0078; mod->inst->input->MouseEvent(mod->inst->input, flags, 0, 0); + break; case 108: break; case 109: /* wheel down */ flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0088; mod->inst->input->MouseEvent(mod->inst->input, flags, 0, 0); + break; case 110: break; case 200: @@ -296,8 +298,8 @@ lxrdp_event(struct mod *mod, int msg, long param1, long param2, size = (int)param2; data = (char *)param3; total_size = (int)param4; - LLOGLN(12, ("lxrdp_event: client to server flags %d", flags)); + LLOGLN(12, ("lxrdp_event: client to server ,chanid= %d flags= %d", chanid, flags)); if ((chanid < 0) || (chanid >= mod->inst->settings->num_channels)) { LLOGLN(0, ("lxrdp_event: error chanid %d", chanid)); @@ -491,7 +493,7 @@ lfreerdp_begin_paint(rdpContext *context) { struct mod *mod; - LLOGLN(10, ("lfreerdp_begin_paint:")); + LLOGLN(12, ("lfreerdp_begin_paint:")); mod = ((struct mod_context *)context)->modi; mod->server_begin_update(mod); } @@ -502,7 +504,7 @@ lfreerdp_end_paint(rdpContext *context) { struct mod *mod; - LLOGLN(10, ("lfreerdp_end_paint:")); + LLOGLN(12, ("lfreerdp_end_paint:")); mod = ((struct mod_context *)context)->modi; mod->server_end_update(mod); } @@ -517,7 +519,7 @@ lfreerdp_set_bounds(rdpContext *context, rdpBounds *bounds) int cx; int cy; - LLOGLN(10, ("lfreerdp_set_bounds: %p", bounds)); + LLOGLN(12, ("lfreerdp_set_bounds: %p", bounds)); mod = ((struct mod_context *)context)->modi; if (bounds != 0) @@ -734,7 +736,7 @@ lfreerdp_mem_blt(rdpContext *context, MEMBLT_ORDER *memblt) struct bitmap_item *bi; mod = ((struct mod_context *)context)->modi; - LLOGLN(10, ("lfreerdp_mem_blt: cacheId %d cacheIndex %d", + LLOGLN(12, ("lfreerdp_mem_blt: cacheId %d cacheIndex %d", memblt->cacheId, memblt->cacheIndex)); id = memblt->cacheId; @@ -1353,7 +1355,7 @@ static void DEFAULT_CC lfreerdp_syncronize(rdpContext* context) { struct mod *mod; mod = ((struct mod_context *)context)->modi; - LLOGLN(0, ("lfreerdp_synchronize received - not handled")); + LLOGLN(12, ("lfreerdp_synchronize received - not handled")); } /******************************************************************************/ @@ -1378,8 +1380,8 @@ lfreerdp_pre_connect(freerdp *instance) while (error == 0) { num_chans++; - LLOGLN(10, ("lfreerdp_pre_connect: got channel [%s], flags [0x%8.8x]", - ch_name, ch_flags)); + LLOGLN(10, ("lfreerdp_pre_connect: got channel [%s], id [%d], flags [0x%8.8x]", + ch_name, index, ch_flags)); dst_ch_name = instance->settings->channels[index].name; g_memset(dst_ch_name, 0, 8); g_snprintf(dst_ch_name, 8, "%s", ch_name); @@ -1408,24 +1410,25 @@ lfreerdp_pre_connect(freerdp *instance) instance->settings->order_support[NEG_MEM3BLT_INDEX] = 0; instance->settings->order_support[NEG_MEM3BLT_V2_INDEX] = 0; instance->settings->bitmapCacheV2NumCells = 3; // 5; - instance->settings->bitmapCacheV2CellInfo[0].numEntries = 0x78; // 600; + instance->settings->bitmapCacheV2CellInfo[0].numEntries = 600; // 0x78; instance->settings->bitmapCacheV2CellInfo[0].persistent = 0; - instance->settings->bitmapCacheV2CellInfo[1].numEntries = 0x78; // 600; + instance->settings->bitmapCacheV2CellInfo[1].numEntries = 600; //0x78; // 600; instance->settings->bitmapCacheV2CellInfo[1].persistent = 0; - instance->settings->bitmapCacheV2CellInfo[2].numEntries = 0x150; // 2048; + instance->settings->bitmapCacheV2CellInfo[2].numEntries = 2048; //0x150; // 2048; instance->settings->bitmapCacheV2CellInfo[2].persistent = 0; - instance->settings->bitmapCacheV2CellInfo[3].numEntries = 0; // 4096; + instance->settings->bitmapCacheV2CellInfo[3].numEntries = 4096; // 4096; instance->settings->bitmapCacheV2CellInfo[3].persistent = 0; - instance->settings->bitmapCacheV2CellInfo[4].numEntries = 0; // 2048; + instance->settings->bitmapCacheV2CellInfo[4].numEntries = 2048; // 2048; instance->settings->bitmapCacheV2CellInfo[4].persistent = 0; - // instance->settings->BitmapCacheV3Enabled = FALSE; + instance->settings->bitmap_cache_v3 = 1; instance->settings->order_support[NEG_MULTIDSTBLT_INDEX] = 0; instance->settings->order_support[NEG_MULTIPATBLT_INDEX] = 0; instance->settings->order_support[NEG_MULTISCRBLT_INDEX] = 0; instance->settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = 0; instance->settings->order_support[NEG_POLYLINE_INDEX] = 0; + instance->settings->username = g_strdup(mod->username); instance->settings->password = g_strdup(mod->password); @@ -1436,6 +1439,10 @@ lfreerdp_pre_connect(freerdp *instance) instance->settings->rail_langbar_supported = 1; instance->settings->workarea = 1; instance->settings->performance_flags = PERF_DISABLE_WALLPAPER | PERF_DISABLE_FULLWINDOWDRAG; + instance->settings->num_icon_caches = mod->client_info.wnd_num_icon_caches; + instance->settings->num_icon_cache_entries = mod->client_info.wnd_num_icon_cache_entries; + + } else { @@ -1448,8 +1455,16 @@ lfreerdp_pre_connect(freerdp *instance) instance->settings->compression = 0; instance->settings->ignore_certificate = 1; - // here - //instance->settings->RdpVersion = 4; + // Multi Monitor Settings + instance->settings->num_monitors = mod->client_info.monitorCount; + for (index = 0; index < mod->client_info.monitorCount; index++) + { + instance->settings->monitors[index].x = mod->client_info.minfo[index].left; + instance->settings->monitors[index].y = mod->client_info.minfo[index].top; + instance->settings->monitors[index].width = mod->client_info.minfo[index].right; + instance->settings->monitors[index].height = mod->client_info.minfo[index].bottom; + instance->settings->monitors[index].is_primary = mod->client_info.minfo[index].is_primary; + } instance->update->BeginPaint = lfreerdp_begin_paint; instance->update->EndPaint = lfreerdp_end_paint; @@ -1648,21 +1663,21 @@ lrail_NotifyIconCreate(rdpContext *context, WINDOW_ORDER_INFO *orderInfo, rnso.version = notify_icon_state->version; if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_TIP) - { - rnso.tool_tip = freerdp_uniconv_in(uniconv, - notify_icon_state->toolTip.string, notify_icon_state->toolTip.length); - } - if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) - { - rnso.infotip.timeout = notify_icon_state->infoTip.timeout; - rnso.infotip.flags = notify_icon_state->infoTip.flags; - rnso.infotip.text = freerdp_uniconv_in(uniconv, - notify_icon_state->infoTip.text.string, - notify_icon_state->infoTip.text.length); - rnso.infotip.title = freerdp_uniconv_in(uniconv, - notify_icon_state->infoTip.title.string, - notify_icon_state->infoTip.title.length); - } + { + rnso.tool_tip = freerdp_uniconv_in(uniconv, + notify_icon_state->toolTip.string, notify_icon_state->toolTip.length); + } + if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP) + { + rnso.infotip.timeout = notify_icon_state->infoTip.timeout; + rnso.infotip.flags = notify_icon_state->infoTip.flags; + rnso.infotip.text = freerdp_uniconv_in(uniconv, + notify_icon_state->infoTip.text.string, + notify_icon_state->infoTip.text.length); + rnso.infotip.title = freerdp_uniconv_in(uniconv, + notify_icon_state->infoTip.title.string, + notify_icon_state->infoTip.title.length); + } rnso.state = notify_icon_state->state; rnso.icon_cache_entry = notify_icon_state->icon.cacheEntry; @@ -1815,7 +1830,7 @@ lfreerdp_receive_channel_data(freerdp *instance, int channelId, uint8 *data, if (lchid >= 0) { - LLOGLN(10, ("lfreerdp_receive_channel_data: server to client")); + LLOGLN(10, ("lfreerdp_receive_channel_data: server to client, chanid: %d", lchid)); error = mod->server_send_to_channel(mod, lchid, (char *)data, size, total_size, flags); diff --git a/rdp/rdp_bitmap.c b/rdp/rdp_bitmap.c index 0963588f..4ba821d3 100644 --- a/rdp/rdp_bitmap.c +++ b/rdp/rdp_bitmap.c @@ -164,6 +164,7 @@ bitmap_decompress1(char *output, int width, int height, char *input, int size) break; case 8: /* Bicolor */ color1 = CVAL(input); + /* fall through is intentional */ case 3: /* Color */ color2 = CVAL(input); break; @@ -435,6 +436,7 @@ bitmap_decompress2(char *output, int width, int height, char *input, int size) case 8: /* Bicolor */ color1[EIK0] = CVAL(input); color1[EIK1] = CVAL(input); + /* fall through is intentional */ case 3: /* Color */ color2[EIK0] = CVAL(input); color2[EIK1] = CVAL(input); @@ -752,6 +754,7 @@ bitmap_decompress3(char *output, int width, int height, char *input, int size) color1[0] = CVAL(input); color1[1] = CVAL(input); color1[2] = CVAL(input); + /* fall through is intentional */ case 3: /* Color */ color2[0] = CVAL(input); color2[1] = CVAL(input); diff --git a/rdp/rdp_lic.c b/rdp/rdp_lic.c index e3ff3a7e..2441bc7f 100644 --- a/rdp/rdp_lic.c +++ b/rdp/rdp_lic.c @@ -174,6 +174,8 @@ rdp_lic_process_demand(struct rdp_lic *self, struct stream *s) 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); + +#if 0 licence_size = 0; /* todo load_licence(&licence_data); */ if (licence_size > 0) @@ -192,6 +194,7 @@ rdp_lic_process_demand(struct rdp_lic *self, struct stream *s) g_free(licence_data); return; } +#endif rdp_lic_send_request(self, null_data, null_data, self->sec_layer->rdp_layer->mod->username, diff --git a/rdp/rdp_mcs.c b/rdp/rdp_mcs.c index 55067b1f..18c33ac4 100644 --- a/rdp/rdp_mcs.c +++ b/rdp/rdp_mcs.c @@ -19,6 +19,7 @@ */ #include "rdp.h" +#include "common/log.h" /*****************************************************************************/ struct rdp_mcs *APP_CC @@ -598,7 +599,8 @@ failed")); int APP_CC rdp_mcs_init(struct rdp_mcs *self, struct stream *s) { - rdp_iso_init(self->iso_layer, s); + if (rdp_iso_init(self->iso_layer, s)) + log_message(LOG_LEVEL_ERROR, "rdp_mcs.c: rdp_iso_init() failed"); s_push_layer(s, mcs_hdr, 8); return 0; } diff --git a/rdp/rdp_rdp.c b/rdp/rdp_rdp.c index 973b8fe9..9ce63664 100644 --- a/rdp/rdp_rdp.c +++ b/rdp/rdp_rdp.c @@ -427,6 +427,12 @@ rdp_rdp_process_color_pointer_pdu(struct rdp_rdp *self, struct stream *s) return 1; } + /* there are only 32 cursors */ + if (cache_idx > 31) + { + return 1; + } + cursor = self->cursors + cache_idx; in_uint16_le(s, cursor->x); in_uint16_le(s, cursor->y); @@ -457,7 +463,7 @@ rdp_rdp_process_cached_pointer_pdu(struct rdp_rdp *self, struct stream *s) in_uint16_le(s, cache_idx); - if (cache_idx >= sizeof(self->cursors) / sizeof(cursor)) + if (cache_idx > 31) { return 1; } @@ -1164,6 +1170,9 @@ rdp_rec_check_file(struct rdp_rdp *self) } self->rec_fd = g_file_open(file_name); + if (self->rec_fd < 0) + return 1; + make_stream(s); init_stream(s, 8192); out_uint8a(s, "XRDPREC1", 8); diff --git a/rdp/rdp_tcp.c b/rdp/rdp_tcp.c index a919259e..f0a76d7d 100644 --- a/rdp/rdp_tcp.c +++ b/rdp/rdp_tcp.c @@ -157,7 +157,10 @@ int APP_CC 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 (self->sck < 0) + return 1; if (g_tcp_connect(self->sck, ip, port) == 0) { diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 9aa3ebe7..81218db1 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -16,21 +16,11 @@ EXTRA_INCLUDES = EXTRA_LIBS = EXTRA_FLAGS = -if XRDP_SIMPLESOUND -EXTRA_DEFINES += -DXRDP_SIMPLESOUND -EXTRA_LIBS += -lpthread -lpulse -lpulse-simple -endif - if XRDP_FUSE EXTRA_DEFINES += -DXRDP_FUSE EXTRA_LIBS += -lfuse endif -if XRDP_LOAD_PULSE_MODULES -EXTRA_DEFINES += -DXRDP_LOAD_PULSE_MODULES -EXTRA_LIBS += -lpulse -endif - AM_CFLAGS = \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index a89957ba..af2f6957 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -38,7 +38,7 @@ static struct trans *g_lis_trans = 0; static struct trans *g_con_trans = 0; static struct trans *g_api_lis_trans = 0; -static struct trans *g_api_con_trans = 0; +static struct list *g_api_con_trans_list = 0; /* list of apps using api functions */ static struct chan_item g_chan_items[32]; static int g_num_chan_items = 0; static int g_cliprdr_index = -1; @@ -608,7 +608,10 @@ process_message_channel_data(struct stream *s) int rv = 0; int length = 0; int total_length = 0; + int index; struct stream *ls; + struct trans *ltran; + struct xrdp_api_data *api_data; in_uint16_le(s, chan_id); in_uint16_le(s, chan_flags); @@ -641,29 +644,36 @@ process_message_channel_data(struct stream *s) { rv = drdynvc_data_in(s, chan_id, chan_flags, length, total_length); } - else if ((g_api_con_trans != 0) && - (chan_id == ((struct xrdp_api_data *) - (g_api_con_trans->callback_data))->chan_id)) + else if (g_api_con_trans_list != 0) { - LOG(10, ("process_message_channel_data length %d total_length %d " - "chan_flags 0x%8.8x", length, total_length, chan_flags)); - ls = g_api_con_trans->out_s; - - if (chan_flags & 1) /* first */ - { - init_stream(ls, total_length); - } - - out_uint8a(ls, s->p, length); - - if (chan_flags & 2) /* last */ + for (index = 0; index < g_api_con_trans_list->count; index++) { - s_mark_end(ls); - rv = trans_force_write(g_api_con_trans); + ltran = (struct trans *) list_get_item(g_api_con_trans_list, index); + if (ltran != 0) + { + api_data = (struct xrdp_api_data *) (ltran->callback_data); + if (api_data != 0) + { + if (api_data->chan_id == chan_id) + { + ls = ltran->out_s; + if (chan_flags & 1) /* first */ + { + init_stream(ls, total_length); + } + out_uint8a(ls, s->p, length); + if (chan_flags & 2) /* last */ + { + s_mark_end(ls); + rv = trans_force_write(ltran); + } + break; + } + } + } } } } - return rv; } @@ -796,9 +806,12 @@ my_api_trans_data_in(struct trans *trans) return 0; } - if (trans != g_api_con_trans) + if (g_api_con_trans_list != 0) { - return 1; + if (list_index_of(g_api_con_trans_list, (tintptr) trans) == -1) + { + return 1; + } } LOGM((LOG_LEVEL_DEBUG, "my_api_trans_data_in:")); @@ -812,7 +825,8 @@ my_api_trans_data_in(struct trans *trans) in_uint8s(s, 12); in_uint32_le(s, bytes_read); init_stream(s, bytes_read); - trans_force_read(trans, bytes_read); + if (trans_force_read(trans, bytes_read)) + log_message(LOG_LEVEL_ERROR, "chansrv.c: error reading from transport"); } else if (g_tcp_select(trans->sck, 0) & 1) { @@ -932,6 +946,7 @@ my_api_trans_conn_in(struct trans *trans, struct trans *new_trans) { LOG(0, ("my_api_trans_conn_in: trans_force_read failed")); trans_delete(new_trans); + return 1; } s->end = s->data; @@ -987,10 +1002,13 @@ my_api_trans_conn_in(struct trans *trans, struct trans *new_trans) new_trans->callback_data = ad; - trans_delete(g_api_con_trans); - g_api_con_trans = new_trans; - g_api_con_trans->trans_data_in = my_api_trans_data_in; - g_api_con_trans->header_size = 0; + if (g_api_con_trans_list == 0) + { + g_api_con_trans_list = list_create(); + } + new_trans->trans_data_in = my_api_trans_data_in; + new_trans->header_size = 0; + list_add_item(g_api_con_trans_list, (tintptr) new_trans); return 0; } @@ -1011,8 +1029,7 @@ setup_listen(void) { g_lis_trans = trans_create(TRANS_MODE_UNIX, 8192, 8192); g_lis_trans->is_term = g_is_term; - g_snprintf(port, 255, "/tmp/.xrdp/xrdp_chansrv_socket_%d", - 7200 + g_display_num); + g_snprintf(port, 255, XRDP_CHANSRV_STR, g_display_num); } else { @@ -1043,7 +1060,7 @@ setup_api_listen(void) g_api_lis_trans = trans_create(TRANS_MODE_UNIX, 8192 * 4, 8192 * 4); g_api_lis_trans->is_term = g_is_term; - g_snprintf(port, 255, "/tmp/.xrdp/xrdpapi_%d", g_display_num); + g_snprintf(port, 255, CHANSRV_API_STR, g_display_num); g_api_lis_trans->trans_conn_in = my_api_trans_conn_in; error = trans_listen(g_api_lis_trans, port); @@ -1067,7 +1084,9 @@ channel_thread_loop(void *in_val) int num_wobjs; int timeout; int error; + int index; THREAD_RV rv; + struct trans *ltran; LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread start")); rv = 0; @@ -1137,19 +1156,20 @@ channel_thread_loop(void *in_val) } } - LOG(10, ("0 %p", g_api_con_trans)); - - if (g_api_con_trans != 0) + if (g_api_con_trans_list != 0) { - LOG(10, ("1 %p %d", g_api_con_trans, g_tcp_can_recv(g_api_con_trans->sck, 0))); - - if (trans_check_wait_objs(g_api_con_trans) != 0) + for (index = g_api_con_trans_list->count - 1; index >= 0; index--) { - LOG(10, ("channel_thread_loop: trans_check_wait_objs failed, " - "or disconnected")); - g_free(g_api_con_trans->callback_data); - trans_delete(g_api_con_trans); - g_api_con_trans = 0; + ltran = (struct trans *) list_get_item(g_api_con_trans_list, index); + if (ltran != 0) + { + if (trans_check_wait_objs(ltran) != 0) + { + list_remove_item(g_api_con_trans_list, index); + g_free(ltran->callback_data); + trans_delete(ltran); + } + } } } @@ -1166,7 +1186,19 @@ channel_thread_loop(void *in_val) trans_get_wait_objs_rw(g_con_trans, objs, &num_objs, wobjs, &num_wobjs); trans_get_wait_objs(g_api_lis_trans, objs, &num_objs); - trans_get_wait_objs(g_api_con_trans, objs, &num_objs); + + if (g_api_con_trans_list != 0) + { + for (index = g_api_con_trans_list->count - 1; index >= 0; index--) + { + ltran = (struct trans *) list_get_item(g_api_con_trans_list, index); + if (ltran != 0) + { + trans_get_wait_objs(ltran, objs, &num_objs); + } + } + } + xcommon_get_wait_objs(objs, &num_objs, &timeout); sound_get_wait_objs(objs, &num_objs, &timeout); dev_redir_get_wait_objs(objs, &num_objs, &timeout); @@ -1181,8 +1213,20 @@ channel_thread_loop(void *in_val) g_con_trans = 0; trans_delete(g_api_lis_trans); g_api_lis_trans = 0; - trans_delete(g_api_con_trans); - g_api_con_trans = 0; + if (g_api_con_trans_list != 0) + { + for (index = g_api_con_trans_list->count - 1; index >= 0; index--) + { + ltran = (struct trans *) list_get_item(g_api_con_trans_list, index); + if (ltran != 0) + { + list_remove_item(g_api_con_trans_list, index); + g_free(ltran->callback_data); + trans_delete(ltran); + } + } + list_delete(g_api_con_trans_list); + } LOGM((LOG_LEVEL_INFO, "channel_thread_loop: thread stop")); g_set_wait_obj(g_thread_done_event); return rv; @@ -1599,11 +1643,6 @@ remove_struct_with_chan_id(tui32 dvc_chan_id) { int i; - if (dvc_chan_id < 0) - { - return -1; - } - for (i = 0; i < MAX_DVC_CHANNELS; i++) { if (g_dvc_channels[i]->dvc_chan_id == dvc_chan_id) diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index 2eb78ea0..c4532ead 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -39,6 +39,8 @@ //#define USE_SYNC_FLAG +static char g_fuse_mount_name[256] = "xrdp_client"; + /* FUSE mount point */ char g_fuse_root_path[256] = ""; char g_fuse_clipboard_path[256] = ""; /* for clipboard use */ @@ -71,7 +73,7 @@ int xfuse_create_share(tui32 device_id, char *dirname) { r void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId) {} void xfuse_devredir_cb_write_file(void *vp, char *buf, size_t length) {} void xfuse_devredir_cb_read_file(void *vp, char *buf, size_t length) {} -void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) {} +int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) {} void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) {} void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus) {} void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus) {} @@ -369,6 +371,37 @@ int clipboard_request_file_data(int stream_id, int lindex, int offset, static void xfuse_mark_as_stale(int pinode); static void xfuse_delete_stale_entries(int pinode); +/*****************************************************************************/ +int APP_CC +load_fuse_config(void) +{ + int index; + char cfg_file[256]; + struct list *items; + struct list *values; + char *item; + char *value; + + items = list_create(); + items->auto_free = 1; + values = list_create(); + values->auto_free = 1; + g_snprintf(cfg_file, 255, "%s/sesman.ini", XRDP_CFG_PATH); + file_by_name_read_section(cfg_file, "Chansrv", items, values); + for (index = 0; index < items->count; index++) + { + item = (char *)list_get_item(items, index); + value = (char *)list_get_item(values, index); + if (g_strcasecmp(item, "FuseMountName") == 0) + { + g_strncpy(g_fuse_mount_name, value, 255); + } + } + list_delete(items); + list_delete(values); + return 0; +} + /***************************************************************************** ** ** ** public functions - can be called from any code path ** @@ -381,7 +414,8 @@ static void xfuse_delete_stale_entries(int pinode); * @return 0 on success, -1 on failure *****************************************************************************/ -int xfuse_init() +int APP_CC +xfuse_init(void) { struct fuse_args args = FUSE_ARGS_INIT(0, NULL); @@ -398,8 +432,10 @@ int xfuse_init() return -1; } - /* define FUSE mount point to ~/xrdp_client */ - g_snprintf(g_fuse_root_path, 255, "%s/xrdp_client", g_getenv("HOME")); + load_fuse_config(); + + /* define FUSE mount point to ~/xrdp_client, ~/thinclient_drives */ + g_snprintf(g_fuse_root_path, 255, "%s/%s", g_getenv("HOME"), g_fuse_mount_name); g_snprintf(g_fuse_clipboard_path, 255, "%s/.clipboard", g_fuse_root_path); /* if FUSE mount point does not exist, create it */ @@ -460,7 +496,8 @@ int xfuse_init() * @return 0 on success, -1 on failure *****************************************************************************/ -int xfuse_deinit() +int APP_CC +xfuse_deinit(void) { xfuse_deinit_xrdp_fs(); fifo_deinit(&g_fifo_opendir); @@ -1385,7 +1422,7 @@ static void xfuse_update_xrdpfs_size() * Add a file or directory to xrdp file system *****************************************************************************/ -void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) +int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) { XFUSE_INFO *fip = (XFUSE_INFO *) vp; XRDP_INODE *xip = NULL; @@ -1393,13 +1430,14 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) if ((fip == NULL) || (xinode == NULL)) { log_error("fip or xinode are NULL"); - return; + return -1; } if (!xfuse_is_inode_valid(fip->inode)) { log_error("inode %d is not valid", fip->inode); - return; + g_free(xinode); + return -1; } log_debug("parent_inode=%d name=%s", fip->inode, xinode->name); @@ -1407,8 +1445,8 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) /* if filename is . or .. don't add it */ if ((strcmp(xinode->name, ".") == 0) || (strcmp(xinode->name, "..") == 0)) { - free(xinode); - return; + g_free(xinode); + return -1; } xfuse_dump_fs(); @@ -1417,9 +1455,9 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) { log_debug("inode=%d name=%s already exists in xrdp_fs; not adding it", fip->inode, xinode->name); - free(xinode); + g_free(xinode); xip->stale = 0; - return; + return -1; } xinode->parent_inode = fip->inode; @@ -1436,6 +1474,7 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) xfuse_update_xrdpfs_size(); xfuse_dump_fs(); + return 0; } /** @@ -1742,12 +1781,15 @@ void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus) new_xinode = xfuse_get_inode_from_pinode_name(fip->new_inode, fip->new_name); - if (new_xinode->mode & S_IFREG) - xfuse_delete_file_with_xinode(new_xinode); - else - xfuse_delete_dir_with_xinode(new_xinode); + if (new_xinode) + { + if (new_xinode->mode & S_IFREG) + xfuse_delete_file_with_xinode(new_xinode); + else + xfuse_delete_dir_with_xinode(new_xinode); - new_xinode = NULL; + new_xinode = NULL; + } } old_xinode = xfuse_get_inode_from_pinode_name(fip->inode, fip->name); @@ -1759,7 +1801,8 @@ void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus) } old_xinode->parent_inode = fip->new_inode; - strcpy(old_xinode->name, fip->new_name); + strncpy(old_xinode->name, fip->new_name, 1023); + old_xinode->name[1023] = 0; if (fip->inode != fip->new_inode) { @@ -1987,7 +2030,7 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, return; } - di = (struct dir_info *) fi->fh; + di = (struct dir_info *) (tintptr) (fi->fh); if (di == NULL) { /* something seriously wrong somewhere! */ @@ -2142,7 +2185,7 @@ static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent, } strcat(full_path, "/"); - strcat(full_path, name); + strncat(full_path, name, sizeof(full_path) - strlen(full_path)); if (xinode->is_loc_resource) { @@ -2583,7 +2626,6 @@ static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct fip, fip->fi, fip->fi->fh); FileId = handle->FileId; - free(handle); fip->fi->fh = 0; xinode->close_in_progress = 1; @@ -2592,6 +2634,8 @@ static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct log_error("failed to send devredir_close_file() cmd"); fuse_reply_err(req, EREMOTEIO); } + + free(handle); } /** diff --git a/sesman/chansrv/chansrv_fuse.h b/sesman/chansrv/chansrv_fuse.h index 09011452..4638add5 100644 --- a/sesman/chansrv/chansrv_fuse.h +++ b/sesman/chansrv/chansrv_fuse.h @@ -34,7 +34,7 @@ struct xrdp_inode time_t atime; /* Time of last access. */ time_t mtime; /* Time of last modification. */ time_t ctime; /* Time of last status change. */ - char name[256]; /* Dir or filename */ + char name[1024]; /* Dir or filename */ tui32 device_id; /* for file system redirection */ char is_synced; /* dir struct has been read from */ /* remote device, done just once */ @@ -57,7 +57,7 @@ int xfuse_file_contents_size(int stream_id, int file_size); int xfuse_add_clip_dir_item(char *filename, int flags, int size, int lindex); /* functions that are invoked from devredir */ -void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode); +int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode); void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus); void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId); void xfuse_devredir_cb_read_file(void *vp, char *buf, size_t length); diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c index 6d52da85..310e2093 100644 --- a/sesman/chansrv/clipboard.c +++ b/sesman/chansrv/clipboard.c @@ -1048,8 +1048,11 @@ clipboard_process_format_announce(struct stream *s, int clip_msg_status, log_debug("clipboard_process_format_announce: formatId 0x%8.8x " "wszFormatName [%s] clip_msg_len %d", formatId, desc, clip_msg_len); - g_formatIds[g_num_formatIds] = formatId; - g_num_formatIds++; + if (g_num_formatIds <= 15) + { + g_formatIds[g_num_formatIds] = formatId; + g_num_formatIds++; + } if (g_num_formatIds > 15) { log_debug("clipboard_process_format_announce: max formats"); diff --git a/sesman/chansrv/clipboard_file.c b/sesman/chansrv/clipboard_file.c index 96f1b0e8..ff95b0a0 100644 --- a/sesman/chansrv/clipboard_file.c +++ b/sesman/chansrv/clipboard_file.c @@ -446,7 +446,13 @@ clipboard_send_file_data(int streamId, int lindex, full_fn); return 1; } - g_file_seek(fd, nPositionLow); + if (g_file_seek(fd, nPositionLow) < 0) + { + log_message(LOG_LEVEL_ERROR, "clipboard_send_file_data: seek error " + "in file: %s\n", full_fn); + g_file_close(fd); + return 1; + } make_stream(s); init_stream(s, cbRequested + 64); size = g_file_read(fd, s->data + 12, cbRequested); diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c index cdcc9e94..cea42c81 100644 --- a/sesman/chansrv/devredir.c +++ b/sesman/chansrv/devredir.c @@ -118,7 +118,7 @@ dev_redir_init(void) } u; /* get a random number that will act as a unique clientID */ - if ((fd = open("/dev/urandom", O_RDONLY))) + if ((fd = open("/dev/urandom", O_RDONLY)) != -1) { if (read(fd, u.buf, 4) != 4) { @@ -790,10 +790,14 @@ dev_redir_proc_device_iocompletion(struct stream *s) fuse_data = devredir_fuse_data_dequeue(irp); if (fuse_data == NULL) + { log_error("fuse_data is NULL"); - - xfuse_devredir_cb_read_file(fuse_data->data_ptr, s->p, Length); - devredir_irp_delete(irp); + } + else + { + xfuse_devredir_cb_read_file(fuse_data->data_ptr, s->p, Length); + devredir_irp_delete(irp); + } break; case CID_WRITE: @@ -802,10 +806,14 @@ dev_redir_proc_device_iocompletion(struct stream *s) fuse_data = devredir_fuse_data_dequeue(irp); if (fuse_data == NULL) + { log_error("fuse_data is NULL"); - - xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length); - devredir_irp_delete(irp); + } + else + { + xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length); + devredir_irp_delete(irp); + } break; case CID_CLOSE: @@ -879,7 +887,7 @@ dev_redir_proc_query_dir_response(IRP *irp, tui32 IoStatus) { FUSE_DATA *fuse_data = NULL; - XRDP_INODE *xinode = NULL; + XRDP_INODE *xinode; tui32 Length; tui32 NextEntryOffset; @@ -1017,7 +1025,8 @@ dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path) irp->CompletionId = g_completion_id++; irp->completion_type = CID_CREATE_DIR_REQ; irp->DeviceId = device_id; - strcpy(irp->pathname, path); + + strncpy(irp->pathname, path, 255); devredir_fuse_data_enqueue(irp, fusep); DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE; @@ -1060,7 +1069,7 @@ dev_redir_file_open(void *fusep, tui32 device_id, char *path, if (type & OP_RENAME_FILE) { irp->completion_type = CID_RENAME_FILE; - strcpy(irp->gen_buf, gen_buf); + strncpy(irp->gen_buf, gen_buf, 1023); } else { @@ -1069,7 +1078,8 @@ dev_redir_file_open(void *fusep, tui32 device_id, char *path, irp->CompletionId = g_completion_id++; irp->DeviceId = device_id; - strcpy(irp->pathname, path); + + strncpy(irp->pathname, path, 255); devredir_fuse_data_enqueue(irp, fusep); if (mode & O_CREAT) @@ -1174,7 +1184,8 @@ devredir_rmdir_or_file(void *fusep, tui32 device_id, char *path, int mode) irp->CompletionId = g_completion_id++; irp->completion_type = CID_RMDIR_OR_FILE; irp->DeviceId = device_id; - strcpy(irp->pathname, path); + + strncpy(irp->pathname, path, 255); devredir_fuse_data_enqueue(irp, fusep); //DesiredAccess = DA_DELETE | DA_FILE_READ_ATTRIBUTES | DA_SYNCHRONIZE; @@ -1216,6 +1227,7 @@ devredir_file_read(void *fusep, tui32 DeviceId, tui32 FileId, { log_error("no IRP found with FileId = %d", FileId); xfuse_devredir_cb_read_file(fusep, NULL, 0); + xstream_free(s); return -1; } @@ -1224,6 +1236,7 @@ devredir_file_read(void *fusep, tui32 DeviceId, tui32 FileId, { /* system out of memory */ xfuse_devredir_cb_read_file(fusep, NULL, 0); + xstream_free(s); return -1; } new_irp->FileId = 0; @@ -1268,6 +1281,7 @@ dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId, { log_error("no IRP found with FileId = %d", FileId); xfuse_devredir_cb_write_file(fusep, NULL, 0); + xstream_free(s); return -1; } @@ -1276,6 +1290,7 @@ dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId, { /* system out of memory */ xfuse_devredir_cb_write_file(fusep, NULL, 0); + xstream_free(s); return -1; } new_irp->FileId = 0; diff --git a/sesman/chansrv/pcsc/xrdp_pcsc.c b/sesman/chansrv/pcsc/xrdp_pcsc.c index f4aaba14..3b830d60 100644 --- a/sesman/chansrv/pcsc/xrdp_pcsc.c +++ b/sesman/chansrv/pcsc/xrdp_pcsc.c @@ -15,8 +15,13 @@ typedef unsigned char BYTE; typedef BYTE *LPBYTE; -typedef unsigned int LONG; +#ifdef __APPLE__ +typedef int LONG; typedef unsigned int DWORD; +#else +typedef long LONG; +typedef unsigned long DWORD; +#endif typedef DWORD *LPDWORD; typedef const void *LPCVOID; typedef const char *LPCSTR; @@ -59,6 +64,8 @@ PCSC_API SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 }; #define LLOG_LEVEL 5 #define LLOGLN(_level, _args) \ do { if (_level < LLOG_LEVEL) { printf _args ; printf("\n"); } } while (0) +#define LHEXDUMP(_level, _args) \ + do { if (_level < LLOG_LEVEL) { lhexdump _args ; } } while (0) #define SCARD_ESTABLISH_CONTEXT 0x01 #define SCARD_RELEASE_CONTEXT 0x02 @@ -103,6 +110,50 @@ static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; static char g_error_str[512]; /*****************************************************************************/ +/* produce a hex dump */ +static void +lhexdump(void *p, int len) +{ + unsigned char *line; + int i; + int thisline; + int offset; + + line = (unsigned char *)p; + offset = 0; + + while (offset < len) + { + printf("%04x ", offset); + thisline = len - offset; + + if (thisline > 16) + { + thisline = 16; + } + + for (i = 0; i < thisline; i++) + { + printf("%02x ", line[i]); + } + + for (; i < 16; i++) + { + printf(" "); + } + + for (i = 0; i < thisline; i++) + { + printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.'); + } + + printf("\n"); + offset += thisline; + line += thisline; + } +} + +/*****************************************************************************/ static int get_display_num_from_display(const char *display_text) { @@ -156,7 +207,7 @@ get_display_num_from_display(const char *display_text) host[host_index] = 0; disp[disp_index] = 0; scre[scre_index] = 0; - LLOGLN(0, ("get_display_num_from_display: host [%s] disp [%s] scre [%s]", + LLOGLN(10, ("get_display_num_from_display: host [%s] disp [%s] scre [%s]", host, disp, scre)); rv = atoi(disp); return rv; @@ -219,7 +270,7 @@ connect_to_chansrv(void) bytes = sizeof(saddr.sun_path); snprintf(saddr.sun_path, bytes, "%s/.pcsc%d/pcscd.comm", home_str, dis); saddr.sun_path[bytes - 1] = 0; - LLOGLN(0, ("connect_to_chansrv: connecting to %s", saddr.sun_path)); + LLOGLN(10, ("connect_to_chansrv: connecting to %s", saddr.sun_path)); psaddr = (struct sockaddr *) &saddr; bytes = sizeof(struct sockaddr_un); error = connect(g_sck, psaddr, bytes); @@ -256,6 +307,8 @@ send_message(int code, char *data, int bytes) pthread_mutex_unlock(&g_mutex); return 1; } + LLOGLN(10, ("send_message:")); + LHEXDUMP(10, (data, bytes)); pthread_mutex_unlock(&g_mutex); return 0; } @@ -392,7 +445,7 @@ SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, } context = GET_UINT32(msg, 0); status = GET_UINT32(msg, 4); - LLOGLN(10, ("SCardEstablishContext: got context 0x%8.8x", context)); + LLOGLN(10, ("SCardEstablishContext: got context 0x%8.8x", (int)context)); *phContext = context; return status; } @@ -463,7 +516,7 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, LLOGLN(10, ("SCardConnect:")); LLOGLN(10, ("SCardConnect: hContext 0x%8.8x szReader %s dwShareMode %d " "dwPreferredProtocols %d", - hContext, szReader, dwShareMode, dwPreferredProtocols)); + (int)hContext, szReader, (int)dwShareMode, (int)dwPreferredProtocols)); if (g_sck == -1) { LLOGLN(0, ("SCardConnect: error, not connected")); @@ -507,7 +560,7 @@ SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode, status = GET_UINT32(msg, 8); LLOGLN(10, ("SCardConnect: got status 0x%8.8x hCard 0x%8.8x " "dwActiveProtocol %d", - status, *phCard, *pdwActiveProtocol)); + status, (int)*phCard, (int)*pdwActiveProtocol)); return status; } @@ -536,7 +589,7 @@ SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) int status; LLOGLN(10, ("SCardDisconnect: hCard 0x%8.8x dwDisposition %d", - hCard, dwDisposition)); + (int)hCard, (int)dwDisposition)); if (g_sck == -1) { LLOGLN(0, ("SCardDisconnect: error, not connected")); @@ -575,7 +628,7 @@ SCardBeginTransaction(SCARDHANDLE hCard) int bytes; int status; - LLOGLN(10, ("SCardBeginTransaction: hCard 0x%8.8x", hCard)); + LLOGLN(10, ("SCardBeginTransaction: hCard 0x%8.8x", (int)hCard)); if (hCard == 0) { LLOGLN(0, ("SCardBeginTransaction: error, bad hCard")); @@ -665,7 +718,7 @@ SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LLOGLN(10, ("SCardStatus:")); if (hCard == 0) { - LLOGLN(0, ("SCardStatus: error, bad hCard")); + LLOGLN(10, ("SCardStatus: error, bad hCard")); return SCARD_F_INTERNAL_ERROR; } if (g_sck == -1) @@ -673,9 +726,9 @@ SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LLOGLN(0, ("SCardStatus: error, not connected")); return SCARD_F_INTERNAL_ERROR; } - LLOGLN(10, (" hCard 0x%8.8x", hCard)); - LLOGLN(10, (" cchReaderLen %d", *pcchReaderLen)); - LLOGLN(10, (" cbAtrLen %d", *pcbAtrLen)); + LLOGLN(10, (" hCard 0x%8.8x", (int)hCard)); + LLOGLN(10, (" cchReaderLen %d", (int)*pcchReaderLen)); + LLOGLN(10, (" cbAtrLen %d", (int)*pcbAtrLen)); cchReaderLen = *pcchReaderLen; msg = (char *) malloc(8192); @@ -703,10 +756,10 @@ SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, return SCARD_F_INTERNAL_ERROR; } - LLOGLN(10, ("SCardStatus: cchReaderLen in %d", *pcchReaderLen)); + LLOGLN(10, ("SCardStatus: cchReaderLen in %d", (int)*pcchReaderLen)); offset = 0; *pcchReaderLen = GET_UINT32(msg, offset); - LLOGLN(10, ("SCardStatus: cchReaderLen out %d", *pcchReaderLen)); + LLOGLN(10, ("SCardStatus: cchReaderLen out %d", (int)*pcchReaderLen)); offset += 4; if (cchReaderLen > 0) { @@ -721,14 +774,18 @@ SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, LPDWORD pcchReaderLen, LLOGLN(10, ("SCardStatus: mszReaderName out %s", mszReaderName)); offset += *pcchReaderLen; *pdwState = GET_UINT32(msg, offset); - LLOGLN(10, ("SCardStatus: dwState %d", *pdwState)); + if (*pdwState == 1) + { + *pdwState = 0x34; + } + LLOGLN(10, ("SCardStatus: dwState %d", (int)*pdwState)); offset += 4; *pdwProtocol = GET_UINT32(msg, offset); - LLOGLN(10, ("SCardStatus: dwProtocol %d", *pdwProtocol)); + LLOGLN(10, ("SCardStatus: dwProtocol %d", (int)*pdwProtocol)); offset += 4; *pcbAtrLen = GET_UINT32(msg, offset); offset += 4; - LLOGLN(10, ("SCardStatus: cbAtrLen %d", *pcbAtrLen)); + LLOGLN(10, ("SCardStatus: cbAtrLen %d", (int)*pcbAtrLen)); memcpy(pbAtr, msg + offset, *pcbAtrLen); offset += *pcbAtrLen; status = GET_UINT32(msg, offset); @@ -757,7 +814,7 @@ SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, char atr[36]; LLOGLN(10, ("SCardGetStatusChange:")); - LLOGLN(10, (" dwTimeout %d cReaders %d", dwTimeout, cReaders)); + LLOGLN(10, (" dwTimeout %d cReaders %d", (int)dwTimeout, (int)cReaders)); if (g_sck == -1) { LLOGLN(0, ("SCardGetStatusChange: error, not connected")); @@ -829,7 +886,7 @@ SCardGetStatusChange(SCARDCONTEXT hContext, DWORD dwTimeout, } cReaders = GET_UINT32(msg, 0); offset = 4; - LLOGLN(10, ("SCardGetStatusChange: got back cReaders %d", cReaders)); + LLOGLN(10, ("SCardGetStatusChange: got back cReaders %d", (int)cReaders)); for (index = 0; index < cReaders; index++) { rname = rgReaderStates[index].szReader; @@ -897,10 +954,10 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, LLOGLN(0, ("SCardControl: error, not connected")); return SCARD_F_INTERNAL_ERROR; } - LLOGLN(10, (" hCard 0x%8.8x", hCard)); - LLOGLN(10, (" dwControlCode 0x%8.8x", dwControlCode)); - LLOGLN(10, (" cbSendLength %d", cbSendLength)); - LLOGLN(10, (" cbRecvLength %d", cbRecvLength)); + LLOGLN(10, (" hCard 0x%8.8x", (int)hCard)); + LLOGLN(10, (" dwControlCode 0x%8.8x", (int)dwControlCode)); + LLOGLN(10, (" cbSendLength %d", (int)cbSendLength)); + LLOGLN(10, (" cbRecvLength %d", (int)cbRecvLength)); /* #define SCARD_CTL_CODE(code) (0x42000000 + (code)) control_code = (control_code & 0x3ffc) >> 2; @@ -910,7 +967,7 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, dwControlCode = dwControlCode - 0x42000000; dwControlCode = dwControlCode << 2; dwControlCode = dwControlCode | (49 << 16); - LLOGLN(10, (" MS dwControlCode 0x%8.8x", dwControlCode)); + LLOGLN(10, (" MS dwControlCode 0x%8.8d", (int)dwControlCode)); msg = (char *) malloc(8192); offset = 0; @@ -946,7 +1003,7 @@ SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer, } offset = 0; *lpBytesReturned = GET_UINT32(msg, offset); - LLOGLN(10, (" cbRecvLength %d", *lpBytesReturned)); + LLOGLN(10, (" cbRecvLength %d", (int)*lpBytesReturned)); offset += 4; memcpy(pbRecvBuffer, msg + offset, *lpBytesReturned); offset += *lpBytesReturned; @@ -976,9 +1033,10 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, LLOGLN(0, ("SCardTransmit: error, not connected")); return SCARD_F_INTERNAL_ERROR; } - LLOGLN(10, (" hCard 0x%8.8x", hCard)); - LLOGLN(10, (" cbSendLength %d", cbSendLength)); - LLOGLN(10, (" cbRecvLength %d", *pcbRecvLength)); + + LLOGLN(10, (" hCard 0x%8.8x", (int)hCard)); + LLOGLN(10, (" cbSendLength %d", (int)cbSendLength)); + LLOGLN(10, (" cbRecvLength %d", (int)*pcbRecvLength)); LLOGLN(10, (" pioSendPci->dwProtocol %d", (int)(pioSendPci->dwProtocol))); LLOGLN(10, (" pioSendPci->cbPciLength %d", (int)(pioSendPci->cbPciLength))); LLOGLN(10, (" pioRecvPci %p", pioRecvPci)); @@ -993,9 +1051,11 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, offset += 4; SET_UINT32(msg, offset, pioSendPci->dwProtocol); offset += 4; - SET_UINT32(msg, offset, pioSendPci->cbPciLength); +/* SET_UINT32(msg, offset, pioSendPci->cbPciLength); */ + SET_UINT32(msg, offset, 8); offset += 4; - extra_len = pioSendPci->cbPciLength - 8; +/* extra_len = pioSendPci->cbPciLength - 8; */ + extra_len = 0; SET_UINT32(msg, offset, extra_len); offset += 4; memcpy(msg + offset, pioSendPci + 1, extra_len); @@ -1070,8 +1130,9 @@ SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci, } *pcbRecvLength = GET_UINT32(msg, offset); offset += 4; - LLOGLN(10, (" cbRecvLength %d", *pcbRecvLength)); + LLOGLN(10, (" cbRecvLength %d", (int)*pcbRecvLength)); memcpy(pbRecvBuffer, msg + offset, *pcbRecvLength); + LHEXDUMP(10, (pbRecvBuffer, *pcbRecvLength)); offset += *pcbRecvLength; status = GET_UINT32(msg, offset); free(msg); @@ -1113,12 +1174,16 @@ SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, LLOGLN(10, ("SCardListReaders:")); LLOGLN(10, ("SCardListReaders: mszGroups %s", mszGroups)); - LLOGLN(10, ("SCardListReaders: *pcchReaders %d", *pcchReaders)); + LLOGLN(10, ("SCardListReaders: *pcchReaders %d", (int)*pcchReaders)); if (g_sck == -1) { LLOGLN(0, ("SCardListReaders: error, not connected")); return SCARD_F_INTERNAL_ERROR; } + if ((mszGroups == NULL) && (mszReaders == NULL)) + { + *pcchReaders = 0; + } msg = (char *) malloc(8192); offset = 0; SET_UINT32(msg, offset, hContext); diff --git a/sesman/chansrv/pulse/module-xrdp-sink.c b/sesman/chansrv/pulse/module-xrdp-sink.c index d56a4883..8606f412 100644 --- a/sesman/chansrv/pulse/module-xrdp-sink.c +++ b/sesman/chansrv/pulse/module-xrdp-sink.c @@ -58,6 +58,15 @@ #include <pulsecore/thread-mq.h> #include <pulsecore/rtpoll.h> +/* defined in pulse/version.h */ +#if PA_PROTOCOL_VERSION > 28 +/* these used to be defined in pulsecore/macro.h */ +typedef bool pa_bool_t; +#define FALSE ((pa_bool_t) 0) +#define TRUE (!FALSE) +#else +#endif + #include "module-xrdp-sink-symdef.h" PA_MODULE_AUTHOR("Jay Sorg"); @@ -268,6 +277,19 @@ static int get_display_num_from_display(char *display_text) { return display_num; } +static int lsend(int fd, char *data, int bytes) { + int sent = 0; + int error; + while (sent < bytes) { + error = send(fd, data + sent, bytes - sent, 0); + if (error < 1) { + return error; + } + sent += error; + } + return sent; +} + static int data_send(struct userdata *u, pa_memchunk *chunk) { char *data; int bytes; @@ -316,7 +338,7 @@ static int data_send(struct userdata *u, pa_memchunk *chunk) { h.code = 0; h.bytes = bytes + 8; - if (send(u->fd, &h, 8, 0) != 8) { + if (lsend(u->fd, (char*)(&h), 8) != 8) { pa_log("data_send: send failed"); close(u->fd); u->fd = 0; @@ -327,7 +349,7 @@ static int data_send(struct userdata *u, pa_memchunk *chunk) { data = (char*)pa_memblock_acquire(chunk->memblock); data += chunk->index; - sent = send(u->fd, data, bytes, 0); + sent = lsend(u->fd, data, bytes); pa_memblock_release(chunk->memblock); if (sent != bytes) { @@ -349,7 +371,7 @@ static int close_send(struct userdata *u) { } h.code = 1; h.bytes = 8; - if (send(u->fd, &h, 8, 0) != 8) { + if (lsend(u->fd, (char*)(&h), 8) != 8) { pa_log("close_send: send failed"); close(u->fd); u->fd = 0; diff --git a/sesman/chansrv/pulse/module-xrdp-source.c b/sesman/chansrv/pulse/module-xrdp-source.c index 2d7ec4fa..1c03b069 100644 --- a/sesman/chansrv/pulse/module-xrdp-source.c +++ b/sesman/chansrv/pulse/module-xrdp-source.c @@ -45,6 +45,15 @@ #include <pulsecore/thread-mq.h> #include <pulsecore/thread.h> +/* defined in pulse/version.h */ +#if PA_PROTOCOL_VERSION > 28 +/* these used to be defined in pulsecore/macro.h */ +typedef bool pa_bool_t; +#define FALSE ((pa_bool_t) 0) +#define TRUE (!FALSE) +#else +#endif + #include "module-xrdp-source-symdef.h" PA_MODULE_AUTHOR("Laxmikant Rashinkar"); @@ -329,8 +338,7 @@ int pa__init(pa_module *m) { pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME)); pa_source_new_data_set_sample_spec(&data, &ss); pa_source_new_data_set_channel_map(&data, &map); - //pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "Null Input")); - pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "xrdp Input")); + pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "xrdp source")); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract"); u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY | PA_SOURCE_DYNAMIC_LATENCY); @@ -361,7 +369,15 @@ int pa__init(pa_module *m) { u->source->thread_info.max_rewind = pa_usec_to_bytes(u->block_usec, &u->source->sample_spec); - if (!(u->thread = pa_thread_new("null-source", thread_func, u))) { + #if defined(PA_CHECK_VERSION) + #if PA_CHECK_VERSION(0, 9, 22) + if (!(u->thread = pa_thread_new("xrdp-source", thread_func, u))) { + #else + if (!(u->thread = pa_thread_new(thread_func, u))) { + #endif + #else + if (!(u->thread = pa_thread_new(thread_func, u))) + #endif pa_log("Failed to create thread."); goto fail; } diff --git a/sesman/chansrv/rail.c b/sesman/chansrv/rail.c index 4bfeef7e..f3777970 100644 --- a/sesman/chansrv/rail.c +++ b/sesman/chansrv/rail.c @@ -71,6 +71,8 @@ static int g_xrr_event_base = 0; /* non zero means we got extension */ static Cursor g_default_cursor = 0; +static char *g_override_window_title = 0; + /* used in valid field of struct rail_window_data */ #define RWD_X (1 << 0) #define RWD_Y (1 << 1) @@ -621,6 +623,18 @@ rail_process_activate(struct stream *s, int size) } /*****************************************************************************/ +static int +rail_select_input(Window window_id) +{ + XSelectInput(g_display, window_id, + PropertyChangeMask | StructureNotifyMask | + SubstructureNotifyMask | FocusChangeMask | + EnterWindowMask | LeaveWindowMask); + XSync(g_display, 0); + return 0; +} + +/*****************************************************************************/ static int APP_CC rail_restore_windows(void) { @@ -637,6 +651,7 @@ rail_restore_windows(void) XGetWindowAttributes(g_display, children[i], &window_attributes); if (!window_attributes.override_redirect) { + rail_select_input(children[i]); if (window_attributes.map_state == IsViewable) { rail_win_set_state(children[i], 0x0); /* WithdrawnState */ @@ -724,7 +739,7 @@ rail_win_get_state(Window win) (unsigned char **)&data, &nitems); - if (data || nitems > 0) + if (data && nitems > 0) { rv = *(unsigned long *)data; XFree(data); @@ -760,31 +775,40 @@ rail_win_set_state(Window win, unsigned long state) } /*****************************************************************************/ +/* *data pointer that needs g_free */ static int APP_CC rail_win_get_text(Window win, char **data) { int ret = 0; int i = 0; unsigned long nitems = 0; + unsigned char *ldata = 0; + char *lldata = 0; + if (g_override_window_title != 0) + { + *data = g_strdup(g_override_window_title); + return g_strlen(*data); + } ret = rail_get_property(g_display, win, g_utf8_string, g_net_wm_name, - (unsigned char **)data, &nitems); + &ldata, &nitems); if (ret != 0) { /* _NET_WM_NAME isn't set, use WM_NAME (XFetchName) instead */ - XFetchName(g_display, win, data); + XFetchName(g_display, win, &lldata); + *data = g_strdup(lldata); + i = g_strlen(*data); + XFree(lldata); + return i; } - if (data) + *data = 0; + if (ldata) { - char *ptr = *data; - for (; ptr != NULL; i++) - { - if (ptr[i] == '\0') - { - break; - } - } + *data = g_strdup((char *)ldata); + i = g_strlen(*data); + XFree(ldata); + return i; } return i; @@ -1207,6 +1231,7 @@ rail_win_send_text(Window win) int crc; struct rail_window_data* rwd; + LOG(10, ("chansrv::rail_win_send_text:")); len = rail_win_get_text(win, &data); rwd = rail_get_window_data_safe(win); if (rwd != 0) @@ -1219,7 +1244,7 @@ rail_win_send_text(Window win) if (rwd->title_crc == crc) { LOG(10, ("chansrv::rail_win_send_text: skipping, title not changed")); - XFree(data); + g_free(data); XFree(rwd); return 0; } @@ -1229,13 +1254,15 @@ rail_win_send_text(Window win) else { LOG(0, ("chansrv::rail_win_send_text: error rail_get_window_data_safe failed")); + g_free(data); return 1; } - if (data && len > 0) { + if (data && len > 0) + { LOG(10, ("chansrv::rail_win_send_text: 0x%8.8x text %s length %d", win, data, len)); make_stream(s); - init_stream(s, 1024); + init_stream(s, len + 1024); flags = WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_FIELD_TITLE; out_uint32_le(s, 8); /* update title info */ out_uint32_le(s, win); /* window id */ @@ -1251,10 +1278,7 @@ rail_win_send_text(Window win) rwd->title_crc = crc; rail_set_window_data(win, rwd); } - if (data != 0) - { - XFree(data); - } + g_free(data); XFree(rwd); return 0; } @@ -1355,7 +1379,8 @@ rail_create_window(Window window_id, Window owner_id) flags = WINDOW_ORDER_TYPE_WINDOW; } - title_size = rail_win_get_text(window_id, &title_bytes); + title_size = 0; + title_bytes = 0; XGetTransientForHint(g_display, window_id, &transient_for); @@ -1363,21 +1388,24 @@ rail_create_window(Window window_id, Window owner_id) { style = RAIL_STYLE_TOOLTIP; ext_style = RAIL_EXT_STYLE_TOOLTIP; + /* for tooltips, we don't grab the window text */ } else if (transient_for > 0) { style = RAIL_STYLE_DIALOG; ext_style = RAIL_EXT_STYLE_DIALOG; owner_id = transient_for; + title_size = rail_win_get_text(window_id, &title_bytes); } else { style = RAIL_STYLE_NORMAL; ext_style = RAIL_EXT_STYLE_NORMAL; + title_size = rail_win_get_text(window_id, &title_bytes); } make_stream(s); - init_stream(s, 1024); + init_stream(s, title_size + 1024 + num_window_rects * 8 + num_visibility_rects * 8); out_uint32_le(s, 2); /* create_window */ out_uint32_le(s, window_id); /* window_id */ @@ -1387,6 +1415,7 @@ rail_create_window(Window window_id, Window owner_id) out_uint32_le(s, ext_style); /* extended_style */ flags |= WINDOW_ORDER_FIELD_STYLE; out_uint32_le(s, 0x05); /* show_state */ + LOG(10, (" title %s", title_bytes)); flags |= WINDOW_ORDER_FIELD_SHOW; if (title_size > 0) { @@ -1449,7 +1478,7 @@ rail_create_window(Window window_id, Window owner_id) s_mark_end(s); send_rail_drawing_orders(s->data, (int)(s->end - s->data)); free_stream(s); - XFree(title_bytes); + g_free(title_bytes); rail_set_window_data(window_id, rwd); XFree(rwd); return 0; @@ -1608,7 +1637,7 @@ rail_configure_request_window(XConfigureRequestEvent* config) flags = WINDOW_ORDER_TYPE_WINDOW; make_stream(s); - init_stream(s, 1024); + init_stream(s, 1024 + num_window_rects * 8 + num_visibility_rects * 8); out_uint32_le(s, 10); /* configure_window */ out_uint32_le(s, window_id); /* window_id */ @@ -1692,7 +1721,7 @@ rail_configure_window(XConfigureEvent *config) flags = WINDOW_ORDER_TYPE_WINDOW; make_stream(s); - init_stream(s, 1024); + init_stream(s, 1024 + num_window_rects * 8 + num_visibility_rects * 8); out_uint32_le(s, 10); /* configure_window */ out_uint32_le(s, window_id); /* window_id */ @@ -1822,10 +1851,7 @@ rail_xevent(void *xevent) case CreateNotify: LOG(10, (" got CreateNotify window 0x%8.8x parent 0x%8.8x", lxevent->xcreatewindow.window, lxevent->xcreatewindow.parent)); - XSelectInput(g_display, lxevent->xcreatewindow.window, - PropertyChangeMask | StructureNotifyMask | - SubstructureNotifyMask | FocusChangeMask | - EnterWindowMask | LeaveWindowMask); + rail_select_input(lxevent->xcreatewindow.window); break; case DestroyNotify: @@ -1865,7 +1891,7 @@ rail_xevent(void *xevent) XGetWindowAttributes(g_display, lxevent->xmap.window, &wnd_attributes); if (wnd_attributes.map_state == IsViewable) { - rail_create_window(lxevent->xmap.window, lxevent->xmap.event); + rail_create_window(lxevent->xmap.window, g_root_window); if (!wnd_attributes.override_redirect) { rail_win_set_state(lxevent->xmap.window, 0x1); /* NormalState */ @@ -1887,7 +1913,16 @@ rail_xevent(void *xevent) LOG(10, (" window 0x%8.8x is unmapped", lxevent->xunmap.window)); if (index >= 0) { + XGetWindowAttributes(g_display, lxevent->xunmap.window, &wnd_attributes); + if (wnd_attributes.override_redirect) + { + // remove popups + rail_destroy_window(lxevent->xunmap.window); + list_remove_item(g_window_list, index); + } else { rail_show_window(lxevent->xunmap.window, 0x0); + } + rv = 0; } } diff --git a/sesman/chansrv/smartcard.c b/sesman/chansrv/smartcard.c index 0d6d5405..a07e36eb 100644 --- a/sesman/chansrv/smartcard.c +++ b/sesman/chansrv/smartcard.c @@ -861,11 +861,6 @@ scard_make_new_ioctl(IRP *irp, tui32 ioctl) struct stream *s; xstream_new(s, 1024 * 4); - if (s == NULL) - { - log_error("system out of memory"); - return s; - } devredir_insert_DeviceIoRequest(s, irp->DeviceId, diff --git a/sesman/chansrv/smartcard_pcsc.c b/sesman/chansrv/smartcard_pcsc.c index 1d1618dc..9824432e 100644 --- a/sesman/chansrv/smartcard_pcsc.c +++ b/sesman/chansrv/smartcard_pcsc.c @@ -603,6 +603,7 @@ scard_process_list_readers(struct trans *con, struct stream *in_s) { LLOGLN(0, ("scard_process_list_readers: " "get_pcsc_context_by_app_context failed")); + g_free(groups); return 1; } pcscListReaders = g_malloc(sizeof(struct pcsc_list_readers), 1); @@ -1489,6 +1490,7 @@ scard_process_get_status_change(struct trans *con, struct stream *in_s) { LLOGLN(0, ("scard_process_get_status_change: " "get_pcsc_context_by_app_context failed")); + g_free(rsa); return 1; } scard_send_get_status_change(user_data, diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index 8c76c9bc..f5e17fef 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2009-2013 + * Copyright (C) Jay Sorg 2009-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,14 +23,11 @@ #include <signal.h> #include <sys/un.h> -#ifdef XRDP_LOAD_PULSE_MODULES -#include <pulse/util.h> -#endif - #include "sound.h" #include "thread_calls.h" #include "defines.h" #include "fifo.h" +#include "file_loc.h" extern int g_rdpsnd_chan_id; /* in chansrv.c */ extern int g_display_num; /* in chansrv.c */ @@ -56,14 +53,6 @@ int g_buf_index = 0; int g_sent_time[256]; int g_sent_flag[256]; -#if defined(XRDP_SIMPLESOUND) -static void *DEFAULT_CC -read_raw_audio_data(void *arg); -#endif - -#define CHANSRV_PORT_OUT_STR "/tmp/.xrdp/xrdp_chansrv_audio_out_socket_%d" -#define CHANSRV_PORT_IN_STR "/tmp/.xrdp/xrdp_chansrv_audio_in_socket_%d" - struct xr_wave_format_ex { int wFormatTag; @@ -155,6 +144,25 @@ static struct xr_wave_format_ex *g_wave_inp_formats[SND_NUM_INP_FORMATS] = static int g_client_input_format_index = 0; static int g_server_input_format_index = 0; +/* microphone related */ +static int APP_CC +sound_send_server_input_formats(void); +static int APP_CC +sound_process_input_format(int aindex, int wFormatTag, + int nChannels, int nSamplesPerSec, + int nAvgBytesPerSec, int nBlockAlign, + int wBitsPerSample, int cbSize, char *data); +static int APP_CC +sound_process_input_formats(struct stream *s, int size); +static int APP_CC +sound_input_start_recording(void); +static int APP_CC +sound_input_stop_recording(void); +static int APP_CC +sound_process_input_data(struct stream *s, int bytes); +static int DEFAULT_CC +sound_sndsrvr_source_data_in(struct trans *trans); + /*****************************************************************************/ static int APP_CC sound_send_server_output_formats(void) @@ -224,7 +232,6 @@ sound_send_server_output_formats(void) } /*****************************************************************************/ - static int sound_send_training(void) { @@ -365,13 +372,15 @@ sound_send_wave_data_chunk(char *data, int data_bytes) if ((data_bytes < 4) || (data_bytes > 128 * 1024)) { LOG(0, ("sound_send_wave_data_chunk: bad data_bytes %d", data_bytes)); - return 0; + return 1; } + LOG(20, ("sound_send_wave_data_chunk: g_sent_flag[%d] = %d", + g_cBlockNo + 1, g_sent_flag[(g_cBlockNo + 1) & 0xff])); if (g_sent_flag[(g_cBlockNo + 1) & 0xff] & 1) { LOG(10, ("sound_send_wave_data_chunk: no room")); - return 0; + return 2; } else { @@ -430,9 +439,12 @@ sound_send_wave_data(char *data, int data_bytes) int space_left; int chunk_bytes; int data_index; + int error; + int res; LOG(10, ("sound_send_wave_data: sending %d bytes", data_bytes)); data_index = 0; + error = 0; while (data_bytes > 0) { space_left = BBUF_SIZE - g_buf_index; @@ -440,19 +452,33 @@ sound_send_wave_data(char *data, int data_bytes) if (chunk_bytes < 1) { LOG(10, ("sound_send_wave_data: error")); + error = 1; break; } g_memcpy(g_buffer + g_buf_index, data + data_index, chunk_bytes); g_buf_index += chunk_bytes; if (g_buf_index >= BBUF_SIZE) { - sound_send_wave_data_chunk(g_buffer, BBUF_SIZE); g_buf_index = 0; + res = sound_send_wave_data_chunk(g_buffer, BBUF_SIZE); + if (res == 2) + { + /* don't need to error on this */ + LOG(0, ("sound_send_wave_data: dropped, no room")); + break; + } + else if (res != 0) + { + LOG(10, ("sound_send_wave_data: error")); + error = 1; + break; + } } data_bytes -= chunk_bytes; data_index += chunk_bytes; } - return 0; + + return error; } /*****************************************************************************/ @@ -467,9 +493,18 @@ sound_send_close(void) LOG(10, ("sound_send_close:")); /* send any left over data */ - sound_send_wave_data_chunk(g_buffer, g_buf_index); + if (g_buf_index) + { + if (sound_send_wave_data_chunk(g_buffer, g_buf_index) != 0) + { + LOG(10, ("sound_send_close: sound_send_wave_data_chunk failed")); + return 1; + } + } g_buf_index = 0; + g_memset(g_sent_flag, 0, sizeof(g_sent_flag)); + /* send close msg */ make_stream(s); init_stream(s, 8182); out_uint16_le(s, SNDC_CLOSE); @@ -522,23 +557,23 @@ sound_process_wave_confirm(struct stream *s, int size) /*****************************************************************************/ /* process message in from the audio source, eg pulse, alsa - on it's way to the client */ + on it's way to the client. returns error */ static int APP_CC process_pcm_message(int id, int size, struct stream *s) { switch (id) { case 0: - sound_send_wave_data(s->p, size); + return sound_send_wave_data(s->p, size); break; case 1: - sound_send_close(); + return sound_send_close(); break; default: LOG(10, ("process_pcm_message: unknown id %d", id)); break; } - return 0; + return 1; } /*****************************************************************************/ @@ -652,11 +687,6 @@ sound_init(void) g_memset(g_sent_flag, 0, sizeof(g_sent_flag)); -#ifdef XRDP_LOAD_PULSE_MODULES - if (load_pulse_modules()) - LOG(0, ("Audio and microphone redirection will not work!")); -#endif - /* init sound output */ sound_send_server_output_formats(); @@ -682,13 +712,6 @@ sound_init(void) /* save data from sound_server_source */ fifo_init(&in_fifo, 100); -#if defined(XRDP_SIMPLESOUND) - - /* start thread to read raw audio data from pulseaudio device */ - tc_thread_create(read_raw_audio_data, 0); - -#endif - return 0; } @@ -696,6 +719,7 @@ sound_init(void) int APP_CC sound_deinit(void) { + LOG(10, ("sound_deinit:")); if (g_audio_l_trans_out != 0) { trans_delete(g_audio_l_trans_out); @@ -722,10 +746,6 @@ sound_deinit(void) fifo_deinit(&in_fifo); -#ifdef XRDP_LOAD_PULSE_MODULES - system("pulseaudio --kill"); -#endif - return 0; } @@ -814,180 +834,49 @@ sound_get_wait_objs(tbus *objs, int *count, int *timeout) int APP_CC sound_check_wait_objs(void) { + if (g_audio_l_trans_out != 0) { - trans_check_wait_objs(g_audio_l_trans_out); + if (trans_check_wait_objs(g_audio_l_trans_out) != 0) + { + LOG(10, ("sound_check_wait_objs: g_audio_l_trans_out returned non-zero")); + trans_delete(g_audio_l_trans_out); + g_audio_l_trans_out = 0; + } } if (g_audio_c_trans_out != 0) { - trans_check_wait_objs(g_audio_c_trans_out); - } - - if (g_audio_l_trans_in != 0) - { - trans_check_wait_objs(g_audio_l_trans_in); - } - - if (g_audio_c_trans_in != 0) - { - trans_check_wait_objs(g_audio_c_trans_in); - } - - return 0; -} - -/** - * Load xrdp pulseaudio sink and source modules - * - * @return 0 on success, -1 on failure - *****************************************************************************/ - -#ifdef XRDP_LOAD_PULSE_MODULES - -static int APP_CC -load_pulse_modules() -{ - struct sockaddr_un sa; - - pid_t pid; - char* cli; - int fd; - int i; - int rv; - char buf[1024]; - - /* is pulse audio daemon running? */ - if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) - { - LOG(0, ("load_pulse_modules: No PulseAudio daemon running, " - "or not running as session daemon")); - } - - /* get name of unix domain socket used by pulseaudio for CLI */ - if ((cli = (char *) pa_runtime_path("cli")) == NULL) - { - LOG(0, ("load_pulse_modules: Error getting PulesAudio runtime path")); - return -1; - } - - /* open a socket */ - if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) - { - pa_xfree(cli); - LOG(0, ("load_pulse_modules: Socket open error")); - return -1; - } - - /* set it up */ - memset(&sa, 0, sizeof(struct sockaddr_un)); - sa.sun_family = AF_UNIX; - pa_strlcpy(sa.sun_path, cli, sizeof(sa.sun_path)); - pa_xfree(cli); - - for (i = 0; i < 20; i++) - { - if (pa_pid_file_kill(SIGUSR2, NULL, "pulseaudio") < 0) - LOG(0, ("load_pulse_modules: Failed to kill PulseAudio daemon")); - - if ((rv = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && - (errno != ECONNREFUSED && errno != ENOENT)) + if (trans_check_wait_objs(g_audio_c_trans_out) != 0) { - LOG(0, ("load_pulse_modules: connect() failed with error: %s", - strerror(errno))); - return -1; + LOG(10, ("sound_check_wait_objs: g_audio_c_trans_out returned non-zero")); + trans_delete(g_audio_c_trans_out); + g_audio_c_trans_out = 0; } - - if (rv >= 0) - break; - - pa_msleep(300); } - if (i >= 20) - { - LOG(0, ("load_pulse_modules: Daemon not responding")); - return -1; - } - - LOG(0, ("load_pulse_modules: connected to pulseaudio daemon")); - - /* read back PulseAudio sign on message */ - memset(buf, 0, 1024); - recv(fd, buf, 1024, 0); - - /* send cmd to load source module */ - memset(buf, 0, 1024); - sprintf(buf, "load-module module-xrdp-source\n"); - send(fd, buf, strlen(buf), 0); - - /* read back response */ - memset(buf, 0, 1024); - recv(fd, buf, 1024, 0); - if (strcasestr(buf, "Module load failed") != 0) - { - LOG(0, ("load_pulse_modules: Error loading module-xrdp-source")); - } - else + if (g_audio_l_trans_in != 0) { - LOG(0, ("load_pulse_modules: Loaded module-xrdp-source")); - - /* success, set it as the default source */ - memset(buf, 0, 1024); - sprintf(buf, "set-default-source xrdp-source\n"); - send(fd, buf, strlen(buf), 0); - - memset(buf, 0, 1024); - recv(fd, buf, 1024, 0); - - if (strcasestr(buf, "does not exist") != 0) - { - LOG(0, ("load_pulse_modules: Error setting default source")); - } - else + if (trans_check_wait_objs(g_audio_l_trans_in) != 0) { - LOG(0, ("load_pulse_modules: set default source")); + LOG(10, ("sound_check_wait_objs: g_audio_l_trans_in returned non-zero")); + trans_delete(g_audio_l_trans_in); + g_audio_l_trans_in = 0; } } - /* send cmd to load sink module */ - memset(buf, 0, 1024); - sprintf(buf, "load-module module-xrdp-sink\n"); - send(fd, buf, strlen(buf), 0); - - /* read back response */ - memset(buf, 0, 1024); - recv(fd, buf, 1024, 0); - if (strcasestr(buf, "Module load failed") != 0) - { - LOG(0, ("load_pulse_modules: Error loading module-xrdp-sink")); - } - else + if (g_audio_c_trans_in != 0) { - LOG(0, ("load_pulse_modules: Loaded module-xrdp-sink")); - - /* success, set it as the default sink */ - memset(buf, 0, 1024); - sprintf(buf, "set-default-sink xrdp-sink\n"); - send(fd, buf, strlen(buf), 0); - - memset(buf, 0, 1024); - recv(fd, buf, 1024, 0); - - if (strcasestr(buf, "does not exist") != 0) - { - LOG(0, ("load_pulse_modules: Error setting default sink")); - } - else + if (trans_check_wait_objs(g_audio_c_trans_in) != 0) { - LOG(0, ("load_pulse_modules: set default sink")); + LOG(10, ("sound_check_wait_objs: g_audio_c_trans_in returned non-zero")); + trans_delete(g_audio_c_trans_in); + g_audio_c_trans_in = 0; } } - close(fd); return 0; } -#endif /****************************************************************************** ** ** @@ -1152,7 +1041,7 @@ sound_process_input_formats(struct stream *s, int size) *****************************************************************************/ static int APP_CC -sound_input_start_recording() +sound_input_start_recording(void) { struct stream* s; @@ -1186,7 +1075,7 @@ sound_input_start_recording() *****************************************************************************/ static int APP_CC -sound_input_stop_recording() +sound_input_stop_recording(void) { struct stream* s; @@ -1252,14 +1141,14 @@ sound_sndsrvr_source_data_in(struct trans *trans) return 1; ts = trans_get_in_s(trans); - trans_force_read(trans, 3); + if (trans_force_read(trans, 3)) + log_message(LOG_LEVEL_ERROR, "sound.c: error reading from transport"); ts->p = ts->data + 8; in_uint8(ts, cmd); in_uint16_le(ts, bytes_req); - if (bytes_req != 0) - xstream_new(s, bytes_req + 2); + xstream_new(s, bytes_req + 2); if (cmd == PA_CMD_SEND_DATA) { @@ -1309,7 +1198,6 @@ sound_sndsrvr_source_data_in(struct trans *trans) s_mark_end(s); trans_force_write_s(trans, s); - xstream_free(s); } else if (cmd == PA_CMD_START_REC) { @@ -1320,133 +1208,7 @@ sound_sndsrvr_source_data_in(struct trans *trans) sound_input_stop_recording(); } - return 0; -} - -/*****************************************************************************/ - -#if defined(XRDP_SIMPLESOUND) - -#define AUDIO_BUF_SIZE 2048 + xstream_free(s); -static int DEFAULT_CC -sttrans_data_in(struct trans *self) -{ - LOG(0, ("sttrans_data_in:\n")); return 0; } - -/** - * read raw audio data from pulseaudio device and write it - * to a unix domain socket on which trans server is listening - */ - -static void *DEFAULT_CC -read_raw_audio_data(void *arg) -{ - pa_sample_spec samp_spec; - pa_simple *simple = NULL; - uint32_t bytes_read; - char *cptr; - int i; - int error; - struct trans *strans; - char path[256]; - struct stream *outs; - - strans = trans_create(TRANS_MODE_UNIX, 8192, 8192); - - if (strans == 0) - { - LOG(0, ("read_raw_audio_data: trans_create failed\n")); - return 0; - } - - strans->trans_data_in = sttrans_data_in; - g_snprintf(path, 255, CHANSRV_PORT_OUT_STR, g_display_num); - - if (trans_connect(strans, "", path, 100) != 0) - { - LOG(0, ("read_raw_audio_data: trans_connect failed\n")); - trans_delete(strans); - return 0; - } - - /* setup audio format */ - samp_spec.format = PA_SAMPLE_S16LE; - samp_spec.rate = 44100; - samp_spec.channels = 2; - - /* if we are root, then for first 8 seconds connection to pulseaudo server - fails; if we are non-root, then connection succeeds on first attempt; - for now we have changed code to be non-root, but this may change in the - future - so pretend we are root and try connecting to pulseaudio server - for upto one minute */ - for (i = 0; i < 60; i++) - { - simple = pa_simple_new(NULL, "xrdp", PA_STREAM_RECORD, NULL, - "record", &samp_spec, NULL, NULL, &error); - - if (simple) - { - /* connected to pulseaudio server */ - LOG(0, ("read_raw_audio_data: connected to pulseaudio server\n")); - break; - } - - LOG(0, ("read_raw_audio_data: ERROR creating PulseAudio async interface\n")); - LOG(0, ("read_raw_audio_data: %s\n", pa_strerror(error))); - g_sleep(1000); - } - - if (i == 60) - { - /* failed to connect to audio server */ - trans_delete(strans); - return NULL; - } - - /* insert header just once */ - outs = trans_get_out_s(strans, 8192); - out_uint32_le(outs, 0); - out_uint32_le(outs, AUDIO_BUF_SIZE + 8); - cptr = outs->p; - out_uint8s(outs, AUDIO_BUF_SIZE); - s_mark_end(outs); - - while (1) - { - /* read a block of raw audio data... */ - g_memset(cptr, 0, 4); - bytes_read = pa_simple_read(simple, cptr, AUDIO_BUF_SIZE, &error); - - if (bytes_read < 0) - { - LOG(0, ("read_raw_audio_data: ERROR reading from pulseaudio stream\n")); - LOG(0, ("read_raw_audio_data: %s\n", pa_strerror(error))); - break; - } - - /* bug workaround: - even when there is no audio data, pulseaudio is returning without - errors but the data itself is zero; we use this zero data to - determine that there is no audio data present */ - if (*cptr == 0 && *(cptr + 1) == 0 && *(cptr + 2) == 0 && *(cptr + 3) == 0) - { - g_sleep(10); - continue; - } - - if (trans_force_write_s(strans, outs) != 0) - { - LOG(0, ("read_raw_audio_data: ERROR writing audio data to server\n")); - break; - } - } - - pa_simple_free(simple); - trans_delete(strans); - return NULL; -} - -#endif diff --git a/sesman/chansrv/sound.h b/sesman/chansrv/sound.h index c26d0913..f3563dab 100644 --- a/sesman/chansrv/sound.h +++ b/sesman/chansrv/sound.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2009-2013 + * Copyright (C) Jay Sorg 2009-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,11 +19,6 @@ #ifndef _SOUND_H_ #define _SOUND_H_ -#if defined(XRDP_SIMPLESOUND) -#include <pulse/simple.h> -#include <pulse/error.h> -#endif - #include "arch.h" #include "parse.h" #include "os_calls.h" @@ -63,17 +58,4 @@ int APP_CC sound_check_wait_objs(void); int APP_CC sound_data_in(struct stream* s, int chan_id, int chan_flags, int length, int total_length); -/* microphone related */ -static int APP_CC sound_send_server_input_formats(void); - -static int APP_CC sound_process_input_format(int aindex, int wFormatTag, - int nChannels, int nSamplesPerSec, int nAvgBytesPerSec, - int nBlockAlign, int wBitsPerSample, int cbSize, char *data); - -static int APP_CC sound_process_input_formats(struct stream *s, int size); -static int APP_CC sound_input_start_recording(); -static int APP_CC sound_input_stop_recording(); -static int APP_CC sound_process_input_data(struct stream *s, int bytes); -static int DEFAULT_CC sound_sndsrvr_source_data_in(struct trans *trans); -static int APP_CC load_pulse_modules(); #endif diff --git a/sesman/config.c b/sesman/config.c index 877a949c..5a904fc3 100644 --- a/sesman/config.c +++ b/sesman/config.c @@ -74,9 +74,10 @@ config_read(struct config_sesman *cfg) /* read global config */ config_read_globals(fd, cfg, param_n, param_v); - /* read Xvnc/X11rdp parameter list */ + /* read Xvnc/X11rdp/XOrg parameter list */ config_read_vnc_params(fd, cfg, param_n, param_v); config_read_rdp_params(fd, cfg, param_n, param_v); + config_read_xorg_params(fd, cfg, param_n, param_v); /* read logging config */ // config_read_logging(fd, &(cfg->log), param_n, param_v); @@ -87,6 +88,8 @@ config_read(struct config_sesman *cfg) /* read session config */ config_read_sessions(fd, &(cfg->sess), param_n, param_v); + config_read_session_variables(fd, cfg, param_n, param_v); + /* cleanup */ list_delete(sec); list_delete(param_v); @@ -336,6 +339,7 @@ config_read_sessions(int file, struct config_sessions *se, struct list *param_n, se->max_idle_time = 0; se->max_disc_time = 0; se->kill_disconnected = 0; + se->policy = SESMAN_CFG_SESS_POLICY_DFLT; file_read_section(file, SESMAN_CFG_SESSIONS, param_n, param_v); @@ -367,15 +371,49 @@ config_read_sessions(int file, struct config_sessions *se, struct list *param_n, { se->max_disc_time = g_atoi((char *)list_get_item(param_v, i)); } + + if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_POLICY_S)) + { + char *value = (char *)list_get_item(param_v, i); + if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_DFLT_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_DFLT; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBD_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBD; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBI_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBI; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBC_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBC; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBDI_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBDI; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBDC_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBDC; + } + else /* silently ignore typos */ + { + se->policy = SESMAN_CFG_SESS_POLICY_DFLT; + } + } } - /* printing security config */ + /* printing session config */ g_printf("session configuration:\r\n"); g_printf("\tMaxSessions: %i\r\n", se->max_sessions); g_printf("\tX11DisplayOffset: %i\r\n", se->x11_display_offset); g_printf("\tKillDisconnected: %i\r\n", se->kill_disconnected); g_printf("\tIdleTimeLimit: %i\r\n", se->max_idle_time); g_printf("\tDisconnectedTimeLimit: %i\r\n", se->max_idle_time); + g_printf("\tPolicy: %i\r\n", se->policy); return 0; } @@ -412,6 +450,38 @@ config_read_rdp_params(int file, struct config_sesman *cs, struct list *param_n, /******************************************************************************/ int DEFAULT_CC +config_read_xorg_params(int file, struct config_sesman *cs, + struct list *param_n, struct list *param_v) +{ + int i; + + list_clear(param_v); + list_clear(param_n); + + cs->xorg_params = list_create(); + + file_read_section(file, SESMAN_CFG_XORG_PARAMS, param_n, param_v); + + for (i = 0; i < param_n->count; i++) + { + list_add_item(cs->xorg_params, + (long) g_strdup((char *) list_get_item(param_v, i))); + } + + /* printing security config */ + g_printf("XOrg parameters:\r\n"); + + for (i = 0; i < cs->xorg_params->count; i++) + { + g_printf("\tParameter %02d %s\r\n", + i, (char *) list_get_item(cs->xorg_params, i)); + } + + return 0; +} + +/******************************************************************************/ +int DEFAULT_CC config_read_vnc_params(int file, struct config_sesman *cs, struct list *param_n, struct list *param_v) { @@ -439,3 +509,39 @@ config_read_vnc_params(int file, struct config_sesman *cs, struct list *param_n, return 0; } + +/******************************************************************************/ +int DEFAULT_CC +config_read_session_variables(int file, struct config_sesman *cs, + struct list *param_n, struct list *param_v) +{ + int i; + + list_clear(param_v); + list_clear(param_n); + + cs->session_variables1 = list_create(); + cs->session_variables2 = list_create(); + + file_read_section(file, SESMAN_CFG_SESSION_VARIABLES, param_n, param_v); + + for (i = 0; i < param_n->count; i++) + { + list_add_item(cs->session_variables1, + (tintptr) g_strdup((char *) list_get_item(param_n, i))); + list_add_item(cs->session_variables2, + (tintptr) g_strdup((char *) list_get_item(param_v, i))); + } + + /* printing security config */ + g_writeln("%s parameters:", SESMAN_CFG_SESSION_VARIABLES); + + for (i = 0; i < cs->session_variables1->count; i++) + { + g_writeln(" Parameter %02d %s=%s", i, + (char *) list_get_item(cs->session_variables1, i), + (char *) list_get_item(cs->session_variables2, i)); + } + + return 0; +} diff --git a/sesman/config.h b/sesman/config.h index b011ca9b..08d84ce1 100644 --- a/sesman/config.h +++ b/sesman/config.h @@ -42,8 +42,11 @@ #define SESMAN_CFG_AUTH_FILE_PATH "AuthFilePath" #define SESMAN_CFG_RDP_PARAMS "X11rdp" +#define SESMAN_CFG_XORG_PARAMS "Xorg" #define SESMAN_CFG_VNC_PARAMS "Xvnc" +#define SESMAN_CFG_SESSION_VARIABLES "SessionVariables" + /* #define SESMAN_CFG_LOGGING "Logging" #define SESMAN_CFG_LOG_FILE "LogFile" @@ -64,6 +67,29 @@ #define SESMAN_CFG_SESS_IDLE_LIMIT "IdleTimeLimit" #define SESMAN_CFG_SESS_DISC_LIMIT "DisconnectedTimeLimit" +#define SESMAN_CFG_SESS_POLICY_S "Policy" +#define SESMAN_CFG_SESS_POLICY_DFLT_S "Default" +#define SESMAN_CFG_SESS_POLICY_UBD_S "UBD" +#define SESMAN_CFG_SESS_POLICY_UBI_S "UBI" +#define SESMAN_CFG_SESS_POLICY_UBC_S "UBC" +#define SESMAN_CFG_SESS_POLICY_UBDI_S "UBDI" +#define SESMAN_CFG_SESS_POLICY_UBDC_S "UBDC" + +enum SESMAN_CFG_SESS_POLICY_BITS { + SESMAN_CFG_SESS_POLICY_D = 0x01, + SESMAN_CFG_SESS_POLICY_I = 0x02, + SESMAN_CFG_SESS_POLICY_C = 0x04 +}; + +enum SESMAN_CFG_SESS_POLICY { + SESMAN_CFG_SESS_POLICY_DFLT = 0, + SESMAN_CFG_SESS_POLICY_UBD = SESMAN_CFG_SESS_POLICY_D, + SESMAN_CFG_SESS_POLICY_UBI = SESMAN_CFG_SESS_POLICY_I, + SESMAN_CFG_SESS_POLICY_UBC = SESMAN_CFG_SESS_POLICY_C, + SESMAN_CFG_SESS_POLICY_UBDI = SESMAN_CFG_SESS_POLICY_D | SESMAN_CFG_SESS_POLICY_I, + SESMAN_CFG_SESS_POLICY_UBDC = SESMAN_CFG_SESS_POLICY_D | SESMAN_CFG_SESS_POLICY_C +}; + /** * * @struct config_security @@ -134,6 +160,11 @@ struct config_sessions * @brief enables automatic killing of disconnected session */ int kill_disconnected; + /** + * @var policy + * @brief session allocation policy + */ + enum SESMAN_CFG_SESS_POLICY policy; }; /** @@ -192,6 +223,13 @@ struct config_sesman * @var log * @brief Log configuration struct */ + + struct list* xorg_params; + /** + * @var log + * @brief Log configuration struct + */ + //struct log_config log; /** * @var sec @@ -203,6 +241,9 @@ struct config_sesman * @brief Session configuration options struct */ struct config_sessions sess; + + struct list* session_variables1; + struct list* session_variables2; }; /** @@ -285,6 +326,19 @@ int DEFAULT_CC config_read_rdp_params(int file, struct config_sesman* cs, struct list* param_n, struct list* param_v); +/** + * + * @brief Reads sesman [XOrg] configuration section + * @param file configuration file descriptor + * @param cs pointer to a config_sesman struct + * @param param_n parameter name list + * @param param_v parameter value list + * @return 0 on success, 1 on failure + * + */ +int DEFAULT_CC +config_read_xorg_params(int file, struct config_sesman* cs, struct list* param_n, + struct list* param_v); /** * @@ -300,4 +354,8 @@ int DEFAULT_CC config_read_vnc_params(int file, struct config_sesman* cs, struct list* param_n, struct list* param_v); +int DEFAULT_CC +config_read_session_variables(int file, struct config_sesman *cs, + struct list *param_n, struct list *param_v); + #endif diff --git a/sesman/env.c b/sesman/env.c index b650d0b3..227f6bbf 100644 --- a/sesman/env.c +++ b/sesman/env.c @@ -24,6 +24,8 @@ * */ +#include "list.h" + #include "sesman.h" #include "sys/types.h" @@ -60,12 +62,16 @@ env_check_password_file(char *filename, char *password) /******************************************************************************/ int DEFAULT_CC -env_set_user(char *username, char *passwd_file, int display) +env_set_user(char *username, char *passwd_file, int display, + struct list *env_names, struct list* env_values) { int error; int pw_uid; int pw_gid; int uid; + int index; + char *name; + char *value; char pw_shell[256]; char pw_dir[256]; char pw_gecos[256]; @@ -96,7 +102,7 @@ env_set_user(char *username, char *passwd_file, int display) { g_clearenv(); g_setenv("SHELL", pw_shell, 1); - g_setenv("PATH", "/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin", 1); + g_setenv("PATH", "/bin:/usr/bin:/usr/local/bin", 1); g_setenv("USER", username, 1); g_sprintf(text, "%d", uid); g_setenv("UID", text, 1); @@ -106,6 +112,16 @@ env_set_user(char *username, char *passwd_file, int display) g_setenv("DISPLAY", text, 1); g_setenv("LANG", "en_US.UTF-8", 1); g_setenv("XRDP_SESSION", "1", 1); + if ((env_names != 0) && (env_values != 0) && + (env_names->count == env_values->count)) + { + for (index = 0; index < env_names->count; index++) + { + name = (char *) list_get_item(env_names, index), + value = (char *) list_get_item(env_values, index), + g_setenv(name, value, 1); + } + } if (passwd_file != 0) { @@ -113,7 +129,11 @@ env_set_user(char *username, char *passwd_file, int display) { /* if no auth_file_path is set, then we go for $HOME/.vnc/sesman_username_passwd */ - g_mkdir(".vnc"); + if (g_mkdir(".vnc") < 0) + { + log_message(LOG_LEVEL_ERROR, + "env_set_user: error creating .vnc dir"); + } g_sprintf(passwd_file, "%s/.vnc/sesman_%s_passwd", pw_dir, username); } else diff --git a/sesman/env.h b/sesman/env.h index e70bfe6a..50473a01 100644 --- a/sesman/env.h +++ b/sesman/env.h @@ -27,6 +27,8 @@ #ifndef ENV_H #define ENV_H +#include "list.h" + /** * * @brief Creates vnc password file @@ -48,6 +50,7 @@ env_check_password_file(char* filename, char* password); * */ int DEFAULT_CC -env_set_user(char* username, char* passwd_file, int display); +env_set_user(char* username, char* passwd_file, int display, + struct list *env_names, struct list* env_values); #endif diff --git a/sesman/libscp/libscp_session.c b/sesman/libscp/libscp_session.c index 4c389655..d25fc64a 100644 --- a/sesman/libscp/libscp_session.c +++ b/sesman/libscp/libscp_session.c @@ -58,12 +58,19 @@ scp_session_set_type(struct SCP_SESSION *s, tui8 type) case SCP_SESSION_TYPE_XVNC: s->type = SCP_SESSION_TYPE_XVNC; break; + case SCP_SESSION_TYPE_XRDP: s->type = SCP_SESSION_TYPE_XRDP; break; + + case SCP_SESSION_TYPE_XORG: + s->type = SCP_SESSION_TYPE_XORG; + break; + case SCP_GW_AUTHENTICATION: s->type = SCP_GW_AUTHENTICATION; break; + case SCP_SESSION_TYPE_MANAGE: s->type = SCP_SESSION_TYPE_MANAGE; s->mng = (struct SCP_MNG_DATA *)g_malloc(sizeof(struct SCP_MNG_DATA), 1); @@ -75,6 +82,7 @@ scp_session_set_type(struct SCP_SESSION *s, tui8 type) } break; + default: log_message(LOG_LEVEL_WARNING, "[session:%d] set_type: unknown type", __LINE__); return 1; diff --git a/sesman/libscp/libscp_types.h b/sesman/libscp/libscp_types.h index 2140eced..de851867 100644 --- a/sesman/libscp/libscp_types.h +++ b/sesman/libscp/libscp_types.h @@ -41,6 +41,8 @@ #define SCP_SESSION_TYPE_XVNC 0x00 #define SCP_SESSION_TYPE_XRDP 0x01 #define SCP_SESSION_TYPE_MANAGE 0x02 +#define SCP_SESSION_TYPE_XORG 0x03 + /* SCP_GW_AUTHENTICATION can be used when XRDP + sesman act as a gateway * XRDP sends this command to let sesman verify if the user is allowed * to use the gateway */ diff --git a/sesman/libscp/libscp_v0.c b/sesman/libscp/libscp_v0.c index afa09bd8..8cf1340b 100644 --- a/sesman/libscp/libscp_v0.c +++ b/sesman/libscp/libscp_v0.c @@ -56,6 +56,10 @@ scp_v0c_connect(struct SCP_CONNECTION *c, struct SCP_SESSION *s) { out_uint16_be(c->out_s, 10); } + else if (s->type == SCP_SESSION_TYPE_XORG) + { + out_uint16_be(c->out_s, 20); + } else { log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); @@ -191,7 +195,7 @@ scp_v0s_accept(struct SCP_CONNECTION *c, struct SCP_SESSION **s, int skipVchk) in_uint16_be(c->in_s, code); - if (code == 0 || code == 10) + if (code == 0 || code == 10 || code == 20) { session = scp_session_create(); @@ -207,10 +211,14 @@ scp_v0s_accept(struct SCP_CONNECTION *c, struct SCP_SESSION **s, int skipVchk) { scp_session_set_type(session, SCP_SESSION_TYPE_XVNC); } - else + else if (code == 10) { scp_session_set_type(session, SCP_SESSION_TYPE_XRDP); } + else if (code == 20) + { + scp_session_set_type(session, SCP_SESSION_TYPE_XORG); + } /* reading username */ in_uint16_be(c->in_s, sz); diff --git a/sesman/scp_v0.c b/sesman/scp_v0.c index aeaa22ee..ce528d46 100644 --- a/sesman/scp_v0.c +++ b/sesman/scp_v0.c @@ -74,7 +74,7 @@ scp_v0_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s) else if (data) { s_item = session_get_bydata(s->username, s->width, s->height, - s->bpp, s->type); + s->bpp, s->type, s->client_ip); if (s_item != 0) { @@ -122,12 +122,21 @@ scp_v0_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s) s->domain, s->program, s->directory, s->client_ip); } - else + else if (SCP_SESSION_TYPE_XRDP == s->type) { log_message(LOG_LEVEL_INFO, "starting X11rdp session..."); display = session_start(s->width, s->height, s->bpp, s->username, s->password, data, SESMAN_SESSION_TYPE_XRDP, s->domain, s->program, s->directory, + s->client_ip); + } + else if (SCP_SESSION_TYPE_XORG == s->type) + { + /* type is SCP_SESSION_TYPE_XORG */ + log_message(LOG_LEVEL_INFO, "starting Xorg session..."); + display = session_start(s->width, s->height, s->bpp, s->username, + s->password, data, SESMAN_SESSION_TYPE_XORG, + s->domain, s->program, s->directory, s->client_ip); } } diff --git a/sesman/scp_v1.c b/sesman/scp_v1.c index 12115929..2324b750 100644 --- a/sesman/scp_v1.c +++ b/sesman/scp_v1.c @@ -195,8 +195,6 @@ scp_v1_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s) parseCommonStates(e, "scp_v1s_list_sessions()"); break; } - - g_free(slist); } /* resource management */ @@ -208,6 +206,7 @@ scp_v1_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s) /* cleanup */ scp_session_destroy(s); auth_end(data); + g_free(slist); } static void parseCommonStates(enum SCP_SERVER_STATES_E e, char *f) diff --git a/sesman/sesman.c b/sesman/sesman.c index 83db5961..1c620210 100644 --- a/sesman/sesman.c +++ b/sesman/sesman.c @@ -54,7 +54,14 @@ sesman_main_loop(void) /*main program loop*/ log_message(LOG_LEVEL_INFO, "listening..."); + g_sck = g_tcp_socket(); + if (g_sck < 0) + { + log_message(LOG_LEVEL_ERROR, "error opening socket, g_tcp_socket() failed..."); + return 1; + } + g_tcp_set_non_blocking(g_sck); error = scp_tcp_bind(g_sck, g_cfg->listen_address, g_cfg->listen_port); @@ -132,7 +139,8 @@ sesman_main_loop(void) g_get_errno(), g_get_strerror()); } - g_tcp_close(g_sck); + if (g_sck != -1) + g_tcp_close(g_sck); } /******************************************************************************/ @@ -308,9 +316,17 @@ main(int argc, char **argv) g_file_close(1); g_file_close(2); - g_file_open("/dev/null"); - g_file_open("/dev/null"); - g_file_open("/dev/null"); + if (g_file_open("/dev/null") < 0) + { + } + + if (g_file_open("/dev/null") < 0) + { + } + + if (g_file_open("/dev/null") < 0) + { + } } /* initializing locks */ @@ -361,7 +377,11 @@ main(int argc, char **argv) /* make sure the /tmp/.X11-unix directory exist */ if (!g_directory_exist("/tmp/.X11-unix")) { - g_create_dir("/tmp/.X11-unix"); + if (!g_create_dir("/tmp/.X11-unix")) + { + log_message(LOG_LEVEL_ERROR, + "sesman.c: error creating dir /tmp/.X11-unix"); + } g_chmod_hex("/tmp/.X11-unix", 0x1777); } diff --git a/sesman/sesman.ini b/sesman/sesman.ini index 5ee0b4cd..a58af383 100644 --- a/sesman/sesman.ini +++ b/sesman/sesman.ini @@ -10,22 +10,52 @@ AllowRootLogin=1 MaxLoginRetry=4 TerminalServerUsers=tsusers TerminalServerAdmins=tsadmins -# When AlwaysGroupCheck = false access will be permitted +# When AlwaysGroupCheck = false access will be permitted # if the group TerminalServerUsers is not defined. AlwaysGroupCheck = false [Sessions] + +## X11DisplayOffset - x11 display number offset +# Type: integer +# Default: 10 X11DisplayOffset=10 + +## MaxSessions - maximum number of connections to an xrdp server +# Type: integer +# Default: 0 MaxSessions=50 + +## KillDisconnected - kill disconnected sessions +# Type: integer +# Default: 0 # if 1, true, or yes, kill session after 60 seconds KillDisconnected=0 + +## IdleTimeLimit - when to disconnect idle sessions +# Type: integer +# Default: 0 # if not zero, the seconds without mouse or keyboard input before disconnect # not complete yet IdleTimeLimit=0 + +## DisconnectedTimeLimit - when to kill idle sessions +# Type: integer +# Default: 0 # if not zero, the seconds before a disconnected session is killed # min 60 seconds DisconnectedTimeLimit=0 +## Policy - session allocation policy +# Type: enum [ "Default" | "UBD" | "UBI" | "UBC" | "UBDI" | "UBDC" ] +# Default: Xrdp:<User,BitPerPixel> and Xvnc:<User,BitPerPixel,DisplaySize> +# "UBD" session per <User,BitPerPixel,DisplaySize> +# "UBI" session per <User,BitPerPixel,IPAddr> +# "UBC" session per <User,BitPerPixel,Connection> +# "UBDI" session per <User,BitPerPixel,DisplaySize,IPAddr> +# "UBDC" session per <User,BitPerPixel,DisplaySize,Connection> +Policy=Default + [Logging] LogFile=xrdp-sesman.log LogLevel=DEBUG @@ -47,3 +77,20 @@ param4=tcp param5=-localhost param6=-dpi param7=96 + +[Xorg] +param1=-config +param2=xrdp/xorg.conf +param3=-logfile +param4=/dev/null +param5=-noreset +param6=-ac +param7=-nolisten +param8=tcp + +[Chansrv] +# drive redirection, defaults to xrdp_client if not set +FuseMountName=thinclient_drives + +[SessionVariables] +PULSE_SCRIPT=/etc/xrdp/pulse/default.pa diff --git a/sesman/session.c b/sesman/session.c index 665d1138..856c969e 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -90,9 +90,10 @@ dumpItemsToString(struct list *self, char *outstr, int len) /******************************************************************************/ struct session_item *DEFAULT_CC -session_get_bydata(char *name, int width, int height, int bpp, int type) +session_get_bydata(char *name, int width, int height, int bpp, int type, char *client_ip) { struct session_chain *tmp; + enum SESMAN_CFG_SESS_POLICY policy = g_cfg->sess.policy; /*THREAD-FIX require chain lock */ lock_chain_acquire(); @@ -104,23 +105,49 @@ session_get_bydata(char *name, int width, int height, int bpp, int type) { case SCP_SESSION_TYPE_XVNC: /* 0 */ type = SESMAN_SESSION_TYPE_XVNC; /* 2 */ + policy |= SESMAN_CFG_SESS_POLICY_D; /* Xvnc cannot resize */ break; case SCP_SESSION_TYPE_XRDP: /* 1 */ type = SESMAN_SESSION_TYPE_XRDP; /* 1 */ break; + case SCP_SESSION_TYPE_XORG: + type = SESMAN_SESSION_TYPE_XORG; + break; default: lock_chain_release(); return 0; } +#if 0 + log_message(LOG_LEVEL_INFO, + "session_get_bydata: search policy %d U %s W %d H %d bpp %d T %d IP %s", + policy, name, width, height, bpp, type, client_ip); +#endif + while (tmp != 0) { +#if 0 + log_message(LOG_LEVEL_INFO, + "session_get_bydata: try %p U %s W %d H %d bpp %d T %d IP %s", + tmp->item, + tmp->item->name, + tmp->item->width, tmp->item->height, + tmp->item->bpp, tmp->item->type, + tmp->item->client_ip); +#endif + if (type == SESMAN_SESSION_TYPE_XRDP) { /* only name and bpp need to match for X11rdp, it can resize */ if (g_strncmp(name, tmp->item->name, 255) == 0 && - tmp->item->bpp == bpp && - tmp->item->type == type) + (!(policy & SESMAN_CFG_SESS_POLICY_D) || + (tmp->item->width == width && tmp->item->height == height)) && + (!(policy & SESMAN_CFG_SESS_POLICY_I) || + (g_strncmp_d(client_ip, tmp->item->client_ip, ':', 255) == 0)) && + (!(policy & SESMAN_CFG_SESS_POLICY_C) || + (g_strncmp(client_ip, tmp->item->client_ip, 255) == 0)) && + tmp->item->bpp == bpp && + tmp->item->type == type) { /*THREAD-FIX release chain lock */ lock_chain_release(); @@ -129,10 +156,13 @@ session_get_bydata(char *name, int width, int height, int bpp, int type) } if (g_strncmp(name, tmp->item->name, 255) == 0 && - tmp->item->width == width && - tmp->item->height == height && - tmp->item->bpp == bpp && - tmp->item->type == type) + (tmp->item->width == width && tmp->item->height == height) && + (!(policy & SESMAN_CFG_SESS_POLICY_I) || + (g_strncmp_d(client_ip, tmp->item->client_ip, ':', 255) == 0)) && + (!(policy & SESMAN_CFG_SESS_POLICY_C) || + (g_strncmp(client_ip, tmp->item->client_ip, 255) == 0)) && + tmp->item->bpp == bpp && + tmp->item->type == type) { /*THREAD-FIX release chain lock */ lock_chain_release(); @@ -173,26 +203,62 @@ x_server_running_check_ports(int display) if (!x_running) /* check 59xx */ { - sck = g_tcp_socket(); - g_sprintf(text, "59%2.2d", display); - x_running = g_tcp_bind(sck, text); - g_tcp_close(sck); + if ((sck = g_tcp_socket()) != -1) + { + g_sprintf(text, "59%2.2d", display); + x_running = g_tcp_bind(sck, text); + g_tcp_close(sck); + } } if (!x_running) /* check 60xx */ { - sck = g_tcp_socket(); - g_sprintf(text, "60%2.2d", display); - x_running = g_tcp_bind(sck, text); - g_tcp_close(sck); + if ((sck = g_tcp_socket()) != -1) + { + g_sprintf(text, "60%2.2d", display); + x_running = g_tcp_bind(sck, text); + g_tcp_close(sck); + } } if (!x_running) /* check 62xx */ { - sck = g_tcp_socket(); - g_sprintf(text, "62%2.2d", display); - x_running = g_tcp_bind(sck, text); - g_tcp_close(sck); + if ((sck = g_tcp_socket()) != -1) + { + g_sprintf(text, "62%2.2d", display); + x_running = g_tcp_bind(sck, text); + g_tcp_close(sck); + } + } + + if (!x_running) + { + g_sprintf(text, XRDP_CHANSRV_STR, display); + x_running = g_file_exist(text); + } + + if (!x_running) + { + g_sprintf(text, CHANSRV_PORT_OUT_STR, display); + x_running = g_file_exist(text); + } + + if (!x_running) + { + g_sprintf(text, CHANSRV_PORT_IN_STR, display); + x_running = g_file_exist(text); + } + + if (!x_running) + { + g_sprintf(text, CHANSRV_API_STR, display); + x_running = g_file_exist(text); + } + + if (!x_running) + { + g_sprintf(text, XRDP_X11RDP_STR, display); + x_running = g_file_exist(text); } return x_running; @@ -258,7 +324,8 @@ session_start_sessvc(int xpid, int wmpid, long data, char *username, int display list_add_item(sessvc_params, (long)g_strdup(wmpid_str)); list_add_item(sessvc_params, 0); /* mandatory */ - env_set_user(username, 0, display); + env_set_user(username, 0, display, + g_cfg->session_variables1, g_cfg->session_variables2); /* executing sessvc */ g_execvp(exe_path, ((char **)sessvc_params->items)); @@ -471,7 +538,9 @@ session_start_fork(int width, int height, int bpp, char *username, } else if (pampid == 0) /* child: X11/client */ { - env_set_user(username, 0, display); + env_set_user(username, 0, display, + g_cfg->session_variables1, + g_cfg->session_variables2); if (x_server_running(display)) { auth_set_env(data); @@ -564,7 +633,9 @@ session_start_fork(int width, int height, int bpp, char *username, } else if (xpid == 0) /* child */ { - env_set_user(username, passwd_file, display); + env_set_user(username, passwd_file, display, + g_cfg->session_variables1, + g_cfg->session_variables2); env_check_password_file(passwd_file, password); g_snprintf(text, 255, "%d", g_cfg->sess.max_idle_time); @@ -574,10 +645,40 @@ session_start_fork(int width, int height, int bpp, char *username, g_snprintf(text, 255, "%d", g_cfg->sess.kill_disconnected); g_setenv("XRDP_SESMAN_KILL_DISCONNECTED", text, 1); - if (type == SESMAN_SESSION_TYPE_XVNC) + if (type == SESMAN_SESSION_TYPE_XORG) { xserver_params = list_create(); xserver_params->auto_free = 1; + + /* these are the must have parameters */ + list_add_item(xserver_params, (long) g_strdup("/usr/bin/Xorg")); + list_add_item(xserver_params, (long) g_strdup(screen)); + + /* additional parameters from sesman.ini file */ + list_append_list_strdup(g_cfg->xorg_params, xserver_params, 0); + + /* make sure it ends with a zero */ + list_add_item(xserver_params, 0); + + pp1 = (char **) xserver_params->items; + + log_message(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048)); + + /* some args are passed via env vars */ + g_sprintf(geometry, "%d", width); + g_setenv("XRDP_START_WIDTH", geometry, 1); + + g_sprintf(geometry, "%d", height); + g_setenv("XRDP_START_HEIGHT", geometry, 1); + + /* fire up Xorg */ + g_execvp("/usr/bin/Xorg", pp1); + } + else if (type == SESMAN_SESSION_TYPE_XVNC) + { + xserver_params = list_create(); + xserver_params->auto_free = 1; + /* these are the must have parameters */ list_add_item(xserver_params, (long)g_strdup("Xvnc")); list_add_item(xserver_params, (long)g_strdup(screen)); @@ -596,13 +697,14 @@ session_start_fork(int width, int height, int bpp, char *username, /* make sure it ends with a zero */ list_add_item(xserver_params, 0); pp1 = (char **)xserver_params->items; - log_message(LOG_LEVEL_INFO, "Xvnc start:%s", dumpItemsToString(xserver_params, execvpparams, 2048)); + log_message(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048)); g_execvp("Xvnc", pp1); } else if (type == SESMAN_SESSION_TYPE_XRDP) { xserver_params = list_create(); xserver_params->auto_free = 1; + /* these are the must have parameters */ list_add_item(xserver_params, (long)g_strdup("X11rdp")); list_add_item(xserver_params, (long)g_strdup(screen)); @@ -619,7 +721,7 @@ session_start_fork(int width, int height, int bpp, char *username, /* make sure it ends with a zero */ list_add_item(xserver_params, 0); pp1 = (char **)xserver_params->items; - log_message(LOG_LEVEL_INFO, "X11rdp start:%s", dumpItemsToString(xserver_params, execvpparams, 2048)); + log_message(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048)); g_execvp("X11rdp", pp1); } else @@ -693,8 +795,12 @@ session_start_fork(int width, int height, int bpp, char *username, /*THREAD-FIX release chain lock */ lock_chain_release(); + + return display; } + g_free(temp->item); + g_free(temp); return display; } @@ -713,7 +819,8 @@ session_reconnect_fork(int display, char *username) } else if (pid == 0) { - env_set_user(username, 0, display); + env_set_user(username, 0, display, + g_cfg->session_variables1, g_cfg->session_variables2); g_snprintf(text, 255, "%s/%s", XRDP_CFG_PATH, "reconnectwm.sh"); if (g_file_exist(text)) @@ -936,6 +1043,7 @@ session_get_bypid(int pid) "pid %d is null!", pid); /*THREAD-FIX release chain lock */ lock_chain_release(); + g_free(dummy); return 0; } @@ -954,6 +1062,7 @@ session_get_bypid(int pid) /*THREAD-FIX release chain lock */ lock_chain_release(); + g_free(dummy); return 0; } diff --git a/sesman/session.h b/sesman/session.h index 4329df12..05e3b3a9 100644 --- a/sesman/session.h +++ b/sesman/session.h @@ -30,8 +30,9 @@ #include "libscp_types.h" -#define SESMAN_SESSION_TYPE_XRDP 1 -#define SESMAN_SESSION_TYPE_XVNC 2 +#define SESMAN_SESSION_TYPE_XRDP 1 +#define SESMAN_SESSION_TYPE_XVNC 2 +#define SESMAN_SESSION_TYPE_XORG 3 #define SESMAN_SESSION_STATUS_ACTIVE 0x01 #define SESMAN_SESSION_STATUS_IDLE 0x02 @@ -90,9 +91,9 @@ struct session_chain * */ struct session_item* DEFAULT_CC -session_get_bydata(char* name, int width, int height, int bpp, int type); +session_get_bydata(char* name, int width, int height, int bpp, int type, char *client_ip); #ifndef session_find_item - #define session_find_item(a, b, c, d, e) session_get_bydata(a, b, c, d, e); + #define session_find_item(a, b, c, d, e, f) session_get_bydata(a, b, c, d, e, f); #endif /** diff --git a/sesman/sig.c b/sesman/sig.c index 7bb881ce..72892fb2 100644 --- a/sesman/sig.c +++ b/sesman/sig.c @@ -86,6 +86,7 @@ sig_sesman_reload_cfg(int sig) if (config_read(cfg) != 0) { log_message(LOG_LEVEL_ERROR, "error reading config - keeping old cfg"); + g_free(cfg); return; } diff --git a/sesman/tools/dis.c b/sesman/tools/dis.c index adcc3ee0..a21fbac4 100644 --- a/sesman/tools/dis.c +++ b/sesman/tools/dis.c @@ -58,7 +58,12 @@ int main(int argc, char **argv) return 1; } - sck = socket(PF_UNIX, SOCK_DGRAM, 0); + if ((sck = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) + { + printf("socket open error\n"); + return 1; + } + len = sizeof(sa); if (sendto(sck, "sig", 4, 0, (struct sockaddr *)&sa, len) > 0) diff --git a/sesman/tools/sesadmin.c b/sesman/tools/sesadmin.c index 25af850b..32789c6d 100644 --- a/sesman/tools/sesadmin.c +++ b/sesman/tools/sesadmin.c @@ -107,6 +107,12 @@ int main(int argc, char **argv) scp_init(&logging); sock = g_tcp_socket(); + if (sock < 0) + { + LOG_DBG("Socket open error, g_tcp_socket() failed\n"); + return 1; + } + s = scp_session_create(); c = scp_connection_create(sock); @@ -179,16 +185,16 @@ void cmndList(struct SCP_CONNECTION *c) (dsl[idx]).idle_days, (dsl[idx]).idle_hours, (dsl[idx]).idle_minutes, \ (dsl[idx]).conn_year, (dsl[idx]).conn_month, (dsl[idx]).conn_day, (dsl[idx]).conn_hour, (dsl[idx]).conn_minute); } - - if (0 != dsl) - { - g_free(dsl); - } } else { printf("No sessions.\n"); } + + if (0 != dsl) + { + g_free(dsl); + } } void cmndKill(struct SCP_CONNECTION *c, struct SCP_SESSION *s) diff --git a/sesman/tools/sesrun.c b/sesman/tools/sesrun.c index 7ac10102..a9181583 100644 --- a/sesman/tools/sesrun.c +++ b/sesman/tools/sesrun.c @@ -75,7 +75,10 @@ main(int argc, char **argv) init_stream(in_s, 8192); make_stream(out_s); init_stream(out_s, 8192); + sck = g_tcp_socket(); + if (sck < 0) + return 1; if (g_tcp_connect(sck, argv[1], g_cfg.listen_port) == 0) { diff --git a/sesman/tools/sestest.c b/sesman/tools/sestest.c index f2823eb6..d42b31de 100644 --- a/sesman/tools/sestest.c +++ b/sesman/tools/sestest.c @@ -38,6 +38,9 @@ int main(int argc, char **argv) scp_init(&log); sock = g_tcp_socket(); + if (sock < 0) + return 1; + s = scp_session_create(); c = scp_connection_create(sock); diff --git a/sesman/verify_user_pam.c b/sesman/verify_user_pam.c index 4d73f85d..eec12c66 100644 --- a/sesman/verify_user_pam.c +++ b/sesman/verify_user_pam.c @@ -122,6 +122,7 @@ auth_userpass(char *user, char *pass, int *errorcode) *errorcode = error ; } g_printf("pam_start failed: %s\r\n", pam_strerror(auth_info->ph, error)); + pam_end(auth_info->ph, error); g_free(auth_info); return 0; } @@ -135,6 +136,7 @@ auth_userpass(char *user, char *pass, int *errorcode) } g_printf("pam_authenticate failed: %s\r\n", pam_strerror(auth_info->ph, error)); + pam_end(auth_info->ph, error); g_free(auth_info); return 0; } @@ -153,6 +155,7 @@ auth_userpass(char *user, char *pass, int *errorcode) } g_printf("pam_acct_mgmt failed: %s\r\n", pam_strerror(auth_info->ph, error)); + pam_end(auth_info->ph, error); g_free(auth_info); return 0; } @@ -967,7 +967,16 @@ lib_mod_connect(struct vnc *v) make_stream(s); g_sprintf(con_port, "%s", v->port); make_stream(pixel_format); + v->sck = g_tcp_socket(); + if (v->sck < 0) + { + v->server_msg(v, "VNC error: socket create error, g_tcp_socket() failed", 0); + free_stream(s); + free_stream(pixel_format); + return 1; + } + v->sck_obj = g_create_wait_obj_from_socket(v->sck, 0); v->sck_closed = 0; g_sprintf(text, "VNC connecting to %s %s", v->ip, con_port); diff --git a/xorg/X11R7.6/buildx.sh b/xorg/X11R7.6/buildx.sh index 74145e36..22dfe15f 100755 --- a/xorg/X11R7.6/buildx.sh +++ b/xorg/X11R7.6/buildx.sh @@ -59,10 +59,8 @@ remove_modules() while IFS=: read mod_file mod_dir mod_args do - if [ -d build_dir/$mod_dir ]; then - rm -rf build_dir/$mod_dir - fi - done < ../$data_file + (cd build_dir; [ -d $mod_dir ] && rm -rf $mod_dir) + done < $data_file } extract_it() diff --git a/xorg/X11R7.6/rdp/rdp.h b/xorg/X11R7.6/rdp/rdp.h index 7bc2eb6c..00725d11 100644 --- a/xorg/X11R7.6/rdp/rdp.h +++ b/xorg/X11R7.6/rdp/rdp.h @@ -508,7 +508,7 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4); void KbdSync(int param1); int -rdpLoadLayout(int keylayout); +rdpLoadLayout(struct xrdp_client_info *client_info); /* rdpup.c */ int diff --git a/xorg/X11R7.6/rdp/rdpinput.c b/xorg/X11R7.6/rdp/rdpinput.c index 7fb20379..ef0bb929 100644 --- a/xorg/X11R7.6/rdp/rdpinput.c +++ b/xorg/X11R7.6/rdp/rdpinput.c @@ -282,7 +282,7 @@ rdpChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl) /******************************************************************************/ int -rdpLoadLayout(int keylayout) +rdpLoadLayout(struct xrdp_client_info *client_info) { XkbRMLVOSet set; XkbSrvInfoPtr xkbi; @@ -292,8 +292,10 @@ rdpLoadLayout(int keylayout) KeyCode first_key; CARD8 num_keys; - LLOGLN(0, ("rdpLoadLayout: keylayout 0x%8.8x display %s", - keylayout, display)); + int keylayout = client_info->keylayout; + + LLOGLN(0, ("rdpLoadLayout: keylayout 0x%8.8x variant %s display %s", + keylayout, client_info->variant, display)); memset(&set, 0, sizeof(set)); if (g_use_evdev) { @@ -303,42 +305,26 @@ rdpLoadLayout(int keylayout) { set.rules = "base"; } + set.model = "pc104"; set.layout = "us"; - switch (keylayout) - { - case 0x00000407: /* German */ - set.layout = "de"; - break; - case 0x00000409: /* US */ - set.layout = "us"; - break; - case 0x0000040C: /* French */ - set.layout = "fr"; - break; - case 0x00000410: /* Italian */ - set.layout = "it"; - break; - case 0x00000416: /* Portuguese (Brazilian ABNT) */ - set.model = "abnt2"; - set.layout = "br"; - break; - case 0x00000419: /* Russian */ - set.layout = "ru"; - break; - case 0x0000041D: /* Swedish */ - set.layout = "se"; - break; - case 0x00000816: /* Portuguese */ - set.layout = "pt"; - break; - default: - LLOGLN(0, ("rdpLoadLayout: unknown keylayout 0x%8.8x", keylayout)); - break; - } set.variant = ""; set.options = ""; + if (strlen(client_info->model) > 0) + { + set.model = client_info->model; + } + if (strlen(client_info->variant) > 0) + { + set.variant = client_info->variant; + } + if (strlen(client_info->layout) > 0) + { + set.layout = client_info->layout; + } + + retry: /* free some stuff so we can call InitKeyboardDeviceStruct again */ xkbi = g_keyboard->key->xkbInfo; xkb = xkbi->desc; @@ -355,21 +341,30 @@ rdpLoadLayout(int keylayout) rdpChangeKeyboardControl)) { LLOGLN(0, ("rdpLoadLayout: InitKeyboardDeviceStruct failed")); + return 1; } /* notify the X11 clients eg. X_ChangeKeyboardMapping */ keySyms = XkbGetCoreMap(g_keyboard); - first_key = keySyms->minKeyCode; - num_keys = (keySyms->maxKeyCode - keySyms->minKeyCode) + 1; - XkbApplyMappingChange(g_keyboard, keySyms, first_key, num_keys, - NULL, serverClient); - for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + if (keySyms) { - if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) + first_key = keySyms->minKeyCode; + num_keys = (keySyms->maxKeyCode - keySyms->minKeyCode) + 1; + XkbApplyMappingChange(g_keyboard, keySyms, first_key, num_keys, + NULL, serverClient); + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - XkbApplyMappingChange(pDev, keySyms, first_key, num_keys, - NULL, serverClient); + if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) + { + XkbApplyMappingChange(pDev, keySyms, first_key, num_keys, + NULL, serverClient); + } } + } else + { + /* sometimes, variant doesn't support all layouts */ + set.variant = ""; + goto retry; } return 0; diff --git a/xorg/X11R7.6/rdp/rdpup.c b/xorg/X11R7.6/rdp/rdpup.c index 83525251..f25b390a 100644 --- a/xorg/X11R7.6/rdp/rdpup.c +++ b/xorg/X11R7.6/rdp/rdpup.c @@ -1117,7 +1117,7 @@ rdpup_process_msg(struct stream *s) g_do_multimon = 0; } - rdpLoadLayout(g_rdpScreen.client_info.keylayout); + rdpLoadLayout(&(g_rdpScreen.client_info)); } else if (msg_type == 105) @@ -1563,7 +1563,7 @@ convert_pixel(int in_pixel) if (g_rdpScreen.depth == 24) { - if (g_rdpScreen.rdp_bpp == 24) + if (g_rdpScreen.rdp_bpp >= 24) { rv = in_pixel; SPLITCOLOR32(red, green, blue, rv); @@ -1619,7 +1619,7 @@ convert_pixels(void *src, void *dst, int num_pixels) { src32 = (unsigned int *)src; - if (g_rdpScreen.rdp_bpp == 24) + if (g_rdpScreen.rdp_bpp >= 24) { dst32 = (unsigned int *)dst; diff --git a/xorg/X11R7.6/x11_file_list.txt b/xorg/X11R7.6/x11_file_list.txt index d6f86892..254ac7a6 100644 --- a/xorg/X11R7.6/x11_file_list.txt +++ b/xorg/X11R7.6/x11_file_list.txt @@ -59,7 +59,7 @@ mkfontdir-1.0.6.tar.bz2 : mkfontdir-1.0.6 mkfontscale-1.0.8.tar.bz2 : mkfontscale-1.0.8 : xkbcomp-1.2.0.tar.bz2 : xkbcomp-1.2.0 : xdriinfo-1.0.4.tar.bz2 : xdriinfo-1.0.4 : -xorg-server-1.9.3.tar.bz2 : xorg-server-1.9.3 : --with-sha1=libcrypto --disable-dmx +xorg-server-1.9.3.tar.bz2 : xorg-server-1.9.3 : --with-sha1=libcrypto --disable-dmx --without-dtrace applewmproto-1.4.1.tar.bz2 : applewmproto-1.4.1 : bdftopcf-1.0.3.tar.bz2 : bdftopcf-1.0.3 : intltool-0.41.1.tar.gz : intltool-0.41.1 : diff --git a/xorg/server/Makefile b/xorg/server/Makefile index ad82975a..793334c7 100644 --- a/xorg/server/Makefile +++ b/xorg/server/Makefile @@ -1,3 +1,4 @@ +moduledir := $(shell pkg-config xorg-server --variable moduledir) all: allmake @@ -16,7 +17,20 @@ allclean: cd xrdpmouse; $(MAKE) clean xinstall: + strip module/libxorgxrdp.so + strip xrdpdev/xrdpdev_drv.so + strip xrdpmouse/xrdpmouse_drv.so + strip xrdpkeyb/xrdpkeyb_drv.so + + mkdir -p $(HOME)/xorg-modules/drivers $(HOME)/xorg-modules/input cp module/libxorgxrdp.so $(HOME)/xorg-modules/ cp xrdpdev/xrdpdev_drv.so $(HOME)/xorg-modules/drivers/ cp xrdpmouse/xrdpmouse_drv.so $(HOME)/xorg-modules/input/ cp xrdpkeyb/xrdpkeyb_drv.so $(HOME)/xorg-modules/input/ + +install: + install --directory $(DESTDIR)$(moduledir) $(DESTDIR)$(moduledir)/drivers $(DESTDIR)$(moduledir)/input + install --mode=0644 --strip module/libxorgxrdp.so $(DESTDIR)$(moduledir) + install --mode=0644 --strip xrdpdev/xrdpdev_drv.so $(DESTDIR)$(moduledir)/drivers/ + install --mode=0644 --strip xrdpmouse/xrdpmouse_drv.so $(DESTDIR)$(moduledir)/input/ + install --mode=0644 --strip xrdpkeyb/xrdpkeyb_drv.so $(DESTDIR)$(moduledir)/input/ diff --git a/xorg/server/module/Makefile b/xorg/server/module/Makefile index 9003de4d..8f1560d6 100644 --- a/xorg/server/module/Makefile +++ b/xorg/server/module/Makefile @@ -6,11 +6,16 @@ rdpPolyFillArc.o rdpPolyText8.o rdpPolyText16.o rdpImageText8.o \ rdpImageText16.o rdpImageGlyphBlt.o rdpPolyGlyphBlt.o rdpPushPixels.o \ rdpCursor.o rdpMain.o rdpRandR.o rdpMisc.o rdpReg.o \ rdpComposite.o rdpGlyphs.o rdpPixmap.o rdpInput.o rdpClientCon.o rdpCapture.o \ -rdpTrapezoids.o +rdpTrapezoids.o rdpXv.o rdpSimd.o + +;OBJS += cpuid_x86.o i420_to_rgb32_x86_sse2.o yv12_to_rgb32_x86_sse2.o yuy2_to_rgb32_x86_sse2.o uyvy_to_rgb32_x86_sse2.o +;OBJS += cpuid_amd64.o i420_to_rgb32_amd64_sse2.o yv12_to_rgb32_amd64_sse2.o yuy2_to_rgb32_amd64_sse2.o uyvy_to_rgb32_amd64_sse2.o CFLAGS = -g -O2 -Wall -fPIC -I/usr/include/xorg -I/usr/include/pixman-1 \ -I../../../common +;CFLAGS += -DSIMD_USE_ACCEL=1 + LDFLAGS = LIBS = @@ -22,3 +27,34 @@ libxorgxrdp.so: $(OBJS) Makefile clean: rm -f $(OBJS) libxorgxrdp.so + +cpuid_x86.o: x86/cpuid_x86.asm + yasm -f elf32 -g dwarf2 x86/cpuid_x86.asm + +i420_to_rgb32_x86_sse2.o: x86/i420_to_rgb32_x86_sse2.asm + yasm -f elf32 -g dwarf2 x86/i420_to_rgb32_x86_sse2.asm + +yv12_to_rgb32_x86_sse2.o: x86/yv12_to_rgb32_x86_sse2.asm + yasm -f elf32 -g dwarf2 x86/yv12_to_rgb32_x86_sse2.asm + +yuy2_to_rgb32_x86_sse2.o: x86/yuy2_to_rgb32_x86_sse2.asm + yasm -f elf32 -g dwarf2 x86/yuy2_to_rgb32_x86_sse2.asm + +uyvy_to_rgb32_x86_sse2.o: x86/uyvy_to_rgb32_x86_sse2.asm + yasm -f elf32 -g dwarf2 x86/uyvy_to_rgb32_x86_sse2.asm + +cpuid_amd64.o: amd64/cpuid_amd64.asm + yasm -f elf64 -g dwarf2 amd64/cpuid_amd64.asm + +i420_to_rgb32_amd64_sse2.o: amd64/i420_to_rgb32_amd64_sse2.asm + yasm -f elf64 -g dwarf2 amd64/i420_to_rgb32_amd64_sse2.asm + +yv12_to_rgb32_amd64_sse2.o: amd64/yv12_to_rgb32_amd64_sse2.asm + yasm -f elf64 -g dwarf2 amd64/yv12_to_rgb32_amd64_sse2.asm + +yuy2_to_rgb32_amd64_sse2.o: amd64/yuy2_to_rgb32_amd64_sse2.asm + yasm -f elf64 -g dwarf2 amd64/yuy2_to_rgb32_amd64_sse2.asm + +uyvy_to_rgb32_amd64_sse2.o: amd64/uyvy_to_rgb32_amd64_sse2.asm + yasm -f elf64 -g dwarf2 amd64/uyvy_to_rgb32_amd64_sse2.asm + diff --git a/xorg/server/module/amd64/cpuid_amd64.asm b/xorg/server/module/amd64/cpuid_amd64.asm new file mode 100644 index 00000000..b97937ad --- /dev/null +++ b/xorg/server/module/amd64/cpuid_amd64.asm @@ -0,0 +1,41 @@ + +SECTION .text + +%macro PROC 1 + align 16 + global %1 + %1: +%endmacro + +;The first six integer or pointer arguments are passed in registers +;RDI, RSI, RDX, RCX, R8, and R9 + +;int +;cpuid_amd64(int eax_in, int ecx_in, int *eax, int *ebx, int *ecx, int *edx) + +PROC cpuid_amd64 + ; save registers + push rbx + + push rdx + push rcx + push r8 + push r9 + + mov rax, rdi + mov rcx, rsi + cpuid + pop rdi + mov [rdi], edx + pop rdi + mov [rdi], ecx + pop rdi + mov [rdi], ebx + pop rdi + mov [rdi], eax + mov eax, 0 + ; restore registers + pop rbx + ret; + align 16 + diff --git a/xorg/server/module/amd64/funcs_amd64.h b/xorg/server/module/amd64/funcs_amd64.h new file mode 100644 index 00000000..10cffe0d --- /dev/null +++ b/xorg/server/module/amd64/funcs_amd64.h @@ -0,0 +1,39 @@ +/* +Copyright 2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +amd64 asm functions + +*/ + +#ifndef __FUNCS_AMD64_H +#define __FUNCS_AMD64_H + +int +cpuid_amd64(int eax_in, int ecx_in, int *eax, int *ebx, int *ecx, int *edx); +int +yv12_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs); +int +i420_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs); +int +yuy2_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs); +int +uyvy_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs); + +#endif + diff --git a/xorg/server/module/amd64/i420_to_rgb32_amd64_sse2.asm b/xorg/server/module/amd64/i420_to_rgb32_amd64_sse2.asm new file mode 100644 index 00000000..d9760caa --- /dev/null +++ b/xorg/server/module/amd64/i420_to_rgb32_amd64_sse2.asm @@ -0,0 +1,248 @@ +; +;Copyright 2014 Jay Sorg +; +;Permission to use, copy, modify, distribute, and sell this software and its +;documentation for any purpose is hereby granted without fee, provided that +;the above copyright notice appear in all copies and that both that +;copyright notice and this permission notice appear in supporting +;documentation. +; +;The above copyright notice and this permission notice shall be included in +;all copies or substantial portions of the Software. +; +;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +;OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +;AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +;CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +; +;I420 to RGB32 +;amd64 SSE2 32 bit +; +; RGB to YUV +; 0.299 0.587 0.114 +; -0.14713 -0.28886 0.436 +; 0.615 -0.51499 -0.10001 +; YUV to RGB +; 1 0 1.13983 +; 1 -0.39465 -0.58060 +; 1 2.03211 0 +; shift left 12 +; 4096 0 4669 +; 4096 -1616 -2378 +; 4096 9324 0 + +SECTION .data +align 16 +c128 times 8 dw 128 +c4669 times 8 dw 4669 +c1616 times 8 dw 1616 +c2378 times 8 dw 2378 +c9324 times 8 dw 9324 + +SECTION .text + +%macro PROC 1 + align 16 + global %1 + %1: +%endmacro + +do8_uv: + + ; v + movd xmm1, [rbx] ; 4 at a time + lea rbx, [rbx + 4] + punpcklbw xmm1, xmm1 + pxor xmm6, xmm6 + punpcklbw xmm1, xmm6 + movdqa xmm7, [rel c128] + psubw xmm1, xmm7 + psllw xmm1, 4 + + ; v + movd xmm2, [rdx] ; 4 at a time + lea rdx, [rdx + 4] + punpcklbw xmm2, xmm2 + punpcklbw xmm2, xmm6 + psubw xmm2, xmm7 + psllw xmm2, 4 + +do8: + + ; y + movq xmm0, [rsi] ; 8 at a time + lea rsi, [rsi + 8] + pxor xmm6, xmm6 + punpcklbw xmm0, xmm6 + + ; r = y + hiword(4669 * (v << 4)) + movdqa xmm4, [rel c4669] + pmulhw xmm4, xmm1 + movdqa xmm3, xmm0 + paddw xmm3, xmm4 + + ; g = y - hiword(1616 * (u << 4)) - hiword(2378 * (v << 4)) + movdqa xmm5, [rel c1616] + pmulhw xmm5, xmm2 + movdqa xmm6, [rel c2378] + pmulhw xmm6, xmm1 + movdqa xmm4, xmm0 + psubw xmm4, xmm5 + psubw xmm4, xmm6 + + ; b = y + hiword(9324 * (u << 4)) + movdqa xmm6, [rel c9324] + pmulhw xmm6, xmm2 + movdqa xmm5, xmm0 + paddw xmm5, xmm6 + + packuswb xmm3, xmm3 ; b + packuswb xmm4, xmm4 ; g + punpcklbw xmm3, xmm4 ; gb + + pxor xmm4, xmm4 ; a + packuswb xmm5, xmm5 ; r + punpcklbw xmm5, xmm4 ; ar + + movdqa xmm4, xmm3 + punpcklwd xmm3, xmm5 ; argb + movdqa [rdi], xmm3 + lea rdi, [rdi + 16] + punpckhwd xmm4, xmm5 ; argb + movdqa [rdi], xmm4 + lea rdi, [rdi + 16] + + ret; + +;The first six integer or pointer arguments are passed in registers +; RDI, RSI, RDX, RCX, R8, and R9 + +;int +;i420_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs) + +PROC i420_to_rgb32_amd64_sse2 + push rbx + push rsi + push rdi + push rbp + + push rdi + push rdx + mov rdi, rcx ; rgbs + + mov rcx, rsi ; width + mov rdx, rcx + pop rbp ; height + mov rax, rbp + shr rbp, 1 + imul rax, rcx ; rax = width * height + + pop rsi ; y + + mov rbx, rsi ; u = y + width * height + add rbx, rax + + ; local vars + ; char* yptr1 + ; char* yptr2 + ; char* uptr + ; char* vptr + ; int* rgbs1 + ; int* rgbs2 + ; int width + sub rsp, 56 ; local vars, 56 bytes + mov [rsp + 0], rsi ; save y1 + add rsi, rdx + mov [rsp + 8], rsi ; save y2 + mov [rsp + 16], rbx ; save u + shr rax, 2 + add rbx, rax ; v = u + (width * height / 4) + mov [rsp + 24], rbx ; save v + + mov [rsp + 32], rdi ; save rgbs1 + mov rax, rdx + shl rax, 2 + add rdi, rax + mov [rsp + 40], rdi ; save rgbs2 + +loop_y: + + mov rcx, rdx ; width + shr rcx, 3 + + ; save rdx + mov [rsp + 48], rdx + + ;prefetchnta 4096[rsp + 0] ; y + ;prefetchnta 1024[rsp + 16] ; u + ;prefetchnta 1024[rsp + 24] ; v + +loop_x: + + mov rsi, [rsp + 0] ; y1 + mov rbx, [rsp + 16] ; u + mov rdx, [rsp + 24] ; v + mov rdi, [rsp + 32] ; rgbs1 + + ; y1 + call do8_uv + + mov [rsp + 0], rsi ; y1 + mov [rsp + 32], rdi ; rgbs1 + + mov rsi, [rsp + 8] ; y2 + mov rdi, [rsp + 40] ; rgbs2 + + ; y2 + call do8 + + mov [rsp + 8], rsi ; y2 + mov [rsp + 16], rbx ; u + mov [rsp + 24], rdx ; v + mov [rsp + 40], rdi ; rgbs2 + + dec rcx ; width + jnz loop_x + + ; restore rdx + mov rdx, [rsp + 48] + + ; update y1 and 2 + mov rax, [rsp + 0] + mov rbx, rdx + add rax, rbx + mov [rsp + 0], rax + + mov rax, [rsp + 8] + add rax, rbx + mov [rsp + 8], rax + + ; update rgb1 and 2 + mov rax, [rsp + 32] + mov rbx, rdx + shl rbx, 2 + add rax, rbx + mov [rsp + 32], rax + + mov rax, [rsp + 40] + add rax, rbx + mov [rsp + 40], rax + + mov rcx, rbp + dec rcx ; height + mov rbp, rcx + jnz loop_y + + add rsp, 56 + + mov rax, 0 + pop rbp + pop rdi + pop rsi + pop rbx + ret + align 16 + + diff --git a/xorg/server/module/amd64/uyvy_to_rgb32_amd64_sse2.asm b/xorg/server/module/amd64/uyvy_to_rgb32_amd64_sse2.asm new file mode 100644 index 00000000..8866fd0f --- /dev/null +++ b/xorg/server/module/amd64/uyvy_to_rgb32_amd64_sse2.asm @@ -0,0 +1,17 @@ + +%macro PROC 1 + align 16 + global %1 + %1: +%endmacro + +;int +;uyvy_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs) + +PROC uyvy_to_rgb32_amd64_sse2 + push rbx + mov rax, 0 + pop rbx + ret + align 16 + diff --git a/xorg/server/module/amd64/yuy2_to_rgb32_amd64_sse2.asm b/xorg/server/module/amd64/yuy2_to_rgb32_amd64_sse2.asm new file mode 100644 index 00000000..c0ac5c1b --- /dev/null +++ b/xorg/server/module/amd64/yuy2_to_rgb32_amd64_sse2.asm @@ -0,0 +1,17 @@ + +%macro PROC 1 + align 16 + global %1 + %1: +%endmacro + +;int +;yuy2_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs) + +PROC yuy2_to_rgb32_amd64_sse2 + push rbx + mov rax, 0 + pop rbx + ret + align 16 + diff --git a/xorg/server/module/amd64/yv12_to_rgb32_amd64_sse2.asm b/xorg/server/module/amd64/yv12_to_rgb32_amd64_sse2.asm new file mode 100644 index 00000000..13e46878 --- /dev/null +++ b/xorg/server/module/amd64/yv12_to_rgb32_amd64_sse2.asm @@ -0,0 +1,248 @@ +; +;Copyright 2014 Jay Sorg +; +;Permission to use, copy, modify, distribute, and sell this software and its +;documentation for any purpose is hereby granted without fee, provided that +;the above copyright notice appear in all copies and that both that +;copyright notice and this permission notice appear in supporting +;documentation. +; +;The above copyright notice and this permission notice shall be included in +;all copies or substantial portions of the Software. +; +;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +;OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +;AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +;CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +; +;YV12 to RGB32 +;amd64 SSE2 32 bit +; +; RGB to YUV +; 0.299 0.587 0.114 +; -0.14713 -0.28886 0.436 +; 0.615 -0.51499 -0.10001 +; YUV to RGB +; 1 0 1.13983 +; 1 -0.39465 -0.58060 +; 1 2.03211 0 +; shift left 12 +; 4096 0 4669 +; 4096 -1616 -2378 +; 4096 9324 0 + +SECTION .data +align 16 +c128 times 8 dw 128 +c4669 times 8 dw 4669 +c1616 times 8 dw 1616 +c2378 times 8 dw 2378 +c9324 times 8 dw 9324 + +SECTION .text + +%macro PROC 1 + align 16 + global %1 + %1: +%endmacro + +do8_uv: + + ; u + movd xmm1, [rbx] ; 4 at a time + lea rbx, [rbx + 4] + punpcklbw xmm1, xmm1 + pxor xmm6, xmm6 + punpcklbw xmm1, xmm6 + movdqa xmm7, [rel c128] + psubw xmm1, xmm7 + psllw xmm1, 4 + + ; v + movd xmm2, [rdx] ; 4 at a time + lea rdx, [rdx + 4] + punpcklbw xmm2, xmm2 + punpcklbw xmm2, xmm6 + psubw xmm2, xmm7 + psllw xmm2, 4 + +do8: + + ; y + movq xmm0, [rsi] ; 8 at a time + lea rsi, [rsi + 8] + pxor xmm6, xmm6 + punpcklbw xmm0, xmm6 + + ; r = y + hiword(4669 * (v << 4)) + movdqa xmm4, [rel c4669] + pmulhw xmm4, xmm2 + movdqa xmm3, xmm0 + paddw xmm3, xmm4 + + ; g = y - hiword(1616 * (u << 4)) - hiword(2378 * (v << 4)) + movdqa xmm5, [rel c1616] + pmulhw xmm5, xmm1 + movdqa xmm6, [rel c2378] + pmulhw xmm6, xmm2 + movdqa xmm4, xmm0 + psubw xmm4, xmm5 + psubw xmm4, xmm6 + + ; b = y + hiword(9324 * (u << 4)) + movdqa xmm6, [rel c9324] + pmulhw xmm6, xmm1 + movdqa xmm5, xmm0 + paddw xmm5, xmm6 + + packuswb xmm3, xmm3 ; b + packuswb xmm4, xmm4 ; g + punpcklbw xmm3, xmm4 ; gb + + pxor xmm4, xmm4 ; a + packuswb xmm5, xmm5 ; r + punpcklbw xmm5, xmm4 ; ar + + movdqa xmm4, xmm3 + punpcklwd xmm3, xmm5 ; argb + movdqa [rdi], xmm3 + lea rdi, [rdi + 16] + punpckhwd xmm4, xmm5 ; argb + movdqa [rdi], xmm4 + lea rdi, [rdi + 16] + + ret; + +;The first six integer or pointer arguments are passed in registers +; RDI, RSI, RDX, RCX, R8, and R9 + +;int +;yv12_to_rgb32_amd64_sse2(unsigned char *yuvs, int width, int height, int *rgbs) + +PROC yv12_to_rgb32_amd64_sse2 + push rbx + push rsi + push rdi + push rbp + + push rdi + push rdx + mov rdi, rcx ; rgbs + + mov rcx, rsi ; width + mov rdx, rcx + pop rbp ; height + mov rax, rbp + shr rbp, 1 + imul rax, rcx ; rax = width * height + + pop rsi ; y + + mov rbx, rsi ; u = y + width * height + add rbx, rax + + ; local vars + ; char* yptr1 + ; char* yptr2 + ; char* uptr + ; char* vptr + ; int* rgbs1 + ; int* rgbs2 + ; int width + sub rsp, 56 ; local vars, 56 bytes + mov [rsp + 0], rsi ; save y1 + add rsi, rdx + mov [rsp + 8], rsi ; save y2 + mov [rsp + 16], rbx ; save u + shr rax, 2 + add rbx, rax ; v = u + (width * height / 4) + mov [rsp + 24], rbx ; save v + + mov [rsp + 32], rdi ; save rgbs1 + mov rax, rdx + shl rax, 2 + add rdi, rax + mov [rsp + 40], rdi ; save rgbs2 + +loop_y: + + mov rcx, rdx ; width + shr rcx, 3 + + ; save rdx + mov [rsp + 48], rdx + + ;prefetchnta 4096[rsp + 0] ; y + ;prefetchnta 1024[rsp + 16] ; u + ;prefetchnta 1024[rsp + 24] ; v + +loop_x: + + mov rsi, [rsp + 0] ; y1 + mov rbx, [rsp + 16] ; u + mov rdx, [rsp + 24] ; v + mov rdi, [rsp + 32] ; rgbs1 + + ; y1 + call do8_uv + + mov [rsp + 0], rsi ; y1 + mov [rsp + 32], rdi ; rgbs1 + + mov rsi, [rsp + 8] ; y2 + mov rdi, [rsp + 40] ; rgbs2 + + ; y2 + call do8 + + mov [rsp + 8], rsi ; y2 + mov [rsp + 16], rbx ; u + mov [rsp + 24], rdx ; v + mov [rsp + 40], rdi ; rgbs2 + + dec rcx ; width + jnz loop_x + + ; restore rdx + mov rdx, [rsp + 48] + + ; update y1 and 2 + mov rax, [rsp + 0] + mov rbx, rdx + add rax, rbx + mov [rsp + 0], rax + + mov rax, [rsp + 8] + add rax, rbx + mov [rsp + 8], rax + + ; update rgb1 and 2 + mov rax, [rsp + 32] + mov rbx, rdx + shl rbx, 2 + add rax, rbx + mov [rsp + 32], rax + + mov rax, [rsp + 40] + add rax, rbx + mov [rsp + 40], rax + + mov rcx, rbp + dec rcx ; height + mov rbp, rcx + jnz loop_y + + add rsp, 56 + + mov rax, 0 + pop rbp + pop rdi + pop rsi + pop rbx + ret + align 16 + + diff --git a/xorg/server/module/rdp.h b/xorg/server/module/rdp.h index ba1bcfd0..8a4d58c4 100644 --- a/xorg/server/module/rdp.h +++ b/xorg/server/module/rdp.h @@ -30,9 +30,46 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "rdpPri.h" +#define XRDP_MODULE_NAME "XRDPMOD" +#define XRDP_DRIVER_NAME "XRDPDEV" +#define XRDP_MOUSE_NAME "XRDPMOUSE" +#define XRDP_KEYB_NAME "XRDPKEYB" +#define XRDP_VERSION 1000 + +#define PACKAGE_VERSION_MAJOR 1 +#define PACKAGE_VERSION_MINOR 0 +#define PACKAGE_VERSION_PATCHLEVEL 0 + +#define COLOR8(r, g, b) \ + ((((r) >> 5) << 0) | (((g) >> 5) << 3) | (((b) >> 6) << 6)) +#define COLOR15(r, g, b) \ + ((((r) >> 3) << 10) | (((g) >> 3) << 5) | (((b) >> 3) << 0)) +#define COLOR16(r, g, b) \ + ((((r) >> 3) << 11) | (((g) >> 2) << 5) | (((b) >> 3) << 0)) +#define COLOR24(r, g, b) \ + ((((r) >> 0) << 0) | (((g) >> 0) << 8) | (((b) >> 0) << 16)) +#define SPLITCOLOR32(r, g, b, c) \ + do { \ + r = ((c) >> 16) & 0xff; \ + g = ((c) >> 8) & 0xff; \ + b = (c) & 0xff; \ + } while (0) + +/* PIXMAN_a8b8g8r8 */ +#define XRDP_a8b8g8r8 \ +((32 << 24) | (3 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8) /* PIXMAN_a8r8g8b8 */ #define XRDP_a8r8g8b8 \ -((32 << 24) | (2 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8) +((32 << 24) | (2 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8) +/* PIXMAN_r5g6b5 */ +#define XRDP_r5g6b5 \ +((16 << 24) | (2 << 16) | (0 << 12) | (5 << 8) | (6 << 4) | 5) +/* PIXMAN_a1r5g5b5 */ +#define XRDP_a1r5g5b5 \ +((16 << 24) | (2 << 16) | (1 << 12) | (5 << 8) | (5 << 4) | 5) +/* PIXMAN_r3g3b2 */ +#define XRDP_r3g3b2 \ +((8 << 24) | (2 << 16) | (0 << 12) | (3 << 8) | (3 << 4) | 2) #define PixelDPI 100 #define PixelToMM(_size) (((_size) * 254 + (PixelDPI) * 5) / ((PixelDPI) * 10)) @@ -40,7 +77,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define RDPMIN(_val1, _val2) ((_val1) < (_val2) ? (_val1) : (_val2)) #define RDPMAX(_val1, _val2) ((_val1) < (_val2) ? (_val2) : (_val1)) #define RDPCLAMP(_val, _lo, _hi) \ - (_val) < (_lo) ? (_lo) : (_val) > (_hi) ? (_hi) : (_val) + (_val) < (_lo) ? (_lo) : (_val) > (_hi) ? (_hi) : (_val) +#define RDPALIGN(_val, _al) ((((long)(_val)) + ((_al) - 1)) & ~((_al) - 1)) #define XRDP_CD_NODRAW 0 #define XRDP_CD_NOCLIP 1 @@ -157,6 +195,8 @@ struct _rdpCounts CARD32 callCount[64 - 23]; }; +typedef int (*yuv_to_rgb32_proc)(unsigned char *yuvs, int width, int height, int *rgbs); + /* move this to common header */ struct _rdpRec { @@ -228,6 +268,15 @@ struct _rdpRec struct _rdpCounts counts; + yuv_to_rgb32_proc i420_to_rgb32; + yuv_to_rgb32_proc yv12_to_rgb32; + yuv_to_rgb32_proc yuy2_to_rgb32; + yuv_to_rgb32_proc uyvy_to_rgb32; + char *xv_data; + int xv_data_bytes; + int xv_timer_schedualed; + OsTimerPtr xv_timer; + }; typedef struct _rdpRec rdpRec; typedef struct _rdpRec * rdpPtr; @@ -250,63 +299,63 @@ typedef struct _rdpGCRec * rdpGCPtr; struct urdp_draw_item_fill { - int opcode; - int fg_color; - int bg_color; - int pad0; + int opcode; + int fg_color; + int bg_color; + int pad0; }; struct urdp_draw_item_img { - int opcode; - int pad0; + int opcode; + int pad0; }; struct urdp_draw_item_line { - int opcode; - int fg_color; - int bg_color; - int width; - xSegment* segs; - int nseg; - int flags; + int opcode; + int fg_color; + int bg_color; + int width; + xSegment* segs; + int nseg; + int flags; }; struct urdp_draw_item_scrblt { - int srcx; - int srcy; - int dstx; - int dsty; - int cx; - int cy; + int srcx; + int srcy; + int dstx; + int dsty; + int cx; + int cy; }; struct urdp_draw_item_text { - int opcode; - int fg_color; - struct rdp_text* rtext; /* in rdpglyph.h */ + int opcode; + int fg_color; + struct rdp_text* rtext; /* in rdpglyph.h */ }; union urdp_draw_item { - struct urdp_draw_item_fill fill; - struct urdp_draw_item_img img; - struct urdp_draw_item_line line; - struct urdp_draw_item_scrblt scrblt; - struct urdp_draw_item_text text; + struct urdp_draw_item_fill fill; + struct urdp_draw_item_img img; + struct urdp_draw_item_line line; + struct urdp_draw_item_scrblt scrblt; + struct urdp_draw_item_text text; }; struct rdp_draw_item { - int type; /* RDI_FILL, RDI_IMGLL, ... */ - int flags; - struct rdp_draw_item* prev; - struct rdp_draw_item* next; - RegionPtr reg; - union urdp_draw_item u; + int type; /* RDI_FILL, RDI_IMGLL, ... */ + int flags; + struct rdp_draw_item* prev; + struct rdp_draw_item* next; + RegionPtr reg; + union urdp_draw_item u; }; #define XRDP_USE_COUNT_THRESHOLD 1 diff --git a/xorg/server/module/rdpCapture.c b/xorg/server/module/rdpCapture.c index 8819713a..5163e6ae 100644 --- a/xorg/server/module/rdpCapture.c +++ b/xorg/server/module/rdpCapture.c @@ -33,34 +33,249 @@ #include "rdpDraw.h" #include "rdpClientCon.h" #include "rdpReg.h" +#include "rdpMisc.h" #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) +#define RDP_MAX_TILES 1024 + +/******************************************************************************/ +static int +rdpLimitRects(RegionPtr reg, int max_rects, BoxPtr *rects) +{ + int nrects; + + nrects = REGION_NUM_RECTS(reg); + if (nrects > max_rects) + { + nrects = 1; + *rects = rdpRegionExtents(reg); + } + else + { + *rects = REGION_RECTS(reg); + } + return nrects; +} + +/******************************************************************************/ +/* copy rects with no error checking */ +static int +rdpCopyBox_a8r8g8b8_to_a8r8g8b8(void *src, int src_stride, int srcx, int srcy, + void *dst, int dst_stride, int dstx, int dsty, + BoxPtr rects, int num_rects) +{ + char *s8; + char *d8; + int index; + int jndex; + int bytes; + int height; + BoxPtr box; + + for (index = 0; index < num_rects; index++) + { + box = rects + index; + s8 = ((char *) src) + (box->y1 - srcy) * src_stride; + s8 += (box->x1 - srcx) * 4; + d8 = ((char *) dst) + (box->y1 - dsty) * dst_stride; + d8 += (box->x1 - dstx) * 4; + bytes = box->x2 - box->x1; + bytes *= 4; + height = box->y2 - box->y1; + for (jndex = 0; jndex < height; jndex++) + { + memcpy(d8, s8, bytes); + d8 += dst_stride; + s8 += src_stride; + } + } + return 0; +} + +/******************************************************************************/ +static int +rdpFillBox_yuvalp(int ax, int ay, + void *dst, int dst_stride) +{ + dst = ((char *) dst) + (ay << 8) * (dst_stride >> 8) + (ax << 8); + memset(dst, 0, 64 * 64 * 4); + return 0; +} + +/******************************************************************************/ +/* copy rects with no error checking + * convert ARGB32 to 64x64 linear planar YUVA */ +/* http://msdn.microsoft.com/en-us/library/ff635643.aspx + * 0.299 -0.168935 0.499813 + * 0.587 -0.331665 -0.418531 + * 0.114 0.50059 -0.081282 + y = r * 0.299000 + g * 0.587000 + b * 0.114000; + u = r * -0.168935 + g * -0.331665 + b * 0.500590; + v = r * 0.499813 + g * -0.418531 + b * -0.081282; */ +/* 19595 38470 7471 + -11071 -21736 32807 + 32756 -27429 -5327 */ +static int +rdpCopyBox_a8r8g8b8_to_yuvalp(int ax, int ay, + void *src, int src_stride, + void *dst, int dst_stride, + BoxPtr rects, int num_rects) +{ + char *s8; + char *d8; + char *yptr; + char *uptr; + char *vptr; + char *aptr; + int *s32; + int index; + int jndex; + int kndex; + int width; + int height; + int pixel; + int a; + int r; + int g; + int b; + int y; + int u; + int v; + BoxPtr box; + + dst = ((char *) dst) + (ay << 8) * (dst_stride >> 8) + (ax << 8); + for (index = 0; index < num_rects; index++) + { + box = rects + index; + s8 = ((char *) src) + box->y1 * src_stride; + s8 += box->x1 * 4; + d8 = ((char *) dst) + (box->y1 - ay) * 64; + d8 += box->x1 - ax; + width = box->x2 - box->x1; + height = box->y2 - box->y1; + for (jndex = 0; jndex < height; jndex++) + { + s32 = (int *) s8; + yptr = d8; + uptr = yptr + 64 * 64; + vptr = uptr + 64 * 64; + aptr = vptr + 64 * 64; + kndex = 0; + while (kndex < width) + { + pixel = *(s32++); + a = (pixel >> 24) & 0xff; + r = (pixel >> 16) & 0xff; + g = (pixel >> 8) & 0xff; + b = (pixel >> 0) & 0xff; + y = (r * 19595 + g * 38470 + b * 7471) >> 16; + u = (r * -11071 + g * -21736 + b * 32807) >> 16; + v = (r * 32756 + g * -27429 + b * -5327) >> 16; + y = y - 128; + y = max(y, -128); + u = max(u, -128); + v = max(v, -128); + y = min(y, 127); + u = min(u, 127); + v = min(v, 127); + *(yptr++) = y; + *(uptr++) = u; + *(vptr++) = v; + *(aptr++) = a; + kndex++; + } + d8 += 64; + s8 += src_stride; + } + } + return 0; +} + +/******************************************************************************/ +/* copy rects with no error checking */ +static int +rdpCopyBox_a8r8g8b8_to_a8b8g8r8(void *src, int src_stride, + void *dst, int dst_stride, + BoxPtr rects, int num_rects) +{ + char *s8; + char *d8; + int index; + int jndex; + int kndex; + int bytes; + int width; + int height; + int red; + int green; + int blue; + BoxPtr box; + unsigned int *s32; + unsigned int *d32; + + for (index = 0; index < num_rects; index++) + { + box = rects + index; + s8 = ((char *) src) + box->y1 * src_stride; + s8 += box->x1 * 4; + d8 = ((char *) dst) + box->y1 * dst_stride; + d8 += box->x1 * 4; + bytes = box->x2 - box->x1; + bytes *= 4; + width = box->x2 - box->x1; + height = box->y2 - box->y1; + for (jndex = 0; jndex < height; jndex++) + { + s32 = (unsigned int *) s8; + d32 = (unsigned int *) d8; + for (kndex = 0; kndex < width; kndex++) + { + SPLITCOLOR32(red, green, blue, *s32); + *d32 = COLOR24(red, green, blue); + s32++; + d32++; + } + d8 += dst_stride; + s8 += src_stride; + } + } + return 0; +} + /******************************************************************************/ static Bool -rdpCapture0(RegionPtr in_reg, RegionPtr out_reg, +rdpCapture0(rdpClientCon *clientCon, + RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects, void *src, int src_width, int src_height, int src_stride, int src_format, void *dst, int dst_width, int dst_height, int dst_stride, int dst_format, int max_rects) { - BoxPtr prects; + BoxPtr psrc_rects; BoxRec rect; RegionRec reg; char *src_rect; char *dst_rect; - int num_regions; - int bytespp; + int num_rects; + int src_bytespp; + int dst_bytespp; int width; int height; int src_offset; int dst_offset; - int bytes; int i; int j; + int k; + int red; + int green; + int blue; Bool rv; + unsigned int *s32; + unsigned short *d16; + unsigned char *d8; LLOGLN(10, ("rdpCapture0:")); @@ -73,47 +288,320 @@ rdpCapture0(RegionPtr in_reg, RegionPtr out_reg, rdpRegionInit(®, &rect, 0); rdpRegionIntersect(®, in_reg, ®); + psrc_rects = 0; + num_rects = rdpLimitRects(®, max_rects, &psrc_rects); + if (num_rects < 1) + { + rdpRegionUninit(®); + return FALSE; + } + + *num_out_rects = num_rects; + + *out_rects = (BoxPtr) g_malloc(sizeof(BoxRec) * num_rects, 0); + for (i = 0; i < num_rects; i++) + { + rect = psrc_rects[i]; + (*out_rects)[i] = rect; + } + + if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_a8r8g8b8)) + { + rdpCopyBox_a8r8g8b8_to_a8r8g8b8(src, src_stride, 0, 0, + dst, dst_stride, 0, 0, + psrc_rects, num_rects); + } + else if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_a8b8g8r8)) + { + rdpCopyBox_a8r8g8b8_to_a8b8g8r8(src, src_stride, + dst, dst_stride, + psrc_rects, num_rects); + } + else if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_r5g6b5)) + { + src_bytespp = 4; + dst_bytespp = 2; + + for (i = 0; i < num_rects; i++) + { + /* get rect to copy */ + rect = (*out_rects)[i]; + + /* get rect dimensions */ + width = rect.x2 - rect.x1; + height = rect.y2 - rect.y1; + + /* point to start of each rect in respective memory */ + src_offset = rect.y1 * src_stride + rect.x1 * src_bytespp; + dst_offset = rect.y1 * dst_stride + rect.x1 * dst_bytespp; + src_rect = src + src_offset; + dst_rect = dst + dst_offset; + + /* copy one line at a time */ + for (j = 0; j < height; j++) + { + s32 = (unsigned int *) src_rect; + d16 = (unsigned short *) dst_rect; + for (k = 0; k < width; k++) + { + SPLITCOLOR32(red, green, blue, *s32); + *d16 = COLOR16(red, green, blue); + s32++; + d16++; + } + src_rect += src_stride; + dst_rect += dst_stride; + } + } + } + else if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_a1r5g5b5)) + { + src_bytespp = 4; + dst_bytespp = 2; + + for (i = 0; i < num_rects; i++) + { + /* get rect to copy */ + rect = (*out_rects)[i]; + + /* get rect dimensions */ + width = rect.x2 - rect.x1; + height = rect.y2 - rect.y1; + + /* point to start of each rect in respective memory */ + src_offset = rect.y1 * src_stride + rect.x1 * src_bytespp; + dst_offset = rect.y1 * dst_stride + rect.x1 * dst_bytespp; + src_rect = src + src_offset; + dst_rect = dst + dst_offset; + + /* copy one line at a time */ + for (j = 0; j < height; j++) + { + s32 = (unsigned int *) src_rect; + d16 = (unsigned short *) dst_rect; + for (k = 0; k < width; k++) + { + SPLITCOLOR32(red, green, blue, *s32); + *d16 = COLOR15(red, green, blue); + s32++; + d16++; + } + src_rect += src_stride; + dst_rect += dst_stride; + } + } + } + else if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_r3g3b2)) + { + src_bytespp = 4; + dst_bytespp = 1; + + for (i = 0; i < num_rects; i++) + { + /* get rect to copy */ + rect = (*out_rects)[i]; + + /* get rect dimensions */ + width = rect.x2 - rect.x1; + height = rect.y2 - rect.y1; + + /* point to start of each rect in respective memory */ + src_offset = rect.y1 * src_stride + rect.x1 * src_bytespp; + dst_offset = rect.y1 * dst_stride + rect.x1 * dst_bytespp; + src_rect = src + src_offset; + dst_rect = dst + dst_offset; + + /* copy one line at a time */ + for (j = 0; j < height; j++) + { + s32 = (unsigned int *) src_rect; + d8 = (unsigned char *) dst_rect; + for (k = 0; k < width; k++) + { + SPLITCOLOR32(red, green, blue, *s32); + *d8 = COLOR8(red, green, blue); + s32++; + d8++; + } + src_rect += src_stride; + dst_rect += dst_stride; + } + } + } + else + { + LLOGLN(0, ("rdpCapture0: unimp color conversion")); + } + rdpRegionUninit(®); + return rv; +} + +/******************************************************************************/ +/* make out_rects always multiple of 16 width and height */ +static Bool +rdpCapture1(rdpClientCon *clientCon, + RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, int max_rects) +{ + BoxPtr psrc_rects; + BoxRec rect; + RegionRec reg; + char *src_rect; + char *dst_rect; + int num_regions; + int src_bytespp; + int dst_bytespp; + int width; + int height; + int min_width; + int min_height; + int src_offset; + int dst_offset; + int index; + int jndex; + int kndex; + int red; + int green; + int blue; + int ex; + int ey; + Bool rv; + unsigned int *s32; + unsigned int *d32; + + LLOGLN(10, ("rdpCapture1:")); + + rv = TRUE; + + min_width = RDPMIN(dst_width, src_width); + min_height = RDPMIN(dst_height, src_height); + + rect.x1 = 0; + rect.y1 = 0; + rect.x2 = min_width; + rect.y2 = min_height; + rdpRegionInit(®, &rect, 0); + rdpRegionIntersect(®, in_reg, ®); + num_regions = REGION_NUM_RECTS(®); if (num_regions > max_rects) { num_regions = 1; - prects = rdpRegionExtents(®); - rdpRegionUninit(out_reg); - rdpRegionInit(out_reg, prects, 0); + psrc_rects = rdpRegionExtents(®); } else { - prects = REGION_RECTS(®); - rdpRegionCopy(out_reg, ®); + psrc_rects = REGION_RECTS(®); } - if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_a8r8g8b8)) + if (num_regions < 1) { - bytespp = 4; + return FALSE; + } - for (i = 0; i < num_regions; i++) + *num_out_rects = num_regions; + + *out_rects = (BoxPtr) g_malloc(sizeof(BoxRec) * num_regions * 4, 0); + index = 0; + while (index < num_regions) + { + rect = psrc_rects[index]; + width = rect.x2 - rect.x1; + height = rect.y2 - rect.y1; + ex = ((width + 15) & ~15) - width; + if (ex != 0) + { + rect.x2 += ex; + if (rect.x2 > min_width) + { + rect.x1 -= rect.x2 - min_width; + rect.x2 = min_width; + } + if (rect.x1 < 0) + { + rect.x1 += 16; + } + } + ey = ((height + 15) & ~15) - height; + if (ey != 0) + { + rect.y2 += ey; + if (rect.y2 > min_height) + { + rect.y1 -= rect.y2 - min_height; + rect.y2 = min_height; + } + if (rect.y1 < 0) + { + rect.y1 += 16; + } + } +#if 0 + if (rect.x1 < 0) + { + LLOGLN(0, ("rdpCapture1: error")); + } + if (rect.y1 < 0) + { + LLOGLN(0, ("rdpCapture1: error")); + } + if (rect.x2 > min_width) + { + LLOGLN(0, ("rdpCapture1: error")); + } + if (rect.y2 > min_height) + { + LLOGLN(0, ("rdpCapture1: error")); + } + if ((rect.x2 - rect.x1) % 16 != 0) + { + LLOGLN(0, ("rdpCapture1: error")); + } + if ((rect.y2 - rect.y1) % 16 != 0) + { + LLOGLN(0, ("rdpCapture1: error")); + } +#endif + (*out_rects)[index] = rect; + index++; + } + + if ((src_format == XRDP_a8r8g8b8) && (dst_format == XRDP_a8b8g8r8)) + { + src_bytespp = 4; + dst_bytespp = 4; + + for (index = 0; index < num_regions; index++) { /* get rect to copy */ - rect = prects[i]; + rect = (*out_rects)[index]; /* get rect dimensions */ width = rect.x2 - rect.x1; height = rect.y2 - rect.y1; /* point to start of each rect in respective memory */ - src_offset = rect.y1 * src_stride + rect.x1 * bytespp; - dst_offset = rect.y1 * dst_stride + rect.x1 * bytespp; + src_offset = rect.y1 * src_stride + rect.x1 * src_bytespp; + dst_offset = rect.y1 * dst_stride + rect.x1 * dst_bytespp; src_rect = src + src_offset; dst_rect = dst + dst_offset; - /* bytes per line */ - bytes = width * bytespp; - /* copy one line at a time */ - for (j = 0; j < height; j++) + for (jndex = 0; jndex < height; jndex++) { - memcpy(dst_rect, src_rect, bytes); + s32 = (unsigned int *) src_rect; + d32 = (unsigned int *) dst_rect; + for (kndex = 0; kndex < width; kndex++) + { + SPLITCOLOR32(red, green, blue, *s32); + *d32 = COLOR24(red, green, blue); + s32++; + d32++; + } src_rect += src_stride; dst_rect += dst_stride; } @@ -121,17 +609,130 @@ rdpCapture0(RegionPtr in_reg, RegionPtr out_reg, } else { - LLOGLN(0, ("rdpCapture0: unimp color conversion")); + LLOGLN(0, ("rdpCapture1: unimp color conversion")); } rdpRegionUninit(®); return rv; } +/******************************************************************************/ +static Bool +rdpCapture2(rdpClientCon *clientCon, + RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects, + void *src, int src_width, int src_height, + int src_stride, int src_format, + void *dst, int dst_width, int dst_height, + int dst_stride, int dst_format, int max_rects) +{ + int x; + int y; + int out_rect_index; + int num_rects; + int rcode; + BoxRec rect; + BoxRec extents_rect; + BoxPtr rects; + RegionRec tile_reg; + RegionRec lin_reg; + RegionRec temp_reg; + RegionPtr pin_reg; + + LLOGLN(10, ("rdpCapture2:")); + + *out_rects = (BoxPtr) g_malloc(sizeof(BoxRec) * RDP_MAX_TILES, 0); + if (*out_rects == NULL) + { + return FALSE; + } + out_rect_index = 0; + + /* clip for smaller of 2 */ + rect.x1 = 0; + rect.y1 = 0; + rect.x2 = min(dst_width, src_width); + rect.y2 = min(dst_height, src_height); + rdpRegionInit(&temp_reg, &rect, 0); + rdpRegionIntersect(&temp_reg, in_reg, &temp_reg); + + /* limit the numer of rects */ + num_rects = REGION_NUM_RECTS(&temp_reg); + if (num_rects > max_rects) + { + LLOGLN(10, ("rdpCapture2: too many rects")); + rdpRegionInit(&lin_reg, rdpRegionExtents(&temp_reg), 0); + pin_reg = &lin_reg; + } + else + { + LLOGLN(10, ("rdpCapture2: not too many rects")); + rdpRegionInit(&lin_reg, NullBox, 0); + pin_reg = &temp_reg; + } + extents_rect = *rdpRegionExtents(pin_reg); + y = extents_rect.y1 & ~63; + while (y < extents_rect.y2) + { + x = extents_rect.x1 & ~63; + while (x < extents_rect.x2) + { + rect.x1 = x; + rect.y1 = y; + rect.x2 = rect.x1 + 64; + rect.y2 = rect.y1 + 64; + rcode = rdpRegionContainsRect(pin_reg, &rect); + LLOGLN(10, ("rdpCapture2: rcode %d", rcode)); + + if (rcode != rgnOUT) + { + if (rcode == rgnPART) + { + LLOGLN(10, ("rdpCapture2: rgnPART")); + rdpFillBox_yuvalp(x, y, dst, dst_stride); + rdpRegionInit(&tile_reg, &rect, 0); + rdpRegionIntersect(&tile_reg, pin_reg, &tile_reg); + rects = REGION_RECTS(&tile_reg); + num_rects = REGION_NUM_RECTS(&tile_reg); + rdpCopyBox_a8r8g8b8_to_yuvalp(x, y, + src, src_stride, + dst, dst_stride, + rects, num_rects); + rdpRegionUninit(&tile_reg); + } + else /* rgnIN */ + { + LLOGLN(10, ("rdpCapture2: rgnIN")); + rdpCopyBox_a8r8g8b8_to_yuvalp(x, y, + src, src_stride, + dst, dst_stride, + &rect, 1); + } + (*out_rects)[out_rect_index] = rect; + out_rect_index++; + if (out_rect_index >= RDP_MAX_TILES) + { + g_free(*out_rects); + *out_rects = NULL; + rdpRegionUninit(&temp_reg); + rdpRegionUninit(&lin_reg); + return FALSE; + } + } + x += 64; + } + y += 64; + } + *num_out_rects = out_rect_index; + rdpRegionUninit(&temp_reg); + rdpRegionUninit(&lin_reg); + return TRUE; +} + /** * Copy an array of rectangles from one memory area to another *****************************************************************************/ Bool -rdpCapture(RegionPtr in_reg, RegionPtr out_reg, +rdpCapture(rdpClientCon *clientCon, + RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects, void *src, int src_width, int src_height, int src_stride, int src_format, void *dst, int dst_width, int dst_height, @@ -141,7 +742,19 @@ rdpCapture(RegionPtr in_reg, RegionPtr out_reg, switch (mode) { case 0: - return rdpCapture0(in_reg, out_reg, + return rdpCapture0(clientCon, in_reg, out_rects, num_out_rects, + src, src_width, src_height, + src_stride, src_format, + dst, dst_width, dst_height, + dst_stride, dst_format, 15); + case 1: + return rdpCapture1(clientCon, in_reg, out_rects, num_out_rects, + src, src_width, src_height, + src_stride, src_format, + dst, dst_width, dst_height, + dst_stride, dst_format, 15); + case 2: + return rdpCapture2(clientCon, in_reg, out_rects, num_out_rects, src, src_width, src_height, src_stride, src_format, dst, dst_width, dst_height, @@ -150,5 +763,5 @@ rdpCapture(RegionPtr in_reg, RegionPtr out_reg, LLOGLN(0, ("rdpCapture: unimp mode")); break; } - return TRUE; + return FALSE; } diff --git a/xorg/server/module/rdpCapture.h b/xorg/server/module/rdpCapture.h index f92508c4..4dff1eea 100644 --- a/xorg/server/module/rdpCapture.h +++ b/xorg/server/module/rdpCapture.h @@ -19,9 +19,9 @@ */ Bool -rdpCapture(RegionPtr in_reg, RegionPtr out_reg, +rdpCapture(rdpClientCon *clientCon, + RegionPtr in_reg, BoxPtr *out_rects, int *num_out_rects, void *src, int src_width, int src_height, int src_stride, int src_format, void *dst, int dst_width, int dst_height, - int dst_stride, int dst_format, - int mode); + int dst_stride, int dst_format, int mode); diff --git a/xorg/server/module/rdpClientCon.c b/xorg/server/module/rdpClientCon.c index 3c9cdad5..35369063 100644 --- a/xorg/server/module/rdpClientCon.c +++ b/xorg/server/module/rdpClientCon.c @@ -50,21 +50,6 @@ Client connection to xrdp #define LTOUI32(_in) ((unsigned int)(_in)) -#define COLOR8(r, g, b) \ - ((((r) >> 5) << 0) | (((g) >> 5) << 3) | (((b) >> 6) << 6)) -#define COLOR15(r, g, b) \ - ((((r) >> 3) << 10) | (((g) >> 3) << 5) | (((b) >> 3) << 0)) -#define COLOR16(r, g, b) \ - ((((r) >> 3) << 11) | (((g) >> 2) << 5) | (((b) >> 3) << 0)) -#define COLOR24(r, g, b) \ - ((((r) >> 0) << 0) | (((g) >> 0) << 8) | (((b) >> 0) << 16)) -#define SPLITCOLOR32(r, g, b, c) \ - do { \ - r = ((c) >> 16) & 0xff; \ - g = ((c) >> 8) & 0xff; \ - b = (c) & 0xff; \ - } while (0) - #define USE_MAX_OS_BYTES 1 #define MAX_OS_BYTES (16 * 1024 * 1024) @@ -107,6 +92,9 @@ static int g_rdp_opcodes[16] = 0xff /* GXset 0xf 1 */ }; +static int +rdpClientConDisconnect(rdpPtr dev, rdpClientCon *clientCon); + /******************************************************************************/ static int rdpClientConGotConnection(ScreenPtr pScreen, rdpPtr dev) @@ -144,6 +132,15 @@ rdpClientConGotConnection(ScreenPtr pScreen, rdpPtr dev) AddEnabledDevice(clientCon->sck); } +#if 0 + if (dev->clientConTail != NULL) + { + rdpClientConDisconnect(dev, dev->clientConTail); + dev->clientConHead = NULL; + dev->clientConTail = NULL; + } +#endif + if (dev->clientConTail == NULL) { LLOGLN(0, ("rdpClientConGotConnection: adding only clientCon")); @@ -274,6 +271,11 @@ rdpClientConDisconnect(rdpPtr dev, rdpClientCon *clientCon) } rdpRegionDestroy(clientCon->dirtyRegion); rdpRegionDestroy(clientCon->shmRegion); + if (clientCon->updateTimer != NULL) + { + TimerCancel(clientCon->updateTimer); + TimerFree(clientCon->updateTimer); + } g_free(clientCon); return 0; } @@ -533,6 +535,8 @@ rdpClientConProcessMsgVersion(rdpPtr dev, rdpClientCon *clientCon, return 0; } +#define LALIGN(_num, _po2) ((_num + ((_po2) - 1)) & ~((_po2) - 1)) + /******************************************************************************/ /* this from miScreenInit @@ -549,31 +553,37 @@ rdpClientConProcessScreenSizeMsg(rdpPtr dev, rdpClientCon *clientCon, int bytes; Bool ok; - LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: set width %d height %d bpp %d", - width, height, bpp)); + LLOGLN(0, ("rdpClientConProcessScreenSizeMsg: set width %d height %d " + "bpp %d", width, height, bpp)); clientCon->rdp_width = width; clientCon->rdp_height = height; clientCon->rdp_bpp = bpp; + clientCon->cap_width = width; + clientCon->cap_height = height; if (bpp < 15) { clientCon->rdp_Bpp = 1; clientCon->rdp_Bpp_mask = 0xff; + clientCon->rdp_format = PIXMAN_r3g3b2; } else if (bpp == 15) { clientCon->rdp_Bpp = 2; clientCon->rdp_Bpp_mask = 0x7fff; + clientCon->rdp_format = XRDP_a1r5g5b5; } else if (bpp == 16) { clientCon->rdp_Bpp = 2; clientCon->rdp_Bpp_mask = 0xffff; + clientCon->rdp_format = XRDP_r5g6b5; } else if (bpp > 16) { clientCon->rdp_Bpp = 4; clientCon->rdp_Bpp_mask = 0xffffff; + clientCon->rdp_format = XRDP_a8r8g8b8; } if (clientCon->shmemptr != 0) @@ -655,12 +665,13 @@ rdpClientConProcessMsgClientInput(rdpPtr dev, rdpClientCon *clientCon) } else if (msg == 300) /* resize desktop */ { - rdpClientConProcessScreenSizeMsg(dev, clientCon, param1, param2, param3); + rdpClientConProcessScreenSizeMsg(dev, clientCon, param1, + param2, param3); } else if (msg == 301) /* version */ { rdpClientConProcessMsgVersion(dev, clientCon, - param1, param2, param3, param4); + param1, param2, param3, param4); } else { @@ -697,6 +708,32 @@ rdpClientConProcessMsgClientInfo(rdpPtr dev, rdpClientCon *clientCon) i1 = clientCon->client_info.offscreen_cache_entries; LLOGLN(0, (" offscreen entries %d", i1)); + if (clientCon->client_info.capture_format != 0) + { + clientCon->rdp_format = clientCon->client_info.capture_format; + } + + if (clientCon->client_info.capture_code == 2) /* RFX */ + { + LLOGLN(0, ("rdpClientConProcessMsgClientInfo: got RFX capture")); + clientCon->cap_width = LALIGN(clientCon->rdp_width, 64); + clientCon->cap_height = LALIGN(clientCon->rdp_height, 64); + LLOGLN(0, (" cap_width %d cap_height %d", + clientCon->cap_width, clientCon->cap_height)); + if (clientCon->shmemptr != 0) + { + shmdt(clientCon->shmemptr); + } + bytes = clientCon->cap_width * clientCon->cap_height * + clientCon->rdp_Bpp; + clientCon->shmemid = shmget(IPC_PRIVATE, bytes, IPC_CREAT | 0777); + clientCon->shmemptr = shmat(clientCon->shmemid, 0, 0); + shmctl(clientCon->shmemid, IPC_RMID, NULL); + LLOGLN(0, ("rdpClientConProcessMsgClientInfo: shmemid %d shmemptr %p " + "bytes %d", clientCon->shmemid, clientCon->shmemptr, bytes)); + clientCon->shmem_lineBytes = clientCon->rdp_Bpp * clientCon->cap_width; + } + if (clientCon->client_info.offscreen_support_level > 0) { if (clientCon->client_info.offscreen_cache_entries > 0) @@ -808,7 +845,7 @@ rdpClientConProcessMsgClientRegionEx(rdpPtr dev, rdpClientCon *clientCon) { struct stream *s; int flags; - + LLOGLN(10, ("rdpClientConProcessMsgClientRegionEx:")); s = clientCon->in_s; @@ -1878,19 +1915,29 @@ rdpClientConCheckDirtyScreen(rdpPtr dev, rdpClientCon *clientCon) static int rdpClientConSendPaintRectShmEx(rdpPtr dev, rdpClientCon *clientCon, struct image_data *id, - RegionPtr dirtyReg, RegionPtr copyReg) + RegionPtr dirtyReg, + BoxPtr copyRects, int numCopyRects) { int index; int size; int num_rects_d; int num_rects_c; + short x; + short y; + short cx; + short cy; struct stream *s; BoxRec box; rdpClientConBeginUpdate(dev, clientCon); num_rects_d = REGION_NUM_RECTS(dirtyReg); - num_rects_c = REGION_NUM_RECTS(copyReg); + num_rects_c = numCopyRects; + if ((num_rects_c < 1) || (num_rects_d < 1)) + { + LLOGLN(0, ("rdpClientConSendPaintRectShmEx: nothing to send")); + return 0; + } size = 2 + 2 + 2 + num_rects_d * 8 + 2 + num_rects_c * 8; size += 4 + 4 + 4 + 4 + 2 + 2; rdpClientConPreCheck(dev, clientCon, size); @@ -1904,20 +1951,28 @@ rdpClientConSendPaintRectShmEx(rdpPtr dev, rdpClientCon *clientCon, for (index = 0; index < num_rects_d; index++) { box = REGION_RECTS(dirtyReg)[index]; - out_uint16_le(s, box.x1); - out_uint16_le(s, box.y1); - out_uint16_le(s, box.x2 - box.x1); - out_uint16_le(s, box.y2 - box.y1); + x = box.x1; + y = box.y1; + cx = box.x2 - box.x1; + cy = box.y2 - box.y1; + out_uint16_le(s, x); + out_uint16_le(s, y); + out_uint16_le(s, cx); + out_uint16_le(s, cy); } out_uint16_le(s, num_rects_c); for (index = 0; index < num_rects_c; index++) { - box = REGION_RECTS(copyReg)[index]; - out_uint16_le(s, box.x1); - out_uint16_le(s, box.y1); - out_uint16_le(s, box.x2 - box.x1); - out_uint16_le(s, box.y2 - box.y1); + box = copyRects[index]; + x = box.x1; + y = box.y1; + cx = box.x2 - box.x1; + cy = box.y2 - box.y1; + out_uint16_le(s, x); + out_uint16_le(s, y); + out_uint16_le(s, cx); + out_uint16_le(s, cy); } out_uint32_le(s, 0); @@ -1925,30 +1980,36 @@ rdpClientConSendPaintRectShmEx(rdpPtr dev, rdpClientCon *clientCon, out_uint32_le(s, clientCon->rect_id); out_uint32_le(s, id->shmem_id); out_uint32_le(s, id->shmem_offset); - out_uint16_le(s, clientCon->rdp_width); - out_uint16_le(s, clientCon->rdp_height); + out_uint16_le(s, clientCon->cap_width); + out_uint16_le(s, clientCon->cap_height); rdpClientConEndUpdate(dev, clientCon); return 0; } - + /******************************************************************************/ static CARD32 rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) { rdpClientCon *clientCon; - RegionRec reg; + BoxPtr rects; + int num_rects; struct image_data id; LLOGLN(10, ("rdpDeferredUpdateCallback:")); clientCon = (rdpClientCon *) arg; - if (clientCon->rect_id != clientCon->rect_id_ack) + if ((clientCon->rect_id > clientCon->rect_id_ack) || + /* do not allow captures until we have the client_info */ + clientCon->client_info.size == 0) { - LLOGLN(0, ("rdpDeferredUpdateCallback: reschedual")); + LLOGLN(0, ("rdpDeferredUpdateCallback: reschedual rect_id %d " + "rect_id_ack %d", + clientCon->rect_id, clientCon->rect_id_ack)); clientCon->updateTimer = TimerSet(clientCon->updateTimer, 0, 40, - rdpDeferredUpdateCallback, clientCon); + rdpDeferredUpdateCallback, + clientCon); return 0; } else @@ -1961,17 +2022,29 @@ rdpDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg) clientCon->rdp_width, clientCon->rdp_height, clientCon->rdp_Bpp, id.width, id.height)); clientCon->updateSchedualed = FALSE; - rdpRegionInit(®, NullBox, 0); - rdpCapture(clientCon->dirtyRegion, ®, - id.pixels, id.width, id.height, - id.lineBytes, XRDP_a8r8g8b8, - id.shmem_pixels, clientCon->rdp_width, clientCon->rdp_height, - clientCon->rdp_width * clientCon->rdp_Bpp , XRDP_a8r8g8b8, 0); - rdpClientConSendPaintRectShmEx(clientCon->dev, clientCon, &id, - clientCon->dirtyRegion, ®); + rects = 0; + num_rects = 0; + LLOGLN(10, ("rdpDeferredUpdateCallback: capture_code %d", + clientCon->client_info.capture_code)); + if (rdpCapture(clientCon, clientCon->dirtyRegion, &rects, &num_rects, + id.pixels, id.width, id.height, + id.lineBytes, XRDP_a8r8g8b8, id.shmem_pixels, + clientCon->cap_width, clientCon->cap_height, + clientCon->cap_width * clientCon->rdp_Bpp, + clientCon->rdp_format, clientCon->client_info.capture_code)) + { + LLOGLN(10, ("rdpDeferredUpdateCallback: num_rects %d", num_rects)); + rdpClientConSendPaintRectShmEx(clientCon->dev, clientCon, &id, + clientCon->dirtyRegion, + rects, num_rects); + g_free(rects); + } + else + { + LLOGLN(0, ("rdpDeferredUpdateCallback: rdpCapture failed")); + } rdpRegionDestroy(clientCon->dirtyRegion); clientCon->dirtyRegion = rdpRegionCreate(NullBox, 0); - rdpRegionUninit(®); return 0; } diff --git a/xorg/server/module/rdpClientCon.h b/xorg/server/module/rdpClientCon.h index 9cbe493a..a66abbcd 100644 --- a/xorg/server/module/rdpClientCon.h +++ b/xorg/server/module/rdpClientCon.h @@ -79,6 +79,9 @@ struct _rdpClientCon int rdp_Bpp_mask; int rdp_width; int rdp_height; + int rdp_format; /* XRDP_a8r8g8b8, XRDP_r5g6b5, ... */ + int cap_width; + int cap_height; int rdpIndex; /* current os target */ @@ -88,8 +91,6 @@ struct _rdpClientCon struct font_cache font_cache[12][256]; int font_stamp; - RegionPtr dirtyRegion; - struct xrdp_client_info client_info; char *shmemptr; @@ -102,6 +103,8 @@ struct _rdpClientCon OsTimerPtr updateTimer; int updateSchedualed; /* boolean */ + RegionPtr dirtyRegion; + struct _rdpClientCon *next; }; diff --git a/xorg/server/module/rdpCursor.c b/xorg/server/module/rdpCursor.c index 3859e8e7..d4862df7 100644 --- a/xorg/server/module/rdpCursor.c +++ b/xorg/server/module/rdpCursor.c @@ -39,11 +39,18 @@ cursor #include <cursor.h> #include <cursorstr.h> +#include <X11/Xarch.h> + #include "rdp.h" #include "rdpMain.h" #include "rdpDraw.h" #include "rdpClientCon.h" +#ifndef X_BYTE_ORDER +#warning X_BYTE_ORDER not defined +#endif + +#if (X_BYTE_ORDER == X_LITTLE_ENDIAN) /* Copied from Xvnc/lib/font/util/utilbitmap.c */ static unsigned char g_reverse_byte[0x100] = { @@ -80,6 +87,7 @@ static unsigned char g_reverse_byte[0x100] = 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff }; +#endif /******************************************************************************/ #define LOG_LEVEL 1 diff --git a/xorg/server/module/rdpMain.c b/xorg/server/module/rdpMain.c index a8786ac2..2f6db7c7 100644 --- a/xorg/server/module/rdpMain.c +++ b/xorg/server/module/rdpMain.c @@ -47,14 +47,6 @@ rdp module main #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) -#define XRDP_DRIVER_NAME "XORGXRDP" -#define XRDP_NAME "XORGXRDP" -#define XRDP_VERSION 1000 - -#define PACKAGE_VERSION_MAJOR 1 -#define PACKAGE_VERSION_MINOR 0 -#define PACKAGE_VERSION_PATCHLEVEL 0 - static Bool g_initialised = FALSE; /*****************************************************************************/ @@ -95,7 +87,7 @@ xorgxrdpDownDown(ScreenPtr pScreen) static MODULESETUPPROTO(xorgxrdpSetup); static XF86ModuleVersionInfo RDPVersRec = { - XRDP_DRIVER_NAME, + XRDP_MODULE_NAME, MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, diff --git a/xorg/server/module/rdpSimd.c b/xorg/server/module/rdpSimd.c new file mode 100644 index 00000000..7215bf86 --- /dev/null +++ b/xorg/server/module/rdpSimd.c @@ -0,0 +1,138 @@ +/* +Copyright 2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +SIMD function asign + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* this should be before all X11 .h files */ +#include <xorg-server.h> +#include <xorgVersion.h> + +/* all driver need this */ +#include <xf86.h> +#include <xf86_OSproc.h> + +#include "rdp.h" +#include "rdpXv.h" + +/* use simd, run time */ +int g_simd_use_accel = 1; + +/* use simd, compile time, if zero, g_simd_use_accel does not matter */ +#if !defined(SIMD_USE_ACCEL) +#define SIMD_USE_ACCEL 0 +#endif + +#if SIMD_USE_ACCEL +#if defined(__x86_64__) || defined(__AMD64__) || defined (_M_AMD64) +#include "amd64/funcs_amd64.h" +#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__) +#include "x86/funcs_x86.h" +#endif +#endif + +#define LOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +/*****************************************************************************/ +Bool +rdpSimdInit(ScreenPtr pScreen, ScrnInfoPtr pScrn) +{ + rdpPtr dev; + + dev = XRDPPTR(pScrn); + /* assign functions */ + LLOGLN(0, ("rdpSimdInit: assigning yuv functions")); +#if SIMD_USE_ACCEL + if (g_simd_use_accel) + { +#if defined(__x86_64__) || defined(__AMD64__) || defined (_M_AMD64) + int ax, bx, cx, dx; + cpuid_amd64(1, 0, &ax, &bx, &cx, &dx); + LLOGLN(0, ("rdpSimdInit: cpuid ax 1 cx 0 return ax 0x%8.8x bx " + "0x%8.8x cx 0x%8.8x dx 0x%8.8x", ax, bx, cx, dx)); + if (dx & (1 << 26)) /* SSE 2 */ + { + dev->yv12_to_rgb32 = yv12_to_rgb32_amd64_sse2; + dev->i420_to_rgb32 = i420_to_rgb32_amd64_sse2; + dev->yuy2_to_rgb32 = yuy2_to_rgb32_amd64_sse2; + dev->uyvy_to_rgb32 = uyvy_to_rgb32_amd64_sse2; + LLOGLN(0, ("rdpSimdInit: sse2 amd64 yuv functions assigned")); + } + else + { + dev->yv12_to_rgb32 = YV12_to_RGB32; + dev->i420_to_rgb32 = I420_to_RGB32; + dev->yuy2_to_rgb32 = YUY2_to_RGB32; + dev->uyvy_to_rgb32 = UYVY_to_RGB32; + LLOGLN(0, ("rdpSimdInit: warning, c yuv functions assigned")); + } +#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__) + int ax, bx, cx, dx; + cpuid_x86(1, 0, &ax, &bx, &cx, &dx); + LLOGLN(0, ("rdpSimdInit: cpuid ax 1 cx 0 return ax 0x%8.8x bx " + "0x%8.8x cx 0x%8.8x dx 0x%8.8x", ax, bx, cx, dx)); + if (dx & (1 << 26)) /* SSE 2 */ + { + dev->yv12_to_rgb32 = yv12_to_rgb32_x86_sse2; + dev->i420_to_rgb32 = i420_to_rgb32_x86_sse2; + dev->yuy2_to_rgb32 = yuy2_to_rgb32_x86_sse2; + dev->uyvy_to_rgb32 = uyvy_to_rgb32_x86_sse2; + LLOGLN(0, ("rdpSimdInit: sse2 x86 yuv functions assigned")); + } + else + { + dev->yv12_to_rgb32 = YV12_to_RGB32; + dev->i420_to_rgb32 = I420_to_RGB32; + dev->yuy2_to_rgb32 = YUY2_to_RGB32; + dev->uyvy_to_rgb32 = UYVY_to_RGB32; + LLOGLN(0, ("rdpSimdInit: warning, c yuv functions assigned")); + } +#else + dev->yv12_to_rgb32 = YV12_to_RGB32; + dev->i420_to_rgb32 = I420_to_RGB32; + dev->yuy2_to_rgb32 = YUY2_to_RGB32; + dev->uyvy_to_rgb32 = UYVY_to_RGB32; + LLOGLN(0, ("rdpSimdInit: warning, c yuv functions assigned")); +#endif + } + else + { + dev->yv12_to_rgb32 = YV12_to_RGB32; + dev->i420_to_rgb32 = I420_to_RGB32; + dev->yuy2_to_rgb32 = YUY2_to_RGB32; + dev->uyvy_to_rgb32 = UYVY_to_RGB32; + LLOGLN(0, ("rdpSimdInit: warning, c yuv functions assigned")); + } +#else + dev->yv12_to_rgb32 = YV12_to_RGB32; + dev->i420_to_rgb32 = I420_to_RGB32; + dev->yuy2_to_rgb32 = YUY2_to_RGB32; + dev->uyvy_to_rgb32 = UYVY_to_RGB32; + LLOGLN(0, ("rdpSimdInit: warning, c yuv functions assigned")); +#endif + return 1; +} + diff --git a/xorg/server/module/rdpSimd.h b/xorg/server/module/rdpSimd.h new file mode 100644 index 00000000..73bf1ba5 --- /dev/null +++ b/xorg/server/module/rdpSimd.h @@ -0,0 +1,34 @@ +/* +Copyright 2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +SIMD function asign + +*/ + +#ifndef __RDPSIMD_H +#define __RDPSIMD_H + +#include <xorg-server.h> +#include <xorgVersion.h> +#include <xf86.h> + +Bool +rdpSimdInit(ScreenPtr pScreen, ScrnInfoPtr pScrn); + +#endif diff --git a/xorg/server/module/rdpXv.c b/xorg/server/module/rdpXv.c new file mode 100644 index 00000000..1557f892 --- /dev/null +++ b/xorg/server/module/rdpXv.c @@ -0,0 +1,678 @@ +/* +Copyright 2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +XVideo + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* this should be before all X11 .h files */ +#include <xorg-server.h> +#include <xorgVersion.h> + +/* all driver need this */ +#include <xf86.h> +#include <xf86_OSproc.h> + +#include <xf86xv.h> +#include <X11/extensions/Xv.h> +#include <fourcc.h> + +#include <fb.h> + +#include "rdp.h" +#include "rdpMisc.h" +#include "rdpReg.h" +#include "rdpClientCon.h" + +#define LOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) + +#define T_NUM_ENCODINGS 1 +static XF86VideoEncodingRec g_xrdpVidEncodings[T_NUM_ENCODINGS] = +{ { 0, "XV_IMAGE", 2046, 2046, { 1, 1 } } }; + +#define T_NUM_FORMATS 1 +static XF86VideoFormatRec g_xrdpVidFormats[T_NUM_FORMATS] = +{ { 0, TrueColor } }; + +/* YV12 + I420 + 12 bpp planar + YUV 4:2:0 8 bit Y plane followed by 8 bit 2x2 subsampled + U and V planes. */ + +/* YUY2 + UYVY + 16 bpp packed + YUV 4:2:2 Y sample at every pixel, U and V sampled at + every second pixel */ + +/* XVIMAGE_YV12 FOURCC_YV12 0x32315659 */ +/* XVIMAGE_I420 FOURCC_I420 0x30323449 */ +/* XVIMAGE_YUY2 FOURCC_YUY2 0x32595559 */ +/* XVIMAGE_UYVY FOURCC_UYVY 0x59565955 */ + +static XF86ImageRec g_xrdpVidImages[] = +{ XVIMAGE_YV12, XVIMAGE_I420, XVIMAGE_YUY2, XVIMAGE_UYVY }; + +#define T_MAX_PORTS 1 + +/*****************************************************************************/ +static int +xrdpVidPutVideo(ScrnInfoPtr pScrn, short vid_x, short vid_y, + short drw_x, short drw_y, short vid_w, short vid_h, + short drw_w, short drw_h, RegionPtr clipBoxes, + pointer data, DrawablePtr pDraw) +{ + LLOGLN(0, ("xrdpVidPutVideo:")); + return Success; +} + +/*****************************************************************************/ +static int +xrdpVidPutStill(ScrnInfoPtr pScrn, short vid_x, short vid_y, + short drw_x, short drw_y, short vid_w, short vid_h, + short drw_w, short drw_h, RegionPtr clipBoxes, + pointer data, DrawablePtr pDraw) +{ + LLOGLN(0, ("xrdpVidPutStill:")); + return Success; +} + +/*****************************************************************************/ +static int +xrdpVidGetVideo(ScrnInfoPtr pScrn, short vid_x, short vid_y, + short drw_x, short drw_y, short vid_w, short vid_h, + short drw_w, short drw_h, RegionPtr clipBoxes, + pointer data, DrawablePtr pDraw) +{ + LLOGLN(0, ("xrdpVidGetVideo:")); + return Success; +} + +/*****************************************************************************/ +static int +xrdpVidGetStill(ScrnInfoPtr pScrn, short vid_x, short vid_y, + short drw_x, short drw_y, short vid_w, short vid_h, + short drw_w, short drw_h, RegionPtr clipBoxes, + pointer data, DrawablePtr pDraw) +{ + LLOGLN(0, ("FBDevTIVidGetStill:")); + return Success; +} + +/*****************************************************************************/ +static void +xrdpVidStopVideo(ScrnInfoPtr pScrn, pointer data, Bool Cleanup) +{ + LLOGLN(0, ("xrdpVidStopVideo:")); +} + +/*****************************************************************************/ +static int +xrdpVidSetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 value, pointer data) +{ + LLOGLN(0, ("xrdpVidSetPortAttribute:")); + return Success; +} + +/*****************************************************************************/ +static int +xrdpVidGetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, + INT32 *value, pointer data) +{ + LLOGLN(0, ("xrdpVidGetPortAttribute:")); + return Success; +} + +/*****************************************************************************/ +static void +xrdpVidQueryBestSize(ScrnInfoPtr pScrn, Bool motion, + short vid_w, short vid_h, short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, pointer data) +{ + LLOGLN(0, ("xrdpVidQueryBestSize:")); +} + +/*****************************************************************************/ +int +YV12_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs) +{ + int size_total; + int y; + int u; + int v; + int c; + int d; + int e; + int r; + int g; + int b; + int t; + int i; + int j; + + size_total = width * height; + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + y = yuvs[j * width + i]; + u = yuvs[(j / 2) * (width / 2) + (i / 2) + size_total]; + v = yuvs[(j / 2) * (width / 2) + (i / 2) + size_total + (size_total / 4)]; + c = y - 16; + d = u - 128; + e = v - 128; + t = (298 * c + 409 * e + 128) >> 8; + b = RDPCLAMP(t, 0, 255); + t = (298 * c - 100 * d - 208 * e + 128) >> 8; + g = RDPCLAMP(t, 0, 255); + t = (298 * c + 516 * d + 128) >> 8; + r = RDPCLAMP(t, 0, 255); + rgbs[j * width + i] = (r << 16) | (g << 8) | b; + } + } + return 0; +} + +/*****************************************************************************/ +int +I420_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs) +{ + int size_total; + int y; + int u; + int v; + int c; + int d; + int e; + int r; + int g; + int b; + int t; + int i; + int j; + + size_total = width * height; + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + y = yuvs[j * width + i]; + v = yuvs[(j / 2) * (width / 2) + (i / 2) + size_total]; + u = yuvs[(j / 2) * (width / 2) + (i / 2) + size_total + (size_total / 4)]; + c = y - 16; + d = u - 128; + e = v - 128; + t = (298 * c + 409 * e + 128) >> 8; + b = RDPCLAMP(t, 0, 255); + t = (298 * c - 100 * d - 208 * e + 128) >> 8; + g = RDPCLAMP(t, 0, 255); + t = (298 * c + 516 * d + 128) >> 8; + r = RDPCLAMP(t, 0, 255); + rgbs[j * width + i] = (r << 16) | (g << 8) | b; + } + } + return 0; +} + +/*****************************************************************************/ +int +YUY2_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs) +{ + int y1; + int y2; + int u; + int v; + int c; + int d; + int e; + int r; + int g; + int b; + int t; + int i; + int j; + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + y1 = *(yuvs++); + v = *(yuvs++); + y2 = *(yuvs++); + u = *(yuvs++); + + c = y1 - 16; + d = u - 128; + e = v - 128; + t = (298 * c + 409 * e + 128) >> 8; + b = RDPCLAMP(t, 0, 255); + t = (298 * c - 100 * d - 208 * e + 128) >> 8; + g = RDPCLAMP(t, 0, 255); + t = (298 * c + 516 * d + 128) >> 8; + r = RDPCLAMP(t, 0, 255); + rgbs[j * width + i] = (r << 16) | (g << 8) | b; + + i++; + c = y2 - 16; + d = u - 128; + e = v - 128; + t = (298 * c + 409 * e + 128) >> 8; + b = RDPCLAMP(t, 0, 255); + t = (298 * c - 100 * d - 208 * e + 128) >> 8; + g = RDPCLAMP(t, 0, 255); + t = (298 * c + 516 * d + 128) >> 8; + r = RDPCLAMP(t, 0, 255); + rgbs[j * width + i] = (r << 16) | (g << 8) | b; + } + } + return 0; +} + +/*****************************************************************************/ +int +UYVY_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs) +{ + int y1; + int y2; + int u; + int v; + int c; + int d; + int e; + int r; + int g; + int b; + int t; + int i; + int j; + + for (j = 0; j < height; j++) + { + for (i = 0; i < width; i++) + { + v = *(yuvs++); + y1 = *(yuvs++); + u = *(yuvs++); + y2 = *(yuvs++); + + c = y1 - 16; + d = u - 128; + e = v - 128; + t = (298 * c + 409 * e + 128) >> 8; + b = RDPCLAMP(t, 0, 255); + t = (298 * c - 100 * d - 208 * e + 128) >> 8; + g = RDPCLAMP(t, 0, 255); + t = (298 * c + 516 * d + 128) >> 8; + r = RDPCLAMP(t, 0, 255); + rgbs[j * width + i] = (r << 16) | (g << 8) | b; + + i++; + c = y2 - 16; + d = u - 128; + e = v - 128; + t = (298 * c + 409 * e + 128) >> 8; + b = RDPCLAMP(t, 0, 255); + t = (298 * c - 100 * d - 208 * e + 128) >> 8; + g = RDPCLAMP(t, 0, 255); + t = (298 * c + 516 * d + 128) >> 8; + r = RDPCLAMP(t, 0, 255); + rgbs[j * width + i] = (r << 16) | (g << 8) | b; + } + } + return 0; +} + +#if 0 +/*****************************************************************************/ +static int +stretch_RGB32_RGB32(int *src, int src_width, int src_height, + int src_x, int src_y, int src_w, int src_h, + int *dst, int dst_w, int dst_h) +{ + int mwidth; + int mheight; + int index; + + mwidth = RDPMIN(src_width, dst_w); + mheight = RDPMIN(src_height, dst_h); + for (index = 0; index < mheight; index++) + { + g_memcpy(dst, src, mwidth * 4); + src += src_width; + dst += dst_w; + } + return 0; +} +#endif + +/*****************************************************************************/ +static int +stretch_RGB32_RGB32(int *src, int src_width, int src_height, + int src_x, int src_y, int src_w, int src_h, + int *dst, int dst_w, int dst_h) +{ + int index; + int jndex; + int lndex; + int last_lndex; + int oh; + int ih; + int ov; + int iv; + int pix; + int *src32; + int *dst32; + + LLOGLN(10, ("stretch_RGB32_RGB32: oh 0x%8.8x ov 0x%8.8x", oh, ov)); + oh = (src_w << 16) / dst_w; + ov = (src_h << 16) / dst_h; + iv = ov; + lndex = src_y; + last_lndex = -1; + for (index = 0; index < dst_h; index++) + { + if (lndex == last_lndex) + { + /* repeat line */ + dst32 = dst + index * dst_w; + src32 = dst32 - dst_w; + g_memcpy(dst32, src32, dst_w * 4); + } + else + { + ih = oh; + src32 = src + lndex * src_width + src_x; + pix = *src32; + dst32 = dst + index * dst_w; + for (jndex = 0; jndex < dst_w; jndex++) + { + *dst32 = pix; + while (ih > (1 << 16) - 1) + { + ih -= 1 << 16; + src32++; + } + pix = *src32; + ih += oh; + dst32++; + } + } + last_lndex = lndex; + while (iv > (1 << 16) - 1) + { + iv -= 1 << 16; + lndex++; + } + iv += ov; + + } + LLOGLN(10, ("stretch_RGB32_RGB32: out")); + return 0; +} + +/******************************************************************************/ +/* returns error */ +static CARD32 +rdpDeferredXvCleanup(OsTimerPtr timer, CARD32 now, pointer arg) +{ + rdpPtr dev; + + LLOGLN(0, ("rdpDeferredXvCleanup:")); + dev = (rdpPtr) arg; + dev->xv_timer_schedualed = 0; + dev->xv_data_bytes = 0; + g_free(dev->xv_data); + dev->xv_data = 0; + return 0; +} + +/*****************************************************************************/ +/* see hw/xfree86/common/xf86xv.c for info */ +static int +xrdpVidPutImage(ScrnInfoPtr pScrn, + short src_x, short src_y, short drw_x, short drw_y, + short src_w, short src_h, short drw_w, short drw_h, + int format, unsigned char* buf, + short width, short height, + Bool sync, RegionPtr clipBoxes, + pointer data, DrawablePtr dst) +{ + rdpPtr dev; + int *rgborg32; + int *rgbend32; + int index; + int error; + GCPtr tempGC; + + LLOGLN(10, ("xrdpVidPutImage: format 0x%8.8x", format)); + LLOGLN(10, ("xrdpVidPutImage: src_x %d srcy_y %d", src_x, src_y)); + dev = XRDPPTR(pScrn); + + if (dev->xv_timer_schedualed) + { + TimerCancel(dev->xv_timer); + dev->xv_timer = TimerSet(dev->xv_timer, 0, 2000, + rdpDeferredXvCleanup, dev); + } + else + { + dev->xv_timer_schedualed = 1; + dev->xv_timer = TimerSet(dev->xv_timer, 0, 2000, + rdpDeferredXvCleanup, dev); + } + + index = width * height * 4 + drw_w * drw_h * 4 + 64; + if (index > dev->xv_data_bytes) + { + g_free(dev->xv_data); + dev->xv_data = g_malloc(index, 0); + if (dev->xv_data == NULL) + { + LLOGLN(0, ("xrdpVidPutImage: memory alloc error")); + dev->xv_data_bytes = 0; + return Success; + } + dev->xv_data_bytes = index; + } + rgborg32 = (int *) RDPALIGN(dev->xv_data, 16); + rgbend32 = rgborg32 + width * height; + rgbend32 = (int *) RDPALIGN(rgbend32, 16); + error = 0; + switch (format) + { + case FOURCC_YV12: + LLOGLN(10, ("xrdpVidPutImage: FOURCC_YV12")); + error = dev->yv12_to_rgb32(buf, width, height, rgborg32); + break; + case FOURCC_I420: + LLOGLN(10, ("xrdpVidPutImage: FOURCC_I420")); + error = dev->i420_to_rgb32(buf, width, height, rgborg32); + break; + case FOURCC_YUY2: + LLOGLN(10, ("xrdpVidPutImage: FOURCC_YUY2")); + error = dev->yuy2_to_rgb32(buf, width, height, rgborg32); + break; + case FOURCC_UYVY: + LLOGLN(10, ("xrdpVidPutImage: FOURCC_UYVY")); + error = dev->uyvy_to_rgb32(buf, width, height, rgborg32); + break; + default: + LLOGLN(0, ("xrdpVidPutImage: unknown format 0x%8.8x", format)); + return Success; + } + if (error != 0) + { + return Success; + } + error = stretch_RGB32_RGB32(rgborg32, width, height, + src_x, src_y, src_w, src_h, + rgbend32, drw_w, drw_h); + if (error != 0) + { + return Success; + } + + tempGC = GetScratchGC(dst->depth, pScrn->pScreen); + if (tempGC != NULL) + { + ValidateGC(dst, tempGC); + (*tempGC->ops->PutImage)(dst, tempGC, 24, + drw_x - dst->x, drw_y - dst->y, + drw_w, drw_h, 0, ZPixmap, (char*)rgbend32); + FreeScratchGC(tempGC); + } + + return Success; +} + +/*****************************************************************************/ +static int +xrdpVidQueryImageAttributes(ScrnInfoPtr pScrn, int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets) +{ + int size, tmp; + + LLOGLN(10, ("xrdpVidQueryImageAttributes:")); + /* this is same code as all drivers currently have */ + if (*w > 2046) + { + *w = 2046; + } + if (*h > 2046) + { + *h = 2046; + } + /* make w multiple of 4 so that resizing works properly */ + *w = (*w + 3) & ~3; + if (offsets != NULL) + { + offsets[0] = 0; + } + switch (id) + { + case FOURCC_YV12: + case FOURCC_I420: + /* make h be even */ + *h = (*h + 1) & ~1; + /* make w be multiple of 4 (ie. pad it) */ + size = (*w + 3) & ~3; + /* width of a Y row => width of image */ + if (pitches != NULL) + { + pitches[0] = size; + } + /* offset of U plane => w * h */ + size *= *h; + if (offsets != NULL) + { + offsets[1] = size; + } + /* width of U, V row => width / 2 */ + tmp = ((*w >> 1) + 3) & ~3; + if (pitches != NULL) + { + pitches[1] = pitches[2] = tmp; + } + /* offset of V => Y plane + U plane (w * h + w / 2 * h / 2) */ + tmp *= (*h >> 1); + size += tmp; + if (offsets != NULL) + { + offsets[2] = size; + } + size += tmp; + break; + case FOURCC_YUY2: + case FOURCC_UYVY: + size = (*w) * 2; + if (pitches != NULL) + { + pitches[0] = size; + } + size *= *h; + break; + default: + LLOGLN(0, ("xrdpVidQueryImageAttributes: Unsupported image")); + return 0; + } + LLOGLN(10, ("xrdpVidQueryImageAttributes: finished size %d id 0x%x", size, id)); + return size; +} + +/*****************************************************************************/ +Bool +rdpXvInit(ScreenPtr pScreen, ScrnInfoPtr pScrn) +{ + XF86VideoAdaptorPtr adaptor; + DevUnion* pDevUnion; + int bytes; + + adaptor = xf86XVAllocateVideoAdaptorRec(pScrn); + if (adaptor == 0) + { + LLOGLN(0, ("rdpXvInit: xf86XVAllocateVideoAdaptorRec failed")); + return 0; + } + adaptor->type = XvInputMask | XvImageMask | XvVideoMask | XvStillMask | XvWindowMask | XvPixmapMask; + //adaptor->flags = VIDEO_NO_CLIPPING; + //adaptor->flags = VIDEO_CLIP_TO_VIEWPORT; + adaptor->flags = 0; + adaptor->name = XRDP_MODULE_NAME " XVideo Adaptor"; + adaptor->nEncodings = T_NUM_ENCODINGS; + adaptor->pEncodings = &(g_xrdpVidEncodings[0]); + adaptor->nFormats = T_NUM_FORMATS; + adaptor->pFormats = &(g_xrdpVidFormats[0]); + adaptor->pFormats[0].depth = pScrn->depth; + LLOGLN(0, ("rdpXvInit: depth %d", pScrn->depth)); + adaptor->nImages = sizeof(g_xrdpVidImages) / sizeof(XF86ImageRec); + adaptor->pImages = g_xrdpVidImages; + adaptor->nAttributes = 0; + adaptor->pAttributes = 0; + adaptor->nPorts = T_MAX_PORTS; + bytes = sizeof(DevUnion) * T_MAX_PORTS; + pDevUnion = (DevUnion*) g_malloc(bytes, 1); + adaptor->pPortPrivates = pDevUnion; + adaptor->PutVideo = xrdpVidPutVideo; + adaptor->PutStill = xrdpVidPutStill; + adaptor->GetVideo = xrdpVidGetVideo; + adaptor->GetStill = xrdpVidGetStill; + adaptor->StopVideo = xrdpVidStopVideo; + adaptor->SetPortAttribute = xrdpVidSetPortAttribute; + adaptor->GetPortAttribute = xrdpVidGetPortAttribute; + adaptor->QueryBestSize = xrdpVidQueryBestSize; + adaptor->PutImage = xrdpVidPutImage; + adaptor->QueryImageAttributes = xrdpVidQueryImageAttributes; + if (!xf86XVScreenInit(pScreen, &adaptor, 1)) + { + LLOGLN(0, ("rdpXvInit: xf86XVScreenInit failed")); + return 0; + } + xf86XVFreeVideoAdaptorRec(adaptor); + return 1; +} + diff --git a/xorg/server/module/rdpXv.h b/xorg/server/module/rdpXv.h new file mode 100644 index 00000000..9cf28700 --- /dev/null +++ b/xorg/server/module/rdpXv.h @@ -0,0 +1,43 @@ +/* +Copyright 2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +XVideo + +*/ + +#ifndef __RDPXV_H +#define __RDPXV_H + +#include <xorg-server.h> +#include <xorgVersion.h> +#include <xf86.h> + +Bool +rdpXvInit(ScreenPtr pScreen, ScrnInfoPtr pScrn); + +int +YV12_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs); +int +I420_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs); +int +YUY2_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs); +int +UYVY_to_RGB32(unsigned char *yuvs, int width, int height, int *rgbs); + +#endif diff --git a/xorg/server/module/x86/cpuid_x86.asm b/xorg/server/module/x86/cpuid_x86.asm new file mode 100644 index 00000000..6f9e8c2d --- /dev/null +++ b/xorg/server/module/x86/cpuid_x86.asm @@ -0,0 +1,39 @@ + +SECTION .text + +%macro PROC 1 + align 16 + global %1 + %1: +%endmacro + +;int +;cpuid_x86(int eax_in, int ecx_in, int *eax, int *ebx, int *ecx, int *edx) + +PROC cpuid_x86 + ; save registers + push ebx + push ecx + push edx + push edi + ; cpuid + mov eax, [esp + 20] + mov ecx, [esp + 24] + cpuid + mov edi, [esp + 28] + mov [edi], eax + mov edi, [esp + 32] + mov [edi], ebx + mov edi, [esp + 36] + mov [edi], ecx + mov edi, [esp + 40] + mov [edi], edx + mov eax, 0 + ; restore registers + pop edi + pop edx + pop ecx + pop ebx + ret; + align 16 + diff --git a/xorg/server/module/x86/funcs_x86.h b/xorg/server/module/x86/funcs_x86.h new file mode 100644 index 00000000..00724e62 --- /dev/null +++ b/xorg/server/module/x86/funcs_x86.h @@ -0,0 +1,39 @@ +/* +Copyright 2014 Jay Sorg + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +x86 asm files + +*/ + +#ifndef __FUNCS_X86_H +#define __FUNCS_X86_H + +int +cpuid_x86(int eax_in, int ecx_in, int *eax, int *ebx, int *ecx, int *edx); +int +yv12_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs); +int +i420_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs); +int +yuy2_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs); +int +uyvy_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs); + +#endif + diff --git a/xorg/server/module/x86/i420_to_rgb32_x86_sse2.asm b/xorg/server/module/x86/i420_to_rgb32_x86_sse2.asm new file mode 100644 index 00000000..0c7a6e1e --- /dev/null +++ b/xorg/server/module/x86/i420_to_rgb32_x86_sse2.asm @@ -0,0 +1,243 @@ +; +;Copyright 2014 Jay Sorg +; +;Permission to use, copy, modify, distribute, and sell this software and its +;documentation for any purpose is hereby granted without fee, provided that +;the above copyright notice appear in all copies and that both that +;copyright notice and this permission notice appear in supporting +;documentation. +; +;The above copyright notice and this permission notice shall be included in +;all copies or substantial portions of the Software. +; +;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +;OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +;AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +;CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +; +;I420 to RGB32 +;x86 SSE2 32 bit +; +; RGB to YUV +; 0.299 0.587 0.114 +; -0.14713 -0.28886 0.436 +; 0.615 -0.51499 -0.10001 +; YUV to RGB +; 1 0 1.13983 +; 1 -0.39465 -0.58060 +; 1 2.03211 0 +; shift left 12 +; 4096 0 4669 +; 4096 -1616 -2378 +; 4096 9324 0 + +SECTION .data +align 16 +c128 times 8 dw 128 +c4669 times 8 dw 4669 +c1616 times 8 dw 1616 +c2378 times 8 dw 2378 +c9324 times 8 dw 9324 + +SECTION .text + +%macro PROC 1 + align 16 + global %1 + %1: +%endmacro + +do8_uv: + + ; v + movd xmm1, [ebx] ; 4 at a time + lea ebx, [ebx + 4] + punpcklbw xmm1, xmm1 + pxor xmm6, xmm6 + punpcklbw xmm1, xmm6 + movdqa xmm7, [c128] + psubw xmm1, xmm7 + psllw xmm1, 4 + + ; u + movd xmm2, [edx] ; 4 at a time + lea edx, [edx + 4] + punpcklbw xmm2, xmm2 + punpcklbw xmm2, xmm6 + psubw xmm2, xmm7 + psllw xmm2, 4 + +do8: + + ; y + movq xmm0, [esi] ; 8 at a time + lea esi, [esi + 8] + pxor xmm6, xmm6 + punpcklbw xmm0, xmm6 + + ; r = y + hiword(4669 * (v << 4)) + movdqa xmm4, [c4669] + pmulhw xmm4, xmm1 + movdqa xmm3, xmm0 + paddw xmm3, xmm4 + + ; g = y - hiword(1616 * (u << 4)) - hiword(2378 * (v << 4)) + movdqa xmm5, [c1616] + pmulhw xmm5, xmm2 + movdqa xmm6, [c2378] + pmulhw xmm6, xmm1 + movdqa xmm4, xmm0 + psubw xmm4, xmm5 + psubw xmm4, xmm6 + + ; b = y + hiword(9324 * (u << 4)) + movdqa xmm6, [c9324] + pmulhw xmm6, xmm2 + movdqa xmm5, xmm0 + paddw xmm5, xmm6 + + packuswb xmm3, xmm3 ; b + packuswb xmm4, xmm4 ; g + punpcklbw xmm3, xmm4 ; gb + + pxor xmm4, xmm4 ; a + packuswb xmm5, xmm5 ; r + punpcklbw xmm5, xmm4 ; ar + + movdqa xmm4, xmm3 + punpcklwd xmm3, xmm5 ; argb + movdqa [edi], xmm3 + lea edi, [edi + 16] + punpckhwd xmm4, xmm5 ; argb + movdqa [edi], xmm4 + lea edi, [edi + 16] + + ret; + +;int +;i420_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs) + +PROC i420_to_rgb32_x86_sse2 + push ebx + push esi + push edi + push ebp + + mov edi, [esp + 32] ; rgbs + + mov ecx, [esp + 24] ; width + mov edx, ecx + mov ebp, [esp + 28] ; height + mov eax, ebp + shr ebp, 1 + imul eax, ecx ; eax = width * height + + mov esi, [esp + 20] ; y + + mov ebx, esi ; u = y + width * height + add ebx, eax + + ; local vars + ; char* yptr1 + ; char* yptr2 + ; char* uptr + ; char* vptr + ; int* rgbs1 + ; int* rgbs2 + ; int width + sub esp, 28 ; local vars, 28 bytes + mov [esp + 0], esi ; save y1 + add esi, edx + mov [esp + 4], esi ; save y2 + mov [esp + 8], ebx ; save u + shr eax, 2 + add ebx, eax ; v = u + (width * height / 4) + mov [esp + 12], ebx ; save v + + mov [esp + 16], edi ; save rgbs1 + mov eax, edx + shl eax, 2 + add edi, eax + mov [esp + 20], edi ; save rgbs2 + +loop_y: + + mov ecx, edx ; width + shr ecx, 3 + + ; save edx + mov [esp + 24], edx + + ;prefetchnta 4096[esp + 0] ; y + ;prefetchnta 1024[esp + 8] ; u + ;prefetchnta 1024[esp + 12] ; v + +loop_x: + + mov esi, [esp + 0] ; y1 + mov ebx, [esp + 8] ; u + mov edx, [esp + 12] ; v + mov edi, [esp + 16] ; rgbs1 + + ; y1 + call do8_uv + + mov [esp + 0], esi ; y1 + mov [esp + 16], edi ; rgbs1 + + mov esi, [esp + 4] ; y2 + mov edi, [esp + 20] ; rgbs2 + + ; y2 + call do8 + + mov [esp + 4], esi ; y2 + mov [esp + 8], ebx ; u + mov [esp + 12], edx ; v + mov [esp + 20], edi ; rgbs2 + + dec ecx ; width + jnz loop_x + + ; restore edx + mov edx, [esp + 24] + + ; update y1 and 2 + mov eax, [esp + 0] + mov ebx, edx + add eax, ebx + mov [esp + 0], eax + + mov eax, [esp + 4] + add eax, ebx + mov [esp + 4], eax + + ; update rgb1 and 2 + mov eax, [esp + 16] + mov ebx, edx + shl ebx, 2 + add eax, ebx + mov [esp + 16], eax + + mov eax, [esp + 20] + add eax, ebx + mov [esp + 20], eax + + mov ecx, ebp + dec ecx ; height + mov ebp, ecx + jnz loop_y + + add esp, 28 + + mov eax, 0 + pop ebp + pop edi + pop esi + pop ebx + ret + align 16 + + diff --git a/xorg/server/module/x86/uyvy_to_rgb32_x86_sse2.asm b/xorg/server/module/x86/uyvy_to_rgb32_x86_sse2.asm new file mode 100644 index 00000000..d3ba81d3 --- /dev/null +++ b/xorg/server/module/x86/uyvy_to_rgb32_x86_sse2.asm @@ -0,0 +1,22 @@ + +%macro PROC 1 + align 16 + global %1 + %1: +%endmacro + +;int +;uyvy_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs) + +PROC uyvy_to_rgb32_x86_sse2 + push ebx + push esi + push edi + + mov eax, 0 + pop edi + pop esi + pop ebx + ret + align 16 + diff --git a/xorg/server/module/x86/yuy2_to_rgb32_x86_sse2.asm b/xorg/server/module/x86/yuy2_to_rgb32_x86_sse2.asm new file mode 100644 index 00000000..da03e26f --- /dev/null +++ b/xorg/server/module/x86/yuy2_to_rgb32_x86_sse2.asm @@ -0,0 +1,22 @@ + +%macro PROC 1 + align 16 + global %1 + %1: +%endmacro + +;int +;yuy2_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs) + +PROC yuy2_to_rgb32_x86_sse2 + push ebx + push esi + push edi + + mov eax, 0 + pop edi + pop esi + pop ebx + ret + align 16 + diff --git a/xorg/server/module/x86/yv12_to_rgb32_x86_sse2.asm b/xorg/server/module/x86/yv12_to_rgb32_x86_sse2.asm new file mode 100644 index 00000000..d50a65a2 --- /dev/null +++ b/xorg/server/module/x86/yv12_to_rgb32_x86_sse2.asm @@ -0,0 +1,243 @@ +; +;Copyright 2014 Jay Sorg +; +;Permission to use, copy, modify, distribute, and sell this software and its +;documentation for any purpose is hereby granted without fee, provided that +;the above copyright notice appear in all copies and that both that +;copyright notice and this permission notice appear in supporting +;documentation. +; +;The above copyright notice and this permission notice shall be included in +;all copies or substantial portions of the Software. +; +;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +;OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +;AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +;CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +; +;YV12 to RGB32 +;x86 SSE2 32 bit +; +; RGB to YUV +; 0.299 0.587 0.114 +; -0.14713 -0.28886 0.436 +; 0.615 -0.51499 -0.10001 +; YUV to RGB +; 1 0 1.13983 +; 1 -0.39465 -0.58060 +; 1 2.03211 0 +; shift left 12 +; 4096 0 4669 +; 4096 -1616 -2378 +; 4096 9324 0 + +SECTION .data +align 16 +c128 times 8 dw 128 +c4669 times 8 dw 4669 +c1616 times 8 dw 1616 +c2378 times 8 dw 2378 +c9324 times 8 dw 9324 + +SECTION .text + +%macro PROC 1 + align 16 + global %1 + %1: +%endmacro + +do8_uv: + + ; u + movd xmm1, [ebx] ; 4 at a time + lea ebx, [ebx + 4] + punpcklbw xmm1, xmm1 + pxor xmm6, xmm6 + punpcklbw xmm1, xmm6 + movdqa xmm7, [c128] + psubw xmm1, xmm7 + psllw xmm1, 4 + + ; v + movd xmm2, [edx] ; 4 at a time + lea edx, [edx + 4] + punpcklbw xmm2, xmm2 + punpcklbw xmm2, xmm6 + psubw xmm2, xmm7 + psllw xmm2, 4 + +do8: + + ; y + movq xmm0, [esi] ; 8 at a time + lea esi, [esi + 8] + pxor xmm6, xmm6 + punpcklbw xmm0, xmm6 + + ; r = y + hiword(4669 * (v << 4)) + movdqa xmm4, [c4669] + pmulhw xmm4, xmm2 + movdqa xmm3, xmm0 + paddw xmm3, xmm4 + + ; g = y - hiword(1616 * (u << 4)) - hiword(2378 * (v << 4)) + movdqa xmm5, [c1616] + pmulhw xmm5, xmm1 + movdqa xmm6, [c2378] + pmulhw xmm6, xmm2 + movdqa xmm4, xmm0 + psubw xmm4, xmm5 + psubw xmm4, xmm6 + + ; b = y + hiword(9324 * (u << 4)) + movdqa xmm6, [c9324] + pmulhw xmm6, xmm1 + movdqa xmm5, xmm0 + paddw xmm5, xmm6 + + packuswb xmm3, xmm3 ; b + packuswb xmm4, xmm4 ; g + punpcklbw xmm3, xmm4 ; gb + + pxor xmm4, xmm4 ; a + packuswb xmm5, xmm5 ; r + punpcklbw xmm5, xmm4 ; ar + + movdqa xmm4, xmm3 + punpcklwd xmm3, xmm5 ; argb + movdqa [edi], xmm3 + lea edi, [edi + 16] + punpckhwd xmm4, xmm5 ; argb + movdqa [edi], xmm4 + lea edi, [edi + 16] + + ret; + +;int +;yv12_to_rgb32_x86_sse2(unsigned char *yuvs, int width, int height, int *rgbs) + +PROC yv12_to_rgb32_x86_sse2 + push ebx + push esi + push edi + push ebp + + mov edi, [esp + 32] ; rgbs + + mov ecx, [esp + 24] ; width + mov edx, ecx + mov ebp, [esp + 28] ; height + mov eax, ebp + shr ebp, 1 + imul eax, ecx ; eax = width * height + + mov esi, [esp + 20] ; y + + mov ebx, esi ; u = y + width * height + add ebx, eax + + ; local vars + ; char* yptr1 + ; char* yptr2 + ; char* uptr + ; char* vptr + ; int* rgbs1 + ; int* rgbs2 + ; int width + sub esp, 28 ; local vars, 28 bytes + mov [esp + 0], esi ; save y1 + add esi, edx + mov [esp + 4], esi ; save y2 + mov [esp + 8], ebx ; save u + shr eax, 2 + add ebx, eax ; v = u + (width * height / 4) + mov [esp + 12], ebx ; save v + + mov [esp + 16], edi ; save rgbs1 + mov eax, edx + shl eax, 2 + add edi, eax + mov [esp + 20], edi ; save rgbs2 + +loop_y: + + mov ecx, edx ; width + shr ecx, 3 + + ; save edx + mov [esp + 24], edx + + ;prefetchnta 4096[esp + 0] ; y + ;prefetchnta 1024[esp + 8] ; u + ;prefetchnta 1024[esp + 12] ; v + +loop_x: + + mov esi, [esp + 0] ; y1 + mov ebx, [esp + 8] ; u + mov edx, [esp + 12] ; v + mov edi, [esp + 16] ; rgbs1 + + ; y1 + call do8_uv + + mov [esp + 0], esi ; y1 + mov [esp + 16], edi ; rgbs1 + + mov esi, [esp + 4] ; y2 + mov edi, [esp + 20] ; rgbs2 + + ; y2 + call do8 + + mov [esp + 4], esi ; y2 + mov [esp + 8], ebx ; u + mov [esp + 12], edx ; v + mov [esp + 20], edi ; rgbs2 + + dec ecx ; width + jnz loop_x + + ; restore edx + mov edx, [esp + 24] + + ; update y1 and 2 + mov eax, [esp + 0] + mov ebx, edx + add eax, ebx + mov [esp + 0], eax + + mov eax, [esp + 4] + add eax, ebx + mov [esp + 4], eax + + ; update rgb1 and 2 + mov eax, [esp + 16] + mov ebx, edx + shl ebx, 2 + add eax, ebx + mov [esp + 16], eax + + mov eax, [esp + 20] + add eax, ebx + mov [esp + 20], eax + + mov ecx, ebp + dec ecx ; height + mov ebp, ecx + jnz loop_y + + add esp, 28 + + mov eax, 0 + pop ebp + pop edi + pop esi + pop ebx + ret + align 16 + + diff --git a/xorg/server/xrdpdev/xrdpdev.c b/xorg/server/xrdpdev/xrdpdev.c index 7e5959ba..5a863f00 100644 --- a/xorg/server/xrdpdev/xrdpdev.c +++ b/xorg/server/xrdpdev/xrdpdev.c @@ -39,6 +39,8 @@ This is the main driver file #include <mi.h> #include <randrstr.h> +#include <xf86Modes.h> + #include "rdp.h" #include "rdpPri.h" #include "rdpDraw.h" @@ -51,14 +53,8 @@ This is the main driver file #include "rdpGlyphs.h" #include "rdpPixmap.h" #include "rdpClientCon.h" - -#define XRDP_DRIVER_NAME "XRDPDEV" -#define XRDP_NAME "XRDPDEV" -#define XRDP_VERSION 1000 - -#define PACKAGE_VERSION_MAJOR 1 -#define PACKAGE_VERSION_MINOR 0 -#define PACKAGE_VERSION_PATCHLEVEL 0 +#include "rdpXv.h" +#include "rdpSimd.h" #define LLOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -449,13 +445,20 @@ rdpScreenInit(ScreenPtr pScreen, int argc, char **argv) LLOGLN(0, ("rdpScreenInit: fbScreenInit failed")); return FALSE; } + +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 14, 0, 0, 0) + /* 1.13 has this function, 1.14 and up does not */ miInitializeBackingStore(pScreen); +#endif + + /* try in init simd functions */ + rdpSimdInit(pScreen, pScrn); -#if 0 +#if defined(XvExtension) && XvExtension /* XVideo */ - if (rdp_xv_init(pScreen, pScrn) != 0) + if (!rdpXvInit(pScreen, pScrn)) { - LLOGLN(0, ("rdpScreenInit: rdp_xv_init failed")); + LLOGLN(0, ("rdpScreenInit: rdpXvInit failed")); } #endif @@ -658,7 +661,7 @@ rdpProbe(DriverPtr drv, int flags) found_screen = 1; pscrn->driverVersion = XRDP_VERSION; pscrn->driverName = XRDP_DRIVER_NAME; - pscrn->name = XRDP_NAME; + pscrn->name = XRDP_DRIVER_NAME; pscrn->Probe = rdpProbe; pscrn->PreInit = rdpPreInit; pscrn->ScreenInit = rdpScreenInit; @@ -710,7 +713,7 @@ static void rdpIdentify(int flags) { LLOGLN(0, ("rdpIdentify:")); - xf86PrintChipsets(XRDP_NAME, "driver for xrdp", g_Chipsets); + xf86PrintChipsets(XRDP_DRIVER_NAME, "driver for xrdp", g_Chipsets); } /*****************************************************************************/ diff --git a/xorg/server/xrdpkeyb/rdpKeyboard.c b/xorg/server/xrdpkeyb/rdpKeyboard.c index a1e840b2..0157de21 100644 --- a/xorg/server/xrdpkeyb/rdpKeyboard.c +++ b/xorg/server/xrdpkeyb/rdpKeyboard.c @@ -52,14 +52,6 @@ xrdp keyboard module #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) -#define XRDP_DRIVER_NAME "XRDPKEYB" -#define XRDP_NAME "XRDPKEYB" -#define XRDP_VERSION 1000 - -#define PACKAGE_VERSION_MAJOR 1 -#define PACKAGE_VERSION_MINOR 0 -#define PACKAGE_VERSION_PATCHLEVEL 0 - #define MIN_KEY_CODE 8 #define MAX_KEY_CODE 255 #define NO_OF_KEYS ((MAX_KEY_CODE - MIN_KEY_CODE) + 1) @@ -688,7 +680,7 @@ rdpkeybUnInit(InputDriverPtr drv, InputInfoPtr info, int flags) static InputDriverRec rdpkeyb = { PACKAGE_VERSION_MAJOR, /* version */ - XRDP_NAME, /* name */ + XRDP_KEYB_NAME, /* name */ NULL, /* identify */ rdpkeybPreInit, /* preinit */ rdpkeybUnInit, /* uninit */ @@ -715,7 +707,7 @@ rdpkeybUnplug(pointer p) /******************************************************************************/ static XF86ModuleVersionInfo rdpkeybVersionRec = { - XRDP_DRIVER_NAME, + XRDP_KEYB_NAME, MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, diff --git a/xorg/server/xrdpmouse/rdpMouse.c b/xorg/server/xrdpmouse/rdpMouse.c index 2d8213cd..d64e9233 100644 --- a/xorg/server/xrdpmouse/rdpMouse.c +++ b/xorg/server/xrdpmouse/rdpMouse.c @@ -50,14 +50,6 @@ xrdp mouse module #define LLOGLN(_level, _args) \ do { if (_level < LOG_LEVEL) { ErrorF _args ; ErrorF("\n"); } } while (0) -#define XRDP_DRIVER_NAME "XRDPMOUSE" -#define XRDP_NAME "XRDPMOUSE" -#define XRDP_VERSION 1000 - -#define PACKAGE_VERSION_MAJOR 1 -#define PACKAGE_VERSION_MINOR 0 -#define PACKAGE_VERSION_PATCHLEVEL 0 - /******************************************************************************/ static void rdpmouseDeviceInit(void) @@ -323,7 +315,7 @@ rdpmouseUnInit(InputDriverPtr drv, InputInfoPtr info, int flags) static InputDriverRec rdpmouse = { PACKAGE_VERSION_MAJOR, /* version */ - XRDP_NAME, /* name */ + XRDP_MOUSE_NAME, /* name */ NULL, /* identify */ rdpmousePreInit, /* preinit */ rdpmouseUnInit, /* uninit */ @@ -350,7 +342,7 @@ rdpmouseUnplug(pointer p) /******************************************************************************/ static XF86ModuleVersionInfo rdpmouseVersionRec = { - XRDP_DRIVER_NAME, + XRDP_MOUSE_NAME, MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 71d84a33..4fd9a689 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -15,6 +15,12 @@ EXTRA_INCLUDES += -I$(prefix)/include EXTRA_FLAGS += -L$(prefix)/lib -Wl,-rpath -Wl,$(prefix)/lib endif +if XRDP_RFXCODEC +EXTRA_DEFINES += -DXRDP_RFXCODEC +EXTRA_INCLUDES += -I$(top_srcdir)/librfxcodec/include +EXTRA_LIBS += $(top_srcdir)/librfxcodec/src/librfxencode.a +endif + AM_CFLAGS = \ -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ -DXRDP_SBIN_PATH=\"${sbindir}\" \ @@ -45,11 +51,13 @@ xrdp_SOURCES = \ xrdp_painter.c \ xrdp_process.c \ xrdp_region.c \ - xrdp_wm.c + xrdp_wm.c \ + xrdp_encoder.c xrdp_LDADD = \ $(top_builddir)/common/libcommon.la \ - $(top_builddir)/libxrdp/libxrdp.la + $(top_builddir)/libxrdp/libxrdp.la \ + $(EXTRA_LIBS) xrdp_LDFLAGS = \ $(EXTRA_FLAGS) @@ -57,7 +65,8 @@ xrdp_LDFLAGS = \ xrdpsysconfdir=$(sysconfdir)/xrdp xrdpsysconf_DATA = \ - xrdp.ini + xrdp.ini \ + xrdp_keyboard.ini xrdppkgdatadir=$(datadir)/xrdp @@ -70,4 +79,3 @@ xrdppkgdata_DATA = \ sans-10.fv1 \ cursor0.cur \ cursor1.cur - diff --git a/xrdp/funcs.c b/xrdp/funcs.c index cd2ccf16..add5417e 100644 --- a/xrdp/funcs.c +++ b/xrdp/funcs.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/xrdp/lang.c b/xrdp/lang.c index 24dafb6a..5ffff0eb 100644 --- a/xrdp/lang.c +++ b/xrdp/lang.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -231,7 +231,7 @@ get_keymaps(int keylayout, struct xrdp_keymap *keymap) { fd = g_file_open(filename); - if (fd > 0) + if (fd != -1) { lkeymap = (struct xrdp_keymap *)g_malloc(sizeof(struct xrdp_keymap), 0); /* make a copy of the build in kaymap */ diff --git a/xrdp/rdp-scan-codes.txt b/xrdp/rdp-scan-codes.txt index 649bc5eb..938ce4c5 100644 --- a/xrdp/rdp-scan-codes.txt +++ b/xrdp/rdp-scan-codes.txt @@ -64,6 +64,7 @@ m 0x32 50 0000 8000 , 0x33 51 0000 8000 . 0x34 52 0000 8000 / 0x35 53 0000 8000 +/(keypad) 0x35 53 0100 8100 right shift 0x36 54 0000/4000 c000 *(keypad) 0x37 55 0000 8000 print scrn 0x37 55 0100 8100 @@ -87,7 +88,7 @@ scroll lock 0x46 70 0000/4000 c000 home 0x47 71 0100 8100 8(keypad) 0x48 72 0000 8000 up arrow 0x48 72 0100 8100 -9(kaypad) 0x49 73 0000 8000 +9(keypad) 0x49 73 0000 8000 pg up 0x49 73 0100 8100 -(keypad) 0x4a 74 0000 8000 4(keypad) 0x4b 75 0000 8000 @@ -102,7 +103,7 @@ end 0x4f 79 0100 8100 down arrow 0x50 80 0100 8100 3(keypad) 0x51 81 0000 8000 pg down 0x51 81 0100 8100 -o(keypad) 0x52 82 0000 8000 +0(keypad) 0x52 82 0000 8000 insert 0x52 82 0100 8100 .(keypad) 0x53 83 0000 8000 delete 0x53 83 0100 8100 diff --git a/xrdp/xrdp.c b/xrdp/xrdp.c index 887ada68..a80687b1 100644 --- a/xrdp/xrdp.c +++ b/xrdp/xrdp.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,10 @@ #include "xrdp.h" #include "log.h" +#if !defined(PACKAGE_VERSION) +#define PACKAGE_VERSION "???" +#endif + #define THREAD_WAITING 100 static struct xrdp_listen *g_listen = 0; @@ -435,8 +439,8 @@ main(int argc, char **argv) { g_writeln(""); g_writeln("xrdp: A Remote Desktop Protocol server."); - g_writeln("Copyright (C) Jay Sorg 2004-2013"); - g_writeln("See http://xrdp.sourceforge.net for more information."); + g_writeln("Copyright (C) Jay Sorg 2004-2014"); + g_writeln("See http://www.xrdp.org for more information."); g_writeln(""); g_writeln("Usage: xrdp [options]"); g_writeln(" --help: show help"); @@ -453,8 +457,8 @@ main(int argc, char **argv) { g_writeln(""); g_writeln("xrdp: A Remote Desktop Protocol server."); - g_writeln("Copyright (C) Jay Sorg 2004-2013"); - g_writeln("See http://xrdp.sourceforge.net for more information."); + g_writeln("Copyright (C) Jay Sorg 2004-2014"); + g_writeln("See http://www.xrdp.org for more information."); g_writeln("Version %s", PACKAGE_VERSION); g_writeln(""); g_deinit(); @@ -538,9 +542,19 @@ main(int argc, char **argv) g_file_close(0); g_file_close(1); g_file_close(2); - g_file_open("/dev/null"); - g_file_open("/dev/null"); - g_file_open("/dev/null"); + + if (g_file_open("/dev/null") < 0) + { + } + + if (g_file_open("/dev/null") < 0) + { + } + + if (g_file_open("/dev/null") < 0) + { + } + /* end of daemonizing code */ } diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index a778058f..67488a60 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ #include "parse.h" #include "trans.h" #include "list.h" +#include "list16.h" #include "libxrdpinc.h" #include "xrdp_constants.h" #include "xrdp_types.h" @@ -137,6 +138,8 @@ callback(long id, int msg, long param1, long param2, long param3, long param4); int APP_CC xrdp_wm_delete_all_childs(struct xrdp_wm* self); int APP_CC +xrdp_wm_show_log(struct xrdp_wm *self); +int APP_CC xrdp_wm_log_msg(struct xrdp_wm* self, char* msg); int APP_CC xrdp_wm_get_wait_objs(struct xrdp_wm* self, tbus* robjs, int* rc, @@ -206,6 +209,8 @@ xrdp_bitmap_copy_box(struct xrdp_bitmap* self, struct xrdp_bitmap* dest, int x, int y, int cx, int cy); int APP_CC +xrdp_bitmap_hash_crc(struct xrdp_bitmap *self); +int APP_CC xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap* self, struct xrdp_bitmap* dest, int x, int y, int cx, int cy); @@ -213,9 +218,6 @@ int APP_CC xrdp_bitmap_compare(struct xrdp_bitmap* self, struct xrdp_bitmap* b); int APP_CC -xrdp_bitmap_compare_with_crc(struct xrdp_bitmap* self, - struct xrdp_bitmap* b); -int APP_CC xrdp_bitmap_invalidate(struct xrdp_bitmap* self, struct xrdp_rect* rect); int APP_CC xrdp_bitmap_def_proc(struct xrdp_bitmap* self, int msg, @@ -404,7 +406,8 @@ server_composite(struct xrdp_mod* mod, int srcidx, int srcformat, int srcwidth, int DEFAULT_CC server_paint_rects(struct xrdp_mod* mod, int num_drects, short *drects, int num_crects, short *crects, - char *data, int width, int height, int flags); + char *data, int width, int height, + int flags, int frame_id); int DEFAULT_CC server_set_pointer(struct xrdp_mod* mod, int x, int y, char* data, char* mask); diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini index 70c917e1..59122a00 100644 --- a/xrdp/xrdp.ini +++ b/xrdp/xrdp.ini @@ -1,4 +1,3 @@ - [globals] # xrdp.ini file version number ini_version=1 @@ -6,10 +5,19 @@ ini_version=1 bitmap_cache=yes bitmap_compression=yes port=3389 -crypt_level=high allow_channels=true -max_bpp=24 +max_bpp=32 fork=yes +# minimum security level allowed for client +# can be 'none', 'low', 'medium', 'high', 'fips' +crypt_level=high +# security layer can be 'tls', 'rdp' or 'negotiate' +# for client compatible layer +security_layer=rdp +# X.509 certificate and private key +# openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 365 +certificate= +key_file= # regulate if the listening socket use socket option tcp_nodelay # no buffering will be performed in the TCP stack @@ -42,18 +50,22 @@ grey=dedede # when true, userid/password *must* be passed on cmd line # require_credentials=yes -#bulk_compression=yes +bulk_compression=yes # You can set the PAM error text in a gateway setup (MAX 256 chars) #pamerrortxt=change your password according to policy at http://url -#new_cursors=no -#nego_sec_layer=0 +new_cursors=yes allow_multimon=true +# fastpath - can be set to input / output / both / none +use_fastpath=both # # configure login screen # +# Login Screen Window Title +#ls_title=My Login Title + # top level window background color in RGB format ls_top_window_bg_color=009cb5 @@ -64,7 +76,11 @@ ls_height=430 # login screen background color in RGB format ls_bg_color=dedede +# optional background image filename (bmp format). +#ls_background_image= + # logo +# full path to bmp-file or file in shared folder ls_logo_filename= ls_logo_x_pos=55 ls_logo_y_pos=50 @@ -112,6 +128,7 @@ drdynvc=true cliprdr=true rail=true xrdpvr=true +tcutils=true # for debugging xrdp, in section xrdp1, change port=-1 to this: # port=/tmp/.xrdp/xrdp_display_10 @@ -178,6 +195,16 @@ port=ask3389 username=ask password=ask +[Session manager] +name=Session manager +lib=libxup.so +username=ask +password=ask +ip=127.0.0.1 +port=-1 +xserverbpp=24 +code=20 + # You can override the common channel settings for each session type #channel.rdpdr=true #channel.rdpsnd=true diff --git a/xrdp/xrdp_bitmap.c b/xrdp/xrdp_bitmap.c index c3eef7a1..aafc19f2 100644 --- a/xrdp/xrdp_bitmap.c +++ b/xrdp/xrdp_bitmap.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,9 +23,22 @@ #include "xrdp.h" #include "log.h" - -static int g_crc_seed = 0xffffffff; -static int g_crc_table[256] = +#include "crc16.h" + +#define LLOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do \ + { \ + if (_level < LLOG_LEVEL) \ + { \ + g_write("xrdp:xrdp_bitmap [%10.10u]: ", g_time3()); \ + g_writeln _args ; \ + } \ + } \ + while (0) + + +static const int g_crc_table[256] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, @@ -72,10 +85,10 @@ static int g_crc_table[256] = 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; -#define CRC_START(in_crc) (in_crc) = g_crc_seed +#define CRC_START(in_crc) (in_crc) = 0xFFFFFFFF #define CRC_PASS(in_pixel, in_crc) \ (in_crc) = g_crc_table[((in_crc) ^ (in_pixel)) & 0xff] ^ ((in_crc) >> 8) -#define CRC_END(in_crc) (in_crc) = ((in_crc) ^ g_crc_seed) +#define CRC_END(in_crc) (in_crc) = ((in_crc) ^ 0xFFFFFFFF) /*****************************************************************************/ struct xrdp_bitmap *APP_CC @@ -136,15 +149,44 @@ xrdp_bitmap_create_with_data(int width, int height, struct xrdp_wm *wm) { struct xrdp_bitmap *self = (struct xrdp_bitmap *)NULL; +#if defined(NEED_ALIGN) + tintptr data_as_int; + int Bpp; +#endif self = (struct xrdp_bitmap *)g_malloc(sizeof(struct xrdp_bitmap), 1); self->type = WND_TYPE_BITMAP; self->width = width; self->height = height; self->bpp = bpp; - self->data = data; - self->do_not_free_data = 1; self->wm = wm; +#if defined(NEED_ALIGN) + data_as_int = (tintptr) data; + if (((bpp >= 24) && (data_as_int & 3)) || + (((bpp == 15) || (bpp == 16)) && (data_as_int & 1))) + { + /* got to copy data here, it's not alligned + other calls in this file assume alignment */ + Bpp = 4; + switch (bpp) + { + case 8: + Bpp = 1; + break; + case 15: + Bpp = 2; + break; + case 16: + Bpp = 2; + break; + } + self->data = (char *)g_malloc(width * height * Bpp, 0); + g_memcpy(self->data, data, width * height * Bpp); + return self; + } +#endif + self->data = data; + self->do_not_free_data = 1; return self; } @@ -400,7 +442,6 @@ xrdp_bitmap_load(struct xrdp_bitmap *self, const char *filename, int *palette) return 1; } - s = (struct stream *)NULL; fd = g_file_open(filename); if (fd != -1) @@ -428,7 +469,14 @@ xrdp_bitmap_load(struct xrdp_bitmap *self, const char *filename, int *palette) g_file_read(fd, s->data, 4); in_uint32_le(s, size); /* read bmp header */ - g_file_seek(fd, 14); + if (g_file_seek(fd, 14) < 0) + { + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: seek error in file %s\n", + filename); + free_stream(s); + g_file_close(fd); + return 1; + } init_stream(s, 8192); g_file_read(fd, s->data, 40); /* size better be 40 */ in_uint32_le(s, header.size); @@ -455,7 +503,11 @@ xrdp_bitmap_load(struct xrdp_bitmap *self, const char *filename, int *palette) if (header.bit_count == 24) /* 24 bit bitmap */ { - g_file_seek(fd, 14 + header.size); + if (g_file_seek(fd, 14 + header.size) < 0) + { + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: seek error in file %s\n", + filename); + } xrdp_bitmap_resize(self, header.image_width, header.image_height); size = header.image_width * header.image_height * 3; init_stream(s, size); @@ -508,7 +560,11 @@ xrdp_bitmap_load(struct xrdp_bitmap *self, const char *filename, int *palette) else if (header.bit_count == 8) /* 8 bit bitmap */ { /* read palette */ - g_file_seek(fd, 14 + header.size); + if (g_file_seek(fd, 14 + header.size) < 0) + { + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: seek error in file %s\n", + filename); + } init_stream(s, 8192); g_file_read(fd, s->data, header.clr_used * sizeof(int)); @@ -565,7 +621,11 @@ xrdp_bitmap_load(struct xrdp_bitmap *self, const char *filename, int *palette) else if (header.bit_count == 4) /* 4 bit bitmap */ { /* read palette */ - g_file_seek(fd, 14 + header.size); + if (g_file_seek(fd, 14 + header.size) < 0) + { + log_message(LOG_LEVEL_ERROR, "xrdp_bitmap_load: seek error in file %s\n", + filename); + } init_stream(s, 8192); g_file_read(fd, s->data, header.clr_used * sizeof(int)); @@ -666,7 +726,7 @@ xrdp_bitmap_get_pixel(struct xrdp_bitmap *self, int x, int y) { return GETPIXEL16(self->data, x, y, self->width); } - else if (self->bpp == 24) + else if (self->bpp >= 24) { return GETPIXEL32(self->data, x, y, self->width); } @@ -699,7 +759,7 @@ xrdp_bitmap_set_pixel(struct xrdp_bitmap *self, int x, int y, int pixel) { SETPIXEL16(self->data, x, y, self->width, pixel); } - else if (self->bpp == 24) + else if (self->bpp >= 24) { SETPIXEL32(self->data, x, y, self->width, pixel); } @@ -716,11 +776,17 @@ xrdp_bitmap_copy_box(struct xrdp_bitmap *self, struct xrdp_bitmap *dest, int x, int y, int cx, int cy) { - int i = 0; - int j = 0; - int destx = 0; - int desty = 0; - int pixel = 0; + int i; + int destx; + int desty; + int incs; + int incd; + tui8 *s8; + tui8 *d8; + tui16 *s16; + tui16 *d16; + tui32 *s32; + tui32 *d32; if (self == 0) { @@ -760,37 +826,56 @@ xrdp_bitmap_copy_box(struct xrdp_bitmap *self, return 1; } - if (self->bpp == 24) + if (self->bpp >= 24) { + s32 = ((tui32 *)(self->data)) + (self->width * y + x); + d32 = ((tui32 *)(dest->data)) + (dest->width * desty + destx); + incs = self->width - cx; + incd = dest->width - cx; + for (i = 0; i < cy; i++) { - for (j = 0; j < cx; j++) - { - pixel = GETPIXEL32(self->data, j + x, i + y, self->width); - SETPIXEL32(dest->data, j + destx, i + desty, dest->width, pixel); - } + g_memcpy(d32, s32, cx * 4); + s32 += cx; + d32 += cx; + + s32 += incs; + d32 += incd; } + } else if (self->bpp == 15 || self->bpp == 16) { + s16 = ((tui16 *)(self->data)) + (self->width * y + x); + d16 = ((tui16 *)(dest->data)) + (dest->width * desty + destx); + incs = self->width - cx; + incd = dest->width - cx; + for (i = 0; i < cy; i++) { - for (j = 0; j < cx; j++) - { - pixel = GETPIXEL16(self->data, j + x, i + y, self->width); - SETPIXEL16(dest->data, j + destx, i + desty, dest->width, pixel); - } + g_memcpy(d16, s16, cx * 2); + s16 += cx; + d16 += cx; + + s16 += incs; + d16 += incd; } } else if (self->bpp == 8) { + s8 = ((tui8 *)(self->data)) + (self->width * y + x); + d8 = ((tui8 *)(dest->data)) + (dest->width * desty + destx); + incs = self->width - cx; + incd = dest->width - cx; + for (i = 0; i < cy; i++) { - for (j = 0; j < cx; j++) - { - pixel = GETPIXEL8(self->data, j + x, i + y, self->width); - SETPIXEL8(dest->data, j + destx, i + desty, dest->width, pixel); - } + g_memcpy(d8, s8, cx); + s8 += cx; + d8 += cx; + + s8 += incs; + d8 += incd; } } else @@ -802,6 +887,51 @@ xrdp_bitmap_copy_box(struct xrdp_bitmap *self, } /*****************************************************************************/ +int APP_CC +xrdp_bitmap_hash_crc(struct xrdp_bitmap *self) +{ + void *hash; + int bytes; + int crc; + int index; + char hash_data[16]; + + if (self->bpp >= 24) + { + bytes = self->width * self->height * 4; + } + else if (self->bpp == 15 || self->bpp == 16) + { + bytes = self->width * self->height * 2; + } + else if (self->bpp == 8) + { + bytes = self->width * self->height; + } + else + { + return 1; + } + hash = ssl_md5_info_create(); + ssl_md5_transform(hash, self->data, bytes); + ssl_md5_complete(hash, hash_data); + ssl_md5_info_delete(hash); + CRC_START(crc); + CRC_PASS(self->width, crc); + CRC_PASS(self->width >> 8, crc); + CRC_PASS(self->height, crc); + CRC_PASS(self->height >> 8, crc); + for (index = 0; index < 16; index++) + { + CRC_PASS(hash_data[index], crc); + } + CRC_END(crc); + self->crc32 = crc; + self->crc16 = self->crc32 & 0xffff; + return 0; +} + +/*****************************************************************************/ /* copy part of self at x, y to 0, 0 in dest */ /* returns error */ int APP_CC @@ -809,20 +939,20 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap *self, struct xrdp_bitmap *dest, int x, int y, int cx, int cy) { - int i = 0; - int j = 0; - int destx = 0; - int desty = 0; - int pixel = 0; - int crc = 0; - int incs = 0; - int incd = 0; - unsigned char *s8 = (unsigned char *)NULL; - unsigned char *d8 = (unsigned char *)NULL; - unsigned short *s16 = (unsigned short *)NULL; - unsigned short *d16 = (unsigned short *)NULL; - unsigned int *s32; - unsigned int *d32; + int i; + int j; + int destx; + int desty; + int pixel; + int crc; + int incs; + int incd; + tui8 *s8; + tui8 *d8; + tui16 *s16; + tui16 *d16; + tui32 *s32; + tui32 *d32; if (self == 0) { @@ -864,47 +994,123 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap *self, CRC_START(crc); - if (self->bpp == 24) + CRC_PASS(self->width, crc); + CRC_PASS(self->width >> 8, crc); + + CRC_PASS(self->height, crc); + CRC_PASS(self->height >> 8, crc); + + if (self->bpp == 32) { - s32 = ((unsigned int *)(self->data)) + (self->width * y + x); - d32 = ((unsigned int *)(dest->data)) + (dest->width * desty + destx); + s32 = ((tui32 *)(self->data)) + (self->width * y + x); + d32 = ((tui32 *)(dest->data)) + (dest->width * desty + destx); incs = self->width - cx; incd = dest->width - cx; for (i = 0; i < cy; i++) { j = 0; + while (j < cx - 4) { pixel = *s32; + *d32 = pixel; CRC_PASS(pixel, crc); CRC_PASS(pixel >> 8, crc); CRC_PASS(pixel >> 16, crc); + CRC_PASS(pixel >> 24, crc); + s32++; + d32++; + + pixel = *s32; *d32 = pixel; + CRC_PASS(pixel, crc); + CRC_PASS(pixel >> 8, crc); + CRC_PASS(pixel >> 16, crc); + CRC_PASS(pixel >> 24, crc); s32++; d32++; pixel = *s32; + *d32 = pixel; CRC_PASS(pixel, crc); CRC_PASS(pixel >> 8, crc); CRC_PASS(pixel >> 16, crc); + CRC_PASS(pixel >> 24, crc); + s32++; + d32++; + + pixel = *s32; *d32 = pixel; + CRC_PASS(pixel, crc); + CRC_PASS(pixel >> 8, crc); + CRC_PASS(pixel >> 16, crc); + CRC_PASS(pixel >> 24, crc); s32++; d32++; + j += 4; + } + while (j < cx) + { pixel = *s32; + *d32 = pixel; CRC_PASS(pixel, crc); CRC_PASS(pixel >> 8, crc); CRC_PASS(pixel >> 16, crc); + CRC_PASS(pixel >> 24, crc); + s32++; + d32++; + + j += 1; + } + + s32 += incs; + d32 += incd; + } + } + else if (self->bpp == 24) + { + s32 = ((tui32 *)(self->data)) + (self->width * y + x); + d32 = ((tui32 *)(dest->data)) + (dest->width * desty + destx); + incs = self->width - cx; + incd = dest->width - cx; + + for (i = 0; i < cy; i++) + { + j = 0; + + while (j < cx - 4) + { + pixel = *s32; *d32 = pixel; + CRC_PASS(pixel, crc); + CRC_PASS(pixel >> 8, crc); + CRC_PASS(pixel >> 16, crc); s32++; d32++; pixel = *s32; + *d32 = pixel; CRC_PASS(pixel, crc); CRC_PASS(pixel >> 8, crc); CRC_PASS(pixel >> 16, crc); + s32++; + d32++; + + pixel = *s32; + *d32 = pixel; + CRC_PASS(pixel, crc); + CRC_PASS(pixel >> 8, crc); + CRC_PASS(pixel >> 16, crc); + s32++; + d32++; + + pixel = *s32; *d32 = pixel; + CRC_PASS(pixel, crc); + CRC_PASS(pixel >> 8, crc); + CRC_PASS(pixel >> 16, crc); s32++; d32++; @@ -913,10 +1119,10 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap *self, while (j < cx) { pixel = *s32; + *d32 = pixel; CRC_PASS(pixel, crc); CRC_PASS(pixel >> 8, crc); CRC_PASS(pixel >> 16, crc); - *d32 = pixel; s32++; d32++; @@ -929,8 +1135,8 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap *self, } else if (self->bpp == 15 || self->bpp == 16) { - s16 = ((unsigned short *)(self->data)) + (self->width * y + x); - d16 = ((unsigned short *)(dest->data)) + (dest->width * desty + destx); + s16 = ((tui16 *)(self->data)) + (self->width * y + x); + d16 = ((tui16 *)(dest->data)) + (dest->width * desty + destx); incs = self->width - cx; incd = dest->width - cx; @@ -939,9 +1145,9 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap *self, for (j = 0; j < cx; j++) { pixel = *s16; + *d16 = pixel; CRC_PASS(pixel, crc); CRC_PASS(pixel >> 8, crc); - *d16 = pixel; s16++; d16++; } @@ -952,8 +1158,8 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap *self, } else if (self->bpp == 8) { - s8 = ((unsigned char *)(self->data)) + (self->width * y + x); - d8 = ((unsigned char *)(dest->data)) + (dest->width * desty + destx); + s8 = ((tui8 *)(self->data)) + (self->width * y + x); + d8 = ((tui8 *)(dest->data)) + (dest->width * desty + destx); incs = self->width - cx; incd = dest->width - cx; @@ -962,8 +1168,8 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap *self, for (j = 0; j < cx; j++) { pixel = *s8; - CRC_PASS(pixel, crc); *d8 = pixel; + CRC_PASS(pixel, crc); s8++; d8++; } @@ -978,7 +1184,14 @@ xrdp_bitmap_copy_box_with_crc(struct xrdp_bitmap *self, } CRC_END(crc); - dest->crc = crc; + dest->crc32 = crc; + dest->crc16 = dest->crc32 & 0xffff; + + LLOGLN(10, ("xrdp_bitmap_copy_box_with_crc: crc16 0x%4.4x", + dest->crc16)); + LLOGLN(10, ("xrdp_bitmap_copy_box_with_crc: width %d height %d", + dest->width, dest->height)); + return 0; } @@ -988,45 +1201,8 @@ int APP_CC xrdp_bitmap_compare(struct xrdp_bitmap *self, struct xrdp_bitmap *b) { - if (self == 0) - { - return 0; - } - - if (b == 0) - { - return 0; - } - - if (self->bpp != b->bpp) - { - return 0; - } - - if (self->width != b->width) - { - return 0; - } - - if (self->height != b->height) - { - return 0; - } + LLOGLN(10, ("xrdp_bitmap_compare:")); - if (g_memcmp(self->data, b->data, b->height * b->line_size) == 0) - { - return 1; - } - - return 0; -} - -/*****************************************************************************/ -/* returns true if they are the same, else returns false */ -int APP_CC -xrdp_bitmap_compare_with_crc(struct xrdp_bitmap *self, - struct xrdp_bitmap *b) -{ if (self == 0) { return 0; @@ -1052,7 +1228,7 @@ xrdp_bitmap_compare_with_crc(struct xrdp_bitmap *self, return 0; } - if (self->crc == b->crc) + if (g_memcmp(self->data, b->data, b->height * b->line_size) == 0) { return 1; } @@ -1617,42 +1793,6 @@ xrdp_bitmap_def_proc(struct xrdp_bitmap *self, int msg, if (self->child_list != 0) { i = list_index_of(self->child_list, (long)self->focused_control); - } - - if (shift) - { - i--; - - if (i < 0) - { - i = self->child_list->count - 1; - } - } - else - { - i++; - - if (i >= self->child_list->count) - { - i = 0; - } - } - - n = self->child_list->count; - b = (struct xrdp_bitmap *)list_get_item(self->child_list, i); - - while (b != self->focused_control && b != 0 && n > 0) - { - n--; - - if (b->tab_stop) - { - focus_out_control = self->focused_control; - self->focused_control = b; - xrdp_bitmap_invalidate(focus_out_control, 0); - xrdp_bitmap_invalidate(b, 0); - break; - } if (shift) { @@ -1673,7 +1813,43 @@ xrdp_bitmap_def_proc(struct xrdp_bitmap *self, int msg, } } + n = self->child_list->count; b = (struct xrdp_bitmap *)list_get_item(self->child_list, i); + + while (b != self->focused_control && b != 0 && n > 0) + { + n--; + + if (b->tab_stop) + { + focus_out_control = self->focused_control; + self->focused_control = b; + xrdp_bitmap_invalidate(focus_out_control, 0); + xrdp_bitmap_invalidate(b, 0); + break; + } + + if (shift) + { + i--; + + if (i < 0) + { + i = self->child_list->count - 1; + } + } + else + { + i++; + + if (i >= self->child_list->count) + { + i = 0; + } + } + + b = (struct xrdp_bitmap *)list_get_item(self->child_list, i); + } } } else if (scan_code == 28) /* enter */ diff --git a/xrdp/xrdp_cache.c b/xrdp/xrdp_cache.c index c57fc2ad..834271db 100644 --- a/xrdp/xrdp_cache.c +++ b/xrdp/xrdp_cache.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ #include "xrdp.h" #include "log.h" +#include "crc16.h" #define LLOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -34,6 +35,59 @@ while (0) /*****************************************************************************/ +static int APP_CC +xrdp_cache_reset_lru(struct xrdp_cache *self) +{ + int index; + int jndex; + struct xrdp_lru_item *lru; + + for (index = 0; index < XRDP_MAX_BITMAP_CACHE_ID; index++) + { + /* fist item */ + lru = &(self->bitmap_lrus[index][0]); + lru->next = 1; + lru->prev = -1; + /* middle items */ + for (jndex = 1; jndex < XRDP_MAX_BITMAP_CACHE_IDX - 1; jndex++) + { + lru = &(self->bitmap_lrus[index][jndex]); + lru->next = jndex + 1; + lru->prev = jndex - 1; + } + /* last item */ + lru = &(self->bitmap_lrus[index][XRDP_MAX_BITMAP_CACHE_IDX - 1]); + lru->next = -1; + lru->prev = XRDP_MAX_BITMAP_CACHE_IDX - 2; + + self->lru_head[index] = 0; + self->lru_tail[index] = XRDP_MAX_BITMAP_CACHE_IDX - 1; + + self->lru_reset[index] = 1; + } + return 0; +} + +/*****************************************************************************/ +static int APP_CC +xrdp_cache_reset_crc(struct xrdp_cache *self) +{ + int index; + int jndex; + + for (index = 0; index < XRDP_MAX_BITMAP_CACHE_ID; index++) + { + for (jndex = 0; jndex < 64 * 1024; jndex++) + { + /* it's ok to deinit a zero'ed out struct list16 */ + list16_deinit(&(self->crc16[index][jndex])); + list16_init(&(self->crc16[index][jndex])); + } + } + return 0; +} + +/*****************************************************************************/ struct xrdp_cache *APP_CC xrdp_cache_create(struct xrdp_wm *owner, struct xrdp_session *session, @@ -65,6 +119,8 @@ xrdp_cache_create(struct xrdp_wm *owner, self->bitmap_cache_version = client_info->bitmap_cache_version; self->pointer_cache_entries = client_info->pointer_cache_entries; self->xrdp_os_del_list = list_create(); + xrdp_cache_reset_lru(self); + xrdp_cache_reset_crc(self); LLOGLN(10, ("xrdp_cache_create: 0 %d 1 %d 2 %d", self->cache1_entries, self->cache2_entries, self->cache3_entries)); return self; @@ -108,6 +164,15 @@ xrdp_cache_delete(struct xrdp_cache *self) list_delete(self->xrdp_os_del_list); + /* free all crc lists */ + for (i = 0; i < XRDP_MAX_BITMAP_CACHE_ID; i++) + { + for (j = 0; j < 64 * 1024; j++) + { + list16_deinit(&(self->crc16[i][j])); + } + } + g_free(self); } @@ -157,157 +222,228 @@ xrdp_cache_reset(struct xrdp_cache *self, self->bitmap_cache_persist_enable = client_info->bitmap_cache_persist_enable; self->bitmap_cache_version = client_info->bitmap_cache_version; self->pointer_cache_entries = client_info->pointer_cache_entries; + xrdp_cache_reset_lru(self); + xrdp_cache_reset_crc(self); return 0; } -#define COMPARE_WITH_CRC(_b1, _b2) \ - ((_b1 != 0) && (_b2 != 0) && (_b1->crc == _b2->crc) && \ +#define COMPARE_WITH_CRC32(_b1, _b2) \ + ((_b1 != 0) && (_b2 != 0) && (_b1->crc32 == _b2->crc32) && \ (_b1->bpp == _b2->bpp) && \ (_b1->width == _b2->width) && (_b1->height == _b2->height)) /*****************************************************************************/ -/* returns cache id */ -int APP_CC -xrdp_cache_add_bitmap(struct xrdp_cache *self, struct xrdp_bitmap *bitmap, - int hints) +static int APP_CC +xrdp_cache_update_lru(struct xrdp_cache *self, int cache_id, int lru_index) { - int i = 0; - int j = 0; - int oldest = 0; - int cache_id = 0; - int cache_idx = 0; - int bmp_size = 0; - int e = 0; - int Bpp = 0; + int tail_index; + struct xrdp_lru_item *nextlru; + struct xrdp_lru_item *prevlru; + struct xrdp_lru_item *thislru; + struct xrdp_lru_item *taillru; + + LLOGLN(10, ("xrdp_cache_update_lru: lru_index %d", lru_index)); + if ((lru_index < 0) || (lru_index >= XRDP_MAX_BITMAP_CACHE_IDX)) + { + LLOGLN(0, ("xrdp_cache_update_lru: error")); + return 1; + } + if (self->lru_tail[cache_id] == lru_index) + { + /* nothing to do */ + return 0; + } + else if (self->lru_head[cache_id] == lru_index) + { + /* moving head item to tail */ - e = bitmap->width % 4; + thislru = &(self->bitmap_lrus[cache_id][lru_index]); + nextlru = &(self->bitmap_lrus[cache_id][thislru->next]); + tail_index = self->lru_tail[cache_id]; + taillru = &(self->bitmap_lrus[cache_id][tail_index]); - if (e != 0) + /* unhook old */ + nextlru->prev = -1; + + /* set head to next */ + self->lru_head[cache_id] = thislru->next; + + /* move to tail and hook up */ + taillru->next = lru_index; + thislru->prev = tail_index; + thislru->next = -1; + + /* update tail */ + self->lru_tail[cache_id] = lru_index; + + } + else { - e = 4 - e; + /* move middle item */ + + thislru = &(self->bitmap_lrus[cache_id][lru_index]); + prevlru = &(self->bitmap_lrus[cache_id][thislru->prev]); + nextlru = &(self->bitmap_lrus[cache_id][thislru->next]); + tail_index = self->lru_tail[cache_id]; + taillru = &(self->bitmap_lrus[cache_id][tail_index]); + + /* unhook old */ + prevlru->next = thislru->next; + nextlru->prev = thislru->prev; + + /* move to tail and hook up */ + taillru->next = lru_index; + thislru->prev = tail_index; + thislru->next = -1; + + /* update tail */ + self->lru_tail[cache_id] = lru_index; } + return 0; +} + +/*****************************************************************************/ +/* returns cache id */ +int APP_CC +xrdp_cache_add_bitmap(struct xrdp_cache *self, struct xrdp_bitmap *bitmap, + int hints) +{ + int index; + int jndex; + int cache_id; + int cache_idx; + int bmp_size; + int e; + int Bpp; + int crc16; + int iig; + int found; + int cache_entries; + int lru_index; + struct list16 *ll; + struct xrdp_bitmap *lbm; + struct xrdp_lru_item *llru; + + LLOGLN(10, ("xrdp_cache_add_bitmap:")); + LLOGLN(10, ("xrdp_cache_add_bitmap: crc16 0x%4.4x", + bitmap->crc16)); + + e = (4 - (bitmap->width % 4)) & 3; + found = 0; + cache_id = 0; + cache_entries = 0; + /* client Bpp, bmp_size */ Bpp = (bitmap->bpp + 7) / 8; bmp_size = (bitmap->width + e) * bitmap->height * Bpp; self->bitmap_stamp++; - /* look for match */ if (bmp_size <= self->cache1_size) { - i = 0; - - for (j = 0; j < self->cache1_entries; j++) - { -#ifdef USE_CRC - if (COMPARE_WITH_CRC(self->bitmap_items[i][j].bitmap, bitmap)) -#else - if (xrdp_bitmap_compare(self->bitmap_items[i][j].bitmap, bitmap)) -#endif - { - self->bitmap_items[i][j].stamp = self->bitmap_stamp; - LLOGLN(10, ("found bitmap at %d %d", i, j)); - xrdp_bitmap_delete(bitmap); - return MAKELONG(j, i); - } - } + cache_id = 0; + cache_entries = self->cache1_entries; } else if (bmp_size <= self->cache2_size) { - i = 1; - - for (j = 0; j < self->cache2_entries; j++) - { -#ifdef USE_CRC - if (COMPARE_WITH_CRC(self->bitmap_items[i][j].bitmap, bitmap)) -#else - if (xrdp_bitmap_compare(self->bitmap_items[i][j].bitmap, bitmap)) -#endif - { - self->bitmap_items[i][j].stamp = self->bitmap_stamp; - LLOGLN(10, ("found bitmap at %d %d", i, j)); - xrdp_bitmap_delete(bitmap); - return MAKELONG(j, i); - } - } + cache_id = 1; + cache_entries = self->cache2_entries; } else if (bmp_size <= self->cache3_size) { - i = 2; - - for (j = 0; j < self->cache3_entries; j++) - { -#ifdef USE_CRC - if (COMPARE_WITH_CRC(self->bitmap_items[i][j].bitmap, bitmap)) -#else - if (xrdp_bitmap_compare(self->bitmap_items[i][j].bitmap, bitmap)) -#endif - { - self->bitmap_items[i][j].stamp = self->bitmap_stamp; - LLOGLN(10, ("found bitmap at %d %d", i, j)); - xrdp_bitmap_delete(bitmap); - return MAKELONG(j, i); - } - } + cache_id = 2; + cache_entries = self->cache3_entries; } else { - log_message(LOG_LEVEL_ERROR,"error in xrdp_cache_add_bitmap, too big(%d) bpp %d", bmp_size, bitmap->bpp); + log_message(LOG_LEVEL_ERROR, "error in xrdp_cache_add_bitmap, " + "too big(%d) bpp %d", bmp_size, bitmap->bpp); + return 0; } - /* look for oldest */ - cache_id = 0; - cache_idx = 0; - oldest = 0x7fffffff; - - if (bmp_size <= self->cache1_size) + crc16 = bitmap->crc16; + ll = &(self->crc16[cache_id][crc16]); + for (jndex = 0; jndex < ll->count; jndex++) { - i = 0; - - for (j = 0; j < self->cache1_entries; j++) + cache_idx = list16_get_item(ll, jndex); + if (COMPARE_WITH_CRC32 + (self->bitmap_items[cache_id][cache_idx].bitmap, bitmap)) { - if (self->bitmap_items[i][j].stamp < oldest) - { - oldest = self->bitmap_items[i][j].stamp; - cache_id = i; - cache_idx = j; - } + LLOGLN(10, ("found bitmap at %d %d", index, jndex)); + found = 1; + break; } } - else if (bmp_size <= self->cache2_size) + if (found) { - i = 1; + lru_index = self->bitmap_items[cache_id][cache_idx].lru_index; + self->bitmap_items[cache_id][cache_idx].stamp = self->bitmap_stamp; + xrdp_bitmap_delete(bitmap); - for (j = 0; j < self->cache2_entries; j++) - { - if (self->bitmap_items[i][j].stamp < oldest) - { - oldest = self->bitmap_items[i][j].stamp; - cache_id = i; - cache_idx = j; - } - } + /* update lru to end */ + xrdp_cache_update_lru(self, cache_id, lru_index); + + return MAKELONG(cache_idx, cache_id); } - else if (bmp_size <= self->cache3_size) + + /* find lru */ + + /* check for reset */ + if (self->lru_reset[cache_id]) { - i = 2; + self->lru_reset[cache_id] = 0; + LLOGLN(0, ("xrdp_cache_add_bitmap: reset detected cache_id %d", + cache_id)); + self->lru_tail[cache_id] = cache_entries - 1; + index = self->lru_tail[cache_id]; + llru = &(self->bitmap_lrus[cache_id][index]); + llru->next = -1; + } + + /* lru is item at head */ + lru_index = self->lru_head[cache_id]; + cache_idx = lru_index; + + /* update lru to end */ + xrdp_cache_update_lru(self, cache_id, lru_index); + + LLOGLN(10, ("xrdp_cache_add_bitmap: oldest %d %d", cache_id, cache_idx)); + + LLOGLN(10, ("adding bitmap at %d %d old ptr %p new ptr %p", + cache_id, cache_idx, + self->bitmap_items[cache_id][cache_idx].bitmap, + bitmap)); - for (j = 0; j < self->cache3_entries; j++) + /* remove old, about to be deleted, from crc16 list */ + lbm = self->bitmap_items[cache_id][cache_idx].bitmap; + if (lbm != 0) + { + crc16 = lbm->crc16; + ll = &(self->crc16[cache_id][crc16]); + iig = list16_index_of(ll, cache_idx); + if (iig == -1) { - if (self->bitmap_items[i][j].stamp < oldest) - { - oldest = self->bitmap_items[i][j].stamp; - cache_id = i; - cache_idx = j; - } + LLOGLN(0, ("xrdp_cache_add_bitmap: error removing cache_idx")); } + LLOGLN(10, ("xrdp_cache_add_bitmap: removing index %d from crc16 %d", + iig, crc16)); + list16_remove_item(ll, iig); + xrdp_bitmap_delete(lbm); } - LLOGLN(10, ("adding bitmap at %d %d ptr %p", cache_id, cache_idx, - self->bitmap_items[cache_id][cache_idx].bitmap)); /* set, send bitmap and return */ - xrdp_bitmap_delete(self->bitmap_items[cache_id][cache_idx].bitmap); + self->bitmap_items[cache_id][cache_idx].bitmap = bitmap; self->bitmap_items[cache_id][cache_idx].stamp = self->bitmap_stamp; + self->bitmap_items[cache_id][cache_idx].lru_index = lru_index; + + /* add to crc16 list */ + crc16 = bitmap->crc16; + ll = &(self->crc16[cache_id][crc16]); + list16_add_item(ll, cache_idx); + if (ll->count > 1) + { + LLOGLN(10, ("xrdp_cache_add_bitmap: count %d", ll->count)); + } if (self->use_bitmap_comp) { diff --git a/xrdp/xrdp_encoder.c b/xrdp/xrdp_encoder.c new file mode 100644 index 00000000..78d1b52e --- /dev/null +++ b/xrdp/xrdp_encoder.c @@ -0,0 +1,479 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2004-2014 + * + * 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. + * + * Encoder + */ + +#include "xrdp_encoder.h" +#include "xrdp.h" +#include "thread_calls.h" +#include "fifo.h" + +#ifdef XRDP_RFXCODEC +#include "rfxcodec_encode.h" +#endif + +#define LLOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do \ + { \ + if (_level < LLOG_LEVEL) \ + { \ + g_write("xrdp:xrdp_encoder [%10.10u]: ", g_time3()); \ + g_writeln _args ; \ + } \ + } \ + while (0) + +#define JPG_CODEC 0 +#define RFX_CODEC 1 + +/*****************************************************************************/ +static int +process_enc_jpg(struct xrdp_mm *self, XRDP_ENC_DATA *enc); +static int +process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc); + +/** + * Init encoder + * + * @return 0 on success, -1 on failure + *****************************************************************************/ +/* called from main thread */ +int APP_CC +init_xrdp_encoder(struct xrdp_mm *self) +{ + char buf[1024]; + int pid; + + if (self == 0) + { + return -1; + } + + LLOGLN(0, ("init_xrdp_encoder: initing encoder codec_id %d", self->codec_id)); + + /* setup required FIFOs */ + self->fifo_to_proc = fifo_create(); + self->fifo_processed = fifo_create(); + self->mutex = tc_mutex_create(); + + pid = g_getpid(); + /* setup wait objects for signalling */ + g_snprintf(buf, 1024, "xrdp_%8.8x_encoder_event_to_proc", pid); + self->xrdp_encoder_event_to_proc = g_create_wait_obj(buf); + g_snprintf(buf, 1024, "xrdp_%8.8x_encoder_event_processed", pid); + self->xrdp_encoder_event_processed = g_create_wait_obj(buf); + g_snprintf(buf, 1024, "xrdp_%8.8x_encoder_term", pid); + self->xrdp_encoder_term = g_create_wait_obj(buf); + + switch (self->codec_id) + { + case 2: + self->process_enc = process_enc_jpg; + break; + case 3: + self->process_enc = process_enc_rfx; +#ifdef XRDP_RFXCODEC + self->codec_handle = + rfxcodec_encode_create(self->wm->screen->width, + self->wm->screen->height, + RFX_FORMAT_YUV, 0); + //RFX_FORMAT_BGRA, 0); +#endif + break; + default: + LLOGLN(0, ("init_xrdp_encoder: unknown codec_id %d", + self->codec_id)); + break; + + } + + /* create thread to process messages */ + tc_thread_create(proc_enc_msg, self); + + return 0; +} + +/** + * Deinit xrdp encoder + *****************************************************************************/ +/* called from main thread */ +void APP_CC +deinit_xrdp_encoder(struct xrdp_mm *self) +{ + XRDP_ENC_DATA *enc; + XRDP_ENC_DATA_DONE *enc_done; + FIFO *fifo; + + LLOGLN(0, ("deinit_xrdp_encoder: deiniting encoder")); + + if (self == 0) + { + return; + } + + if (self->in_codec_mode == 0) + { + return; + } + /* tell worker thread to shut down */ + g_set_wait_obj(self->xrdp_encoder_term); + g_sleep(1000); + + if (self->codec_id == 3) + { +#ifdef XRDP_RFXCODEC + rfxcodec_encode_destroy(self->codec_handle); +#endif + } + + /* destroy wait objects used for signalling */ + g_delete_wait_obj(self->xrdp_encoder_event_to_proc); + g_delete_wait_obj(self->xrdp_encoder_event_processed); + g_delete_wait_obj(self->xrdp_encoder_term); + + /* cleanup fifo_to_proc */ + fifo = self->fifo_to_proc; + if (fifo) + { + while (!fifo_is_empty(fifo)) + { + enc = fifo_remove_item(fifo); + if (enc == 0) + { + continue; + } + g_free(enc->drects); + g_free(enc->crects); + g_free(enc); + } + + fifo_delete(fifo); + } + + /* cleanup fifo_processed */ + fifo = self->fifo_processed; + if (fifo) + { + while (!fifo_is_empty(fifo)) + { + enc_done = fifo_remove_item(fifo); + if (enc == 0) + { + continue; + } + g_free(enc_done->comp_pad_data); + g_free(enc_done); + } + fifo_delete(fifo); + } +} + +/*****************************************************************************/ +/* called from encoder thread */ +static int +process_enc_jpg(struct xrdp_mm *self, XRDP_ENC_DATA *enc) +{ + int index; + int x; + int y; + int cx; + int cy; + int quality; + int error; + int out_data_bytes; + int count; + char *out_data; + XRDP_ENC_DATA_DONE *enc_done; + FIFO *fifo_processed; + tbus mutex; + tbus event_processed; + + LLOGLN(10, ("process_enc_jpg:")); + quality = self->codec_quality; + fifo_processed = self->fifo_processed; + mutex = self->mutex; + event_processed = self->xrdp_encoder_event_processed; + count = enc->num_crects; + for (index = 0; index < count; index++) + { + x = enc->crects[index * 4 + 0]; + y = enc->crects[index * 4 + 1]; + cx = enc->crects[index * 4 + 2]; + cy = enc->crects[index * 4 + 3]; + if (cx < 1 || cy < 1) + { + LLOGLN(0, ("process_enc_jpg: error 1")); + continue; + } + + LLOGLN(10, ("process_enc_jpg: x %d y %d cx %d cy %d", x, y, cx, cy)); + + out_data_bytes = MAX((cx + 4) * cy * 4, 8192); + if ((out_data_bytes < 1) || (out_data_bytes > 16 * 1024 * 1024)) + { + LLOGLN(0, ("process_enc_jpg: error 2")); + return 1; + } + out_data = (char *) g_malloc(out_data_bytes + 256 + 2, 0); + if (out_data == 0) + { + LLOGLN(0, ("process_enc_jpg: error 3")); + return 1; + } + out_data[256] = 0; /* header bytes */ + out_data[257] = 0; + error = libxrdp_codec_jpeg_compress(self->wm->session, 0, enc->data, + enc->width, enc->height, + enc->width * 4, x, y, cx, cy, + quality, + out_data + 256 + 2, &out_data_bytes); + if (error < 0) + { + LLOGLN(0, ("process_enc_jpg: jpeg error %d bytes %d", + error, out_data_bytes)); + g_free(out_data); + return 1; + } + LLOGLN(10, ("jpeg error %d bytes %d", error, out_data_bytes)); + enc_done = (XRDP_ENC_DATA_DONE *) + g_malloc(sizeof(XRDP_ENC_DATA_DONE), 1); + enc_done->comp_bytes = out_data_bytes + 2; + enc_done->pad_bytes = 256; + enc_done->comp_pad_data = out_data; + enc_done->enc = enc; + enc_done->last = index == (enc->num_crects - 1); + enc_done->x = x; + enc_done->y = y; + enc_done->cx = cx; + enc_done->cy = cy; + /* done with msg */ + /* inform main thread done */ + tc_mutex_lock(mutex); + fifo_add_item(fifo_processed, enc_done); + tc_mutex_unlock(mutex); + /* signal completion for main thread */ + g_set_wait_obj(event_processed); + } + return 0; +} + +#ifdef XRDP_RFXCODEC + +/*****************************************************************************/ +/* called from encoder thread */ +static int +process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc) +{ + int index; + int x; + int y; + int cx; + int cy; + int out_data_bytes; + int count; + int error; + char *out_data; + XRDP_ENC_DATA_DONE *enc_done; + FIFO *fifo_processed; + tbus mutex; + tbus event_processed; + struct rfx_tile *tiles; + struct rfx_rect *rfxrects; + + LLOGLN(10, ("process_enc_rfx:")); + LLOGLN(10, ("process_enc_rfx: num_crects %d num_drects %d", + enc->num_crects, enc->num_drects)); + fifo_processed = self->fifo_processed; + mutex = self->mutex; + event_processed = self->xrdp_encoder_event_processed; + + if ((enc->num_crects > 512) || (enc->num_drects > 512)) + { + return 0; + } + + out_data_bytes = 16 * 1024 * 1024; + index = 256 + sizeof(struct rfx_tile) * 512 + + sizeof(struct rfx_rect) * 512; + out_data = (char *) g_malloc(out_data_bytes + index, 0); + if (out_data == 0) + { + return 0; + } + tiles = (struct rfx_tile *) (out_data + out_data_bytes + 256); + rfxrects = (struct rfx_rect *) (tiles + 512); + + count = enc->num_crects; + for (index = 0; index < count; index++) + { + x = enc->crects[index * 4 + 0]; + y = enc->crects[index * 4 + 1]; + cx = enc->crects[index * 4 + 2]; + cy = enc->crects[index * 4 + 3]; + LLOGLN(10, ("process_enc_rfx:")); + tiles[index].x = x; + tiles[index].y = y; + tiles[index].cx = cx; + tiles[index].cy = cy; + LLOGLN(10, ("x %d y %d cx %d cy %d", x, y, cx, cy)); + tiles[index].quant_y = 0; + tiles[index].quant_cb = 0; + tiles[index].quant_cr = 0; + } + + count = enc->num_drects; + for (index = 0; index < count; index++) + { + x = enc->drects[index * 4 + 0]; + y = enc->drects[index * 4 + 1]; + cx = enc->drects[index * 4 + 2]; + cy = enc->drects[index * 4 + 3]; + LLOGLN(10, ("process_enc_rfx:")); + rfxrects[index].x = x; + rfxrects[index].y = y; + rfxrects[index].cx = cx; + rfxrects[index].cy = cy; + } + + error = rfxcodec_encode(self->codec_handle, out_data + 256, &out_data_bytes, + enc->data, enc->width, enc->height, enc->width * 4, + rfxrects, enc->num_drects, + tiles, enc->num_crects, 0, 0); + LLOGLN(10, ("process_enc_rfx: rfxcodec_encode rv %d", error)); + + enc_done = (XRDP_ENC_DATA_DONE *) + g_malloc(sizeof(XRDP_ENC_DATA_DONE), 1); + enc_done->comp_bytes = out_data_bytes; + enc_done->pad_bytes = 256; + enc_done->comp_pad_data = out_data; + enc_done->enc = enc; + enc_done->last = 1; + enc_done->cx = self->wm->screen->width; + enc_done->cy = self->wm->screen->height; + + /* done with msg */ + /* inform main thread done */ + tc_mutex_lock(mutex); + fifo_add_item(fifo_processed, enc_done); + tc_mutex_unlock(mutex); + /* signal completion for main thread */ + g_set_wait_obj(event_processed); + + return 0; +} + +#else + +/*****************************************************************************/ +/* called from encoder thread */ +static int +process_enc_rfx(struct xrdp_mm *self, XRDP_ENC_DATA *enc) +{ + return 0; +} + +#endif + +/** + * Encoder thread main loop + *****************************************************************************/ +THREAD_RV THREAD_CC +proc_enc_msg(void *arg) +{ + XRDP_ENC_DATA *enc; + FIFO *fifo_to_proc; + tbus mutex; + tbus event_to_proc; + tbus term_obj; + tbus lterm_obj; + int robjs_count; + int wobjs_count; + int cont; + int timeout; + tbus robjs[32]; + tbus wobjs[32]; + struct xrdp_mm *self; + + LLOGLN(0, ("proc_enc_msg: thread is running")); + + self = (struct xrdp_mm *) arg; + if (self == 0) + { + LLOGLN(0, ("proc_enc_msg: self nil")); + return 0; + } + + fifo_to_proc = self->fifo_to_proc; + mutex = self->mutex; + event_to_proc = self->xrdp_encoder_event_to_proc; + + term_obj = g_get_term_event(); + lterm_obj = self->xrdp_encoder_term; + + cont = 1; + while (cont) + { + timeout = -1; + robjs_count = 0; + wobjs_count = 0; + robjs[robjs_count++] = term_obj; + robjs[robjs_count++] = lterm_obj; + robjs[robjs_count++] = event_to_proc; + + if (g_obj_wait(robjs, robjs_count, wobjs, wobjs_count, timeout) != 0) + { + /* error, should not get here */ + g_sleep(100); + } + + if (g_is_wait_obj_set(term_obj)) /* global term */ + { + LLOGLN(0, ("proc_enc_msg: global term")); + break; + } + + if (g_is_wait_obj_set(lterm_obj)) /* xrdp_mm term */ + { + LLOGLN(0, ("proc_enc_msg: xrdp_mm term")); + break; + } + + if (g_is_wait_obj_set(event_to_proc)) + { + /* clear it right away */ + g_reset_wait_obj(event_to_proc); + /* get first msg */ + tc_mutex_lock(mutex); + enc = (XRDP_ENC_DATA *) fifo_remove_item(fifo_to_proc); + tc_mutex_unlock(mutex); + while (enc != 0) + { + /* do work */ + self->process_enc(self, enc); + /* get next msg */ + tc_mutex_lock(mutex); + enc = (XRDP_ENC_DATA *) fifo_remove_item(fifo_to_proc); + tc_mutex_unlock(mutex); + } + } + + } /* end while (cont) */ + LLOGLN(0, ("proc_enc_msg: thread exit")); + return 0; +} diff --git a/xrdp/xrdp_encoder.h b/xrdp/xrdp_encoder.h new file mode 100644 index 00000000..1d525f12 --- /dev/null +++ b/xrdp/xrdp_encoder.h @@ -0,0 +1,16 @@ + +#ifndef _XRDP_ENCODER_H +#define _XRDP_ENCODER_H + +#include "arch.h" + +struct xrdp_mm; + +int APP_CC +init_xrdp_encoder(struct xrdp_mm *self); +void APP_CC +deinit_xrdp_encoder(struct xrdp_mm *self); +THREAD_RV THREAD_CC +proc_enc_msg(void *arg); + +#endif diff --git a/xrdp/xrdp_font.c b/xrdp/xrdp_font.c index 1b7271ee..12c34d7f 100644 --- a/xrdp/xrdp_font.c +++ b/xrdp/xrdp_font.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/xrdp/xrdp_keyboard.ini b/xrdp/xrdp_keyboard.ini new file mode 100644 index 00000000..bd4e4e68 --- /dev/null +++ b/xrdp/xrdp_keyboard.ini @@ -0,0 +1,105 @@ +# +# RDP Keyboard <-> X11 Keyboard layout map +# +# How this file works: +# 1. load the file and scan each section to find matching "keyboard_type" +# and "keyboard_subtype" based on the values received from the client. +# If not found, then jump to default section. +# 2. in the selected section, look for "rdp_layouts" and "layouts_map". +# Based on the "keylayout" value from the client, find the right x11 +# layout value. +# 3. model/variant are inferred based on the "keyboard_type" and +# "keyboard_subtype", but they can be overridden. +# + +# +# RDP Keyboard Type (http://msdn.microsoft.com/en-us/library/cc240563.aspx) +# +# 0 is not a valid value +# +# 1 - IBM PC/XT or compatible (83-key) keyboard +# 2 - Olivetti "ICO" (102-key) keyboard +# 3 - IBM PC/AT (84-key) or similar keyboard +# 4 - IBM enhanced (101- or 102-key) keyboard +# 5 - Nokia 1050 and similar keyboards +# 6 - Nokia 9140 and similar keyboards +# 7 - Japanese keyboard +# +# RDP Keyboard Subtype is vendor dependent. XRDP defines as follows: +# +# 0 is not a valid value +# +# 1 - Standard +# 2 - FreeRDP JP keyboard +# 3 - Macintosh +# ... - < any vendor dependent subtype > +# +# The list can be augmented. +# + + +# default +[default] +# keyboard_type and keyboard_subtype is not readed for default section. It +# is only as a place holder to keep consistency. Default model/variant are +# platform dependent, and could be overridden if needed. +keyboard_type=0 +keyboard_subtype=0 + +# user could override variant and model, but generally they should be inferred +# automatically based on keyboard type and subtype +#variant= +#model= + +# A list of supported RDP keyboard layouts +rdp_layouts=default_rdp_layouts +# The map from RDP keyboard layout to X11 keyboard layout +layouts_map=default_layouts_map + +[default_rdp_layouts] +rdp_layout_us=0x00000409 +rdp_layout_de=0x00000407 +rdp_layout_fr=0x0000040C +rdp_layout_it=0x00000410 +rdp_layout_jp=0x00000411 +rdp_layout_ru=0x00000419 +rdp_layout_se=0x0000041D +rdp_layout_pt=0x00000816 +rdp_layout_br=0x00000416 + +# <rdp layout name> = <X11 keyboard layout value> +[default_layouts_map] +rdp_layout_us=us +rdp_layout_de=de +rdp_layout_fr=fr +rdp_layout_it=it +rdp_layout_jp=jp +rdp_layout_ru=ru +rdp_layout_se=se +rdp_layout_pt=pt +rdp_layout_br=br(abnt2) + +# if two sections have the same keyboard_type and keyboard_subtype, then +# the latter could override the former. +[rdp_keyboard_mac] +keyboard_type=4 +keyboard_subtype=3 +rdp_layouts=default_rdp_layouts +layouts_map=rdp_layouts_map_mac + +[rdp_keyboard_jp] +keyboard_type=7 +keyboard_subtype=2 +rdp_layouts=default_rdp_layouts +layouts_map=default_layouts_map + +[rdp_layouts_map_mac] +rdp_layout_us=us +rdp_layout_de=de +rdp_layout_fr=fr +rdp_layout_jp=jp +rdp_layout_it=it +rdp_layout_ru=ru +rdp_layout_se=se +rdp_layout_pt=pt +rdp_layout_br=br(abnt2) diff --git a/xrdp/xrdp_listen.c b/xrdp/xrdp_listen.c index 5d7edf83..b2b19ca2 100644 --- a/xrdp/xrdp_listen.c +++ b/xrdp/xrdp_listen.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,6 +60,7 @@ xrdp_listen_create(void) g_process_sem = tc_sem_create(0); } + /* setting TCP mode now, may change later */ self->listen_trans = trans_create(TRANS_MODE_TCP, 16, 16); if (self->listen_trans == 0) @@ -168,7 +169,7 @@ xrdp_listen_get_port_address(char *port, int port_bytes, *tcp_nodelay = 0 ; *tcp_keepalive = 0 ; - if (fd > 0) + if (fd != -1) { names = list_create(); names->auto_free = 1; @@ -186,12 +187,18 @@ xrdp_listen_get_port_address(char *port, int port_bytes, if (g_strcasecmp(val, "port") == 0) { val = (char *)list_get_item(values, index); - error = g_atoi(val); - - if ((error > 0) && (error < 65000)) + if (val[0] == '/') { g_strncpy(port, val, port_bytes - 1); } + else + { + error = g_atoi(val); + if ((error > 0) && (error < 65000)) + { + g_strncpy(port, val, port_bytes - 1); + } + } } if (g_strcasecmp(val, "address") == 0) @@ -235,9 +242,11 @@ xrdp_listen_get_port_address(char *port, int port_bytes, list_delete(names); list_delete(values); - g_file_close(fd); } + if (fd != -1) + g_file_close(fd); + /* startup_param overrides */ if (startup_param->port[0] != 0) { @@ -348,7 +357,15 @@ xrdp_listen_main_loop(struct xrdp_listen *self) return 1; } - /*Create socket*/ + if (port[0] == '/') + { + /* set UDS mode */ + self->listen_trans->mode = TRANS_MODE_UNIX; + /* not valid with UDS */ + tcp_nodelay = 0; + } + + /* Create socket */ error = trans_listen_address(self->listen_trans, port, address); if (error == 0) @@ -433,7 +450,7 @@ xrdp_listen_main_loop(struct xrdp_listen *self) robjs[robjs_count++] = done_obj; timeout = -1; - if (self->listen_trans != 0) + /* if (self->listen_trans != 0) */ { if (trans_get_wait_objs(self->listen_trans, robjs, &robjs_count) != 0) diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c index 2e53fca5..357b4e2a 100644 --- a/xrdp/xrdp_login_wnd.c +++ b/xrdp/xrdp_login_wnd.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -242,6 +242,89 @@ xrdp_wm_ok_clicked(struct xrdp_bitmap *wnd) return 0; } +/*****************************************************************************/ +/** +* This is an internal function in this file used to parse the domain +* information sent from the client. If the information starts +* with '_' the domain field contains the IP/DNS to connect to. +* If the domain field contains an additional '__' the char that +* follows this '__' is an index number of a preferred combo choice. +* Valid values for this choice is 0-9. But this function will only return +* index numbers between 0 and the max number of combo items -1. +* Example: _192.168.1.2__1 result in a resultbuffer containing +* 192.168.1.2 and the return value will be 1. Meaning that +* index 1 is the preferred combo choice. +* +* Users can create shortcuts where this information is configured. These +* shortcuts simplifies login. +* @param orginalDomainInfo indata to this function +* @param comboMax the max number of combo choices +* @param decode if true then we perform decoding of combo choice +* @param resultBuffer must be pre allocated before calling this function. +* Holds the IP. The size of this buffer must be 256 bytes +* @return the index number of the combobox that the user prefer. +* 0 if the user does not prefer any choice. +*/ +static int APP_CC +xrdp_wm_parse_domain_information(char *orginalDomainInfo, int comboMax, + int decode, char *resultBuffer) +{ + int ret; + int pos; + int comboxindex; + char index[2]; + char debugstr[256]; + + /* If the first char in the domain name is '_' we use the domain + name as IP*/ + ret = 0; /* default return value */ + /* resultBuffer assumed to be 256 chars */ + g_memset(resultBuffer, 0, 256); + if (orginalDomainInfo[0] == '_') + { + /* we try to locate a number indicating what combobox index the user + * prefer the information is loaded from domain field, from the client + * log_message(LOG_LEVEL_DEBUG, "domain contains _"); + * We must use valid chars in the domain name. + * Underscore is a valid name in the domain. + * Invalid chars are ignored in microsoft client therefore we use '_' + * again. this sec '__' contains the split for index.*/ + pos = g_pos(&orginalDomainInfo[1], "__"); + if (pos > 0) + { + /* an index is found we try to use it + log_message(LOG_LEVEL_DEBUG, "domain contains index char __");*/ + if (decode) + { + g_memset(index, 0, 2); + /* we just accept values 0-9 (one figure) */ + g_strncpy(index, &orginalDomainInfo[pos + 3], 1); + comboxindex = g_htoi(index); + g_snprintf(debugstr, 255, "Value of index (as char): %s " + "(converted) : %d (max) : %d", index, comboxindex, + comboMax - 1); + debugstr[255] = 0; + log_message(LOG_LEVEL_DEBUG, debugstr); + /* limit to max number of items in combo box */ + if ((comboxindex > 0) && (comboxindex < comboMax)) + { + log_message(LOG_LEVEL_DEBUG, "domain contains a valid " + "index number"); + ret = comboxindex; /* preferred index for combo box. */ + } + } + /* pos limit the String to only contain the IP */ + g_strncpy(resultBuffer, &orginalDomainInfo[1], pos); + } + else + { + /* log_message(LOG_LEVEL_DEBUG, "domain does not contain _"); */ + g_strncpy(resultBuffer, &orginalDomainInfo[1], 255); + } + } + return ret; +} + /******************************************************************************/ static int APP_CC xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo) @@ -255,6 +338,7 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo) struct xrdp_mod_data *mod; struct xrdp_bitmap *b; struct xrdp_cfg_globals *globals; + char resultIP[256]; globals = &self->xrdp_config->cfg_globals; @@ -269,7 +353,7 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo) } insert_index = list_index_of(self->login_window->child_list, - (long)combo); + (long)combo); /* find combo in the list */ insert_index++; mod = (struct xrdp_mod_data *) list_get_item(combo->data_list, combo->item_index); @@ -322,19 +406,26 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo) { self->login_window->focused_control = b; } - /*Use the domain name as the destination IP/DNS - This is useful in a gateway setup.*/ - if (g_strncmp(name, "ip", 255) == 0) - { - /* If the first char in the domain name is '_' we use the domain name as IP*/ - if(self->session->client_info->domain[0]=='_') - { - g_strncpy(b->caption1, &self->session->client_info->domain[1], 255); - b->edit_pos = g_mbstowcs(0, b->caption1, 0); - } - - } - if (g_strncmp(name, "username", 255) == 0) + + /* Use the domain name as the destination IP/DNS + This is useful in a gateway setup. */ + if (g_strncmp(name, "ip", 255) == 0) + { + /* If the first char in the domain name is '_' we use the + domain name as IP */ + if (self->session->client_info->domain[0] == '_') + { + xrdp_wm_parse_domain_information( + self->session->client_info->domain, + combo->data_list->count, 0, resultIP); + g_strncpy(b->caption1, resultIP, 255); + b->edit_pos = g_mbstowcs(0, b->caption1, 0); + } + + } + + if (g_strncmp(name, "username", 255) == 0 && + self->session->client_info->username[0]) { g_strncpy(b->caption1, self->session->client_info->username, 255); b->edit_pos = g_mbstowcs(0, b->caption1, 0); @@ -456,9 +547,13 @@ xrdp_wm_login_fill_in_combo(struct xrdp_wm *self, struct xrdp_bitmap *b) g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); fd = g_file_open(cfg_file); /* xrdp.ini */ - if (fd < 1) + if (fd < 0) { log_message(LOG_LEVEL_ERROR, "Could not read xrdp ini file %s", cfg_file); + list_delete(sections); + list_delete(section_names); + list_delete(section_values); + return 1; } file_read_sections(fd, sections); @@ -519,6 +614,7 @@ xrdp_login_wnd_create(struct xrdp_wm *self) char buf[256]; char buf1[256]; + char resultIP[256]; int log_width; int log_height; int regular; @@ -559,12 +655,39 @@ xrdp_login_wnd_create(struct xrdp_wm *self) self->login_window->notify = xrdp_wm_login_notify; - g_gethostname(buf1, 256); - g_sprintf(buf, "Login to %s", buf1); - set_string(&self->login_window->caption1, buf); + /* if window title not specified, use hostname as default */ + if (globals->ls_title[0] == 0) + { + g_gethostname(buf1, 256); + g_sprintf(buf, "Login to %s", buf1); + set_string(&self->login_window->caption1, buf); + } + else + { + /*self->login_window->caption1 = globals->ls_title[0];*/ + g_sprintf(buf, "%s", globals->ls_title); + set_string(&self->login_window->caption1, buf); + } if (regular) { + /* Load the background image. */ + /* If no file is specified no default image will be loaded. */ + /* We only load the image if bpp > 8 */ + if (globals->ls_background_image[0] != 0 && self->screen->bpp > 8) + { + char fileName[256] ; + but = xrdp_bitmap_create(4, 4, self->screen->bpp, WND_TYPE_IMAGE, self); + g_snprintf(fileName, 255, "%s/%s", XRDP_SHARE_PATH, globals->ls_background_image); + log_message(LOG_LEVEL_DEBUG, "We try to load the following background file: %s", fileName); + xrdp_bitmap_load(but, fileName, self->palette); + but->parent = self->screen; + but->owner = self->screen; + but->left = self->screen->width - but->width; + but->top = self->screen->height - but->height; + list_add_item(self->screen->child_list, (long)but); + } + /* if logo image not specified, use default */ if (globals->ls_logo_filename[0] == 0) g_snprintf(globals->ls_logo_filename, 255, "%s/xrdp_logo.bmp", XRDP_SHARE_PATH); @@ -631,7 +754,14 @@ xrdp_login_wnd_create(struct xrdp_wm *self) but->tab_stop = 1; self->login_window->esc_button = but; - /* labels and edits */ + /* labels and edits. + * parameter: 1 = decode domain field index information from client. + * We only perform this the first time for each connection. + */ + combo->item_index = xrdp_wm_parse_domain_information( + self->session->client_info->domain, + combo->data_list->count, 1, + resultIP /* just a dummy place holder, we ignore */ ); xrdp_wm_show_edits(self, combo); return 0; @@ -826,12 +956,22 @@ load_xrdp_config(struct xrdp_config *config, int bpp) else if (g_strncmp(n, "ls_bg_color", 64) == 0) globals->ls_bg_color = HCOLOR(bpp, xrdp_wm_htoi(v)); + else if (g_strncmp(n, "ls_title", 255) == 0) + { + g_strncpy(globals->ls_title, v, 255); + globals->ls_title[255] = 0; + } + else if (g_strncmp(n, "ls_logo_filename", 255) == 0) { g_strncpy(globals->ls_logo_filename, v, 255); globals->ls_logo_filename[255] = 0; } - + else if (g_strncmp(n, "ls_background_image", 255) == 0) + { + g_strncpy(globals->ls_background_image, v, 255); + globals->ls_background_image[255] = 0; + } else if (g_strncmp(n, "ls_logo_x_pos", 64) == 0) globals->ls_logo_x_pos = g_atoi(v); @@ -916,6 +1056,7 @@ load_xrdp_config(struct xrdp_config *config, int bpp) g_writeln("ls_width: %d", globals->ls_width); g_writeln("ls_height: %d", globals->ls_height); g_writeln("ls_bg_color: %x", globals->ls_bg_color); + g_writeln("ls_title: %s", globals->ls_title); g_writeln("ls_logo_filename: %s", globals->ls_logo_filename); g_writeln("ls_logo_x_pos: %d", globals->ls_logo_x_pos); g_writeln("ls_logo_y_pos: %d", globals->ls_logo_y_pos); diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 494d79d3..76957ad6 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,9 @@ * module manager */ +#if defined(HAVE_CONFIG_H) #include <config_ac.h> +#endif #define ACCESS #include "xrdp.h" #include "log.h" @@ -28,6 +30,20 @@ #endif #endif +#include "xrdp_encoder.h" + +#define LLOG_LEVEL 1 +#define LLOGLN(_level, _args) \ + do \ + { \ + if (_level < LLOG_LEVEL) \ + { \ + g_write("xrdp:xrdp_mm [%10.10u]: ", g_time3()); \ + g_writeln _args ; \ + } \ + } \ + while (0) + /*****************************************************************************/ struct xrdp_mm *APP_CC xrdp_mm_create(struct xrdp_wm *owner) @@ -40,6 +56,49 @@ xrdp_mm_create(struct xrdp_wm *owner) self->login_names->auto_free = 1; self->login_values = list_create(); self->login_values->auto_free = 1; + + LLOGLN(0, ("xrdp_mm_create: bpp %d mcs_connection_type %d " + "jpeg_codec_id %d v3_codec_id %d rfx_codec_id %d", + self->wm->client_info->bpp, + self->wm->client_info->mcs_connection_type, + self->wm->client_info->jpeg_codec_id, + self->wm->client_info->v3_codec_id, + self->wm->client_info->rfx_codec_id)); + /* go into jpeg codec mode if jpeg set, lan set */ + if (self->wm->client_info->mcs_connection_type == 6) /* LAN */ + { + if (self->wm->client_info->jpeg_codec_id == 2) /* JPEG */ + { + if (self->wm->client_info->bpp > 16) + { + LLOGLN(0, ("xrdp_mm_create: starting jpeg codec session")); + self->codec_id = 2; + self->in_codec_mode = 1; + self->codec_quality = self->wm->client_info->jpeg_prop[0]; + self->wm->client_info->capture_code = 0; + self->wm->client_info->capture_format = + /* PIXMAN_a8b8g8r8 */ + (32 << 24) | (3 << 16) | (8 << 12) | (8 << 8) | (8 << 4) | 8; + } + } + else if (self->wm->client_info->rfx_codec_id == 3) /* RFX */ + { + if (self->wm->client_info->bpp > 16) + { + LLOGLN(0, ("xrdp_mm_create: starting rfx codec session")); + self->codec_id = 3; + self->in_codec_mode = 1; + self->wm->client_info->capture_code = 2; + } + } + } + + if (self->in_codec_mode) + { + /* setup thread to handle codec mode messages */ + init_xrdp_encoder(self); + } + return self; } @@ -68,7 +127,7 @@ xrdp_mm_sync_load(long param1, long param2) static void APP_CC xrdp_mm_module_cleanup(struct xrdp_mm *self) { - log_message(LOG_LEVEL_DEBUG,"xrdp_mm_module_cleanup"); + log_message(LOG_LEVEL_DEBUG, "xrdp_mm_module_cleanup"); if (self->mod != 0) { @@ -92,6 +151,14 @@ xrdp_mm_module_cleanup(struct xrdp_mm *self) self->mod_exit = 0; self->mod = 0; self->mod_handle = 0; + + if (self->wm->hide_log_window) + { + /* make sure autologin is off */ + self->wm->session->client_info->rdp_autologin = 0; + xrdp_wm_set_login_mode(self->wm, 0); /* reset session */ + } + } /*****************************************************************************/ @@ -105,6 +172,10 @@ xrdp_mm_delete(struct xrdp_mm *self) /* free any module stuff */ xrdp_mm_module_cleanup(self); + + /* shutdown thread */ + deinit_xrdp_encoder(self); + trans_delete(self->sesman_trans); self->sesman_trans = 0; self->sesman_trans_up = 0; @@ -151,7 +222,7 @@ xrdp_mm_send_login(struct xrdp_mm *self) } else if (g_strcasecmp(name, "code") == 0) { - /* this code is either 0 for Xvnc or 10 for X11rdp */ + /* this code is either 0 for Xvnc, 10 for X11rdp or 20 for Xorg */ self->code = g_atoi(value); } else if (g_strcasecmp(name, "xserverbpp") == 0) @@ -168,7 +239,7 @@ xrdp_mm_send_login(struct xrdp_mm *self) s = trans_get_out_s(self->sesman_trans, 8192); s_push_layer(s, channel_hdr, 8); - /* this code is either 0 for Xvnc or 10 for X11rdp */ + /* this code is either 0 for Xvnc, 10 for X11rdp or 20 for Xorg */ out_uint16_be(s, self->code); index = g_strlen(username); out_uint16_be(s, index); @@ -465,7 +536,7 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self) { g_snprintf(text, 255, "%d", 5900 + self->display); } - else if (self->code == 10) /* X11rdp */ + else if (self->code == 10 || self->code == 20) /* X11rdp/Xorg */ { use_uds = 1; @@ -479,7 +550,7 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self) if (use_uds) { - g_snprintf(text, 255, "/tmp/.xrdp/xrdp_display_%d", self->display); + g_snprintf(text, 255, XRDP_X11RDP_STR, self->display); } else { @@ -526,6 +597,10 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self) { rv = 0; /* connect success */ } + else + { + xrdp_wm_show_log(self->wm); + } } if (rv == 0) @@ -1157,9 +1232,9 @@ xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s) self->wm->dragging = 0; /* connect channel redir */ - if ((ip == 0) || (g_strcmp(ip, "127.0.0.1") == 0) || (ip[0] == 0)) + if ((g_strcmp(ip, "127.0.0.1") == 0) || (ip[0] == 0)) { - g_snprintf(port, 255, "/tmp/.xrdp/xrdp_chansrv_socket_%d", 7200 + display); + g_snprintf(port, 255, XRDP_CHANSRV_STR, display); } else { @@ -1176,6 +1251,7 @@ xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s) "login failed"); log_message(LOG_LEVEL_INFO,"xrdp_mm_process_login_response: " "login failed"); + xrdp_wm_show_log(self->wm); } cleanup_sesman_connection(self); @@ -1234,9 +1310,11 @@ xrdp_mm_get_sesman_port(char *port, int port_bytes) list_delete(names); list_delete(values); - g_file_close(fd); } + if (fd != -1) + g_file_close(fd); + return 0; } @@ -1361,7 +1439,7 @@ access_control(char *username, char *password, char *srv) int index; int socket = g_tcp_socket(); - if (socket > 0) + if (socket != -1) { /* we use a blocking socket here */ reply = g_tcp_connect(socket, srv, "3350"); @@ -1454,6 +1532,9 @@ access_control(char *username, char *password, char *srv) log_message(LOG_LEVEL_ERROR, "Failure creating socket - for access control"); } + if (socket != -1) + g_tcp_close(socket); + return rec; } #endif @@ -1473,7 +1554,7 @@ cleanup_states(struct xrdp_mm *self) self-> sesman_trans_up = 0; /* true once connected to sesman */ self-> delete_sesman_trans = 0; /* boolean set when done with sesman connection */ self-> display = 0; /* 10 for :10.0, 11 for :11.0, etc */ - self-> code = 0; /* 0 Xvnc session 10 X11rdp session */ + self-> code = 0; /* 0 Xvnc session, 10 X11rdp session, 20 Xorg session */ self-> sesman_controlled = 0; /* true if this is a sesman session */ self-> chan_trans = NULL; /* connection to chansrv */ self-> chan_trans_up = 0; /* true once connected to chansrv */ @@ -1875,14 +1956,79 @@ xrdp_mm_get_wait_objs(struct xrdp_mm *self, } } + if (self->in_codec_mode) + { + read_objs[(*rcount)++] = self->xrdp_encoder_event_processed; + } + return rv; } +#define DUMP_JPEG 0 + +#if DUMP_JPEG + +/*****************************************************************************/ +static int APP_CC +xrdp_mm_dump_jpeg(struct xrdp_mm *self, XRDP_ENC_DATA_DONE *enc_done) +{ + static tbus ii; + static int jj; + struct _header + { + char tag[4]; + int width; + int height; + int bytes_follow; + } header; + tui16 *pheader_bytes; + int cx; + int cy; + + pheader_bytes = (tui16 *) (enc_done->comp_pad_data + enc_done->pad_bytes); + + cx = enc_done->enc->crects[enc_done->index * 4 + 2]; + cy = enc_done->enc->crects[enc_done->index * 4 + 3]; + + header.tag[0] = 'B'; + header.tag[1] = 'E'; + header.tag[2] = 'E'; + header.tag[3] = 'F'; + header.width = cx; + header.height = cy; + header.bytes_follow = enc_done->comp_bytes - (2 + pheader_bytes[0]); + if (ii == 0) + { + ii = g_file_open("/tmp/jpeg.beef.bin"); + if (ii == -1) + { + ii = 0; + } + } + if (ii != 0) + { + g_file_write(ii, (char*)&header, sizeof(header)); + g_file_write(ii, enc_done->comp_pad_data + + enc_done->pad_bytes + 2 + pheader_bytes[0], + enc_done->comp_bytes - (2 + pheader_bytes[0])); + jj++; + g_writeln("dumping jpeg index %d", jj); + } + return 0; +} + +#endif + /*****************************************************************************/ int APP_CC xrdp_mm_check_wait_objs(struct xrdp_mm *self) { + XRDP_ENC_DATA_DONE *enc_done; int rv; + int x; + int y; + int cx; + int cy; if (self == 0) { @@ -1931,6 +2077,59 @@ xrdp_mm_check_wait_objs(struct xrdp_mm *self) self->delete_chan_trans = 0; } + if (self->in_codec_mode) + { + if (g_is_wait_obj_set(self->xrdp_encoder_event_processed)) + { + g_reset_wait_obj(self->xrdp_encoder_event_processed); + tc_mutex_lock(self->mutex); + enc_done = (XRDP_ENC_DATA_DONE*) + fifo_remove_item(self->fifo_processed); + tc_mutex_unlock(self->mutex); + while (enc_done != 0) + { + /* do something with msg */ + LLOGLN(10, ("xrdp_mm_check_wait_objs: message back bytes %d", + enc_done->comp_bytes)); + + x = enc_done->x; + y = enc_done->y; + cx = enc_done->cx; + cy = enc_done->cy; + +#if DUMP_JPEG + xrdp_mm_dump_jpeg(self, enc_done); +#endif + + if (enc_done->comp_bytes > 0) + { + libxrdp_fastpath_send_surface(self->wm->session, + enc_done->comp_pad_data, + enc_done->pad_bytes, + enc_done->comp_bytes, + x, y, x + cx, y + cy, + 32, self->codec_id, cx, cy); + } + + /* free enc_done */ + if (enc_done->last) + { + LLOGLN(10, ("xrdp_mm_check_wait_objs: last set")); + self->mod->mod_frame_ack(self->mod, + enc_done->enc->flags, enc_done->enc->frame_id); + g_free(enc_done->enc->drects); + g_free(enc_done->enc->crects); + g_free(enc_done->enc); + } + g_free(enc_done->comp_pad_data); + g_free(enc_done); + tc_mutex_lock(self->mutex); + enc_done = (XRDP_ENC_DATA_DONE*) + fifo_remove_item(self->fifo_processed); + tc_mutex_unlock(self->mutex); + } + } + } return rv; } @@ -2140,17 +2339,78 @@ server_composite(struct xrdp_mod* mod, int srcidx, int srcformat, /*****************************************************************************/ int DEFAULT_CC server_paint_rects(struct xrdp_mod* mod, int num_drects, short *drects, - int num_crects, short *crects, - char *data, int width, int height, int flags) + int num_crects, short *crects, char *data, int width, + int height, int flags, int frame_id) { struct xrdp_wm* wm; + struct xrdp_mm* mm; struct xrdp_painter* p; struct xrdp_bitmap *b; short *s; int index; + XRDP_ENC_DATA *enc_data; - //g_writeln("server_paint_rects:"); wm = (struct xrdp_wm*)(mod->wm); + mm = wm->mm; + + LLOGLN(10, ("server_paint_rects:")); + LLOGLN(10, ("server_paint_rects: %d", mm->in_codec_mode)); + + if (mm->in_codec_mode) + { + /* copy formal params to XRDP_ENC_DATA */ + enc_data = (XRDP_ENC_DATA *) g_malloc(sizeof(XRDP_ENC_DATA), 1); + if (enc_data == 0) + { + return 1; + } + + enc_data->drects = (short *) + g_malloc(sizeof(short) * num_drects * 4, 0); + if (enc_data->drects == 0) + { + g_free(enc_data); + return 1; + } + + enc_data->crects = (short *) + g_malloc(sizeof(short) * num_crects * 4, 0); + if (enc_data->crects == 0) + { + g_free(enc_data->drects); + g_free(enc_data); + return 1; + } + + g_memcpy(enc_data->drects, drects, sizeof(short) * num_drects * 4); + g_memcpy(enc_data->crects, crects, sizeof(short) * num_crects * 4); + + enc_data->mod = mod; + enc_data->num_drects = num_drects; + enc_data->num_crects = num_crects; + enc_data->data = data; + enc_data->width = width; + enc_data->height = height; + enc_data->flags = flags; + enc_data->frame_id = frame_id; + if (width == 0 || height == 0) + { + LLOGLN(10, ("server_paint_rects: error")); + } + + /* insert into fifo for encoder thread to process */ + tc_mutex_lock(mm->mutex); + fifo_add_item(mm->fifo_to_proc, (void *) enc_data); + tc_mutex_unlock(mm->mutex); + + /* signal xrdp_encoder thread */ + g_set_wait_obj(mm->xrdp_encoder_event_to_proc); + + return 0; + } + + //g_writeln("server_paint_rects:"); + p = (struct xrdp_painter*)(mod->painter); if (p == 0) { @@ -2164,8 +2424,9 @@ server_paint_rects(struct xrdp_mod* mod, int num_drects, short *drects, xrdp_painter_copy(p, b, wm->target_surface, s[0], s[1], s[2], s[3], s[0], s[1]); s += 4; - } + } xrdp_bitmap_delete(b); + mm->mod->mod_frame_ack(mm->mod, flags, frame_id); return 0; } @@ -2490,10 +2751,11 @@ int read_allowed_channel_names(struct list *names, struct list *values) int ret = 0; char cfg_file[256]; int pos; + g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); fd = g_file_open(cfg_file); - if (fd > 0) + if (fd != -1) { names->auto_free = 1; values->auto_free = 1; @@ -3045,4 +3307,3 @@ server_add_char_alpha(struct xrdp_mod* mod, int font, int charactor, return libxrdp_orders_send_font(((struct xrdp_wm*)mod->wm)->session, &fi, font, charactor); } - diff --git a/xrdp/xrdp_painter.c b/xrdp/xrdp_painter.c index b9d1da16..e47f36ed 100644 --- a/xrdp/xrdp_painter.c +++ b/xrdp/xrdp_painter.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -848,9 +848,14 @@ xrdp_painter_copy(struct xrdp_painter *self, while (i < (srcx + cx)) { w = MIN(64, ((srcx + cx) - i)); - h = MIN(64, ((srcy + cy) - j)); + h = MIN(63, ((srcy + cy) - j)); b = xrdp_bitmap_create(w, h, src->bpp, 0, self->wm); +#if 1 xrdp_bitmap_copy_box_with_crc(src, b, i, j, w, h); +#else + xrdp_bitmap_copy_box(src, b, i, j, w, h); + xrdp_bitmap_hash_crc(b); +#endif bitmap_id = xrdp_cache_add_bitmap(self->wm->cache, b, self->wm->hints); cache_id = HIWORD(bitmap_id); cache_idx = LOWORD(bitmap_id); @@ -878,7 +883,7 @@ xrdp_painter_copy(struct xrdp_painter *self, i += 64; } - j += 64; + j += 63; } xrdp_region_delete(region); @@ -913,19 +918,19 @@ xrdp_painter_composite(struct xrdp_painter* self, int palette_id; int cache_srcidx; int cache_mskidx; - + if (self == 0 || src == 0 || dst == 0) { return 0; } - + /* todo data */ - + if (dst->type == WND_TYPE_BITMAP) { return 0; } - + if (src->type == WND_TYPE_OFFSCREEN) { xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy); @@ -933,7 +938,7 @@ xrdp_painter_composite(struct xrdp_painter* self, xrdp_region_add_rect(region, &clip_rect); dstx += dx; dsty += dy; - + palette_id = 0; cache_srcidx = src->item_index; cache_mskidx = -1; @@ -944,7 +949,7 @@ xrdp_painter_composite(struct xrdp_painter* self, cache_mskidx = msk->item_index; // todo } } - + k = 0; while (xrdp_region_get_rect(region, k, &rect1) == 0) { diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c index 78576f1f..5a7cd1d8 100644 --- a/xrdp/xrdp_process.c +++ b/xrdp/xrdp_process.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -70,15 +70,15 @@ xrdp_process_loop(struct xrdp_process *self, struct stream *s) if (self->session != 0) { rv = libxrdp_process_data(self->session, s); - } - if ((self->wm == 0) && (self->session->up_and_running) && (rv == 0)) - { - DEBUG(("calling xrdp_wm_init and creating wm")); - self->wm = xrdp_wm_create(self, self->session->client_info); - /* at this point the wm(window manager) is create and wm::login_mode is - zero and login_mode_event is set so xrdp_wm_init should be called by - xrdp_wm_check_wait_objs */ + if ((self->wm == 0) && (self->session->up_and_running) && (rv == 0)) + { + DEBUG(("calling xrdp_wm_init and creating wm")); + self->wm = xrdp_wm_create(self, self->session->client_info); + /* at this point the wm(window manager) is create and wm::login_mode is + zero and login_mode_event is set so xrdp_wm_init should be called by + xrdp_wm_check_wait_objs */ + } } return rv; @@ -115,62 +115,6 @@ xrdp_process_mod_end(struct xrdp_process *self) } /*****************************************************************************/ -static int APP_CC -xrdp_process_get_pdu_bytes(const char *aheader) -{ - int rv; - const tui8 *header; - - rv = -1; - header = (const tui8 *) aheader; - if (header[0] == 0x03) - { - /* TPKT */ - rv = (header[2] << 8) | header[3]; - } - else if (header[0] == 0x30) - { - /* TSRequest (NLA) */ - if (header[1] & 0x80) - { - if ((header[1] & ~(0x80)) == 1) - { - rv = header[2]; - rv += 3; - } - else if ((header[1] & ~(0x80)) == 2) - { - rv = (header[2] << 8) | header[3]; - rv += 4; - } - else - { - g_writeln("xrdp_process_get_packet_bytes: error TSRequest!"); - return -1; - } - } - else - { - rv = header[1]; - rv += 2; - } - } - else - { - /* Fast-Path */ - if (header[1] & 0x80) - { - rv = ((header[1] & 0x7F) << 8) | header[2]; - } - else - { - rv = header[1]; - } - } - return rv; -} - -/*****************************************************************************/ static int DEFAULT_CC xrdp_process_data_in(struct trans *self) { @@ -196,12 +140,13 @@ xrdp_process_data_in(struct trans *self) { pro->server_trans->extra_flags = 1; pro->server_trans->header_size = 4; + init_stream(s, 0); } break; case 1: /* we have enough now to get the PDU bytes */ - len = xrdp_process_get_pdu_bytes(s->p); + len = libxrdp_get_pdu_bytes(s->p); if (len == -1) { g_writeln("xrdp_process_data_in: " @@ -226,7 +171,6 @@ xrdp_process_data_in(struct trans *self) pro->server_trans->extra_flags = 1; break; } - return 0; } @@ -258,6 +202,8 @@ xrdp_process_main_loop(struct xrdp_process *self) if (libxrdp_process_incomming(self->session) == 0) { + init_stream(self->server_trans->in_s, 32 * 1024); + term_obj = g_get_term_event(); cont = 1; diff --git a/xrdp/xrdp_region.c b/xrdp/xrdp_region.c index c66994f7..c9b6a820 100644 --- a/xrdp/xrdp_region.c +++ b/xrdp/xrdp_region.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 7d7eb72c..89a7ce93 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ #include "xrdp_rail.h" #include "xrdp_constants.h" +#include "fifo.h" #define MAX_NR_CHANNELS 16 #define MAX_CHANNEL_NAME 16 @@ -46,7 +47,8 @@ struct xrdp_mod int (*mod_get_wait_objs)(struct xrdp_mod* v, tbus* read_objs, int* rcount, tbus* write_objs, int* wcount, int* timeout); int (*mod_check_wait_objs)(struct xrdp_mod* v); - long mod_dumby[100 - 9]; /* align, 100 minus the number of mod + int (*mod_frame_ack)(struct xrdp_mod* v, int flags, int frame_id); + long mod_dumby[100 - 10]; /* align, 100 minus the number of mod functions above */ /* server functions */ int (*server_begin_update)(struct xrdp_mod* v); @@ -142,7 +144,8 @@ struct xrdp_mod int (*server_paint_rects)(struct xrdp_mod* v, int num_drects, short *drects, int num_crects, short *crects, - char *data, int width, int height, int flags); + char *data, int width, int height, + int flags, int frame_id); long server_dumby[100 - 43]; /* align, 100 minus the number of server functions above */ /* common */ @@ -177,9 +180,16 @@ struct xrdp_palette_item struct xrdp_bitmap_item { int stamp; + int lru_index; struct xrdp_bitmap* bitmap; }; +struct xrdp_lru_item +{ + int next; + int prev; +}; + struct xrdp_os_bitmap_item { int id; @@ -225,6 +235,17 @@ struct xrdp_cache int bitmap_stamp; struct xrdp_bitmap_item bitmap_items[XRDP_MAX_BITMAP_CACHE_ID] [XRDP_MAX_BITMAP_CACHE_IDX]; + + /* lru optimize */ + struct xrdp_lru_item bitmap_lrus[XRDP_MAX_BITMAP_CACHE_ID] + [XRDP_MAX_BITMAP_CACHE_IDX]; + int lru_head[XRDP_MAX_BITMAP_CACHE_ID]; + int lru_tail[XRDP_MAX_BITMAP_CACHE_ID]; + int lru_reset[XRDP_MAX_BITMAP_CACHE_ID]; + + /* crc optimize */ + struct list16 crc16[XRDP_MAX_BITMAP_CACHE_ID][64 * 1024]; + int use_bitmap_comp; int cache1_entries; int cache1_size; @@ -247,6 +268,9 @@ struct xrdp_cache struct list* xrdp_os_del_list; }; +/* defined later */ +struct xrdp_enc_data; + struct xrdp_mm { struct xrdp_wm* wm; /* owner */ @@ -262,12 +286,25 @@ struct xrdp_mm int (*mod_exit)(struct xrdp_mod*); struct xrdp_mod* mod; /* module interface */ int display; /* 10 for :10.0, 11 for :11.0, etc */ - int code; /* 0 Xvnc session 10 X11rdp session */ + int code; /* 0=Xvnc session, 10=X11rdp session, 20=xorg driver mode */ int sesman_controlled; /* true if this is a sesman session */ struct trans* chan_trans; /* connection to chansrv */ int chan_trans_up; /* true once connected to chansrv */ int delete_chan_trans; /* boolean set when done with channel connection */ int usechansrv; /* true if chansrvport is set in xrdp.ini or using sesman */ + + /* for codec mode operations */ + int in_codec_mode; + int codec_id; + int codec_quality; + tbus xrdp_encoder_event_to_proc; + tbus xrdp_encoder_event_processed; + tbus xrdp_encoder_term; + FIFO *fifo_to_proc; + FIFO *fifo_processed; + tbus mutex; + int (*process_enc)(struct xrdp_mm *self, struct xrdp_enc_data *enc); + void *codec_handle; }; struct xrdp_key_info @@ -453,7 +490,8 @@ struct xrdp_bitmap struct xrdp_bitmap* popped_from; int item_height; /* crc */ - int crc; + int crc32; + int crc16; }; #define NUM_FONTS 0x4e00 @@ -547,6 +585,7 @@ struct xrdp_cfg_globals int ls_height; /* window height */ int ls_bg_color; /* background color */ char ls_logo_filename[256]; /* logo filename */ + char ls_background_image[256]; /* background image file name */ int ls_logo_x_pos; /* logo x co-ordinate */ int ls_logo_y_pos; /* logo y co-ordinate */ int ls_label_x_pos; /* x pos of labels */ @@ -562,6 +601,7 @@ struct xrdp_cfg_globals int ls_btn_cancel_y_pos; /* y pos for Cancel button */ int ls_btn_cancel_width; /* width of Cancel button */ int ls_btn_cancel_height; /* height of Cancel button */ + char ls_title[256]; /* loginscreen window title */ }; struct xrdp_cfg_logging @@ -581,4 +621,39 @@ struct xrdp_config struct xrdp_cfg_channels cfg_channels; }; +/* used when scheduling tasks in xrdp_encoder.c */ +struct xrdp_enc_data +{ + struct xrdp_mod *mod; + int num_drects; + short *drects; /* 4 * num_drects */ + int num_crects; + short *crects; /* 4 * num_crects */ + char *data; + int width; + int height; + int flags; + int frame_id; +}; + +typedef struct xrdp_enc_data XRDP_ENC_DATA; + +/* used when scheduling tasks from xrdp_encoder.c */ +struct xrdp_enc_data_done +{ + int comp_bytes; + int pad_bytes; + char *comp_pad_data; + struct xrdp_enc_data *enc; + int last; /* true is this is last message for enc */ + int x; + int y; + int cx; + int cy; +}; + +typedef struct xrdp_enc_data_done XRDP_ENC_DATA_DONE; + + + #endif diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c index ffc6d3a2..591c8a51 100644 --- a/xrdp/xrdp_wm.c +++ b/xrdp/xrdp_wm.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -236,10 +236,11 @@ xrdp_wm_load_pointer(struct xrdp_wm *self, char *file_name, char *data, init_stream(fs, 8192); fd = g_file_open(file_name); - if (fd < 1) + if (fd < 0) { log_message(LOG_LEVEL_ERROR,"xrdp_wm_load_pointer: error loading pointer from file [%s]", file_name); + xstream_free(fs); return 1; } @@ -259,8 +260,11 @@ xrdp_wm_load_pointer(struct xrdp_wm *self, char *file_name, char *data, { if (bpp == 1) { - in_uint8a(fs, palette, 8); - + for (i = 0; i < 2; i++) + { + in_uint32_le(fs, pixel); + palette[i] = pixel; + } for (i = 0; i < 32; i++) { for (j = 0; j < 32; j++) @@ -279,8 +283,11 @@ xrdp_wm_load_pointer(struct xrdp_wm *self, char *file_name, char *data, } else if (bpp == 4) { - in_uint8a(fs, palette, 64); - + for (i = 0; i < 16; i++) + { + in_uint32_le(fs, pixel); + palette[i] = pixel; + } for (i = 0; i < 32; i++) { for (j = 0; j < 32; j++) @@ -540,17 +547,20 @@ xrdp_wm_init(struct xrdp_wm *self) struct list *values; char *q; char *r; + char param[256]; char section_name[256]; char cfg_file[256]; char autorun_name[256]; + g_writeln("in xrdp_wm_init: "); + load_xrdp_config(self->xrdp_config, self->screen->bpp); xrdp_wm_load_static_colors_plus(self, autorun_name); xrdp_wm_load_static_pointers(self); self->screen->bg_color = self->xrdp_config->cfg_globals.ls_top_window_bg_color; - if (self->session->client_info->rdp_autologin || (autorun_name[0] != 0)) + if (self->session->client_info->rdp_autologin) { /* * NOTE: this should eventually be accessed from self->xrdp_config @@ -558,51 +568,52 @@ xrdp_wm_init(struct xrdp_wm *self) g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH); fd = g_file_open(cfg_file); /* xrdp.ini */ - - if (fd > 0) + if (fd != -1) { names = list_create(); names->auto_free = 1; values = list_create(); values->auto_free = 1; - /* domain names that starts with '_' are reserved for IP/DNS to - * simplify for the user in a gateway setup */ - if (self->session->client_info->domain[0] != '_') + + /* look for module name to be loaded */ + if (autorun_name[0] != 0) { + /* if autorun is configured in xrdp.ini, we enforce that module to be loaded */ + g_strncpy(section_name, autorun_name, 255); + } + else if (self->session->client_info->domain[0] != '_') { + /* domain names that starts with '_' are reserved for IP/DNS to + * simplify for the user in a proxy setup */ + + /* we use the domain name as the module name to be loaded */ g_strncpy(section_name, self->session->client_info->domain, - 255); + 255); } - if (section_name[0] == 0) + else { - if (autorun_name[0] == 0) + /* if no domain is passed, and no autorun in xrdp.ini, + use the first item in the xrdp.ini + file thats not named + 'globals' or 'Logging' or 'channels' */ + /* TODO: change this and have a 'autologin' + line in globals section */ + file_read_sections(fd, names); + for (index = 0; index < names->count; index++) { - /* if no domain is passed, and no autorun in xrdp.ini, - use the first item in the xrdp.ini - file thats not named - 'globals' or 'Logging' or 'channels' */ - /* TODO: change this and have a 'autologin' - line in globals section */ - file_read_sections(fd, names); - for (index = 0; index < names->count; index++) + q = (char *)list_get_item(names, index); + if ((g_strncasecmp("globals", q, 8) != 0) && + (g_strncasecmp("Logging", q, 8) != 0) && + (g_strncasecmp("channels", q, 9) != 0)) { - q = (char *)list_get_item(names, index); - if ((g_strncasecmp("globals", q, 8) != 0) && - (g_strncasecmp("Logging", q, 8) != 0) && - (g_strncasecmp("channels", q, 9) != 0)) - { - g_strncpy(section_name, q, 255); - break; - } + g_strncpy(section_name, q, 255); + break; } } - else - { - g_strncpy(section_name, autorun_name, 255); - } } list_clear(names); + /* look for the required module in xrdp.ini, fetch its parameters */ if (file_read_section(fd, section_name, names, values) == 0) { for (index = 0; index < names->count; index++) @@ -632,6 +643,29 @@ xrdp_wm_init(struct xrdp_wm *self) r = self->session->client_info->username; } } + else if (g_strncmp("ip", q, 255) == 0) + { + /* if the ip has been asked for by the module, use what the + client says (target ip should be in 'domain' field, when starting with "_") + if the ip has been manually set in the config, use that + instead of what the client says. */ + if (g_strncmp("ask", r, 3) == 0) + { + if (self->session->client_info->domain[0] == '_') + { + g_strncpy(param, &self->session->client_info->domain[1], 255); + r = param; + } + + } + } + else if (g_strncmp("port", q, 255) == 0) + { + if (g_strncmp("ask3389", r, 7) == 0) + { + r = "3389"; /* use default */ + } + } list_add_item(self->mm->login_names, (long)g_strdup(q)); list_add_item(self->mm->login_values, (long)g_strdup(r)); @@ -639,6 +673,13 @@ xrdp_wm_init(struct xrdp_wm *self) xrdp_wm_set_login_mode(self, 2); } + else + { + /* requested module name not found in xrdp.ini */ + g_writeln(" xrdp_wm_init: file_read_section returned non-zero, requested section not found in xrdp.ini"); + xrdp_wm_log_msg(self, "ERROR: The requested xrdp module not found in xrdp.ini," + " falling back to login window"); + } list_delete(names); list_delete(values); @@ -651,6 +692,7 @@ xrdp_wm_init(struct xrdp_wm *self) } else { + g_writeln(" xrdp_wm_init: no autologin / auto run detected, draw login window"); xrdp_login_wnd_create(self); /* clear screen */ xrdp_bitmap_invalidate(self->screen, 0); @@ -658,6 +700,7 @@ xrdp_wm_init(struct xrdp_wm *self) xrdp_wm_set_login_mode(self, 1); } + g_writeln("out xrdp_wm_init: "); return 0; } @@ -1706,6 +1749,8 @@ xrdp_wm_login_mode_changed(struct xrdp_wm *self) return 0; } + g_writeln("xrdp_wm_login_mode_changed: login_mode is %d", self->login_mode); + if (self->login_mode == 0) { /* this is the inital state of the login window */ @@ -1825,7 +1870,7 @@ void add_string_to_logwindow(char *msg, struct list *log) /*****************************************************************************/ int APP_CC -xrdp_wm_log_msg(struct xrdp_wm *self, char *msg) +xrdp_wm_show_log(struct xrdp_wm *self) { struct xrdp_bitmap *but; int w; @@ -1835,11 +1880,12 @@ xrdp_wm_log_msg(struct xrdp_wm *self, char *msg) if (self->hide_log_window) { + /* make sure autologin is off */ + self->session->client_info->rdp_autologin = 0; + xrdp_wm_set_login_mode(self, 0); /* reset session */ return 0; } - add_string_to_logwindow(msg, self->log); - if (self->log_wnd == 0) { w = DEFAULT_WND_LOG_W; @@ -1886,7 +1932,15 @@ xrdp_wm_log_msg(struct xrdp_wm *self, char *msg) xrdp_wm_set_focused(self, self->log_wnd); xrdp_bitmap_invalidate(self->log_wnd, 0); - g_sleep(100); + + return 0; +} + +/*****************************************************************************/ +int APP_CC +xrdp_wm_log_msg(struct xrdp_wm *self, char *msg) +{ + add_string_to_logwindow(msg, self->log); return 0; } diff --git a/xrdp/xrdpwin.c b/xrdp/xrdpwin.c index da9ba9e0..ee78273b 100644 --- a/xrdp/xrdpwin.c +++ b/xrdp/xrdpwin.c @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/xrdpapi/xrdpapi.c b/xrdpapi/xrdpapi.c index 4cf8db71..7e9eaa0c 100644 --- a/xrdpapi/xrdpapi.c +++ b/xrdpapi/xrdpapi.c @@ -41,7 +41,7 @@ struct wts_obj { int fd; int status; - char name[8]; + char name[9]; char dname[128]; int display_num; uint32_t flags; @@ -124,12 +124,19 @@ WTSVirtualChannelOpenEx(unsigned int SessionId, const char *pVirtualName, } /* we use unix domain socket to communicate with chansrv */ - wts->fd = socket(AF_UNIX, SOCK_STREAM, 0); + if ((wts->fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + { + g_free(wts); + return NULL; + } /* set non blocking */ llong = fcntl(wts->fd, F_GETFL); llong = llong | O_NONBLOCK; - fcntl(wts->fd, F_SETFL, llong); + if (fcntl(wts->fd, F_SETFL, llong) < 0) + { + LLOGLN(10, ("WTSVirtualChannelOpenEx: set non-block mode failed")); + } /* connect to chansrv session */ memset(&s, 0, sizeof(struct sockaddr_un)); @@ -236,11 +243,13 @@ WTSVirtualChannelWrite(void *hChannelHandle, const char *Buffer, return 0; } +#if 0 /* coverity: this is dead code */ /* error, but is it ok to try again? */ if ((rv == EWOULDBLOCK) || (rv == EAGAIN) || (rv == EINPROGRESS)) { return 0; /* failed to send, but should try again */ } +#endif /* fatal error */ return -1; @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -175,18 +175,14 @@ lib_mod_connect(struct mod *mod) char con_port[256]; LIB_DEBUG(mod, "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); + mod->server_msg(mod, "started connecting", 0); - /* only support 8, 15, 16, and 24 bpp connections from rdp client */ - if (mod->bpp != 8 && mod->bpp != 15 && mod->bpp != 16 && mod->bpp != 24) + /* only support 8, 15, 16, 24, and 32 bpp connections from rdp client */ + if (mod->bpp != 8 && mod->bpp != 15 && mod->bpp != 16 && mod->bpp != 24 && mod->bpp != 32) { mod->server_msg(mod, - "error - only supporting 8, 15, 16, and 24 bpp rdp connections", 0); + "error - only supporting 8, 15, 16, 24, and 32 bpp rdp connections", 0); LIB_DEBUG(mod, "out lib_mod_connect error"); return 1; } @@ -207,6 +203,7 @@ lib_mod_connect(struct mod *mod) use_uds = 1; } + error = 0; mod->sck_closed = 0; i = 0; @@ -215,10 +212,21 @@ lib_mod_connect(struct mod *mod) if (use_uds) { mod->sck = g_tcp_local_socket(); + if (mod->sck < 0) + { + free_stream(s); + return 1; + } } else { mod->sck = g_tcp_socket(); + if (mod->sck < 0) + { + free_stream(s); + return 1; + } + g_tcp_set_non_blocking(mod->sck); g_tcp_set_no_delay(mod->sck); } @@ -1121,13 +1129,22 @@ process_server_paint_rect_shmem(struct mod *mod, struct stream *s) in_uint16_le(s, height); in_sint16_le(s, srcx); in_sint16_le(s, srcy); + bmpdata = 0; + rv = 0; + if (flags == 0) /* screen */ { if (mod->screen_shmem_id == 0) { mod->screen_shmem_id = shmem_id; mod->screen_shmem_pixels = g_shmat(mod->screen_shmem_id); + if (mod->screen_shmem_pixels == (void*)-1) + { + /* failed */ + mod->screen_shmem_id = 0; + mod->screen_shmem_pixels = 0; + } } if (mod->screen_shmem_pixels != 0) { @@ -1140,10 +1157,6 @@ process_server_paint_rect_shmem(struct mod *mod, struct stream *s) bmpdata, width, height, srcx, srcy); } - else - { - rv = 1; - } send_paint_rect_ack(mod, flags, x, y, cx, cy, frame_id); return rv; } @@ -1248,14 +1261,16 @@ process_server_paint_rect_shmem_ex(struct mod *amod, struct stream *s) rv = amod->server_paint_rects(amod, num_drects, ldrects, num_crects, lcrects, - bmpdata, width, height, 0); + bmpdata, width, height, + flags, frame_id); } else { rv = 1; } - send_paint_rect_ex_ack(amod, flags, frame_id); + //g_writeln("frame_id %d", frame_id); + //send_paint_rect_ex_ack(amod, flags, frame_id); g_free(lcrects); g_free(ldrects); @@ -1379,6 +1394,7 @@ lib_send_client_info(struct mod *mod) struct stream *s; int len; + g_writeln("lib_send_client_info:"); make_stream(s); init_stream(s, 8192); s_push_layer(s, iso_hdr, 4); @@ -1587,6 +1603,16 @@ lib_mod_check_wait_objs(struct mod *mod) } /******************************************************************************/ +/* return error */ +int DEFAULT_CC +lib_mod_frame_ack(struct mod *amod, int flags, int frame_id) +{ + LLOGLN(10, ("lib_mod_frame_ack: flags 0x%8.8x frame_id %d", flags, frame_id)); + send_paint_rect_ex_ack(amod, flags, frame_id); + return 0; +} + +/******************************************************************************/ struct mod *EXPORT_CC mod_init(void) { @@ -1604,6 +1630,7 @@ mod_init(void) 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->mod_frame_ack = lib_mod_frame_ack; return mod; } @@ -1,7 +1,7 @@ /** * xrdp: A Remote Desktop Protocol server. * - * Copyright (C) Jay Sorg 2004-2013 + * Copyright (C) Jay Sorg 2004-2014 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,7 +44,8 @@ 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); - tbus mod_dumby[100 - 9]; /* align, 100 minus the number of mod + int (*mod_frame_ack)(struct mod* v, int flags, int frame_id); + tbus mod_dumby[100 - 10]; /* align, 100 minus the number of mod functions above */ /* server functions */ int (*server_begin_update)(struct mod* v); @@ -136,7 +137,8 @@ struct mod int (*server_paint_rects)(struct mod* v, int num_drects, short *drects, int num_crects, short *crects, - char *data, int width, int height, int flags); + char *data, int width, int height, + int flags, int frame_id); tbus server_dumby[100 - 43]; /* align, 100 minus the number of server functions above */ |