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

@ -128,6 +128,11 @@ struct xrdp_client_info
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

@ -18,9 +18,17 @@
* 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
@ -38,6 +46,41 @@ xrdp_tls_create(struct trans *trans, const char *key, const char *cert)
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)
@ -53,6 +96,7 @@ xrdp_tls_accept(struct xrdp_tls *self)
*/
options |= SSL_OP_NO_SSLv2;
#if defined(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.
*/
options |= SSL_OP_NO_COMPRESSION;
#endif
/**
* SSL_OP_TLS_BLOCK_PADDING_BUG:
@ -137,40 +182,6 @@ xrdp_tls_accept(struct xrdp_tls *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_disconnect(struct xrdp_tls *self)
{
int status = SSL_shutdown(self->ssl);
@ -205,7 +216,7 @@ xrdp_tls_delete(struct xrdp_tls *self)
}
/*****************************************************************************/
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;
@ -213,25 +224,25 @@ xrdp_tls_read(struct xrdp_tls *tls, unsigned char *data, int 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;
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, unsigned char *data, int length)
xrdp_tls_write(struct xrdp_tls *tls, char *data, int length)
{
int status;
@ -239,18 +250,18 @@ xrdp_tls_write(struct xrdp_tls *tls, unsigned char *data, int 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;
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;
@ -317,6 +328,58 @@ xrdp_tls_force_read_s(struct trans *self, struct stream *in_s, int size)
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
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;
}
/*****************************************************************************/
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
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_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;
}

@ -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

@ -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;

@ -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)

@ -65,7 +65,8 @@ xrdp_LDFLAGS = \
xrdpsysconfdir=$(sysconfdir)/xrdp
xrdpsysconf_DATA = \
xrdp.ini
xrdp.ini \
xrdp_keyboard.ini
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