Merge branch 'devel' of github.com:NeutrinoLabs/xrdp into devel

ulab-next-nosound
Laxmikant Rashinkar 10 years ago
commit 59bba82f67

@ -23,7 +23,6 @@
#include "arch.h" #include "arch.h"
#include "parse.h" #include "parse.h"
#include <openssl/ssl.h>
#define TRANS_MODE_TCP 1 #define TRANS_MODE_TCP 1
#define TRANS_MODE_UNIX 2 #define TRANS_MODE_UNIX 2
@ -72,8 +71,8 @@ struct trans
/* xrdp_tls */ /* xrdp_tls */
struct xrdp_tls struct xrdp_tls
{ {
SSL *ssl; void *ssl; /* SSL * */
SSL_CTX *ctx; void *ctx; /* SSL_CTX * */
char *cert; char *cert;
char *key; char *key;
struct trans *trans; struct trans *trans;

@ -128,6 +128,11 @@ struct xrdp_client_info
char certificate[1024]; char certificate[1024];
char key_file[1024]; char key_file[1024];
/* X11 keyboard layout - inferred from keyboard type/subtype */
char model[16];
char layout[16];
char variant[16];
}; };
#endif #endif

@ -18,9 +18,17 @@
* transport layer security * transport layer security
*/ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/ssl.h>
#include "os_calls.h"
#include "trans.h" #include "trans.h"
#include "ssl_calls.h" #include "ssl_calls.h"
/*****************************************************************************/ /*****************************************************************************/
struct xrdp_tls * struct xrdp_tls *
APP_CC APP_CC
@ -38,6 +46,41 @@ xrdp_tls_create(struct trans *trans, const char *key, const char *cert)
return self; 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 int APP_CC
xrdp_tls_accept(struct xrdp_tls *self) xrdp_tls_accept(struct xrdp_tls *self)
@ -53,6 +96,7 @@ xrdp_tls_accept(struct xrdp_tls *self)
*/ */
options |= SSL_OP_NO_SSLv2; options |= SSL_OP_NO_SSLv2;
#if defined(SSL_OP_NO_COMPRESSION)
/** /**
* SSL_OP_NO_COMPRESSION: * SSL_OP_NO_COMPRESSION:
* *
@ -63,6 +107,7 @@ xrdp_tls_accept(struct xrdp_tls *self)
* which is why we're disabling it. * which is why we're disabling it.
*/ */
options |= SSL_OP_NO_COMPRESSION; options |= SSL_OP_NO_COMPRESSION;
#endif
/** /**
* SSL_OP_TLS_BLOCK_PADDING_BUG: * SSL_OP_TLS_BLOCK_PADDING_BUG:
@ -137,40 +182,6 @@ xrdp_tls_accept(struct xrdp_tls *self)
} }
/*****************************************************************************/ /*****************************************************************************/
int APP_CC 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_disconnect(struct xrdp_tls *self) xrdp_tls_disconnect(struct xrdp_tls *self)
{ {
int status = SSL_shutdown(self->ssl); int status = SSL_shutdown(self->ssl);
@ -205,7 +216,7 @@ xrdp_tls_delete(struct xrdp_tls *self)
} }
/*****************************************************************************/ /*****************************************************************************/
int APP_CC int APP_CC
xrdp_tls_read(struct xrdp_tls *tls, unsigned char *data, int length) xrdp_tls_read(struct xrdp_tls *tls, char *data, int length)
{ {
int status; int status;
@ -231,7 +242,7 @@ xrdp_tls_read(struct xrdp_tls *tls, unsigned char *data, int length)
} }
/*****************************************************************************/ /*****************************************************************************/
int APP_CC int APP_CC
xrdp_tls_write(struct xrdp_tls *tls, unsigned char *data, int length) xrdp_tls_write(struct xrdp_tls *tls, char *data, int length)
{ {
int status; int status;
@ -317,6 +328,58 @@ xrdp_tls_force_read_s(struct trans *self, struct stream *in_s, int size)
return 0; return 0;
} }
/*****************************************************************************/
int APP_CC
xrdp_tls_send_waiting(struct trans *self, int block)
{
struct stream *temp_s;
int bytes;
int sent;
int timeout;
int cont;
timeout = block ? 100 : 0;
cont = 1;
while (cont)
{
if (self->wait_s != 0)
{
temp_s = self->wait_s;
if (g_tcp_can_send(self->sck, timeout))
{
bytes = (int) (temp_s->end - temp_s->p);
sent = xrdp_tls_write(self->tls, temp_s->p, bytes);
if (sent > 0)
{
temp_s->p += sent;
if (temp_s->p >= temp_s->end)
{
self->wait_s = (struct stream *) (temp_s->next_packet);
free_stream(temp_s);
}
}
else if (sent == 0)
{
return 1;
}
else
{
if (!g_tcp_last_error_would_block(self->sck))
{
return 1;
}
}
}
}
else
{
break;
}
cont = block;
}
return 0;
}
/*****************************************************************************/ /*****************************************************************************/
int APP_CC int APP_CC
xrdp_tls_force_write_s(struct trans *self, struct stream *out_s) xrdp_tls_force_write_s(struct trans *self, struct stream *out_s)
@ -382,54 +445,4 @@ xrdp_tls_force_write_s(struct trans *self, struct stream *out_s)
return 0; return 0;
} }
/*****************************************************************************/
int APP_CC
xrdp_tls_send_waiting(struct trans *self, int block)
{
struct stream *temp_s;
int bytes;
int sent;
int timeout;
int cont;
timeout = block ? 100 : 0;
cont = 1;
while (cont)
{
if (self->wait_s != 0)
{
temp_s = self->wait_s;
if (g_tcp_can_send(self->sck, timeout))
{
bytes = (int) (temp_s->end - temp_s->p);
sent = xrdp_tls_write(self->tls, temp_s->p, bytes);
if (sent > 0)
{
temp_s->p += sent;
if (temp_s->p >= temp_s->end)
{
self->wait_s = (struct stream *) (temp_s->next_packet);
free_stream(temp_s);
}
}
else if (sent == 0)
{
return 1;
}
else
{
if (!g_tcp_last_error_would_block(self->sck))
{
return 1;
}
}
}
}
else
{
break;
}
cont = block;
}
return 0;
}

@ -220,6 +220,210 @@ hex_str_to_bin(char *in, char *out, int out_len)
} }
} }
/*****************************************************************************/
static void APP_CC
xrdp_load_keyboard_layout(struct xrdp_client_info *client_info)
{
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;
file_read_section(fd, q, items, values);
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;
}
}
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);
}
/* 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;
}
}
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
{
LLOGLN(0, ("xrdp_load_keyboard_layout: error opening %d",
keyboard_cfg_file));
}
}
/*****************************************************************************/ /*****************************************************************************/
struct xrdp_sec *APP_CC struct xrdp_sec *APP_CC
xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans) xrdp_sec_create(struct xrdp_rdp *owner, struct trans *trans)
@ -1853,6 +2057,7 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self)
in_uint8s(s, 79); in_uint8s(s, 79);
in_uint32_le(s, client_info->keyboard_type); in_uint32_le(s, client_info->keyboard_type);
in_uint32_le(s, client_info->keyboard_subtype); in_uint32_le(s, client_info->keyboard_subtype);
xrdp_load_keyboard_layout(client_info);
s->p = s->data; s->p = s->data;
return 0; return 0;
} }

@ -508,7 +508,7 @@ KbdAddEvent(int down, int param1, int param2, int param3, int param4);
void void
KbdSync(int param1); KbdSync(int param1);
int int
rdpLoadLayout(int keylayout); rdpLoadLayout(struct xrdp_client_info *client_info);
/* rdpup.c */ /* rdpup.c */
int int

@ -282,7 +282,7 @@ rdpChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
/******************************************************************************/ /******************************************************************************/
int int
rdpLoadLayout(int keylayout) rdpLoadLayout(struct xrdp_client_info *client_info)
{ {
XkbRMLVOSet set; XkbRMLVOSet set;
XkbSrvInfoPtr xkbi; XkbSrvInfoPtr xkbi;
@ -292,8 +292,10 @@ rdpLoadLayout(int keylayout)
KeyCode first_key; KeyCode first_key;
CARD8 num_keys; CARD8 num_keys;
LLOGLN(0, ("rdpLoadLayout: keylayout 0x%8.8x display %s", int keylayout = client_info->keylayout;
keylayout, display));
LLOGLN(0, ("rdpLoadLayout: keylayout 0x%8.8x variant %s display %s",
keylayout, client_info->variant, display));
memset(&set, 0, sizeof(set)); memset(&set, 0, sizeof(set));
if (g_use_evdev) if (g_use_evdev)
{ {
@ -303,42 +305,26 @@ rdpLoadLayout(int keylayout)
{ {
set.rules = "base"; set.rules = "base";
} }
set.model = "pc104"; set.model = "pc104";
set.layout = "us"; 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.variant = "";
set.options = ""; 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 */ /* free some stuff so we can call InitKeyboardDeviceStruct again */
xkbi = g_keyboard->key->xkbInfo; xkbi = g_keyboard->key->xkbInfo;
xkb = xkbi->desc; xkb = xkbi->desc;
@ -355,10 +341,13 @@ rdpLoadLayout(int keylayout)
rdpChangeKeyboardControl)) rdpChangeKeyboardControl))
{ {
LLOGLN(0, ("rdpLoadLayout: InitKeyboardDeviceStruct failed")); LLOGLN(0, ("rdpLoadLayout: InitKeyboardDeviceStruct failed"));
return 1;
} }
/* notify the X11 clients eg. X_ChangeKeyboardMapping */ /* notify the X11 clients eg. X_ChangeKeyboardMapping */
keySyms = XkbGetCoreMap(g_keyboard); keySyms = XkbGetCoreMap(g_keyboard);
if (keySyms)
{
first_key = keySyms->minKeyCode; first_key = keySyms->minKeyCode;
num_keys = (keySyms->maxKeyCode - keySyms->minKeyCode) + 1; num_keys = (keySyms->maxKeyCode - keySyms->minKeyCode) + 1;
XkbApplyMappingChange(g_keyboard, keySyms, first_key, num_keys, XkbApplyMappingChange(g_keyboard, keySyms, first_key, num_keys,
@ -371,6 +360,12 @@ rdpLoadLayout(int keylayout)
NULL, serverClient); NULL, serverClient);
} }
} }
} else
{
/* sometimes, variant doesn't support all layouts */
set.variant = "";
goto retry;
}
return 0; return 0;
} }

@ -1117,7 +1117,7 @@ rdpup_process_msg(struct stream *s)
g_do_multimon = 0; g_do_multimon = 0;
} }
rdpLoadLayout(g_rdpScreen.client_info.keylayout); rdpLoadLayout(&(g_rdpScreen.client_info));
} }
else if (msg_type == 105) else if (msg_type == 105)

@ -65,7 +65,8 @@ xrdp_LDFLAGS = \
xrdpsysconfdir=$(sysconfdir)/xrdp xrdpsysconfdir=$(sysconfdir)/xrdp
xrdpsysconf_DATA = \ xrdpsysconf_DATA = \
xrdp.ini xrdp.ini \
xrdp_keyboard.ini
xrdppkgdatadir=$(datadir)/xrdp xrdppkgdatadir=$(datadir)/xrdp

@ -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)
Loading…
Cancel
Save