Merge branch 'devel' into v0.9

This commit is contained in:
Koichiro IWAO 2021-04-30 21:01:27 +09:00
commit d868b05273
126 changed files with 8602 additions and 5443 deletions

View File

@ -4,13 +4,13 @@ FreeBSD_task:
SSL: libressl
matrix:
freebsd_instance:
image_family: freebsd-12-1
image_family: freebsd-12-2
prepare_script:
- pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm
- pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm fusefs-libs check
- git submodule update --init --recursive
configure_script:
- ./bootstrap
- env CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure --localstatedir=/var --enable-strict-locations --with-pkgconfigdir=/usr/local/libdata/pkgconfig --enable-strict-locations --enable-ipv6 --enable-opus --enable-jpeg --enable-fdkaac --enable-painter --enable-pixman
- env CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure --localstatedir=/var --enable-strict-locations --with-pkgconfigdir=/usr/local/libdata/pkgconfig --enable-strict-locations --enable-ipv6 --enable-opus --enable-jpeg --enable-fdkaac --enable-painter --enable-pixman --enable-fuse
build_script:
- make -j $(sysctl -n hw.ncpu || echo 4)
install_script:

View File

@ -15,7 +15,7 @@ jobs:
fail-fast: false
matrix:
include:
# Minimal 64-bit arch builds
- CC: gcc
feature_set: min
@ -38,19 +38,19 @@ jobs:
arch: amd64
os: ubuntu-latest
DISTCHECK: true
- CC: g++
feature_set: max
arch: amd64
os: ubuntu-latest
DISTCHECK: true
- CC: clang
feature_set: max
arch: amd64
os: ubuntu-latest
DISTCHECK: true
# Maximal debug 64-bit arch builds
- CC: gcc
feature_set: max
@ -58,7 +58,7 @@ jobs:
os: ubuntu-latest
name_extra: and DEBUG
CONF_FLAGS_EXTRA: "--enable-xrdpdebug"
# Maximal 32-bit arch builds
- CC: gcc
feature_set: max
@ -82,12 +82,12 @@ jobs:
runs-on: ${{ matrix.os }}
env:
CC: ${{ matrix.CC }}
# HACK (2020-11-16): github actions dosen't support YAML anchors/aliases to
# avoid repeating long config values. So instead the config values are defined
# as environment variables using a naming convention with fields that come from
# the job config. These environment variables are then referenced as regualr
# environment variables via the naming convention in the "define env" step to
# HACK (2020-11-16): github actions dosen't support YAML anchors/aliases to
# avoid repeating long config values. So instead the config values are defined
# as environment variables using a naming convention with fields that come from
# the job config. These environment variables are then referenced as regualr
# environment variables via the naming convention in the "define env" step to
# define the stardard environment variable used in the rest of the steps.
CONF_FLAGS_amd64_min: "--disable-ipv6 --disable-jpeg --disable-fuse --disable-mp3lame
--disable-fdkaac --disable-opus --disable-rfxcodec --disable-painter
@ -98,13 +98,13 @@ jobs:
CONF_FLAGS_i386_max: "--enable-ipv6 --enable-jpeg --enable-fuse --enable-mp3lame
--enable-fdkaac --enable-opus --enable-rfxcodec --enable-painter
--disable-pixman --host=i686-linux"
PKG_CONFIG_PATH_i386: "/usr/lib/i386-linux-gnu/pkgconfig"
CFLAGS_i386: "-m32"
LDFLAGS_i386: "-m32"
steps:
- name: Define feature and arch dependent environment variables
# Note: any "variable=value" written to the $GITHUB_ENV file will be
# Note: any "variable=value" written to the $GITHUB_ENV file will be
# defined as an environment variable for all future steps in this job
# See: https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable
run: |
@ -119,17 +119,21 @@ jobs:
- run: make
- if: ${{ matrix.DISTCHECK }}
run: make distcheck
cppcheck:
name: cppcheck
runs-on: ubuntu-latest
env:
CC: gcc
# This is required to use a version of cppcheck other than that
# suplied with the operating system
CPPCHECK_VER: 2.1
# supplied with the operating system
CPPCHECK_VER: 2.4
CPPCHECK_REPO: https://github.com/danmar/cppcheck.git
steps:
# This is currently the only way to get a version into
# the cache tag name - see https://github.com/actions/cache/issues/543
- run: |
echo "OS_VERSION=`lsb_release -sr`" >> $GITHUB_ENV
- uses: actions/checkout@v2
- name: Cache cppcheck
uses: actions/cache@v2
@ -137,9 +141,8 @@ jobs:
cache-name: cache-cppcheck
with:
path: ~/cppcheck.local
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.CPPCHECK_VER }}
key: ${{ runner.os }}-${{ env.OS_VERSION }}-build-${{ env.cache-name }}-${{ env.CPPCHECK_VER }}
- run: sudo scripts/install_cppcheck_dependencies_with_apt.sh
- run: ./bootstrap
- run: scripts/install_cppcheck.sh $CPPCHECK_REPO $CPPCHECK_VER
- run: scripts/run_cppcheck.sh -v $CPPCHECK_VER

7
.gitignore vendored
View File

@ -22,6 +22,7 @@ keygen/xrdp-keygen
.libs
libtool
*.lo
*.log
ltmain.sh
Makefile
Makefile.in
@ -41,6 +42,12 @@ sesman/xrdp-sesman
sesman/sesman.ini
*.so
stamp-h1
tap-driver.sh
test-driver
tests/common/test_common
tests/memtest/memtest
tools/devel/tcp_proxy/tcp_proxy
*.trs
xrdp/xrdp
xrdp/xrdp.ini
xrdp_configure_options.h

View File

@ -1,7 +1,8 @@
ACLOCAL_AMFLAGS = -I m4
AM_DISTCHECK_CONFIGURE_FLAGS = \
--without-systemdsystemunitdir \
--enable-strict-locations
--enable-strict-locations \
--enable-tests
EXTRA_DIST = \
COPYING \
@ -20,7 +21,6 @@ EXTRA_DIST = \
m4 \
postinstall-pak \
tcutils \
tests \
vrplayer
if XRDP_NEUTRINORDP
@ -64,7 +64,9 @@ SUBDIRS = \
genkeymap \
xrdpapi \
pkgconfig \
$(XRDPVRDIR)
$(XRDPVRDIR) \
tests \
tools
distclean-local:
-rm -f xrdp_configure_options.h

View File

@ -1,4 +1,4 @@
[![Build Status](https://travis-ci.org/neutrinolabs/xrdp.svg?branch=devel)](https://travis-ci.org/neutrinolabs/xrdp)
[![Build Status](https://github.com/neutrinolabs/xrdp/actions/workflows/build.yml/badge.svg)](https://github.com/neutrinolabs/xrdp/actions)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/neutrinolabs/xrdp-questions)
![Apache-License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)
@ -9,9 +9,15 @@
## Overview
**xrdp** provides a graphical login to remote machines using Microsoft
Remote Desktop Protocol (RDP). xrdp accepts connections from a variety of
RDP clients: FreeRDP, rdesktop, NeutrinoRDP and Microsoft Remote Desktop
Client (for Windows, Mac OS, iOS and Android).
Remote Desktop Protocol (RDP). xrdp accepts connections from a variety of RDP clients:
* FreeRDP
* rdesktop
* KRDC
* NeutrinoRDP
* Windows MSTSC (Microsoft Terminal Services Client, aka `mstsc.exe`)
* Microsoft Remote Desktop (found on Microsoft Store, which is distinct from MSTSC)
Many of these work on some or all of Windows, Mac OS, iOS, and/or Android.
RDP transport is encrypted using TLS by default.
@ -24,13 +30,24 @@ RDP transport is encrypted using TLS by default.
* Connect to a Linux desktop using RDP from anywhere (requires
[xorgxrdp](https://github.com/neutrinolabs/xorgxrdp) Xorg module)
* Reconnect to an existing session
* Session resizing
* Session resizing (both on-connect and on-the-fly)
* RDP/VNC proxy (connect to another RDP/VNC server via xrdp)
### Access to Remote Resources
* two-way clipboard transfer (text, bitmap, file)
* audio redirection ([requires to build additional modules](https://github.com/neutrinolabs/xrdp/wiki/How-to-set-up-audio-redirection))
* drive redirection (mount local client drives on remote machine)
* Two-way clipboard transfer (text, bitmap, file)
* Audio redirection ([requires to build additional modules](https://github.com/neutrinolabs/xrdp/wiki/How-to-set-up-audio-redirection))
* Microphone redirection ([requires to build additional modules](https://github.com/neutrinolabs/xrdp/wiki/How-to-set-up-audio-redirection))
* Drive redirection (mount local client drives on remote machine)
## Supported Platforms
**xrdp** primarily targets GNU/Linux operating system. x86 (including x86-64)
and ARM processors are most mature architecture to run xrdp on.
See also [Platform Support Tier](https://github.com/neutrinolabs/xrdp/wiki/Platform-Support-Tier).
Some components such as xorgxrdp and RemoteFX codec have special optimization
for x86 using SIMD instructions. So running xrdp on x86 processors will get
fully accelerated experience.
## Quick Start
@ -65,20 +82,6 @@ yum install xrdp
`yum` is being replaced with `dnf`, so you may need to use `dnf` instead
of `yum` in the above commands.
## Environment
**xrdp** primarily targets to GNU/Linux. Tested on x86, x86_64, SPARC and
PowerPC.
xorgxrdp and RemoteFX Codec have special optimization for x86 and x86_64 using
SIMD instructions.
FreeBSD is not a primary target of xrdp. It is working on FreeBSD except
for the drive redirection feature.
Other operating systems such as macOS are not supported so far, but we
welcome your contributions.
## Compiling
See also https://github.com/neutrinolabs/xrdp/wiki#building-from-sources
@ -132,9 +135,17 @@ xrdp
├── mc ·········· media center module
├── neutrinordp · RDP client module for proxying RDP connections using NeutrinoRDP
├── pkgconfig ··· pkg-config configuration
├── sesman ······ session manager for xrdp
├── scripts ····· build scripts
├┬─ sesman ······ session manager for xrdp
|├── chansrv ···· channel server for xrdp
|├── libscp ····· authorization library
|└── tools ······ session management tools for sys admins
├── tcutils ····· QT based utility program for thin clients
├── tests ······· tests for the code
├┬─ tools ······· tools
|└┬─ devel ······ development tools
| ├── gtcp_proxy GTK app that forwards TCP connections to a remote host
| └── tcp_proxy · CLI app that forwards TCP connections to a remote host
├── vnc ········· VNC client module for xrdp
├── vrplayer ···· QT player redirecting video/audio to clients over xrdpvr channel
├── xrdp ········ main server code

View File

@ -14,6 +14,7 @@ include_HEADERS = \
ms-rdpegdi.h \
ms-rdpele.h \
ms-rdperp.h \
ms-rdpedisp.h \
ms-smb2.h \
xrdp_client_info.h \
xrdp_constants.h \
@ -32,7 +33,10 @@ if XRDP_DEBUG
AM_CPPFLAGS += -DXRDP_DEBUG
endif
AM_CFLAGS = $(OPENSSL_CFLAGS)
# -no-suppress is an automake-specific flag which is needed
# to prevent us missing compiler errors in some circumstances
# (see https://github.com/neutrinolabs/xrdp/pull/1843 )
AM_CFLAGS = -no-suppress $(OPENSSL_CFLAGS)
module_LTLIBRARIES = \
libcommon.la

View File

@ -64,7 +64,8 @@ typedef int bool_t;
#if !(defined(L_ENDIAN) || defined(B_ENDIAN))
#if defined(__sparc__) || \
defined(__hppa__) || \
defined(__s390__) || defined (__s390x__) || \
defined(__hppa__) || defined (__m68k__) || \
(defined(__PPC__) && defined(__BIG_ENDIAN__)) || \
(defined(__ppc__) && defined(__BIG_ENDIAN__))
#define B_ENDIAN
@ -77,14 +78,16 @@ typedef int bool_t;
/* 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(__mips__) || \
defined(__ia64__) || defined(__arm__) || \
defined(__AIX__) || defined(__m68k__) || defined(__mips__) || \
defined(__ia64__) || defined(__arm__) || defined(__sh__) || \
(defined(__PPC__) && defined(__BIG_ENDIAN__)) || \
(defined(__ppc__) && defined(__BIG_ENDIAN__))
#define NEED_ALIGN
#elif defined(__x86__) || defined(__x86_64__) || \
defined(__AMD64__) || defined(_M_IX86) || defined (_M_AMD64) || \
defined(__i386__) || defined(__aarch64__) || \
defined(__PPC__) || defined(__LITTLE_ENDIAN__) || \
defined(__s390__) || defined (__s390x__) || \
defined(__riscv)
#define NO_NEED_ALIGN
#else
@ -142,7 +145,7 @@ typedef int tsock;
/* format string verification */
#if defined(HAVE_FUNC_ATTRIBUTE_FORMAT)
#define printflike(arg_format, arg_first_check) \
__attribute__((__format__(__printf__, arg_format, arg_first_check)))
__attribute__((__format__(__printf__, arg_format, arg_first_check)))
#else
#define printflike(arg_format, arg_first_check)
#endif
@ -151,8 +154,8 @@ typedef int tsock;
#ifdef __cplusplus
extern "C" {
#endif
tintptr mod_init(void);
int mod_exit(tintptr);
tintptr mod_init(void);
int mod_exit(tintptr);
#ifdef __cplusplus
}
#endif

View File

@ -67,7 +67,7 @@ base64_decode(char *dst, const char *src, size_t len)
bio = BIO_new_mem_buf(b64str, len);
bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
decoded_bytes = BIO_read(bio , dst, len);
decoded_bytes = BIO_read(bio, dst, len);
BIO_free_all(bio);
/* if input is corrupt, return empty string */

View File

@ -21,14 +21,6 @@
#ifndef DEFINES_H
#define DEFINES_H
/* check for debug */
#ifdef XRDP_DEBUG
#define DEBUG(args) g_writeln args;
#define LIB_DEBUG(_mod, _text) _mod->server_msg(_mod, _text, 1);
#else
#define DEBUG(args)
#define LIB_DEBUG(_mod, _text)
#endif
/* other macros */
#undef MIN
#define MIN(x1, x2) ((x1) < (x2) ? (x1) : (x2))
@ -44,25 +36,25 @@
/* graphics macros */
#define MAKERECT(r, x, y, cx, cy) \
{ (r).left = x; (r).top = y; (r).right = (x) + (cx); (r).bottom = (y) + (cy); }
{ (r).left = x; (r).top = y; (r).right = (x) + (cx); (r).bottom = (y) + (cy); }
#define ISRECTEMPTY(r) (((r).right <= (r).left) || ((r).bottom <= (r).top))
#define RECTOFFSET(r, dx, dy) \
{ (r).left += dx; (r).top += dy; (r).right += dx; (r).bottom += dy; }
{ (r).left += dx; (r).top += dy; (r).right += dx; (r).bottom += dy; }
#define GETPIXEL8(d, x, y, w) (*(((unsigned char*)d) + ((y) * (w) + (x))))
#define GETPIXEL16(d, x, y, w) (*(((unsigned short*)d) + ((y) * (w) + (x))))
#define GETPIXEL32(d, x, y, w) (*(((unsigned int*)d) + ((y) * (w) + (x))))
#define SETPIXEL8(d, x, y, w, v) \
(*(((unsigned char*)d) + ((y) * (w) + (x))) = (v))
(*(((unsigned char*)d) + ((y) * (w) + (x))) = (v))
#define SETPIXEL16(d, x, y, w, v) \
(*(((unsigned short*)d) + ((y) * (w) + (x))) = (v))
(*(((unsigned short*)d) + ((y) * (w) + (x))) = (v))
#define SETPIXEL32(d, x, y, w, v) \
(*(((unsigned int*)d) + ((y) * (w) + (x))) = (v))
(*(((unsigned int*)d) + ((y) * (w) + (x))) = (v))
#define COLOR8(r, g, b) \
( \
(((r) >> 5) << 0) | \
(((g) >> 5) << 3) | \
(((b) >> 6) << 6) \
)
( \
(((r) >> 5) << 0) | \
(((g) >> 5) << 3) | \
(((b) >> 6) << 6) \
)
#define COLOR15(r, g, b) ((((r) >> 3) << 10) | (((g) >> 3) << 5) | ((b) >> 3))
#define COLOR16(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
#define COLOR24RGB(r, g, b) (((r) << 16) | ((g) << 8) | (b))
@ -71,43 +63,43 @@
#define HGREEN(c) ((c & 0x00ff00) >> 8)
#define HBLUE(c) ((c & 0x0000ff))
#define HCOLOR(bpp,c) \
( \
(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==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) \
) \
) \
) \
)
#define SPLITCOLOR15(r, g, b, c) \
{ \
r = (((c) >> 7) & 0xf8) | (((c) >> 12) & 0x7); \
g = (((c) >> 2) & 0xf8) | (((c) >> 8) & 0x7); \
b = (((c) << 3) & 0xf8) | (((c) >> 2) & 0x7); \
}
{ \
r = (((c) >> 7) & 0xf8) | (((c) >> 12) & 0x7); \
g = (((c) >> 2) & 0xf8) | (((c) >> 8) & 0x7); \
b = (((c) << 3) & 0xf8) | (((c) >> 2) & 0x7); \
}
#define SPLITCOLOR16(r, g, b, c) \
{ \
r = (((c) >> 8) & 0xf8) | (((c) >> 13) & 0x7); \
g = (((c) >> 3) & 0xfc) | (((c) >> 9) & 0x3); \
b = (((c) << 3) & 0xf8) | (((c) >> 2) & 0x7); \
}
{ \
r = (((c) >> 8) & 0xf8) | (((c) >> 13) & 0x7); \
g = (((c) >> 3) & 0xfc) | (((c) >> 9) & 0x3); \
b = (((c) << 3) & 0xf8) | (((c) >> 2) & 0x7); \
}
#define SPLITCOLOR32(r, g, b, c) \
{ \
r = ((c) >> 16) & 0xff; \
g = ((c) >> 8) & 0xff; \
b = (c) & 0xff; \
}
{ \
r = ((c) >> 16) & 0xff; \
g = ((c) >> 8) & 0xff; \
b = (c) & 0xff; \
}
/* font macros */
#define FONT_DATASIZE(f) \
((((f)->height * (((f)->width + 7) / 8)) + 3) & ~3);
((((f)->height * (((f)->width + 7) / 8)) + 3) & ~3);
/* 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)
(a_ulColor & 0xFF000000) | \
((a_ulColor & 0x00FF0000) >> 16) | \
(a_ulColor & 0x0000FF00) | \
((a_ulColor & 0x000000FF) << 16)
#endif

View File

@ -47,20 +47,24 @@ fifo_delete(FIFO *self)
USER_DATA *udp;
if (!self)
{
return;
}
if (!self->head)
{
/* FIFO is empty */
g_free(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);
@ -73,7 +77,9 @@ fifo_delete(FIFO *self)
udp = self->head;
if (self->auto_free)
{
g_free(udp->item);
}
self->head = udp->next;
g_free(udp);
@ -97,10 +103,14 @@ 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;
@ -135,7 +145,9 @@ fifo_remove_item(FIFO *self)
USER_DATA *udp;
if (!self || !self->head)
{
return 0;
}
if (self->head == self->tail)
{
@ -167,7 +179,9 @@ int
fifo_is_empty(FIFO *self)
{
if (!self)
{
return 1;
}
return (self->head == 0);
}

View File

@ -38,10 +38,10 @@ typedef struct fifo
int auto_free;
} FIFO;
FIFO * fifo_create(void);
FIFO *fifo_create(void);
void fifo_delete(FIFO *self);
int fifo_add_item(FIFO *self, void *item);
void * fifo_remove_item(FIFO *self);
void *fifo_remove_item(FIFO *self);
int fifo_is_empty(FIFO *self);
#endif

View File

@ -24,14 +24,14 @@
#include "arch.h"
int
file_read_sections(int fd, struct list* names);
file_read_sections(int fd, struct list *names);
int
file_by_name_read_sections(const char* file_name, struct list* names);
file_by_name_read_sections(const char *file_name, struct list *names);
int
file_read_section(int fd, const char* section,
struct list* names, struct list* values);
file_read_section(int fd, const char *section,
struct list *names, struct list *values);
int
file_by_name_read_section(const char* file_name, const char* section,
struct list* names, struct list* values);
file_by_name_read_section(const char *file_name, const char *section,
struct list *names, struct list *values);
#endif

View File

@ -26,6 +26,7 @@
#include "os_calls.h"
#include "string_calls.h"
#include "list.h"
#include "log.h"
/*****************************************************************************/
struct list *
@ -221,11 +222,11 @@ list_dump_items(struct list *self)
if (self->count == 0)
{
g_writeln("List is empty");
LOG_DEVEL(LOG_LEVEL_TRACE, "List is empty");
}
for (index = 0; index < self->count; index++)
{
g_writeln("%d: %p", index, (void *) list_get_item(self, index));
LOG_DEVEL(LOG_LEVEL_TRACE, "%d: %p", index, (void *) list_get_item(self, index));
}
}

View File

@ -26,32 +26,32 @@
/* list */
struct list
{
tintptr* items;
tintptr *items;
int count;
int alloc_size;
int grow_by;
int auto_free;
};
struct list*
struct list *
list_create(void);
void
list_delete(struct list* self);
list_delete(struct list *self);
void
list_add_item(struct list* self, tintptr item);
list_add_item(struct list *self, tintptr item);
tintptr
list_get_item(const struct list *self, int index);
void
list_clear(struct list* self);
list_clear(struct list *self);
int
list_index_of(struct list* self, tintptr item);
list_index_of(struct list *self, tintptr item);
void
list_remove_item(struct list* self, int index);
list_remove_item(struct list *self, int index);
void
list_insert_item(struct list* self, int index, tintptr item);
list_insert_item(struct list *self, int index, tintptr item);
void
list_append_list_strdup(struct list* self, struct list* dest, int start_index);
list_append_list_strdup(struct list *self, struct list *dest, int start_index);
void
list_dump_items(struct list* self);
list_dump_items(struct list *self);
#endif

View File

@ -52,7 +52,7 @@ list16_delete(struct list16 *self)
/*****************************************************************************/
void
list16_init(struct list16* self)
list16_init(struct list16 *self)
{
g_memset(self, 0, sizeof(struct list16));
self->max_count = 4;
@ -61,7 +61,7 @@ list16_init(struct list16* self)
/*****************************************************************************/
void
list16_deinit(struct list16* self)
list16_deinit(struct list16 *self)
{
if (self->items != self->mitems)
{

View File

@ -26,31 +26,31 @@
/* list */
struct list16
{
tui16* items;
int count;
int max_count;
tui16 mitems[4];
tui16 *items;
int count;
int max_count;
tui16 mitems[4];
};
struct list16*
struct list16 *
list16_create(void);
void
list16_delete(struct list16* self);
list16_delete(struct list16 *self);
void
list16_init(struct list16* self);
list16_init(struct list16 *self);
void
list16_deinit(struct list16* self);
list16_deinit(struct list16 *self);
void
list16_add_item(struct list16* self, tui16 item);
list16_add_item(struct list16 *self, tui16 item);
tui16
list16_get_item(struct list16* self, int index);
list16_get_item(struct list16 *self, int index);
void
list16_clear(struct list16* self);
list16_clear(struct list16 *self);
int
list16_index_of(struct list16* self, tui16 item);
list16_index_of(struct list16 *self, tui16 item);
void
list16_remove_item(struct list16* self, int index);
list16_remove_item(struct list16 *self, int index);
void
list16_insert_item(struct list16* self, int index, tui16 item);
list16_insert_item(struct list16 *self, int index, tui16 item);
#endif

View File

@ -304,7 +304,7 @@ internal_config_read_logging(int file,
lc->console_level = LOG_LEVEL_INFO;
lc->enable_syslog = 0;
lc->syslog_level = LOG_LEVEL_INFO;
lc->dump_on_start = 1;
lc->dump_on_start = 0;
lc->enable_pid = 0;
g_snprintf(section_name, 511, "%s%s", section_prefix, SESMAN_CFG_LOGGING);
@ -616,7 +616,6 @@ log_config_init_for_console(enum logLevels lvl, const char *override_name)
{
config->console_level = lvl;
}
config->dump_on_start = 0; /* Don't need dump for console only */
}
return config;
}
@ -721,7 +720,8 @@ log_start_from_param(const struct log_config *src_log_config)
* @return 0 on success
*/
enum logReturns
log_start(const char *iniFile, const char *applicationName)
log_start(const char *iniFile, const char *applicationName,
bool_t dump_on_start)
{
enum logReturns ret = LOG_GENERAL_ERROR;
struct log_config *config;
@ -730,6 +730,7 @@ log_start(const char *iniFile, const char *applicationName)
if (config != NULL)
{
config->dump_on_start = dump_on_start;
ret = log_start_from_param(config);
log_config_free(config);
@ -763,7 +764,18 @@ log_end(void)
}
/*****************************************************************************/
/* produce a hex dump */
/* log a hex dump */
enum logReturns
log_hexdump(const enum logLevels log_level,
const char *message,
const char *src,
int len)
{
return log_hexdump_with_location("", "", 0, log_level, message, src, len);
}
/*****************************************************************************/
/* log a hex dump */
enum logReturns
log_hexdump_with_location(const char *function_name,
const char *file_name,
@ -773,38 +785,11 @@ log_hexdump_with_location(const char *function_name,
const char *src,
int len)
{
unsigned char *line;
int i;
int dump_number_lines;
int dump_line_length;
int dump_length;
int dump_offset;
int thisline;
int offset;
char *dump_buffer;
enum logReturns rv;
enum logReturns rv = LOG_STARTUP_OK;
enum logLevels override_log_level;
bool_t override_destination_level = 0;
/* Start the dump on a new line so that the first line of the dump is
aligned to the first column instead of to after the log message
preamble (eg. time, log level, ...)
*/
#define HEX_DUMP_SOURCE_BYTES_PER_LINE (16)
#ifdef _WIN32
#define HEX_DUMP_HEADER ("%s Hex Dump:\r\n")
#define HEX_DUMP_NEWLINE_SIZE (2)
#else
#ifdef _MACOS
#define HEX_DUMP_HEADER ("%s Hex Dump:\r")
#define HEX_DUMP_NEWLINE_SIZE (1)
#else
#define HEX_DUMP_HEADER ("%s Hex Dump:\n")
#define HEX_DUMP_NEWLINE_SIZE (1)
#endif
#endif
#define HEX_DUMP_HEADER_SIZE (sizeof(HEX_DUMP_HEADER) - 1)
override_destination_level = internal_log_location_overrides_level(
function_name,
file_name,
@ -814,107 +799,37 @@ log_hexdump_with_location(const char *function_name,
return LOG_STARTUP_OK;
}
dump_line_length = (4 + 3 /* = 4 offset + 3 space */
+ ((2 + 1) * HEX_DUMP_SOURCE_BYTES_PER_LINE) /* + (2 hex char + 1 space) per source byte */
+ 2 /* + 2 space */
+ HEX_DUMP_SOURCE_BYTES_PER_LINE
+ HEX_DUMP_NEWLINE_SIZE);
dump_number_lines = (len / HEX_DUMP_SOURCE_BYTES_PER_LINE) + 1; /* +1 to round up */
dump_length = (dump_number_lines *dump_line_length /* hex dump lines */
+ HEX_DUMP_HEADER_SIZE
+ 1); /* terminating NULL */
dump_buffer = (char *)g_malloc(dump_length, 1);
if (dump_buffer == NULL)
{
LOG_DEVEL(LOG_LEVEL_WARNING,
"Failed to allocate buffer for hex dump of size %d",
dump_length);
return LOG_ERROR_MALLOC;
}
line = (unsigned char *)src;
offset = 0;
g_memcpy(dump_buffer, HEX_DUMP_HEADER, HEX_DUMP_HEADER_SIZE);
dump_offset = HEX_DUMP_HEADER_SIZE;
while (offset < len)
{
g_sprintf(dump_buffer + dump_offset, "%04x ", offset);
dump_offset += 7;
thisline = len - offset;
if (thisline > HEX_DUMP_SOURCE_BYTES_PER_LINE)
{
thisline = HEX_DUMP_SOURCE_BYTES_PER_LINE;
}
for (i = 0; i < thisline; i++)
{
g_sprintf(dump_buffer + dump_offset, "%02x ", line[i]);
dump_offset += 3;
}
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
{
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
}
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
for (i = 0; i < thisline; i++)
{
dump_buffer[dump_offset++] = (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.';
}
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
{
dump_buffer[dump_offset++] = ' ';
}
/* Start the dump on a new line so that the first line of the dump is
aligned to the first column instead of to after the log message
preamble (eg. time, log level, ...)
*/
#ifdef _WIN32
dump_buffer[dump_offset++] = '\r';
dump_buffer[dump_offset++] = '\n';
#define HEX_DUMP_HEADER ("Hex Dump:\r\n")
#else
#ifdef _MACOS
dump_buffer[dump_offset++] = '\r';
#define HEX_DUMP_HEADER ("Hex Dump:\r")
#else
dump_buffer[dump_offset++] = '\n';
#define HEX_DUMP_HEADER ("Hex Dump:\n")
#endif
#endif
offset += thisline;
line += thisline;
dump_buffer = g_bytes_to_hexdump(src, len);
if ((dump_offset - HEX_DUMP_HEADER_SIZE) % dump_line_length != 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR,
"BUG: dump_offset (%d) at the end of a line is not a "
"multiple of the line length (%d)",
dump_offset, dump_line_length);
}
}
if (dump_offset > dump_length)
if (dump_buffer != NULL)
{
LOG_DEVEL(LOG_LEVEL_ERROR,
"BUG: dump_offset (%d) is larger than the dump_buffer length (%d)",
dump_offset, dump_length);
if (g_strlen(file_name) > 0)
{
rv = log_message_with_location(function_name, file_name, line_number,
log_level, "%s %s%s",
message, HEX_DUMP_HEADER, dump_buffer);
}
else
{
rv = log_message(log_level, "%s %s%s",
message, HEX_DUMP_HEADER, dump_buffer);
}
g_free(dump_buffer);
return LOG_GENERAL_ERROR;
}
/* replace the last new line with the end of the string since log_message
will add a new line */
dump_buffer[dump_offset - HEX_DUMP_NEWLINE_SIZE] = '\0';
rv = log_message_with_location(function_name, file_name, line_number,
log_level, dump_buffer, message);
g_free(dump_buffer);
return rv;
}

View File

@ -22,6 +22,7 @@
#include <pthread.h>
#include "arch.h"
#include "defines.h"
#include "list.h"
/* logging buffer size */
@ -95,7 +96,7 @@ enum logReturns
* @param ... the arguments for the printf format c-string
*/
#define LOG_DEVEL(log_level, args...) \
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args);
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args)
/**
* @brief Logging macro for messages that are for a systeam administrator to
@ -109,7 +110,7 @@ enum logReturns
* @param ... the arguments for the printf format c-string
*/
#define LOG(log_level, args...) \
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args);
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args)
/**
* @brief Logging macro for logging the contents of a byte array using a hex
@ -124,12 +125,31 @@ enum logReturns
* @param length, the length of the byte array to log
*/
#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) \
log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length);
log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length)
/**
* @brief Logging macro for logging the contents of a byte array using a hex
* dump format.
*
* @param log_level, the log level
* @param message, a message prefix for the hex dump. Note: no printf like
* formatting is done to this message.
* @param buffer, a pointer to the byte array to log as a hex dump
* @param length, the length of the byte array to log
*/
#define LOG_HEXDUMP(log_level, message, buffer, length) \
log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length)
#else
#define LOG_DEVEL(log_level, args...)
#define LOG(log_level, args...) log_message(log_level, args);
#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length)
#define LOG(log_level, args...) log_message(log_level, args)
#define LOG_HEXDUMP(log_level, message, buffer, length) \
log_hexdump(log_level, message, buffer, length)
/* Since log_message() returns a value ensure that the elided versions of
* LOG_DEVEL and LOG_DEVEL_HEXDUMP also "fake" returning the success value
*/
#define LOG_DEVEL(log_level, args...) UNUSED_VAR(LOG_STARTUP_OK)
#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) UNUSED_VAR(LOG_STARTUP_OK)
#endif
@ -263,11 +283,15 @@ internal_log_location_overrides_level(const char *function_name,
* This function initialize the log facilities according to the configuration
* file, that is described by the in parameter.
* @param iniFile
* @param applicationName, the name that is used in the log for the running application
* @param applicationName the name that is used in the log for the running
* application
* @param dump_on_start Whether to dump the config on stdout before
* logging is started
* @return LOG_STARTUP_OK on success
*/
enum logReturns
log_start(const char *iniFile, const char *applicationName);
log_start(const char *iniFile, const char *applicationName,
bool_t dump_on_start);
/**
* An alternative log_start where the caller gives the params directly.
@ -336,6 +360,12 @@ log_end(void);
enum logReturns
log_message(const enum logLevels lvl, const char *msg, ...) printflike(2, 3);
enum logReturns
log_hexdump(const enum logLevels log_level,
const char *msg,
const char *p,
int len);
/**
* the log function that all files use to log an event,
* with the function name and file line.

View File

@ -78,7 +78,12 @@
/* This isn't explicitly named in MS-RDPBCGR */
#define CHANNEL_NAME_LEN 7
/* Oprions field */
/* 2.2.1.3.6 Client Monitor Data - */
/* monitorCount (4 bytes): A 32-bit, unsigned integer. The number of display */
/* monitor definitions in the monitorDefArray field (the maximum allowed is 16). */
#define CLIENT_MONITOR_DATA_MAXIMUM_MONITORS 16
/* Options field */
/* NOTE: XR_ prefixed to avoid conflict with FreeRDP */
#define XR_CHANNEL_OPTION_INITIALIZED 0x80000000
#define XR_CHANNEL_OPTION_ENCRYPT_RDP 0x40000000
@ -282,16 +287,16 @@
#define TS_NEG_SCRBLT_INDEX 0x02
#define TS_NEG_MEMBLT_INDEX 0x03
#define TS_NEG_MEM3BLT_INDEX 0x04
/* 0x05 */
/* 0x06 */
/* 0x05 */
/* 0x06 */
#define TS_NEG_DRAWNINEGRID_INDEX 0x07
#define TS_NEG_LINETO_INDEX 0x08
#define TS_NEG_MULTI_DRAWNINEGRID_INDEX 0x09
/* 0x0A */
/* 0x0A */
#define TS_NEG_SAVEBITMAP_INDEX 0x0B
/* 0x0C */
/* 0x0D */
/* 0x0E */
/* 0x0C */
/* 0x0D */
/* 0x0E */
#define TS_NEG_MULTIDSTBLT_INDEX 0x0F
#define TS_NEG_MULTIPATBLT_INDEX 0x10
#define TS_NEG_MULTISCRBLT_INDEX 0x11
@ -300,15 +305,15 @@
#define TS_NEG_POLYGON_SC_INDEX 0x14
#define TS_NEG_POLYGON_CB_INDEX 0x15
#define TS_NEG_POLYLINE_INDEX 0x16
/* 0x17 */
/* 0x17 */
#define TS_NEG_FAST_GLYPH_INDEX 0x18
#define TS_NEG_ELLIPSE_SC_INDEX 0x19
#define TS_NEG_ELLIPSE_CB_INDEX 0x1A
#define TS_NEG_INDEX_INDEX 0x1B
/* 0x1C */
/* 0x1D */
/* 0x1E */
/* 0x1F */
/* 0x1C */
/* 0x1D */
/* 0x1E */
/* 0x1F */
/* Input Capability Set: inputFlags (2.2.7.1.6) */
#define INPUT_FLAG_SCANCODES 0x0001
@ -340,27 +345,27 @@
/* CODEC_GUID_NSCODEC CA8D1BB9-000F-154F-589FAE2D1A87E2D6 */
#define XR_CODEC_GUID_NSCODEC \
"\xb9\x1b\x8d\xca\x0f\x00\x4f\x15\x58\x9f\xae\x2d\x1a\x87\xe2\xd6"
"\xb9\x1b\x8d\xca\x0f\x00\x4f\x15\x58\x9f\xae\x2d\x1a\x87\xe2\xd6"
/* CODEC_GUID_REMOTEFX 76772F12-BD72-4463-AFB3B73C9C6F7886 */
#define XR_CODEC_GUID_REMOTEFX \
"\x12\x2F\x77\x76\x72\xBD\x63\x44\xAF\xB3\xB7\x3C\x9C\x6F\x78\x86"
"\x12\x2F\x77\x76\x72\xBD\x63\x44\xAF\xB3\xB7\x3C\x9C\x6F\x78\x86"
/* CODEC_GUID_IMAGE_REMOTEFX 2744CCD4-9D8A-4E74-803C-0ECBEEA19C54 */
#define XR_CODEC_GUID_IMAGE_REMOTEFX \
"\xD4\xCC\x44\x27\x8A\x9D\x74\x4E\x80\x3C\x0E\xCB\xEE\xA1\x9C\x54"
"\xD4\xCC\x44\x27\x8A\x9D\x74\x4E\x80\x3C\x0E\xCB\xEE\xA1\x9C\x54"
/* MFVideoFormat_H264 0x34363248-0000-0010-800000AA00389B71 */
#define XR_CODEC_GUID_H264 \
"\x48\x32\x36\x34\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71"
"\x48\x32\x36\x34\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71"
/* CODEC_GUID_JPEG 1BAF4CE6-9EED-430C-869ACB8B37B66237 */
#define XR_CODEC_GUID_JPEG \
"\xE6\x4C\xAF\x1B\xED\x9E\x0C\x43\x86\x9A\xCB\x8B\x37\xB6\x62\x37"
"\xE6\x4C\xAF\x1B\xED\x9E\x0C\x43\x86\x9A\xCB\x8B\x37\xB6\x62\x37"
/* CODEC_GUID_PNG 0E0C858D-28E0-45DB-ADAA0F83E57CC560 */
#define XR_CODEC_GUID_PNG \
"\x8D\x85\x0C\x0E\xE0\x28\xDB\x45\xAD\xAA\x0F\x83\xE5\x7C\xC5\x60"
"\x8D\x85\x0C\x0E\xE0\x28\xDB\x45\xAD\xAA\x0F\x83\xE5\x7C\xC5\x60"
/* PDU Types (2.2.8.1.1.1.1) */
#define PDUTYPE_DEMANDACTIVEPDU 0x1
@ -369,6 +374,15 @@
#define PDUTYPE_DATAPDU 0x7
#define PDUTYPE_SERVER_REDIR_PKT 0xA
#define PDUTYPE_TO_STR(pdu_type) \
((pdu_type) == PDUTYPE_DEMANDACTIVEPDU ? "PDUTYPE_DEMANDACTIVEPDU" : \
(pdu_type) == PDUTYPE_CONFIRMACTIVEPDU ? "PDUTYPE_CONFIRMACTIVEPDU" : \
(pdu_type) == PDUTYPE_DEACTIVATEALLPDU ? "PDUTYPE_DEACTIVATEALLPDU" : \
(pdu_type) == PDUTYPE_DATAPDU ? "PDUTYPE_DATAPDU" : \
(pdu_type) == PDUTYPE_SERVER_REDIR_PKT ? "PDUTYPE_SERVER_REDIR_PKT" : \
"unknown" \
)
/* Share Data Header: pduType2 (2.2.8.1.1.1.2) */
/* TODO: to be renamed */
#define RDP_DATA_PDU_UPDATE 2 /* PDUTYPE2_UPDATE */
@ -378,6 +392,9 @@
#define RDP_DATA_PDU_SYNCHRONISE 31
#define PDUTYPE2_REFRESH_RECT 33
#define RDP_DATA_PDU_PLAY_SOUND 34
#define PDUTYPE2_SUPPRESS_OUTPUT 35
#define PDUTYPE2_SHUTDOWN_REQUEST 36
#define PDUTYPE2_SHUTDOWN_DENIED 37
#define RDP_DATA_PDU_LOGON 38
#define RDP_DATA_PDU_FONT2 39
#define RDP_DATA_PDU_DISCONNECT 47
@ -405,7 +422,7 @@
/* Keyboard Event: keyboardFlags (2.2.8.1.1.3.1.1.1) */
/* TODO: to be renamed */
#define KBD_FLAG_RIGHT 0x0001
#define KBD_FLAG_RIGHT 0x0001
#define KBD_FLAG_EXT 0x0100 /* KBDFLAGS_EXTENDED */
#define KBD_FLAG_QUIET 0x1000
#define KBD_FLAG_DOWN 0x4000
@ -457,6 +474,14 @@
#define RDP_UPDATE_PALETTE 2
#define RDP_UPDATE_SYNCHRONIZE 3
#define GRAPHICS_UPDATE_TYPE_TO_STR(type) \
((type) == RDP_UPDATE_ORDERS ? "RDP_UPDATE_ORDERS" : \
(type) == RDP_UPDATE_BITMAP ? "RDP_UPDATE_BITMAP" : \
(type) == RDP_UPDATE_PALETTE ? "RDP_UPDATE_PALETTE" : \
(type) == RDP_UPDATE_SYNCHRONIZE ? "RDP_UPDATE_SYNCHRONIZE" : \
"unknown" \
)
/* Server Pointer Update PDU: messageType (2.2.9.1.1.4) */
/* TODO: to be renamed */
#define RDP_POINTER_SYSTEM 1 /* TS_PTRMSGTYPE_SYSTEM */

29
common/ms-rdpedisp.h Normal file
View File

@ -0,0 +1,29 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* MS-RDPEDISP : Definitions from [MS-RDPEDISP]
*
* 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.
*
* References to MS-RDPEDISP are currently correct for v20201030 of that
* document
*/
#if !defined(MS_RDPEDISP_H)
#define MS_RDPEDISP_H
/* Display Control Messages: Display Virtual Channel Extension (2.2.2) */
#define DISPLAYCONTROL_PDU_TYPE_MONITOR_LAYOUT 0x00000002
#define DISPLAYCONTROL_PDU_TYPE_CAPS 0x00000005
#endif /* MS_RDPEDISP_H */

View File

@ -121,9 +121,9 @@ g_mk_socket_path(const char *app_name)
/* if failed, still check if it got created by someone else */
if (!g_directory_exist(XRDP_SOCKET_PATH))
{
log_message(LOG_LEVEL_ERROR,
"g_mk_socket_path: g_create_path(%s) failed",
XRDP_SOCKET_PATH);
LOG(LOG_LEVEL_ERROR,
"g_mk_socket_path: g_create_path(%s) failed",
XRDP_SOCKET_PATH);
return 1;
}
}
@ -269,7 +269,7 @@ g_write(const char *format, ...)
}
/*****************************************************************************/
/* produce a hex dump */
/* print a hex dump to stdout*/
void
g_hexdump(const char *p, int len)
{
@ -360,13 +360,13 @@ g_tcp_set_no_delay(int sck)
}
else
{
g_writeln("Error setting tcp_nodelay");
LOG(LOG_LEVEL_ERROR, "Error setting tcp_nodelay");
}
}
}
else
{
g_writeln("Error getting tcp_nodelay");
LOG(LOG_LEVEL_ERROR, "Error getting tcp_nodelay");
}
return ret;
@ -399,13 +399,13 @@ g_tcp_set_keepalive(int sck)
}
else
{
g_writeln("Error setting tcp_keepalive");
LOG(LOG_LEVEL_ERROR, "Error setting tcp_keepalive");
}
}
}
else
{
g_writeln("Error getting tcp_keepalive");
LOG(LOG_LEVEL_ERROR, "Error getting tcp_keepalive");
}
return ret;
@ -428,12 +428,12 @@ g_tcp_socket(void)
switch (errno)
{
case EAFNOSUPPORT: /* if IPv6 not supported, retry IPv4 */
log_message(LOG_LEVEL_INFO, "IPv6 not supported, falling back to IPv4");
LOG(LOG_LEVEL_INFO, "IPv6 not supported, falling back to IPv4");
rv = (int)socket(AF_INET, SOCK_STREAM, 0);
break;
default:
log_message(LOG_LEVEL_ERROR, "g_tcp_socket: %s", g_get_strerror());
LOG(LOG_LEVEL_ERROR, "g_tcp_socket: %s", g_get_strerror());
return -1;
}
}
@ -442,12 +442,12 @@ g_tcp_socket(void)
#endif
if (rv < 0)
{
log_message(LOG_LEVEL_ERROR, "g_tcp_socket: %s", g_get_strerror());
LOG(LOG_LEVEL_ERROR, "g_tcp_socket: %s", g_get_strerror());
return -1;
}
#if defined(XRDP_ENABLE_IPV6)
option_len = sizeof(option_value);
if (getsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&option_value,
if (getsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&option_value,
&option_len) == 0)
{
if (option_value != 0)
@ -458,10 +458,10 @@ g_tcp_socket(void)
option_value = 0;
#endif
option_len = sizeof(option_value);
if (setsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&option_value,
option_len) < 0)
if (setsockopt(rv, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&option_value,
option_len) < 0)
{
log_message(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
LOG(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
}
}
}
@ -475,9 +475,9 @@ g_tcp_socket(void)
option_value = 1;
option_len = sizeof(option_value);
if (setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value,
option_len) < 0)
option_len) < 0)
{
log_message(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
LOG(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
}
}
}
@ -492,9 +492,9 @@ g_tcp_socket(void)
option_value = 1024 * 32;
option_len = sizeof(option_value);
if (setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value,
option_len) < 0)
option_len) < 0)
{
log_message(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
LOG(LOG_LEVEL_ERROR, "g_tcp_socket: setsockopt() failed");
}
}
}
@ -638,9 +638,9 @@ g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid)
if (getsockopt(sck, SOL_SOCKET, LOCAL_PEERCRED, &xucred, &xucred_length))
{
return 1;
return 1;
}
if (pid !=0)
if (pid != 0)
{
*pid = 0; /* can't get pid in FreeBSD, OS X */
}
@ -648,7 +648,8 @@ g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid)
{
*uid = xucred.cr_uid;
}
if (gid != 0) {
if (gid != 0)
{
*gid = xucred.cr_gid;
}
return 0;
@ -738,8 +739,8 @@ g_sck_close(int sck)
}
else
{
log_message(LOG_LEVEL_WARNING, "getsockname() failed on socket %d: %s",
sck, g_get_strerror());
LOG(LOG_LEVEL_WARNING, "getsockname() failed on socket %d: %s",
sck, g_get_strerror());
if (errno == EBADF || errno == ENOTSOCK)
{
@ -751,12 +752,12 @@ g_sck_close(int sck)
if (close(sck) == 0)
{
log_message(LOG_LEVEL_DEBUG, "Closed socket %d (%s)", sck, sockname);
LOG(LOG_LEVEL_DEBUG, "Closed socket %d (%s)", sck, sockname);
}
else
{
log_message(LOG_LEVEL_WARNING, "Cannot close socket %d (%s): %s", sck,
sockname, g_get_strerror());
LOG(LOG_LEVEL_WARNING, "Cannot close socket %d (%s): %s", sck,
sockname, g_get_strerror());
}
#endif
@ -777,7 +778,7 @@ connect_loopback(int sck, const char *port)
sa.sin6_family = AF_INET6;
sa.sin6_addr = in6addr_loopback; // IPv6 ::1
sa.sin6_port = htons((tui16)atoi(port));
res = connect(sck, (struct sockaddr*)&sa, sizeof(sa));
res = connect(sck, (struct sockaddr *)&sa, sizeof(sa));
if (res == -1 && errno == EINPROGRESS)
{
return -1;
@ -792,7 +793,7 @@ connect_loopback(int sck, const char *port)
s.sin_family = AF_INET;
s.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // IPv4 127.0.0.1
s.sin_port = htons((tui16)atoi(port));
res = connect(sck, (struct sockaddr*)&s, sizeof(s));
res = connect(sck, (struct sockaddr *)&s, sizeof(s));
if (res == -1 && errno == EINPROGRESS)
{
return -1;
@ -807,7 +808,7 @@ connect_loopback(int sck, const char *port)
sa.sin6_family = AF_INET6;
inet_pton(AF_INET6, "::FFFF:127.0.0.1", &sa.sin6_addr);
sa.sin6_port = htons((tui16)atoi(port));
res = connect(sck, (struct sockaddr*)&sa, sizeof(sa));
res = connect(sck, (struct sockaddr *)&sa, sizeof(sa));
if (res == -1 && errno == EINPROGRESS)
{
return -1;
@ -850,8 +851,8 @@ g_tcp_connect(int sck, const char *address, const char *port)
}
if (res != 0)
{
log_message(LOG_LEVEL_ERROR, "g_tcp_connect(%d, %s, %s): getaddrinfo() failed: %s",
sck, address, port, gai_strerror(res));
LOG(LOG_LEVEL_ERROR, "g_tcp_connect(%d, %s, %s): getaddrinfo() failed: %s",
sck, address, port, gai_strerror(res));
}
if (res > -1)
{
@ -879,10 +880,10 @@ g_tcp_connect(int sck, const char *address, const char *port)
}
#else
int
g_tcp_connect(int sck, const char* address, const char* port)
g_tcp_connect(int sck, const char *address, const char *port)
{
struct sockaddr_in s;
struct hostent* h;
struct hostent *h;
int res;
g_memset(&s, 0, sizeof(struct sockaddr_in));
@ -900,13 +901,13 @@ g_tcp_connect(int sck, const char* address, const char* port)
{
if ((*(h->h_addr_list)) != 0)
{
s.sin_addr.s_addr = *((int*)(*(h->h_addr_list)));
s.sin_addr.s_addr = *((int *)(*(h->h_addr_list)));
}
}
}
}
}
res = connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
res = connect(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_in));
/* Mac OSX connect() returns -1 for already established connections */
if (res == -1 && errno == EISCONN)
@ -951,7 +952,7 @@ g_sck_set_non_blocking(int sck)
i = i | O_NONBLOCK;
if (fcntl(sck, F_SETFL, i) < 0)
{
log_message(LOG_LEVEL_ERROR, "g_sck_set_non_blocking: fcntl() failed");
LOG(LOG_LEVEL_ERROR, "g_sck_set_non_blocking: fcntl() failed");
}
#endif
return 0;
@ -972,7 +973,7 @@ g_tcp_bind(int sck, const char *port)
sa.sin6_family = AF_INET6;
sa.sin6_addr = in6addr_any; // IPv6 ::
sa.sin6_port = htons((tui16)atoi(port));
if (bind(sck, (struct sockaddr*)&sa, sizeof(sa)) == 0)
if (bind(sck, (struct sockaddr *)&sa, sizeof(sa)) == 0)
{
return 0;
}
@ -983,19 +984,19 @@ g_tcp_bind(int sck, const char *port)
s.sin_family = AF_INET;
s.sin_addr.s_addr = htonl(INADDR_ANY); // IPv4 0.0.0.0
s.sin_port = htons((tui16)atoi(port));
if (bind(sck, (struct sockaddr*)&s, sizeof(s)) == 0)
if (bind(sck, (struct sockaddr *)&s, sizeof(s)) == 0)
{
return 0;
}
log_message(LOG_LEVEL_ERROR, "g_tcp_bind(%d, %s) failed "
"bind IPv6 (errno=%d) and IPv4 (errno=%d).",
sck, port, errno6, errno);
LOG(LOG_LEVEL_ERROR, "g_tcp_bind(%d, %s) failed "
"bind IPv6 (errno=%d) and IPv4 (errno=%d).",
sck, port, errno6, errno);
return -1;
}
#else
int
g_tcp_bind(int sck, const char* port)
g_tcp_bind(int sck, const char *port)
{
struct sockaddr_in s;
@ -1003,7 +1004,7 @@ g_tcp_bind(int sck, const char* port)
s.sin_family = AF_INET;
s.sin_port = htons((tui16)atoi(port));
s.sin_addr.s_addr = INADDR_ANY;
return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
return bind(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_in));
}
#endif
@ -1078,7 +1079,7 @@ bind_loopback(int sck, const char *port)
sa.sin6_family = AF_INET6;
sa.sin6_addr = in6addr_loopback; // IPv6 ::1
sa.sin6_port = htons((tui16)atoi(port));
if (bind(sck, (struct sockaddr*)&sa, sizeof(sa)) == 0)
if (bind(sck, (struct sockaddr *)&sa, sizeof(sa)) == 0)
{
return 0;
}
@ -1089,7 +1090,7 @@ bind_loopback(int sck, const char *port)
s.sin_family = AF_INET;
s.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // IPv4 127.0.0.1
s.sin_port = htons((tui16)atoi(port));
if (bind(sck, (struct sockaddr*)&s, sizeof(s)) == 0)
if (bind(sck, (struct sockaddr *)&s, sizeof(s)) == 0)
{
return 0;
}
@ -1100,14 +1101,14 @@ bind_loopback(int sck, const char *port)
sa.sin6_family = AF_INET6;
inet_pton(AF_INET6, "::FFFF:127.0.0.1", &sa.sin6_addr);
sa.sin6_port = htons((tui16)atoi(port));
if (bind(sck, (struct sockaddr*)&sa, sizeof(sa)) == 0)
if (bind(sck, (struct sockaddr *)&sa, sizeof(sa)) == 0)
{
return 0;
}
log_message(LOG_LEVEL_ERROR, "bind_loopback(%d, %s) failed; "
"IPv6 ::1 (errno=%d), IPv4 127.0.0.1 (errno=%d) and IPv6 ::FFFF:127.0.0.1 (errno=%d).",
sck, port, errno6, errno4, errno);
LOG(LOG_LEVEL_ERROR, "bind_loopback(%d, %s) failed; "
"IPv6 ::1 (errno=%d), IPv4 127.0.0.1 (errno=%d) and IPv6 ::FFFF:127.0.0.1 (errno=%d).",
sck, port, errno6, errno4, errno);
return -1;
}
@ -1142,7 +1143,7 @@ getaddrinfo_bind(int sck, const char *port, const char *address)
}
else
{
log_message(LOG_LEVEL_ERROR, "getaddrinfo error: %s", gai_strerror(error));
LOG(LOG_LEVEL_ERROR, "getaddrinfo error: %s", gai_strerror(error));
return -1;
}
return res;
@ -1159,16 +1160,16 @@ g_tcp_bind_address(int sck, const char *port, const char *address)
int res;
if ((address == 0) ||
(address[0] == 0) ||
(g_strcmp(address, "0.0.0.0") == 0) ||
(g_strcmp(address, "::") == 0))
(address[0] == 0) ||
(g_strcmp(address, "0.0.0.0") == 0) ||
(g_strcmp(address, "::") == 0))
{
return g_tcp_bind(sck, port);
}
if ((g_strcmp(address, "127.0.0.1") == 0) ||
(g_strcmp(address, "::1") == 0) ||
(g_strcmp(address, "localhost") == 0))
(g_strcmp(address, "::1") == 0) ||
(g_strcmp(address, "localhost") == 0))
{
return bind_loopback(sck, port);
}
@ -1183,7 +1184,7 @@ g_tcp_bind_address(int sck, const char *port, const char *address)
struct in_addr a;
if ((inet_aton(address, &a) == 1) && (strlen(address) <= 15))
{
char sz[7+15+1];
char sz[7 + 15 + 1];
sprintf(sz, "::FFFF:%s", address);
res = getaddrinfo_bind(sck, port, sz);
if (res == 0)
@ -1192,15 +1193,15 @@ g_tcp_bind_address(int sck, const char *port, const char *address)
}
}
log_message(LOG_LEVEL_ERROR, "g_tcp_bind_address(%d, %s, %s) Failed!",
sck, port, address);
LOG(LOG_LEVEL_ERROR, "g_tcp_bind_address(%d, %s, %s) Failed!",
sck, port, address);
return -1;
}
return 0;
}
#else
int
g_tcp_bind_address(int sck, const char* port, const char* address)
g_tcp_bind_address(int sck, const char *port, const char *address)
{
struct sockaddr_in s;
@ -1212,7 +1213,7 @@ g_tcp_bind_address(int sck, const char* port, const char* address)
{
return -1; /* bad address */
}
return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
return bind(sck, (struct sockaddr *)&s, sizeof(struct sockaddr_in));
}
#endif
@ -1246,7 +1247,7 @@ g_tcp_accept(int sck)
if (ret > 0)
{
switch(sock_info.sock_addr.sa_family)
switch (sock_info.sock_addr.sa_family)
{
case AF_INET:
{
@ -1255,7 +1256,7 @@ g_tcp_accept(int sck)
g_snprintf(msg, sizeof(msg), "A connection received from %s port %d",
inet_ntoa(sock_addr_in->sin_addr),
ntohs(sock_addr_in->sin_port));
log_message(LOG_LEVEL_INFO, "%s", msg);
LOG(LOG_LEVEL_INFO, "%s", msg);
break;
}
@ -1271,7 +1272,7 @@ g_tcp_accept(int sck)
&sock_addr_in6->sin6_addr, addr, sizeof(addr));
g_snprintf(msg, sizeof(msg), "A connection received from %s port %d",
addr, ntohs(sock_addr_in6->sin6_port));
log_message(LOG_LEVEL_INFO, "%s", msg);
LOG(LOG_LEVEL_INFO, "%s", msg);
break;
@ -1310,7 +1311,7 @@ g_sck_accept(int sck, char *addr, int addr_bytes, char *port, int port_bytes)
if (ret > 0)
{
switch(sock_info.sock_addr.sa_family)
switch (sock_info.sock_addr.sa_family)
{
case AF_INET:
{
@ -1380,7 +1381,7 @@ g_sck_accept(int sck, char *addr, int addr_bytes, char *port, int port_bytes)
}
log_message(LOG_LEVEL_INFO, "Socket %d: %s", ret, msg);
LOG(LOG_LEVEL_INFO, "Socket %d: %s", ret, msg);
}
@ -1419,7 +1420,7 @@ g_write_ip_address(int rcv_sck, char *ip_address, int bytes)
if (getpeername(rcv_sck, (struct sockaddr *)&sock_info, &sock_len) == 0)
{
switch(sock_info.sock_addr.sa_family)
switch (sock_info.sock_addr.sa_family)
{
case AF_INET:
{
@ -1806,7 +1807,7 @@ g_set_wait_obj(tintptr obj)
{
error = errno;
if ((error == EAGAIN) || (error == EWOULDBLOCK) ||
(error == EINPROGRESS) || (error == EINTR))
(error == EINPROGRESS) || (error == EINTR))
{
/* ok */
}
@ -1857,7 +1858,7 @@ g_reset_wait_obj(tintptr obj)
{
error = errno;
if ((error == EAGAIN) || (error == EWOULDBLOCK) ||
(error == EINPROGRESS) || (error == EINTR))
(error == EINPROGRESS) || (error == EINTR))
{
/* ok */
}
@ -2008,7 +2009,7 @@ g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs, int wcount,
}
else if (rcount > 0)
{
g_writeln("Programming error read_objs is null");
LOG(LOG_LEVEL_ERROR, "Programming error read_objs is null");
return 1; /* error */
}
@ -2031,7 +2032,7 @@ g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs, int wcount,
}
else if (wcount > 0)
{
g_writeln("Programming error write_objs is null");
LOG(LOG_LEVEL_ERROR, "Programming error write_objs is null");
return 1; /* error */
}
@ -2590,16 +2591,41 @@ g_get_errno(void)
/*****************************************************************************/
/* does not work in win32 */
#define ARGS_STR_LEN 1024
int
g_execvp(const char *p1, char *args[])
{
#if defined(_WIN32)
return 0;
#else
int rv;
char args_str[ARGS_STR_LEN];
int args_len;
args_len = 0;
while (args[args_len] != NULL)
{
args_len++;
}
g_strnjoin(args_str, ARGS_STR_LEN, " ", (const char **) args, args_len);
LOG(LOG_LEVEL_DEBUG,
"Calling exec (excutable: %s, arguments: %s)",
p1, args_str);
g_rm_temp_dir();
rv = execvp(p1, args);
/* should not get here */
LOG(LOG_LEVEL_ERROR,
"Error calling exec (excutable: %s, arguments: %s) "
"returned errno: %d, description: %s",
p1, args_str, g_get_errno(), g_get_strerror());
g_mk_socket_path(0);
return rv;
#endif
@ -2614,9 +2640,24 @@ g_execlp3(const char *a1, const char *a2, const char *a3)
return 0;
#else
int rv;
const char *args[] = {a2, a3, NULL};
char args_str[ARGS_STR_LEN];
g_strnjoin(args_str, ARGS_STR_LEN, " ", args, 2);
LOG(LOG_LEVEL_DEBUG,
"Calling exec (excutable: %s, arguments: %s)",
a1, args_str);
g_rm_temp_dir();
rv = execlp(a1, a2, a3, (void *)0);
/* should not get here */
LOG(LOG_LEVEL_ERROR,
"Error calling exec (excutable: %s, arguments: %s) "
"returned errno: %d, description: %s",
a1, args_str, g_get_errno(), g_get_strerror());
g_mk_socket_path(0);
return rv;
#endif
@ -2715,6 +2756,12 @@ g_fork(void)
{
g_mk_socket_path(0);
}
else if (rv == -1) /* error */
{
LOG(LOG_LEVEL_ERROR,
"Process fork failed with errno: %d, description: %s",
g_get_errno(), g_get_strerror());
}
return rv;
#endif
@ -2875,6 +2922,51 @@ g_waitpid(int pid)
#endif
}
/*****************************************************************************/
/* does not work in win32
returns exit status code of child process with pid */
struct exit_status
g_waitpid_status(int pid)
{
struct exit_status exit_status;
#if defined(_WIN32)
exit_status.exit_code = -1;
exit_status.signal_no = 0;
return exit_status;
#else
int rv;
int status;
exit_status.exit_code = -1;
exit_status.signal_no = 0;
if (pid > 0)
{
LOG(LOG_LEVEL_DEBUG, "waiting for pid %d to exit", pid);
rv = waitpid(pid, &status, 0);
if (rv != -1)
{
if (WIFEXITED(status))
{
exit_status.exit_code = WEXITSTATUS(status);
}
if (WIFSIGNALED(status))
{
exit_status.signal_no = WTERMSIG(status);
}
}
else
{
LOG(LOG_LEVEL_WARNING, "wait for pid %d returned unknown result", pid);
}
}
return exit_status;
#endif
}
/*****************************************************************************/
/* does not work in win32 */
void
@ -3135,11 +3227,11 @@ struct dib_hdr
int vres;
unsigned int ncolors;
unsigned int nimpcolors;
};
};
/******************************************************************************/
int
g_save_to_bmp(const char* filename, char* data, int stride_bytes,
g_save_to_bmp(const char *filename, char *data, int stride_bytes,
int width, int height, int depth, int bits_per_pixel)
{
struct bmp_magic bm;
@ -3152,8 +3244,8 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
int pixel;
int extra;
int file_stride_bytes;
char* line;
char* line_ptr;
char *line;
char *line_ptr;
if ((depth == 24) && (bits_per_pixel == 32))
{
@ -3163,7 +3255,9 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
}
else
{
g_writeln("g_save_to_bpp: unimp");
LOG(LOG_LEVEL_ERROR,
"g_save_to_bpp: unimplemented for: depth %d, bits_per_pixel %d",
depth, bits_per_pixel);
return 1;
}
bm.magic[0] = 'B';
@ -3196,23 +3290,23 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd == -1)
{
g_writeln("g_save_to_bpp: open error");
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: open error");
return 1;
}
bytes = write(fd, &bm, sizeof(bm));
if (bytes != sizeof(bm))
{
g_writeln("g_save_to_bpp: write error");
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: write error");
}
bytes = write(fd, &bh, sizeof(bh));
if (bytes != sizeof(bh))
{
g_writeln("g_save_to_bpp: write error");
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: write error");
}
bytes = write(fd, &dh, sizeof(dh));
if (bytes != sizeof(dh))
{
g_writeln("g_save_to_bpp: write error");
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: write error");
}
data += stride_bytes * height;
data -= stride_bytes;
@ -3225,7 +3319,7 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
line_ptr = line;
for (i1 = 0; i1 < width; i1++)
{
pixel = ((int*)data)[i1];
pixel = ((int *)data)[i1];
*(line_ptr++) = (pixel >> 0) & 0xff;
*(line_ptr++) = (pixel >> 8) & 0xff;
*(line_ptr++) = (pixel >> 16) & 0xff;
@ -3233,7 +3327,7 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
bytes = write(fd, line, file_stride_bytes);
if (bytes != file_stride_bytes)
{
g_writeln("g_save_to_bpp: write error");
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: write error");
}
data -= stride_bytes;
}
@ -3246,14 +3340,16 @@ g_save_to_bmp(const char* filename, char* data, int stride_bytes,
bytes = write(fd, data, width * (bits_per_pixel / 8));
if (bytes != width * (bits_per_pixel / 8))
{
g_writeln("g_save_to_bpp: write error");
LOG(LOG_LEVEL_ERROR, "g_save_to_bpp: write error");
}
data -= stride_bytes;
}
}
else
{
g_writeln("g_save_to_bpp: unimp");
LOG(LOG_LEVEL_ERROR,
"g_save_to_bpp: unimplemented for: depth %d, bits_per_pixel %d",
depth, bits_per_pixel);
}
close(fd);
return 0;
@ -3267,7 +3363,7 @@ g_shmat(int shmid)
#if defined(_WIN32)
return 0;
#else
return shmat(shmid, 0, 0);
return shmat(shmid, 0, 0);
#endif
}
@ -3398,7 +3494,7 @@ g_tcp4_bind_address(int sck, const char *port, const char *address)
{
return -1; /* bad address */
}
if (bind(sck, (struct sockaddr*) &s, sizeof(s)) < 0)
if (bind(sck, (struct sockaddr *) &s, sizeof(s)) < 0)
{
return -1;
}

View File

@ -23,6 +23,15 @@
#include "arch.h"
struct exit_status
{
/* set to -1 when the process exited via a signal */
uint8_t exit_code;
/* set to 0 when the process exited normally */
uint8_t signal_no;
};
#define g_tcp_can_recv g_sck_can_recv
#define g_tcp_can_send g_sck_can_send
#define g_tcp_recv g_sck_recv
@ -38,21 +47,21 @@
#define g_close_wait_obj g_delete_wait_obj
int g_rm_temp_dir(void);
int g_mk_socket_path(const char* app_name);
void g_init(const char* app_name);
int g_mk_socket_path(const char *app_name);
void g_init(const char *app_name);
void g_deinit(void);
void* g_malloc(int size, int zero);
void g_free(void* ptr);
void *g_malloc(int size, int zero);
void g_free(void *ptr);
void g_printf(const char *format, ...) printflike(1, 2);
void g_sprintf(char* dest, const char* format, ...) \
printflike(2, 3);
int g_snprintf(char* dest, int len, const char* format, ...) \
printflike(3, 4);
void g_writeln(const char* format, ...) printflike(1, 2);
void g_write(const char* format, ...) printflike(1, 2);
void g_sprintf(char *dest, const char *format, ...) \
printflike(2, 3);
int g_snprintf(char *dest, int len, const char *format, ...) \
printflike(3, 4);
void g_writeln(const char *format, ...) printflike(1, 2);
void g_write(const char *format, ...) printflike(1, 2);
void g_hexdump(const char *p, int len);
void g_memset(void* ptr, int val, int size);
void g_memcpy(void* d_ptr, const void* s_ptr, int size);
void g_memset(void *ptr, int val, int size);
void g_memcpy(void *d_ptr, const void *s_ptr, int size);
int g_getchar(void);
int g_tcp_set_no_delay(int sck);
int g_tcp_set_keepalive(int sck);
@ -65,26 +74,26 @@ int g_sck_local_socket(void);
int g_sck_vsock_socket(void);
int g_sck_get_peer_cred(int sck, int *pid, int *uid, int *gid);
void g_sck_close(int sck);
int g_tcp_connect(int sck, const char* address, const char* port);
int g_sck_local_connect(int sck, const char* port);
int g_tcp_connect(int sck, const char *address, const char *port);
int g_sck_local_connect(int sck, const char *port);
int g_sck_set_non_blocking(int sck);
int g_tcp_bind(int sck, const char *port);
int g_sck_local_bind(int sck, const char* port);
int g_sck_vsock_bind(int sck, const char* port);
int g_sck_local_bind(int sck, const char *port);
int g_sck_vsock_bind(int sck, const char *port);
int g_sck_vsock_bind_address(int sck, const char *port, const char *address);
int g_tcp_bind_address(int sck, const char* port, const char* address);
int g_tcp_bind_address(int sck, const char *port, const char *address);
int g_sck_listen(int sck);
int g_tcp_accept(int sck);
int g_sck_accept(int sck, char *addr, int addr_bytes,
char *port, int port_bytes);
int g_sck_recv(int sck, void* ptr, int len, int flags);
int g_sck_send(int sck, const void* ptr, int len, int flags);
char *port, int port_bytes);
int g_sck_recv(int sck, void *ptr, int len, int flags);
int g_sck_send(int sck, const void *ptr, int len, int flags);
int g_sck_last_error_would_block(int sck);
int g_sck_socket_ok(int sck);
int g_sck_can_send(int sck, int millis);
int g_sck_can_recv(int sck, int millis);
int g_sck_select(int sck1, int sck2);
void g_write_ip_address(int rcv_sck, char* ip_address, int bytes);
void g_write_ip_address(int rcv_sck, char *ip_address, int bytes);
void g_sleep(int msecs);
tintptr g_create_wait_obj(const char *name);
tintptr g_create_wait_obj_from_socket(tintptr socket, int write);
@ -93,40 +102,40 @@ int g_set_wait_obj(tintptr obj);
int g_reset_wait_obj(tintptr obj);
int g_is_wait_obj_set(tintptr obj);
int g_delete_wait_obj(tintptr obj);
int g_obj_wait(tintptr* read_objs, int rcount, tintptr* write_objs,
int wcount,int mstimeout);
void g_random(char* data, int len);
int g_obj_wait(tintptr *read_objs, int rcount, tintptr *write_objs,
int wcount, int mstimeout);
void g_random(char *data, int len);
int g_abs(int i);
int g_memcmp(const void* s1, const void* s2, int len);
int g_file_open(const char* file_name);
int g_memcmp(const void *s1, const void *s2, int len);
int g_file_open(const char *file_name);
int g_file_open_ex(const char *file_name, int aread, int awrite,
int acreate, int atrunc);
int acreate, int atrunc);
int g_file_close(int fd);
int g_file_read(int fd, char* ptr, int len);
int g_file_read(int fd, char *ptr, int len);
int g_file_write(int fd, const char *ptr, int len);
int g_file_seek(int fd, int offset);
int g_file_lock(int fd, int start, int len);
int g_chmod_hex(const char* filename, int flags);
int g_chown(const char* name, int uid, int gid);
int g_mkdir(const char* dirname);
char* g_get_current_dir(char* dirname, int maxlen);
int g_chmod_hex(const char *filename, int flags);
int g_chown(const char *name, int uid, int gid);
int g_mkdir(const char *dirname);
char *g_get_current_dir(char *dirname, int maxlen);
int g_set_current_dir(const char *dirname);
int g_file_exist(const char* filename);
int g_file_exist(const char *filename);
int g_file_readable(const char *filename);
int g_directory_exist(const char* dirname);
int g_create_dir(const char* dirname);
int g_create_path(const char* path);
int g_remove_dir(const char* dirname);
int g_file_delete(const char* filename);
int g_file_get_size(const char* filename);
long g_load_library(char* in);
int g_directory_exist(const char *dirname);
int g_create_dir(const char *dirname);
int g_create_path(const char *path);
int g_remove_dir(const char *dirname);
int g_file_delete(const char *filename);
int g_file_get_size(const char *filename);
long g_load_library(char *in);
int g_free_library(long lib);
void* g_get_proc_address(long lib, const char* name);
int g_system(char* aexec);
char* g_get_strerror(void);
void *g_get_proc_address(long lib, const char *name);
int g_system(char *aexec);
char *g_get_strerror(void);
int g_get_errno(void);
int g_execvp(const char* p1, char* args[]);
int g_execlp3(const char* a1, const char* a2, const char* a3);
int g_execvp(const char *p1, char *args[]);
int g_execlp3(const char *a1, const char *a2, const char *a3);
void g_signal_child_stop(void (*func)(int));
void g_signal_segfault(void (*func)(int));
void g_signal_hang_up(void (*func)(int));
@ -136,7 +145,7 @@ void g_signal_pipe(void (*func)(int));
void g_signal_usr1(void (*func)(int));
int g_fork(void);
int g_setgid(int pid);
int g_initgroups(const char* user, int gid);
int g_initgroups(const char *user, int gid);
int g_getuid(void);
int g_getgid(void);
int g_setuid(int pid);
@ -145,22 +154,23 @@ int g_getlogin(char *name, unsigned int len);
int g_setlogin(const char *name);
int g_waitchild(void);
int g_waitpid(int pid);
struct exit_status g_waitpid_status(int pid);
void g_clearenv(void);
int g_setenv(const char* name, const char* value, int rewrite);
char* g_getenv(const char* name);
int g_setenv(const char *name, const char *value, int rewrite);
char *g_getenv(const char *name);
int g_exit(int exit_code);
int g_getpid(void);
int g_sigterm(int pid);
int g_getuser_info(const char* username, int* gid, int* uid, char** shell,
char** dir, char** gecos);
int g_getgroup_info(const char* groupname, int* gid);
int g_check_user_in_group(const char* username, int gid, int* ok);
int g_getuser_info(const char *username, int *gid, int *uid, char **shell,
char **dir, char **gecos);
int g_getgroup_info(const char *groupname, int *gid);
int g_check_user_in_group(const char *username, int gid, int *ok);
int g_time1(void);
int g_time2(void);
int g_time3(void);
int g_save_to_bmp(const char* filename, char* data, int stride_bytes,
int width, int height, int depth, int bits_per_pixel);
void * g_shmat(int shmid);
int g_save_to_bmp(const char *filename, char *data, int stride_bytes,
int width, int height, int depth, int bits_per_pixel);
void *g_shmat(int shmid);
int g_shmdt(const void *shmaddr);
int g_gethostname(char *name, int len);
int g_mirror_memcpy(void *dst, const void *src, int len);

View File

@ -26,6 +26,7 @@
#define PARSE_H
#include "arch.h"
#include "log.h"
#if defined(L_ENDIAN)
#elif defined(B_ENDIAN)
@ -54,51 +55,97 @@ struct stream
};
/******************************************************************************/
#define s_check(s) ((s)->p <= (s)->end)
#define s_check(s) s_check_rem(s, 0)
/******************************************************************************/
#define s_check_rem(s, n) ((s)->p + (n) <= (s)->end)
/******************************************************************************/
/**
* @returns true if there are at least n bytes remaining in the stream,
* else false and logs an error message
*/
#define s_check_rem_and_log(s, n, msg_prefix) \
( s_check_rem((s), (n)) ? \
1 : \
LOG(LOG_LEVEL_ERROR, \
"%s Not enough bytes in the stream: expected %d, remaining %d", \
(msg_prefix), (n), s_rem(s)) \
&& 0 )
/******************************************************************************/
#define s_check_rem_out(s, n) ((s)->p + (n) <= (s)->data + (s)->size)
/******************************************************************************/
/**
* @returns true if there are at least n bytes remaining in the stream,
* else false and logs an error message
*/
#define s_check_rem_out_and_log(s, n, msg_prefix) \
( s_check_rem_out((s), (n)) ? \
1 : \
LOG(LOG_LEVEL_ERROR, \
"%s Not enough bytes in the stream: expected %d, remaining %d", \
(msg_prefix), (n), s_rem_out(s)) \
&& 0 )
/******************************************************************************/
#define s_check_end(s) ((s)->p == (s)->end)
/******************************************************************************/
/**
* @returns true if there are exactly 0 bytes remaining in the stream,
* else false and logs an error message
*/
#define s_check_end_and_log(s, msg_prefix) \
( s_check_end((s)) ? \
1 : \
LOG(LOG_LEVEL_ERROR, \
"%s Expected to be at the end of the stream, " \
"but there are %d bytes remaining", \
(msg_prefix), s_rem(s)) \
&& 0 )
/******************************************************************************/
#define s_rem(s) ((int) ((s)->end - (s)->p))
/******************************************************************************/
#define s_rem_out(s) ((int) ((s)->data + (s)->size - (s)->p))
/******************************************************************************/
#define make_stream(s) \
(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; \
} while (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)); \
} while (0)
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); \
} while (0)
{ \
(s)->h = (s)->p; \
(s)->p += (n); \
} while (0)
/******************************************************************************/
#define s_pop_layer(s, h) \
@ -109,238 +156,238 @@ struct stream
(s)->end = (s)->p
#define in_sint8(s, v) do \
{ \
(v) = *((signed char*)((s)->p)); \
(s)->p++; \
} while (0)
{ \
(v) = *((signed char*)((s)->p)); \
(s)->p++; \
} while (0)
/******************************************************************************/
#define in_uint8(s, v) do \
{ \
(v) = *((unsigned char*)((s)->p)); \
(s)->p++; \
} while (0)
{ \
(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; \
} while (0)
{ \
(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; \
} while (0)
{ \
(v) = *((signed short*)((s)->p)); \
(s)->p += 2; \
} while (0)
#endif
/******************************************************************************/
#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; \
} while (0)
{ \
(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; \
} while (0)
{ \
(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++; \
} while (0)
{ \
(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; \
} while (0)
{ \
(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; \
} while (0)
{ \
(v) = *((unsigned int*)((s)->p)); \
(s)->p += 4; \
} while (0)
#endif
/******************************************************************************/
#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; \
} while (0)
{ \
(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; \
} while (0)
{ \
(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++; \
} while (0)
{ \
(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)
/******************************************************************************/
#define out_uint8(s, v) do \
{ \
*((s)->p) = (unsigned char)(v); \
(s)->p++; \
} while (0)
{ \
*((s)->p) = (unsigned char)(v); \
(s)->p++; \
} while (0)
/******************************************************************************/
#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++; \
} while (0)
{ \
*((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; \
} while (0)
{ \
*((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++; \
} while (0)
{ \
*((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++; \
} while (0)
{ \
*((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; \
} while (0)
{ \
*((unsigned int*)((s)->p)) = (v); \
(s)->p += 4; \
} while (0)
#endif
/******************************************************************************/
#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++; \
} while (0)
{ \
*((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; \
} while (0)
{ \
*((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++; \
} while (0)
{ \
*((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); \
} while (0)
{ \
(v) = (s)->p; \
(s)->p += (n); \
} while (0)
/******************************************************************************/
#define in_uint8a(s, v, n) do \
{ \
g_memcpy((v), (s)->p, (n)); \
(s)->p += (n); \
} while (0)
{ \
g_memcpy((v), (s)->p, (n)); \
(s)->p += (n); \
} while (0)
/******************************************************************************/
#define in_uint8s(s, n) \
@ -348,10 +395,10 @@ struct stream
/******************************************************************************/
#define out_uint8p(s, v, n) do \
{ \
g_memcpy((s)->p, (v), (n)); \
(s)->p += (n); \
} while (0)
{ \
g_memcpy((s)->p, (v), (n)); \
(s)->p += (n); \
} while (0)
/******************************************************************************/
#define out_uint8a(s, v, n) \
@ -359,10 +406,10 @@ struct stream
/******************************************************************************/
#define out_uint8s(s, n) do \
{ \
g_memset((s)->p, 0, (n)); \
(s)->p += (n); \
} while (0)
{ \
g_memset((s)->p, 0, (n)); \
(s)->p += (n); \
} while (0)
/*
* @brief allocate a new stream
@ -371,11 +418,11 @@ struct stream
* @param _l length of new stream
******************************************************************************/
#define xstream_new(_s, _l) \
do \
{ \
make_stream((_s)); \
init_stream((_s), (_l)); \
} while (0)
do \
{ \
make_stream((_s)); \
init_stream((_s), (_l)); \
} while (0)
/**
* @brief release a previously allocated stream
@ -401,63 +448,63 @@ do \
#define xstream_wr_s32_le(_s, _var) TODO
#define xstream_rd_u64_le(_s, _v) \
do \
{ \
_v = \
(tui64)(*((unsigned char *)_s->p)) | \
(((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)
do \
{ \
_v = \
(tui64)(*((unsigned char *)_s->p)) | \
(((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)
#define xstream_wr_u64_le(_s, _v) \
do \
{ \
*(((unsigned char *) _s->p) + 0) = (unsigned char) ((_v >> 0) & 0xff); \
*(((unsigned char *) _s->p) + 1) = (unsigned char) ((_v >> 8) & 0xff); \
*(((unsigned char *) _s->p) + 2) = (unsigned char) ((_v >> 16) & 0xff); \
*(((unsigned char *) _s->p) + 3) = (unsigned char) ((_v >> 24) & 0xff); \
*(((unsigned char *) _s->p) + 4) = (unsigned char) ((_v >> 32) & 0xff); \
*(((unsigned char *) _s->p) + 5) = (unsigned char) ((_v >> 40) & 0xff); \
*(((unsigned char *) _s->p) + 6) = (unsigned char) ((_v >> 48) & 0xff); \
*(((unsigned char *) _s->p) + 7) = (unsigned char) ((_v >> 56) & 0xff); \
_s->p += 8; \
} while (0)
do \
{ \
*(((unsigned char *) _s->p) + 0) = (unsigned char) ((_v >> 0) & 0xff); \
*(((unsigned char *) _s->p) + 1) = (unsigned char) ((_v >> 8) & 0xff); \
*(((unsigned char *) _s->p) + 2) = (unsigned char) ((_v >> 16) & 0xff); \
*(((unsigned char *) _s->p) + 3) = (unsigned char) ((_v >> 24) & 0xff); \
*(((unsigned char *) _s->p) + 4) = (unsigned char) ((_v >> 32) & 0xff); \
*(((unsigned char *) _s->p) + 5) = (unsigned char) ((_v >> 40) & 0xff); \
*(((unsigned char *) _s->p) + 6) = (unsigned char) ((_v >> 48) & 0xff); \
*(((unsigned char *) _s->p) + 7) = (unsigned char) ((_v >> 56) & 0xff); \
_s->p += 8; \
} while (0)
/* copy data into stream */
#define xstream_copyin(_s, _dest, _len) \
do \
{ \
g_memcpy((_s)->p, (_dest), (_len)); \
(_s)->p += (_len); \
} while (0)
do \
{ \
g_memcpy((_s)->p, (_dest), (_len)); \
(_s)->p += (_len); \
} while (0)
/* copy data out of stream */
#define xstream_copyout(_dest, _s, _len) \
do \
{ \
g_memcpy((_dest), (_s)->p, (_len)); \
(_s)->p += (_len); \
} while (0)
do \
{ \
g_memcpy((_dest), (_s)->p, (_len)); \
(_s)->p += (_len); \
} while (0)
#define xstream_rd_string(_dest, _s, _len) \
do \
{ \
g_memcpy((_dest), (_s)->p, (_len)); \
(_s)->p += (_len); \
} while (0)
do \
{ \
g_memcpy((_dest), (_s)->p, (_len)); \
(_s)->p += (_len); \
} while (0)
#define xstream_wr_string(_s, _src, _len) \
do \
{ \
g_memcpy((_s)->p, (_src), (_len)); \
(_s)->p += (_len); \
} while (0)
do \
{ \
g_memcpy((_s)->p, (_src), (_len)); \
(_s)->p += (_len); \
} while (0)
#define xstream_len(_s) (int) ((_s)->p - (_s)->data)
#define xstream_seek(_s, _len) (_s)->p += (_len)

File diff suppressed because it is too large Load Diff

View File

@ -56,21 +56,21 @@ typedef struct pixman_region16 pixman_region16_t;
/* creation/destruction */
void pixman_region_init (pixman_region16_t *region);
void pixman_region_init_rect (pixman_region16_t *region,
int x,
int y,
unsigned int width,
unsigned int height);
/**/ int x,
/**/ int y,
/**/ unsigned int width,
/**/ unsigned int height);
void pixman_region_fini (pixman_region16_t *region);
pixman_bool_t pixman_region_union (pixman_region16_t *new_reg,
pixman_region16_t *reg1,
pixman_region16_t *reg2);
/**/ pixman_region16_t *reg1,
/**/ pixman_region16_t *reg2);
pixman_bool_t pixman_region_subtract (pixman_region16_t *reg_d,
pixman_region16_t *reg_m,
pixman_region16_t *reg_s);
/**/ pixman_region16_t *reg_m,
/**/ pixman_region16_t *reg_s);
pixman_bool_t pixman_region_intersect (pixman_region16_t *new_reg,
pixman_region16_t *reg1,
pixman_region16_t *reg2);
pixman_box16_t * pixman_region_rectangles (pixman_region16_t *region,
int *n_rects);
/**/ pixman_region16_t *reg1,
/**/ pixman_region16_t *reg2);
pixman_box16_t *pixman_region_rectangles (pixman_region16_t *region,
/**/ int *n_rects);
#endif

View File

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

View File

@ -64,8 +64,8 @@ static inline void
RSA_get0_key(const RSA *key, const BIGNUM **n, const BIGNUM **e,
const BIGNUM **d)
{
*n = key->n;
*d = key->d;
*n = key->n;
*d = key->d;
}
static inline int
@ -75,7 +75,7 @@ DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
* parameters MUST be non-NULL. q may remain NULL.
*/
if ((dh->p == NULL && p == NULL)
|| (dh->g == NULL && g == NULL))
|| (dh->g == NULL && g == NULL))
{
return 0;
}
@ -230,7 +230,7 @@ ssl_md5_complete(void *md5_info, char *data)
/*****************************************************************************/
void *
ssl_des3_encrypt_info_create(const char *key, const char* ivec)
ssl_des3_encrypt_info_create(const char *key, const char *ivec)
{
EVP_CIPHER_CTX *des3_ctx;
const tui8 *lkey;
@ -246,7 +246,7 @@ ssl_des3_encrypt_info_create(const char *key, const char* ivec)
/*****************************************************************************/
void *
ssl_des3_decrypt_info_create(const char *key, const char* ivec)
ssl_des3_decrypt_info_create(const char *key, const char *ivec)
{
EVP_CIPHER_CTX *des3_ctx;
const tui8 *lkey;
@ -348,7 +348,7 @@ ssl_hmac_transform(void *hmac, const char *data, int len)
const tui8 *ldata;
hmac_ctx = (HMAC_CTX *) hmac;
ldata = (const tui8*) data;
ldata = (const tui8 *) data;
HMAC_Update(hmac_ctx, ldata, len);
}
@ -357,7 +357,7 @@ void
ssl_hmac_complete(void *hmac, char *data, int len)
{
HMAC_CTX *hmac_ctx;
tui8* ldata;
tui8 *ldata;
tui32 llen;
hmac_ctx = (HMAC_CTX *) hmac;
@ -464,7 +464,7 @@ ssl_gen_key_xrdp1(int key_size_in_bits, const char *exp, int exp_len,
int diff;
if ((exp_len != 4) || ((mod_len != 64) && (mod_len != 256)) ||
((pri_len != 64) && (pri_len != 256)))
((pri_len != 64) && (pri_len != 256)))
{
return 1;
}
@ -532,7 +532,8 @@ see also
*/
static DH *ssl_get_dh2236()
{
static unsigned char dh2236_p[] = {
static unsigned char dh2236_p[] =
{
0x0E, 0xF8, 0x69, 0x0B, 0x35, 0x2F, 0x62, 0x59, 0xF7, 0xAF, 0x4E, 0x19,
0xB5, 0x9B, 0xD2, 0xEB, 0x33, 0x78, 0x1D, 0x43, 0x1D, 0xB6, 0xE4, 0xA3,
0x63, 0x47, 0x6A, 0xD4, 0xA8, 0x28, 0x11, 0x8C, 0x3F, 0xC8, 0xF1, 0x32,
@ -558,7 +559,8 @@ static DH *ssl_get_dh2236()
0x70, 0xAC, 0x58, 0x3A, 0x3C, 0x18, 0x15, 0x54, 0x84, 0xA8, 0xAA, 0x41,
0x26, 0x7B, 0xE0, 0xA3,
};
static unsigned char dh2236_g[] = {
static unsigned char dh2236_g[] =
{
0x02,
};
@ -613,14 +615,13 @@ ssl_tls_create(struct trans *trans, const char *key, const char *cert)
}
/*****************************************************************************/
int
ssl_tls_print_error(const char *func, SSL *connection, int value)
static int
ssl_tls_log_error(const char *func, SSL *connection, int value)
{
switch (SSL_get_error(connection, value))
{
case SSL_ERROR_ZERO_RETURN:
g_writeln("ssl_tls_print_error: %s: Server closed TLS connection",
func);
LOG(LOG_LEVEL_ERROR, "%s: Server closed TLS connection", func);
return 1;
case SSL_ERROR_WANT_READ:
@ -628,16 +629,15 @@ ssl_tls_print_error(const char *func, SSL *connection, int value)
return 0;
case SSL_ERROR_SYSCALL:
g_writeln("ssl_tls_print_error: %s: I/O error", func);
LOG(LOG_LEVEL_ERROR, "%s: I/O error", func);
return 1;
case SSL_ERROR_SSL:
g_writeln("ssl_tls_print_error: %s: Failure in SSL library (protocol error?)",
func);
LOG(LOG_LEVEL_ERROR, "%s: Failure in SSL library (protocol error?)", func);
return 1;
default:
g_writeln("ssl_tls_print_error: %s: Unknown error", func);
LOG(LOG_LEVEL_ERROR, "%s: Unknown SSL error", func);
return 1;
}
}
@ -694,7 +694,7 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
self->ctx = SSL_CTX_new(SSLv23_server_method());
if (self->ctx == NULL)
{
log_message(LOG_LEVEL_ERROR, "ssl_tls_accept: SSL_CTX_new failed");
LOG(LOG_LEVEL_ERROR, "Unable to negotiate a TLS connection with the client");
return 1;
}
@ -708,20 +708,19 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
DH *dh = ssl_get_dh2236();
if (dh == NULL)
{
log_message(LOG_LEVEL_ERROR, "ssl_tls_accept: ssl_get_dh2236 failed");
LOG(LOG_LEVEL_ERROR, "Unable to generate DHE parameters for TLS");
return 1;
}
if (SSL_CTX_set_tmp_dh(self->ctx, dh) != 1)
{
log_message(LOG_LEVEL_ERROR,
"ssl_tls_accept: SSL_CTX_set_tmp_dh failed");
LOG(LOG_LEVEL_ERROR, "Unable to setup DHE parameters for TLS");
return 1;
}
DH_free(dh); // ok to free, copied into ctx by SSL_CTX_set_tmp_dh()
#if defined(SSL_CTX_set_ecdh_auto)
if(!SSL_CTX_set_ecdh_auto(self->ctx, 1))
if (!SSL_CTX_set_ecdh_auto(self->ctx, 1))
{
LOG(LOG_LEVEL_WARNING, "TLS ecdh auto failed to be enabled");
}
@ -729,27 +728,26 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
if (g_strlen(tls_ciphers) > 1)
{
log_message(LOG_LEVEL_TRACE, "ssl_tls_accept: tls_ciphers=%s",
tls_ciphers);
LOG(LOG_LEVEL_TRACE, "tls_ciphers=%s", tls_ciphers);
if (SSL_CTX_set_cipher_list(self->ctx, tls_ciphers) == 0)
{
g_writeln("ssl_tls_accept: invalid cipher options");
LOG(LOG_LEVEL_ERROR, "Invalid TLS cipher options %s", tls_ciphers);
return 1;
}
}
SSL_CTX_set_read_ahead(self->ctx, 0);
if (SSL_CTX_use_RSAPrivateKey_file(self->ctx, self->key, SSL_FILETYPE_PEM)
if (SSL_CTX_use_PrivateKey_file(self->ctx, self->key, SSL_FILETYPE_PEM)
<= 0)
{
g_writeln("ssl_tls_accept: SSL_CTX_use_RSAPrivateKey_file failed");
LOG(LOG_LEVEL_ERROR, "Error loading TLS private key from %s", self->key);
return 1;
}
if (SSL_CTX_use_certificate_chain_file(self->ctx, self->cert) <= 0)
{
g_writeln("ssl_tls_accept: SSL_CTX_use_certificate_chain_file failed");
LOG(LOG_LEVEL_ERROR, "Error loading TLS certificate chain from %s", self->cert);
return 1;
}
@ -757,22 +755,24 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
if (self->ssl == NULL)
{
g_writeln("ssl_tls_accept: SSL_new failed");
LOG(LOG_LEVEL_ERROR, "Unable to create an SSL structure");
return 1;
}
if (SSL_set_fd(self->ssl, self->trans->sck) < 1)
{
g_writeln("ssl_tls_accept: SSL_set_fd failed");
LOG(LOG_LEVEL_ERROR, "Unable to set up an SSL structure on fd %d",
(int)self->trans->sck);
return 1;
}
while(1) {
while (1)
{
connection_status = SSL_accept(self->ssl);
if (connection_status <= 0)
{
if (ssl_tls_print_error("SSL_accept", self->ssl, connection_status))
if (ssl_tls_log_error("SSL_accept", self->ssl, connection_status))
{
return 1;
}
@ -797,7 +797,7 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
}
}
g_writeln("ssl_tls_accept: TLS connection accepted");
LOG(LOG_LEVEL_TRACE, "TLS connection accepted");
return 0;
}
@ -823,7 +823,7 @@ ssl_tls_disconnect(struct ssl_tls *self)
status = SSL_shutdown(self->ssl);
if (status <= 0)
{
if (ssl_tls_print_error("SSL_shutdown", self->ssl, status))
if (ssl_tls_log_error("SSL_shutdown", self->ssl, status))
{
return 1;
}
@ -844,10 +844,14 @@ ssl_tls_delete(struct ssl_tls *self)
if (self != NULL)
{
if (self->ssl)
{
SSL_free(self->ssl);
}
if (self->ctx)
{
SSL_CTX_free(self->ctx);
}
g_delete_wait_obj(self->rwo);
@ -862,7 +866,8 @@ ssl_tls_read(struct ssl_tls *tls, char *data, int length)
int status;
int break_flag;
while(1) {
while (1)
{
status = SSL_read(tls->ssl, data, length);
switch (SSL_get_error(tls->ssl, status))
@ -888,7 +893,7 @@ ssl_tls_read(struct ssl_tls *tls, char *data, int length)
return 0;
default:
ssl_tls_print_error("SSL_read", tls->ssl, status);
ssl_tls_log_error("SSL_read", tls->ssl, status);
status = -1;
break_flag = 1;
break;
@ -915,7 +920,8 @@ ssl_tls_write(struct ssl_tls *tls, const char *data, int length)
int status;
int break_flag;
while(1) {
while (1)
{
status = SSL_write(tls->ssl, data, length);
switch (SSL_get_error(tls->ssl, status))
@ -941,7 +947,7 @@ ssl_tls_write(struct ssl_tls *tls, const char *data, int length)
return 0;
default:
ssl_tls_print_error("SSL_write", tls->ssl, status);
ssl_tls_log_error("SSL_write", tls->ssl, status);
status = -1;
break_flag = 1;
break;
@ -1016,68 +1022,68 @@ ssl_get_protocols_from_string(const char *str, long *ssl_protocols)
if (g_pos(str, ",TLSv1.3,") >= 0)
{
#if defined(SSL_OP_NO_TLSv1_3)
log_message(LOG_LEVEL_DEBUG, "TLSv1.3 enabled");
LOG(LOG_LEVEL_DEBUG, "TLSv1.3 enabled");
protocols &= ~SSL_OP_NO_TLSv1_3;
#else
log_message(LOG_LEVEL_WARNING,
"TLSv1.3 enabled by config, "
"but not supported by system OpenSSL");
LOG(LOG_LEVEL_WARNING,
"TLSv1.3 enabled by config, "
"but not supported by system OpenSSL");
rv |= (1 << 6);
#endif
}
if (g_pos(str, ",TLSv1.2,") >= 0)
{
#if defined(SSL_OP_NO_TLSv1_2)
log_message(LOG_LEVEL_DEBUG, "TLSv1.2 enabled");
LOG(LOG_LEVEL_DEBUG, "TLSv1.2 enabled");
protocols &= ~SSL_OP_NO_TLSv1_2;
#else
log_message(LOG_LEVEL_WARNING,
"TLSv1.2 enabled by config, "
"but not supported by system OpenSSL");
LOG(LOG_LEVEL_WARNING,
"TLSv1.2 enabled by config, "
"but not supported by system OpenSSL");
rv |= (1 << 1);
#endif
}
if (g_pos(str, ",TLSv1.1,") >= 0)
{
#if defined(SSL_OP_NO_TLSv1_1)
log_message(LOG_LEVEL_DEBUG, "TLSv1.1 enabled");
LOG(LOG_LEVEL_DEBUG, "TLSv1.1 enabled");
protocols &= ~SSL_OP_NO_TLSv1_1;
#else
log_message(LOG_LEVEL_WARNING,
"TLSv1.1 enabled by config, "
"but not supported by system OpenSSL");
LOG(LOG_LEVEL_WARNING,
"TLSv1.1 enabled by config, "
"but not supported by system OpenSSL");
rv |= (1 << 2);
#endif
}
if (g_pos(str, ",TLSv1,") >= 0)
{
#if defined(SSL_OP_NO_TLSv1)
log_message(LOG_LEVEL_DEBUG, "TLSv1 enabled");
LOG(LOG_LEVEL_DEBUG, "TLSv1 enabled");
protocols &= ~SSL_OP_NO_TLSv1;
#else
log_message(LOG_LEVEL_WARNING,
"TLSv1 enabled by config, "
"but not supported by system OpenSSL");
LOG(LOG_LEVEL_WARNING,
"TLSv1 enabled by config, "
"but not supported by system OpenSSL");
rv |= (1 << 3);
#endif
}
if (g_pos(str, ",SSLv3,") >= 0)
{
#if defined(SSL_OP_NO_SSLv3)
log_message(LOG_LEVEL_DEBUG, "SSLv3 enabled");
LOG(LOG_LEVEL_DEBUG, "SSLv3 enabled");
protocols &= ~SSL_OP_NO_SSLv3;
#else
log_message(LOG_LEVEL_WARNING,
"SSLv3 enabled by config, "
"but not supported by system OpenSSL");
LOG(LOG_LEVEL_WARNING,
"SSLv3 enabled by config, "
"but not supported by system OpenSSL");
rv |= (1 << 4);
#endif
}
if (protocols == bad_protocols)
{
log_message(LOG_LEVEL_WARNING, "No SSL/TLS protocols enabled. "
"At least one protocol should be enabled to accept "
"TLS connections.");
LOG(LOG_LEVEL_WARNING, "No SSL/TLS protocols enabled. "
"At least one protocol should be enabled to accept "
"TLS connections.");
rv |= (1 << 5);
}
*ssl_protocols = protocols;

View File

@ -26,38 +26,38 @@ int
ssl_init(void);
int
ssl_finish(void);
void*
void *
ssl_rc4_info_create(void);
void
ssl_rc4_info_delete(void* rc4_info);
ssl_rc4_info_delete(void *rc4_info);
void
ssl_rc4_set_key(void* rc4_info, char* key, int len);
ssl_rc4_set_key(void *rc4_info, char *key, int len);
void
ssl_rc4_crypt(void* rc4_info, char* data, int len);
void*
ssl_rc4_crypt(void *rc4_info, char *data, int len);
void *
ssl_sha1_info_create(void);
void
ssl_sha1_info_delete(void* sha1_info);
ssl_sha1_info_delete(void *sha1_info);
void
ssl_sha1_clear(void* sha1_info);
ssl_sha1_clear(void *sha1_info);
void
ssl_sha1_transform(void* sha1_info, const char *data, int len);
ssl_sha1_transform(void *sha1_info, const char *data, int len);
void
ssl_sha1_complete(void* sha1_info, char* data);
void*
ssl_sha1_complete(void *sha1_info, char *data);
void *
ssl_md5_info_create(void);
void
ssl_md5_info_delete(void* md5_info);
ssl_md5_info_delete(void *md5_info);
void
ssl_md5_clear(void* md5_info);
ssl_md5_clear(void *md5_info);
void
ssl_md5_transform(void* md5_info, char* data, int len);
ssl_md5_transform(void *md5_info, char *data, int len);
void
ssl_md5_complete(void* md5_info, char* data);
ssl_md5_complete(void *md5_info, char *data);
void *
ssl_des3_encrypt_info_create(const char *key, const char* ivec);
ssl_des3_encrypt_info_create(const char *key, const char *ivec);
void *
ssl_des3_decrypt_info_create(const char *key, const char* ivec);
ssl_des3_decrypt_info_create(const char *key, const char *ivec);
void
ssl_des3_info_delete(void *des3);
int
@ -78,8 +78,8 @@ int
ssl_mod_exp(char *out, int out_len, const char *in, int in_len,
const char *mod, int mod_len, const char *exp, int exp_len);
int
ssl_gen_key_xrdp1(int key_size_in_bits, const char* exp, int exp_len,
char* mod, int mod_len, char* pri, int pri_len);
ssl_gen_key_xrdp1(int key_size_in_bits, const char *exp, int exp_len,
char *mod, int mod_len, char *pri, int pri_len);
/* ssl_tls */
struct ssl_tls

View File

@ -24,9 +24,13 @@
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <ctype.h>
#include "string_calls.h"
#include "log.h"
#include "os_calls.h"
#include "string_calls.h"
#include "defines.h"
unsigned int
g_format_info_string(char *dest, unsigned int len,
@ -139,6 +143,36 @@ g_text2bool(const char *s)
return 0;
}
/*****************************************************************************/
int
g_get_display_num_from_display(const char *display_text)
{
int rv = -1;
const char *p;
/* Skip over the hostname part of the DISPLAY */
if (display_text != NULL && (p = strchr(display_text, ':')) != NULL)
{
++p; /* Skip the ':' */
/* Cater for the (still supported) double-colon. See
* https://www.x.org/releases/X11R7.7/doc/libX11/libX11/libX11.html */
if (*p == ':')
{
++p;
}
/* Check it starts with a digit, to avoid oddities like DISPLAY=":zz.0"
* being parsed successfully */
if (isdigit(*p))
{
rv = g_atoi(p);
}
}
return rv;
}
/*****************************************************************************/
/* returns length of text */
int
@ -470,6 +504,129 @@ g_bytes_to_hexstr(const void *bytes, int num_bytes, char *out_str,
return rv;
}
/*****************************************************************************/
/* convert a byte array into a hex dump */
char *
g_bytes_to_hexdump(const char *src, int len)
{
unsigned char *line;
int i;
int dump_number_lines;
int dump_line_length;
int dump_length;
int dump_offset;
int thisline;
int offset;
char *dump_buffer;
#define HEX_DUMP_SOURCE_BYTES_PER_LINE (16)
#ifdef _WIN32
#define HEX_DUMP_NEWLINE_SIZE (2)
#else
#ifdef _MACOS
#define HEX_DUMP_NEWLINE_SIZE (1)
#else
#define HEX_DUMP_NEWLINE_SIZE (1)
#endif
#endif
dump_line_length = (4 + 3 /* = 4 offset + 3 space */
+ ((2 + 1) * HEX_DUMP_SOURCE_BYTES_PER_LINE) /* + (2 hex char + 1 space) per source byte */
+ 2 /* + 2 space */
+ HEX_DUMP_SOURCE_BYTES_PER_LINE
+ HEX_DUMP_NEWLINE_SIZE);
dump_number_lines = (len / HEX_DUMP_SOURCE_BYTES_PER_LINE) + 1; /* +1 to round up */
dump_length = (dump_number_lines *dump_line_length /* hex dump lines */
+ 1); /* terminating NULL */
dump_buffer = (char *)g_malloc(dump_length, 1);
if (dump_buffer == NULL)
{
LOG_DEVEL(LOG_LEVEL_WARNING,
"Failed to allocate buffer for hex dump of size %d",
dump_length);
return NULL;
}
line = (unsigned char *)src;
offset = 0;
dump_offset = 0;
while (offset < len)
{
g_sprintf(dump_buffer + dump_offset, "%04x ", offset);
dump_offset += 7;
thisline = len - offset;
if (thisline > HEX_DUMP_SOURCE_BYTES_PER_LINE)
{
thisline = HEX_DUMP_SOURCE_BYTES_PER_LINE;
}
for (i = 0; i < thisline; i++)
{
g_sprintf(dump_buffer + dump_offset, "%02x ", line[i]);
dump_offset += 3;
}
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
{
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
}
dump_buffer[dump_offset++] = ' ';
dump_buffer[dump_offset++] = ' ';
for (i = 0; i < thisline; i++)
{
dump_buffer[dump_offset++] = (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.';
}
for (; i < HEX_DUMP_SOURCE_BYTES_PER_LINE; i++)
{
dump_buffer[dump_offset++] = ' ';
}
#ifdef _WIN32
dump_buffer[dump_offset++] = '\r';
dump_buffer[dump_offset++] = '\n';
#else
#ifdef _MACOS
dump_buffer[dump_offset++] = '\r';
#else
dump_buffer[dump_offset++] = '\n';
#endif
#endif
offset += thisline;
line += thisline;
if (dump_offset % dump_line_length != 0)
{
LOG_DEVEL(LOG_LEVEL_WARNING,
"BUG: dump_offset (%d) at the end of a line is not a "
"multiple of the line length (%d)",
dump_offset, dump_line_length);
}
}
if (dump_offset > dump_length)
{
LOG_DEVEL(LOG_LEVEL_WARNING,
"BUG: dump_offset (%d) is larger than the dump_buffer length (%d)",
dump_offset, dump_length);
dump_buffer[0] = '\0';
return dump_buffer;
}
/* replace the last new line with the end of the string since log_message
will add a new line */
dump_buffer[dump_offset - HEX_DUMP_NEWLINE_SIZE] = '\0';
return dump_buffer;
}
/*****************************************************************************/
int
g_pos(const char *str, const char *to_find)
@ -651,3 +808,49 @@ g_strtrim(char *str, int trim_flags)
return 0;
}
/*****************************************************************************/
char *
g_strnjoin(char *dest, int dest_len, const char *joiner, const char *src[], int src_len)
{
int len = 0;
int joiner_len;
int i = 0;
int dest_remaining;
char *dest_pos = dest;
char *dest_end;
if (dest == NULL || dest_len < 1)
{
return dest;
}
if (src == NULL || src_len < 1)
{
dest[0] = '\0';
return dest;
}
dest[0] = '\0';
dest_end = dest + dest_len - 1;
joiner_len = g_strlen(joiner);
for (i = 0; i < src_len - 1 && dest_pos < dest_end; i++)
{
len = g_strlen(src[i]);
dest_remaining = dest_end - dest_pos;
g_strncat(dest_pos, src[i], dest_remaining);
dest_pos += MIN(len, dest_remaining);
if (dest_pos < dest_end)
{
dest_remaining = dest_end - dest_pos;
g_strncat(dest_pos, joiner, dest_remaining);
dest_pos += MIN(joiner_len, dest_remaining);
}
}
if (i == src_len - 1 && dest_pos < dest_end)
{
g_strncat(dest_pos, src[i], dest_end - dest_pos);
}
return dest;
}

View File

@ -80,6 +80,66 @@ g_bool2text(int value);
int
g_text2bool(const char *s);
/**
* Joins an array of strings into a single string.
*
* Note: The joiner is placed between each source string. The joiner is not
* placed after the last source string. If there is only one source string,
* then the result string will be equal to the source string.
*
* Note: any content that is present in dest will be overwritten with the new
* joined string.
*
* Note: If the destination array is not large enough to hold the entire
* contents of the joined string, then the joined string will be truncated
* to fit in the destination array.
*
* @param[out] dest The destination array to write the joined string into.
* @param[in] dest_len The max number of characters to write to the destination
* array including the terminating null. Must be > 0
* @param[in] joiner The string to concatenate between each source string.
* The joiner string may be NULL which is processed as a zero length string.
* @param[in] src An array of strings to join. The array must be non-null.
* Array items may be NULL and are processed as zero length strings.
* @param[in] src_len The number of strings to join in the src array. Must be > 0
* @return A pointer to the begining of the joined string (ie. returns dest).
*/
char *
g_strnjoin(char *dest, int dest_len, const char *joiner, const char *src[], int src_len);
/**
* Converts a binary array into a hux dump suitable for displaying to a user.
*
* The format of the hex dump is:
* 0000 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 ................
* /\ /\ /\
* | | |
* | | ascii representation of bytes
* | hex representation of bytes
* offset from beginning of the byte array in hex
*
* Note: the ascii representation uses '.' for all non-printable
* characters (eg. below 32 or above 127).
*
* Note: the string contains embedded new lines, but is not new line terminated.
*
* @param[in] src Value to convert
* @param[in] len The number of bytes in src to convert
* @return string containing the hex dump that must be free'd by the caller
*/
char *
g_bytes_to_hexdump(const char *src, int len);
/**
* Extracts the display number from an X11 display string
*
* @param Display string (i.e. g_getenv("DISPLAY"))
*
* @result <0 if the string could not be parsed, or >=0 for a display number
*/
int
g_get_display_num_from_display(const char *display_text);
int g_strlen(const char *text);
const char *g_strchr(const char *text, int c);
char *g_strcpy(char *dest, const char *src);

View File

@ -55,7 +55,7 @@ tc_thread_create(unsigned long (__stdcall *start_routine)(void *), void *arg)
}
#else
int
tc_thread_create(void * (* start_routine)(void *), void *arg)
tc_thread_create(void *(* start_routine)(void *), void *arg)
{
int rv = 0;
pthread_t thread = (pthread_t)0;

View File

@ -24,7 +24,7 @@
#include "arch.h"
int
tc_thread_create(THREAD_RV (THREAD_CC * start_routine)(void*), void* arg);
tc_thread_create(THREAD_RV (THREAD_CC *start_routine)(void *), void *arg);
tbus
tc_get_threadid(void);
int

View File

@ -28,6 +28,7 @@
#include "arch.h"
#include "parse.h"
#include "ssl_calls.h"
#include "log.h"
#define MAX_SBYTES 0
@ -454,7 +455,7 @@ trans_force_read_s(struct trans *self, struct stream *in_s, int size)
int rcvd;
if (self->status != TRANS_STATUS_UP ||
size < 0 || !s_check_rem_out(in_s, size))
size < 0 || !s_check_rem_out(in_s, size))
{
return 1;
}
@ -635,7 +636,7 @@ trans_write_copy_s(struct trans *self, struct stream *out_s)
if (self->si != 0)
{
if ((self->si->cur_source != XRDP_SOURCE_NONE) &&
(self->si->cur_source != self->my_source))
(self->si->cur_source != self->my_source))
{
self->si->source[self->si->cur_source] += size;
wait_s->source = self->si->source + self->si->cur_source;
@ -662,7 +663,7 @@ trans_write_copy_s(struct trans *self, struct stream *out_s)
/*****************************************************************************/
int
trans_write_copy(struct trans* self)
trans_write_copy(struct trans *self)
{
return trans_write_copy_s(self, self->out_s);
}
@ -824,7 +825,9 @@ trans_listen_address(struct trans *self, char *port, const char *address)
{
self->sck = g_tcp_socket();
if (self->sck < 0)
{
return 1;
}
g_tcp_set_non_blocking(self->sck);
@ -846,7 +849,9 @@ trans_listen_address(struct trans *self, char *port, const char *address)
self->sck = g_tcp_local_socket();
if (self->sck < 0)
{
return 1;
}
g_tcp_set_non_blocking(self->sck);
@ -975,13 +980,13 @@ trans_set_tls_mode(struct trans *self, const char *key, const char *cert,
self->tls = ssl_tls_create(self, key, cert);
if (self->tls == NULL)
{
g_writeln("trans_set_tls_mode: ssl_tls_create malloc error");
LOG(LOG_LEVEL_ERROR, "trans_set_tls_mode: ssl_tls_create malloc error");
return 1;
}
if (ssl_tls_accept(self->tls, ssl_protocols, tls_ciphers) != 0)
{
g_writeln("trans_set_tls_mode: ssl_tls_accept failed");
LOG(LOG_LEVEL_ERROR, "trans_set_tls_mode: ssl_tls_accept failed");
return 1;
}

View File

@ -40,9 +40,9 @@
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 (*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 (*trans_recv_proc) (struct trans *self, char *ptr, int len);
typedef int (*trans_send_proc) (struct trans *self, const char *data, int len);
@ -97,13 +97,13 @@ struct trans
int type1; /* 1 listener 2 server 3 client */
ttrans_data_in trans_data_in;
ttrans_conn_in trans_conn_in;
void* callback_data;
void *callback_data;
int header_size;
struct stream* in_s;
struct stream* out_s;
char* listen_filename;
struct stream *in_s;
struct stream *out_s;
char *listen_filename;
tis_term is_term; /* used to test for exit */
struct stream* wait_s;
struct stream *wait_s;
char addr[256];
char port[256];
int no_stream_init_on_data_in;
@ -118,43 +118,43 @@ struct trans
enum xrdp_source my_source;
};
struct trans*
struct trans *
trans_create(int mode, int in_size, int out_size);
void
trans_delete(struct trans* self);
trans_delete(struct trans *self);
void
trans_delete_from_child(struct trans* self);
trans_delete_from_child(struct trans *self);
int
trans_get_wait_objs(struct trans* self, tbus* objs, int* count);
trans_get_wait_objs(struct trans *self, tbus *objs, int *count);
int
trans_get_wait_objs_rw(struct trans *self,
tbus *robjs, int *rcount,
tbus *wobjs, int *wcount, int *timeout);
int
trans_check_wait_objs(struct trans* self);
trans_check_wait_objs(struct trans *self);
int
trans_force_read_s(struct trans* self, struct stream* in_s, int size);
trans_force_read_s(struct trans *self, struct stream *in_s, int size);
int
trans_force_write_s(struct trans* self, struct stream* out_s);
trans_force_write_s(struct trans *self, struct stream *out_s);
int
trans_force_read(struct trans* self, int size);
trans_force_read(struct trans *self, int size);
int
trans_force_write(struct trans* self);
trans_force_write(struct trans *self);
int
trans_write_copy(struct trans* self);
trans_write_copy(struct trans *self);
int
trans_write_copy_s(struct trans* self, struct stream* out_s);
trans_write_copy_s(struct trans *self, struct stream *out_s);
int
trans_connect(struct trans* self, const char* server, const char* port,
trans_connect(struct trans *self, const char *server, const char *port,
int timeout);
int
trans_listen_address(struct trans* self, char* port, const char* address);
trans_listen_address(struct trans *self, char *port, const char *address);
int
trans_listen(struct trans* self, char* port);
struct stream*
trans_get_in_s(struct trans* self);
struct stream*
trans_get_out_s(struct trans* self, int size);
trans_listen(struct trans *self, char *port);
struct stream *
trans_get_in_s(struct trans *self);
struct stream *
trans_get_out_s(struct trans *self, int size);
int
trans_set_tls_mode(struct trans *self, const char *key, const char *cert,
long ssl_protocols, const char *tls_ciphers);

View File

@ -19,149 +19,162 @@
*/
#include "xrdp_constants.h"
#include "ms-rdpbcgr.h"
#if !defined(XRDP_CLIENT_INFO_H)
#define XRDP_CLIENT_INFO_H
struct monitor_info
{
int left;
int top;
int right;
int bottom;
int is_primary;
int left;
int top;
int right;
int bottom;
int is_primary;
};
/**
* Information about the xrdp client
*
* @note This structure is shared with xorgxrdp. If you change anything
* above the 'private to xrdp below this line' comment, you MUST
* bump the CLIENT_INFO_CURRENT_VERSION number so that the mismatch
* can be detected.
*/
struct xrdp_client_info
{
int size; /* bytes for this structure */
int bpp;
int width;
int height;
/* bitmap cache info */
int cache1_entries;
int cache1_size;
int cache2_entries;
int cache2_size;
int cache3_entries;
int cache3_size;
int bitmap_cache_persist_enable; /* 0 or 2 */
int bitmap_cache_version; /* ored 1 = original version, 2 = v2, 4 = v3 */
/* pointer info */
int pointer_cache_entries;
/* other */
int use_bitmap_comp;
int use_bitmap_cache;
int op1; /* use smaller bitmap header, non cache */
int op2; /* use smaller bitmap header in bitmap cache */
int desktop_cache;
int use_compact_packets; /* rdp5 smaller packets */
char hostname[32];
int build;
int keylayout;
char username[INFO_CLIENT_MAX_CB_LEN];
char password[INFO_CLIENT_MAX_CB_LEN];
char domain[INFO_CLIENT_MAX_CB_LEN];
char program[INFO_CLIENT_MAX_CB_LEN];
char directory[INFO_CLIENT_MAX_CB_LEN];
int rdp_compression;
int rdp_autologin;
int crypt_level; /* 1, 2, 3 = low, medium, high */
int channels_allowed; /* 0 = no channels 1 = channels */
int sound_code; /* 1 = leave sound at server */
int is_mce;
int rdp5_performanceflags;
int brush_cache_code; /* 0 = no cache 1 = 8x8 standard cache
int size; /* bytes for this structure */
int version; /* Should be CLIENT_INFO_CURRENT_VERSION */
int bpp;
int width;
int height;
/* bitmap cache info */
int cache1_entries;
int cache1_size;
int cache2_entries;
int cache2_size;
int cache3_entries;
int cache3_size;
int bitmap_cache_persist_enable; /* 0 or 2 */
int bitmap_cache_version; /* ored 1 = original version, 2 = v2, 4 = v3 */
/* pointer info */
int pointer_cache_entries;
/* other */
int use_bitmap_comp;
int use_bitmap_cache;
int op1; /* use smaller bitmap header, non cache */
int op2; /* use smaller bitmap header in bitmap cache */
int desktop_cache;
int use_compact_packets; /* rdp5 smaller packets */
char hostname[32];
int build;
int keylayout;
char username[INFO_CLIENT_MAX_CB_LEN];
char password[INFO_CLIENT_MAX_CB_LEN];
char domain[INFO_CLIENT_MAX_CB_LEN];
char program[INFO_CLIENT_MAX_CB_LEN];
char directory[INFO_CLIENT_MAX_CB_LEN];
int rdp_compression;
int rdp_autologin;
int crypt_level; /* 1, 2, 3 = low, medium, high */
int channels_allowed; /* 0 = no channels 1 = channels */
int sound_code; /* 1 = leave sound at server */
int is_mce;
int rdp5_performanceflags;
int brush_cache_code; /* 0 = no cache 1 = 8x8 standard cache
2 = arbitrary dimensions */
char client_ip[256];
int max_bpp;
int jpeg; /* non standard bitmap cache v2 cap */
int offscreen_support_level;
int offscreen_cache_size;
int offscreen_cache_entries;
int rfx;
char client_ip[256];
int max_bpp;
int jpeg; /* non standard bitmap cache v2 cap */
int offscreen_support_level;
int offscreen_cache_size;
int offscreen_cache_entries;
int rfx;
/* CAPSETTYPE_RAIL */
int rail_support_level;
/* CAPSETTYPE_WINDOW */
int wnd_support_level;
int wnd_num_icon_caches;
int wnd_num_icon_cache_entries;
/* codecs */
int rfx_codec_id;
int rfx_prop_len;
char rfx_prop[64];
int ns_codec_id;
int ns_prop_len;
char ns_prop[64];
int jpeg_codec_id;
int jpeg_prop_len;
char jpeg_prop[64];
int v3_codec_id;
int rfx_min_pixel;
char orders[32];
int order_flags_ex;
int use_bulk_comp;
int pointer_flags; /* 0 color, 1 new, 2 no new */
int use_fast_path;
int require_credentials; /* when true, credentials *must* be passed on cmd line */
char client_addr[256];
char client_port[256];
/* CAPSETTYPE_RAIL */
int rail_support_level;
/* CAPSETTYPE_WINDOW */
int wnd_support_level;
int wnd_num_icon_caches;
int wnd_num_icon_cache_entries;
/* codecs */
int rfx_codec_id;
int rfx_prop_len;
char rfx_prop[64];
int ns_codec_id;
int ns_prop_len;
char ns_prop[64];
int jpeg_codec_id;
int jpeg_prop_len;
char jpeg_prop[64];
int v3_codec_id;
int rfx_min_pixel;
char orders[32];
int order_flags_ex;
int use_bulk_comp;
int pointer_flags; /* 0 color, 1 new, 2 no new */
int use_fast_path;
int require_credentials; /* when true, credentials *must* be passed on cmd line */
char client_addr[256];
char client_port[256];
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 */
struct monitor_info minfo_wm[16]; /* client monitor data, non-negative values */
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[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data */
struct monitor_info minfo_wm[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS]; /* client monitor data, non-negative values */
int keyboard_type;
int keyboard_subtype;
int keyboard_type;
int keyboard_subtype;
int png_codec_id;
int png_prop_len;
char png_prop[64];
int vendor_flags[4];
int mcs_connection_type;
int mcs_early_capability_flags;
int png_codec_id;
int png_prop_len;
char png_prop[64];
int vendor_flags[4];
int mcs_connection_type;
int mcs_early_capability_flags;
int max_fastpath_frag_bytes;
int capture_code;
int capture_format;
int max_fastpath_frag_bytes;
int capture_code;
int capture_format;
char certificate[1024];
char key_file[1024];
char certificate[1024];
char key_file[1024];
/* X11 keyboard layout - inferred from keyboard type/subtype */
char model[16];
char layout[16];
char variant[16];
char options[256];
/* X11 keyboard layout - inferred from keyboard type/subtype */
char model[16];
char layout[16];
char variant[16];
char options[256];
/* !!!!!!!!!!!!!!!!!!!!!!!!!! */
/* NO CHANGES ABOVE THIS LINE */
/* !!!!!!!!!!!!!!!!!!!!!!!!!! */
/* ==================================================================== */
/* Private to xrdp below this line */
/* ==================================================================== */
/* codec */
int h264_codec_id;
int h264_prop_len;
char h264_prop[64];
/* codec */
int h264_codec_id;
int h264_prop_len;
char h264_prop[64];
int use_frame_acks;
int max_unacknowledged_frame_count;
int use_frame_acks;
int max_unacknowledged_frame_count;
long ssl_protocols;
char *tls_ciphers;
long ssl_protocols;
char *tls_ciphers;
int client_os_major;
int client_os_minor;
int client_os_major;
int client_os_minor;
int no_orders_supported;
int use_cache_glyph_v2;
int rail_enable;
int suppress_output;
int no_orders_supported;
int use_cache_glyph_v2;
int rail_enable;
int suppress_output;
int enable_token_login;
char domain_user_separator[16];
int enable_token_login;
char domain_user_separator[16];
};
/* yyyymmdd of last incompatible change to xrdp_client_info */
#define CLIENT_INFO_CURRENT_VERSION 20210225
#endif

View File

@ -95,8 +95,8 @@
* not yet sorted out
*/
#define MCS_CONNECT_INITIAL 0x7f65
#define MCS_CONNECT_RESPONSE 0x7f66
#define MCS_CONNECT_INITIAL 0x7f65 /* MCS BER: big endian, class=application (0x4000), constructed (0x2000), tag number > 30 (0x1f00), tag number=101 (0x0065) */
#define MCS_CONNECT_RESPONSE 0x7f66 /* MCS BER: application 102 */
#define BER_TAG_BOOLEAN 1
#define BER_TAG_INTEGER 2
@ -180,7 +180,7 @@
#define MASK_REMOVE_BITS(var, mask) (var &= ~mask)
#define MASK_HAS_BITS(var, mask) ((var & mask)>0)
#define MASK_CHANGE_BIT(var, mask, active) \
(var = ((var & ~mask) | (active ? mask : 0)))
(var = ((var & ~mask) | (active ? mask : 0)))
/* Clipboard constants, "borrowed" from GCC system headers in
the w32 cross compiler */

View File

@ -65,6 +65,10 @@ if test "x$with_systemdsystemunitdir" != xno; then
fi
AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
AC_ARG_ENABLE(tests,
AC_HELP_STRING([--enable-tests],
[Ensure dependencies for the tests are installed]),
[ensure_tests_deps=yes], [])
AC_ARG_ENABLE(pam, AS_HELP_STRING([--enable-pam],
[Build PAM support (default: yes)]),
[], [enable_pam=yes])
@ -263,9 +267,9 @@ then
AC_DEFINE([XRDP_ENABLE_IPV6],1,[Enable IPv6])
fi
if test "x$enable_pam" != "xyes"
if test "x$enable_pam" = "xyes"
then
AC_DEFINE([USE_NOPAM],1,[Disable PAM])
AC_DEFINE([USE_PAM],1,[Enable PAM])
fi
AS_IF( [test "x$enable_neutrinordp" = "xyes"] , [PKG_CHECK_MODULES(FREERDP, freerdp >= 1.0.0)] )
@ -357,6 +361,24 @@ AC_CHECK_HEADER([X11/extensions/Xrandr.h], [],
CFLAGS="$save_CFLAGS"
# perform unit tests if libcheck found
if test "x$ensure_tests_deps" == "xyes"; then
PKG_CHECK_MODULES([CHECK], [check >= 0.10.0],
[perform_unit_tests=yes],
[AC_MSG_ERROR([please install check, the unit test framework])])
else
PKG_CHECK_MODULES([CHECK], [check >= 0.10.0],
[perform_unit_tests=yes],
[perform_unit_tests=no])
fi
if test "x$perform_unit_tests" == "xyes"; then
AC_MSG_NOTICE([libcheck found, unit tests will be performed])
else
AC_MSG_NOTICE([libcheck not found, unit tests will be skipped])
fi
# -- end perform unit tests
AC_SUBST([moduledir], '${libdir}/xrdp')
AC_ARG_ENABLE([strict-locations],
@ -397,6 +419,12 @@ AC_CONFIG_FILES([
sesman/libscp/Makefile
sesman/Makefile
sesman/tools/Makefile
tests/Makefile
tests/common/Makefile
tests/memtest/Makefile
tools/Makefile
tools/devel/Makefile
tools/devel/tcp_proxy/Makefile
vnc/Makefile
xrdpapi/Makefile
xrdp/Makefile
@ -404,6 +432,7 @@ AC_CONFIG_FILES([
xup/Makefile
])
AC_REQUIRE_AUX_FILE([tap-driver.sh])
AC_OUTPUT
echo ""
@ -432,6 +461,8 @@ echo " libdir $libdir"
echo " bindir $bindir"
echo " sysconfdir $sysconfdir"
echo ""
echo " unit tests performable $perform_unit_tests"
echo ""
echo " CFLAGS = $CFLAGS"
echo " LDFLAGS = $LDFLAGS"

View File

@ -15,10 +15,12 @@ EXTRA_DIST = $(man_MANS:=.in)
SUBST_VARS = sed \
-e 's|@PACKAGE_VERSION[@]|$(PACKAGE_VERSION)|g' \
-e 's|@bindir[@]|$(bindir)|g' \
-e 's|@sbindir[@]|$(sbindir)|g' \
-e 's|@localstatedir[@]|$(localstatedir)|g' \
-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
-e 's|@socketdir[@]|$(socketdir)|g' \
-e 's|@xrdpconfdir[@]|$(sysconfdir)/xrdp|g'
-e 's|@xrdpconfdir[@]|$(sysconfdir)/xrdp|g' \
-e 's|@xrdphomeurl[@]|http://www.xrdp.org/|g'
subst_verbose = $(subst_verbose_@AM_V@)
subst_verbose_ = $(subst_verbose_@AM_DEFAULT_V@)

View File

@ -304,4 +304,6 @@ environment variables in the user's session.
.BR xrdp (8),
.BR xrdp.ini (5)
For more info on \fBxrdp\fR see http://www.xrdp.org/
For more info on \fBxrdp\fR see
.UR @xrdphomeurl@
.UE

View File

@ -57,4 +57,6 @@ description of \fBCHANSRV_LOG_PATH\fP above for the file's location.
.BR xrdp\-sesman (8),
.BR sesman.ini (5).
for more info on \fBxrdp\fR see http://www.xrdp.org/
For more info on \fBxrdp\fR see
.UR @xrdphomeurl@
.UE

View File

@ -61,7 +61,13 @@ Simone Fedele <ilsimo@users.sourceforge.net>
.SH "SEE ALSO"
.BR xrdp (8),
.BR setxkbmap (1),
.BR unicode (7),
.URL "https://github.com/FreeRDP/FreeRDP/wiki/Keyboard" "Description of Keyboard Input mapping" .
for more info on \fBxrdp\fR see http://www.xrdp.org/
.BR unicode (7)
.PP
Description of Keyboard Input mapping on the
.UR https://github.com/FreeRDP/FreeRDP/wiki/Keyboard
FreeRDP wiki
.UE
.PP
For more info on \fBxrdp\fR see
.UR @xrdphomeurl@
.UE

View File

@ -55,3 +55,8 @@ xrdp\-sesadmin.log
.SH SEE ALSO
.BR xrdp (8).
More info on \fBxrdp\fR can be found on the
.UR @xrdphomeurl@
xrdp homepage
.UE

View File

@ -13,7 +13,7 @@ xrdp\-sesman \- \fBxrdp\fR(8) session manager
\-\-version
.br
.B xrdp\-sesman
[ \-\-nodaemon ] [ --config /path/to/sesman.ini ]
[\-\-nodaemon] [\-\-dump\-config] [\-\-config /path/to/sesman.ini]
.SH "DESCRIPTION"
\fBxrdp\-sesman\fR is \fBxrdp\fR(8) session manager.
@ -34,6 +34,10 @@ Output version information and exit.
\fB\-n\fR, \fB\-\-nodaemon\fR
Starts \fBxrdp\-sesman\fR in foreground instead of starting it as a daemon.
.TP
\fB\-\-dump\-config\fR
Print the configuration on stdout before starting the daemon.
The default is not to do this.
.TP
\fB\-c\fR, \fB\-\-config\fR
Specify a path to a different \fIsesman.ini\fR file. This option is intended
to be used primarily for testing or for unusual configurations.
@ -45,7 +49,7 @@ the system (notably \fBxrdp(8)\fR and \fBxrdp\-chansrv(8)\fR) will want
to read it.
.RE
.SH "FILES"
@bindir@/xrdp\-sesman
@sbindir@/xrdp\-sesman
.br
@bindir@/xrdp\-sesrun
.br
@ -66,4 +70,6 @@ Simone Fedele <ilsimo@users.sourceforge.net>
.BR xrdp (8),
.BR xrdp.ini (5)
for more info on \fBxrdp\fR see http://www.xrdp.org/
for more info on \fBxrdp\fR see
.UR @xrdphomeurl@
.UE

View File

@ -77,7 +77,7 @@ properly. Note you would need to install the \fBxterm\fR utility
first. The \fBgnome\-terminal\fR utility probably won't work here.
.SH "FILES"
@bindir@/xrdp\-sesman
@sbindir@/xrdp\-sesman
.br
@bindir@/xrdp\-sesrun
.br
@ -94,4 +94,6 @@ Simone Fedele <ilsimo@users.sourceforge.net>
.BR xrdp (8),
.BR xrdp.ini (5)
for more info on \fBxrdp\fR see http://www.xrdp.org/
For more info on \fBxrdp\fR see
.UR @xrdphomeurl@
.UE

View File

@ -13,7 +13,7 @@
\-\-version
.br
.B xrdp
[ \-\-nodaemon ] [ --port port ] [ --fork ] [ --config /path/to/xrdp.ini ]
[\-\-nodaemon] [\-\-port port] [\-\-fork] [\-\-dump\-config] [\-\-config /path/to/xrdp.ini]
.SH "DESCRIPTION"
\fBxrdp\fR is a Remote Desktop Protocol (RDP) Server.
@ -45,13 +45,17 @@ Fork a new process on a new connection. If not enabled, use a new thread
for every connection. This overrides \fIfork\fR setting in
\fIxrdp.ini\fR file.
.TP
\fB\-\-dump\-config\fR
Print the configuration on stdout before starting the daemon.
The default is not to do this.
.TP
\fB\-c\fR, \fB\-\-config\fR
Specify a path to a different \fIxrdp.ini\fR file. This option is intended
to be used primarily for testing or for unusual configurations.
.SH "FILES"
@bindir@/xrdp
@sbindir@/xrdp
.br
@sysconfdir@/xrdp/xrdp.ini
.br
@ -70,4 +74,6 @@ Simone Fedele <ilsimo@users.sourceforge.net>
.BR sesman.ini (5),
.BR sesrun (8)
for more info on \fBxrdp\fR see http://www.xrdp.org/
for more info on \fBxrdp\fR see
.UR @xrdphomeurl@
.UE

View File

@ -232,7 +232,7 @@ This option can have one of the following values:
\fBINFO\fR or \fB3\fR \- Logs errors, warnings and informational messages
\fBDEBUG\fR or \fB4\fR \- Log everything. If \fBsesman\fR is compiled in debug mode, this options will output many more low\-level message, useful for developers
\fBDEBUG\fR or \fB4\fR \- Log everything. If \fBxrdp-sesman\fR is compiled in debug mode, this options will output many more low\-level message, useful for developers
.TP
\fBEnableSyslog\fR=\fI[true|false]\fR
@ -338,6 +338,16 @@ values supported for a particular release of \fBxrdp\fR(8) are documented in
Specifies the session type. The default, \fI0\fR, is Xvnc, \fI10\fR is
X11rdp, and \fI20\fR is Xorg with xorgxrdp modules.
.TP
\fBchansrvport\fR=\fBDISPLAY(\fR\fIn\fR\fB)\fR|\fI/path/to/domain-socket\fR
Asks xrdp to connect to a manually started \fBxrdp-chansrv\fR instance.
This can be useful if you wish to use to use xrdp to connect to a VNC session
which has been started other than by \fBxrdp-sesman\fR, as you can then make
use of \fBxrdp\-chansrv\fR facilities in the VNC session.
The first form of this setting is recommended, replacing \fIn\fR with the
X11 display number of the session.
.SH "EXAMPLES"
This is an example \fBxrdp.ini\fR:
@ -369,8 +379,11 @@ password={base64}cGFzc3dvcmQhCg==
.SH "SEE ALSO"
.BR xrdp (8),
.BR sesman (8),
.BR sesrun (8),
.BR xrdp\-chansrv (8),
.BR xrdp\-sesman (8),
.BR xrdp\-sesrun (8),
.BR sesman.ini (5)
for more info on \fBxrdp\fR see http://www.xrdp.org/
For more info on \fBxrdp\fR see
.UR @xrdphomeurl@
.UE

View File

@ -132,19 +132,19 @@ libxrdp_force_read(struct trans *trans)
if (trans_force_read(trans, 4) != 0)
{
LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: header read error");
return 0;
LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: header read error");
return NULL;
}
bytes = libxrdp_get_pdu_bytes(s->data);
if (bytes < 4 || bytes > s->size)
{
LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: bad header length %d", bytes);
return 0;
LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: bad header length %d", bytes);
return NULL;
}
if (trans_force_read(trans, bytes - 4) != 0)
{
LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: Can't read PDU");
return 0;
LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: Can't read PDU");
return NULL;
}
return s;
}
@ -234,12 +234,16 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s)
dead_lock_counter++;
break;
case PDUTYPE_CONFIRMACTIVEPDU:
LOG_DEVEL(LOG_LEVEL_TRACE, "Processing received "
"[MS-RDPBCGR] PDUTYPE_CONFIRMACTIVEPDU");
xrdp_caps_process_confirm_active(rdp, s);
break;
case PDUTYPE_DATAPDU:
LOG_DEVEL(LOG_LEVEL_TRACE, "Processing received "
"[MS-RDPBCGR] PDUTYPE_DATAPDU");
if (xrdp_rdp_process_data(rdp, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data returned non zero");
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data: xrdp_rdp_process_data failed");
cont = 0;
term = 1;
}
@ -247,13 +251,13 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s)
case 2: /* FASTPATH_INPUT_EVENT */
if (xrdp_fastpath_process_input_event(rdp->sec_layer->fastpath_layer, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data returned non zero");
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data: xrdp_fastpath_process_input_event failed");
cont = 0;
term = 1;
}
break;
default:
LOG(LOG_LEVEL_ERROR, "unknown in libxrdp_process_data: code= %d", code);
LOG(LOG_LEVEL_WARNING, "unknown code = %d (ignored)", code);
dead_lock_counter++;
break;
}
@ -262,8 +266,9 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s)
{
/*This situation can happen and this is a workaround*/
cont = 0;
LOG(LOG_LEVEL_ERROR, "Serious programming error: we were locked in a deadly loop");
LOG(LOG_LEVEL_ERROR, "Remaining: %d", (int) (s->end - s->next_packet));
LOG(LOG_LEVEL_WARNING,
"Serious programming error: we were locked in a deadly loop. "
"Remaining bytes: %d", (int) (s->end - s->next_packet));
s->next_packet = 0;
}
@ -292,7 +297,9 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette)
return 0;
}
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_palette sending palette");
LOG_DEVEL(LOG_LEVEL_DEBUG, "sending palette (%s)",
((session->client_info->use_fast_path & 1) ?
"fastpath" : "slowpath"));
/* clear orders */
libxrdp_orders_force_send(session);
@ -301,25 +308,25 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette)
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_palette: fastpath");
if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_palette: xrdp_rdp_init_fastpath failed");
free_stream(s);
return 1;
}
}
else
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "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 */
out_uint16_le(s, 0);
out_uint16_le(s, RDP_UPDATE_PALETTE); /* updateType */
out_uint16_le(s, 0); /* pad2Octets */
out_uint16_le(s, 256); /* # of colors (low-bytes) */
out_uint16_le(s, 0); /* # of colors (high-bytes) */
/* paletteEntries */
for (i = 0; i < 256; i++)
{
color = palette[i];
@ -331,15 +338,24 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette)
s_mark_end(s);
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
{
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_UPDATE_PALETTE "
"paletteUpdateData = { updateType %d (UPDATETYPE_PALETTE), "
"pad2Octets <ignored>, numberColors 256, "
"paletteEntries <omitted from log> }", RDP_UPDATE_PALETTE);
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
FASTPATH_UPDATETYPE_PALETTE) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_palette: xrdp_rdp_send_fastpath failed");
free_stream(s);
return 1;
}
}
else
{
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_PALETTE_DATA "
"updateType %d (UPDATETYPE_PALETTE), pad2Octets <ignored>, "
"numberColors 256, paletteEntries <omitted from log>",
RDP_UPDATE_PALETTE);
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
RDP_DATA_PDU_UPDATE);
}
@ -364,24 +380,25 @@ libxrdp_send_bell(struct xrdp_session *session)
{
struct stream *s = (struct stream *)NULL;
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_bell sending bell signal");
/* see MS documentation: Server play sound PDU, TS_PLAY_SOUND_PDU_DATA */
make_stream(s);
init_stream(s, 8192);
if (xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_bell: xrdp_rdp_init_data failed");
free_stream(s);
return 1;
}
out_uint32_le(s, 440); /* frequency */
out_uint32_le(s, 100); /* duration (ms) */
out_uint32_le(s, 440); /* frequency */
s_mark_end(s);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_PLAY_SOUND_PDU_DATA "
"duration 100 ms, frequency 440 Hz");
if (xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_PLAY_SOUND) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_bell: xrdp_rdp_send_data failed");
free_stream(s);
return 1;
}
@ -459,7 +476,7 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
total_bufsize = 0;
num_updates = 0;
xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s);
out_uint16_le(s, RDP_UPDATE_BITMAP);
out_uint16_le(s, RDP_UPDATE_BITMAP); /* updateType */
p_num_updates = s->p;
out_uint8s(s, 2); /* num_updates set later */
@ -562,6 +579,11 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
p_num_updates[0] = num_updates;
p_num_updates[1] = num_updates >> 8;
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_BITMAP_DATA "
"updateType %d (UPDATETYPE_BITMAP), numberRectangles %d, "
"rectangles <omitted from log>",
RDP_UPDATE_BITMAP, num_updates);
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
RDP_DATA_PDU_UPDATE);
@ -666,6 +688,10 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
}
s_mark_end(s);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_BITMAP_DATA "
"updateType %d (UPDATETYPE_BITMAP), numberRectangles 1, "
"rectangles <omitted from log>",
RDP_UPDATE_BITMAP);
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
RDP_DATA_PDU_UPDATE);
i = i + lines_sending;
@ -690,7 +716,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
int j;
int data_bytes;
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_pointer sending cursor");
LOG_DEVEL(LOG_LEVEL_DEBUG, "sending cursor");
if (bpp == 0)
{
bpp = 24;
@ -700,14 +726,17 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
{
if (bpp != 24)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: error client does not support "
"new cursors and bpp is %d", bpp);
LOG(LOG_LEVEL_ERROR, "Send pointer: client does not support "
"new cursors. The only valid bpp is 24, received %d", bpp);
return 1;
}
}
if ((bpp == 15) && (bpp != 16) && (bpp != 24) && (bpp != 32))
if ((bpp != 16) && (bpp != 24) && (bpp != 32))
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: error");
LOG(LOG_LEVEL_ERROR,
"Send pointer: invalid bpp value. Expected 16 or 24 or 32, "
"received %d", bpp);
return 1;
}
make_stream(s);
@ -718,6 +747,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: fastpath");
if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_init_fastpath failed");
free_stream(s);
return 1;
}
@ -729,7 +759,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
else
{
data_bytes = ((bpp + 7) / 8) * 32 * 32;
out_uint16_le(s, bpp);
out_uint16_le(s, bpp); /* TS_FP_POINTERATTRIBUTE -> newPointerUpdateData.xorBpp */
}
}
else /* slowpath */
@ -741,25 +771,34 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
out_uint16_le(s, RDP_POINTER_COLOR);
out_uint16_le(s, 0); /* pad */
data_bytes = 3072;
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU "
"messageType %d (TS_PTRMSGTYPE_COLOR), pad2Octets <ignored>",
RDP_POINTER_COLOR);
}
else
{
out_uint16_le(s, RDP_POINTER_POINTER);
out_uint16_le(s, 0); /* pad */
out_uint16_le(s, bpp);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU "
"messageType %d (TS_PTRMSGTYPE_POINTER), pad2Octets <ignored>",
RDP_POINTER_POINTER);
out_uint16_le(s, bpp); /* TS_POINTERATTRIBUTE -> xorBpp */
data_bytes = ((bpp + 7) / 8) * 32 * 32;
}
}
/* the TS_COLORPOINTERATTRIBUTE field which is shared by
all of the pointer attribute PDU types */
out_uint16_le(s, cache_idx); /* cache_idx */
out_uint16_le(s, x); /* hotSpot.xPos */
out_uint16_le(s, y); /* hotSpot.yPos */
out_uint16_le(s, 32); /* width */
out_uint16_le(s, 32); /* height */
out_uint16_le(s, 128); /* lengthAndMask */
out_uint16_le(s, data_bytes); /* lengthXorMask */
out_uint16_le(s, cache_idx); /* cache_idx */
out_uint16_le(s, x);
out_uint16_le(s, y);
out_uint16_le(s, 32);
out_uint16_le(s, 32);
out_uint16_le(s, 128);
out_uint16_le(s, data_bytes);
/* xorMaskData */
switch (bpp)
{
//case 15: /* coverity: this is logically dead code */
@ -802,25 +841,42 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
break;
}
out_uint8a(s, mask, 128); /* mask */
out_uint8a(s, mask, 128); /* andMaskData */
out_uint8(s, 0); /* pad */
s_mark_end(s);
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
{
if ((session->client_info->pointer_flags & 1) == 0)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_COLORPOINTERATTRIBUTE "
"cachedPointerUpdateData = { cacheIndex %d, "
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
"height 32, lengthAndMask 128, lengthXorMask %d, "
"xorMaskData <omitted from log>, "
"andMaskData <omitted from log> }",
cache_idx, x, y, data_bytes);
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
FASTPATH_UPDATETYPE_COLOR) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_send_fastpath failed");
free_stream(s);
return 1;
}
}
else
{
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_POINTERATTRIBUTE "
"newPointerUpdateData.xorBpp %d, "
"newPointerUpdateData.colorPtrAttr = { cacheIndex %d, "
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
"height 32, lengthAndMask 128, lengthXorMask %d, "
"xorMaskData <omitted from log>, "
"andMaskData <omitted from log> }",
bpp, cache_idx, x, y, data_bytes);
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
FASTPATH_UPDATETYPE_POINTER) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_send_fastpath failed");
free_stream(s);
return 1;
}
@ -828,6 +884,26 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
}
else
{
if ((session->client_info->pointer_flags & 1) == 0)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_COLORPOINTERATTRIBUTE "
"cacheIndex %d, "
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
"height 32, lengthAndMask 128, lengthXorMask %d, "
"xorMaskData <omitted from log>, "
"andMaskData <omitted from log>",
cache_idx, x, y, data_bytes);
}
else
{
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_POINTERATTRIBUTE "
"xorBpp %d, colorPtrAttr = { cacheIndex %d, "
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
"height 32, lengthAndMask 128, lengthXorMask %d, "
"xorMaskData <omitted from log>, "
"andMaskData <omitted from log> }",
bpp, cache_idx, x, y, data_bytes);
}
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
RDP_DATA_PDU_POINTER);
}
@ -841,26 +917,26 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx)
{
struct stream *s;
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_set_pointer sending cursor index");
make_stream(s);
init_stream(s, 8192);
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: fastpath");
if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_set_pointer: xrdp_rdp_init_fastpath failed");
free_stream(s);
return 1;
}
}
else
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "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 */
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU "
"messageType %d (TS_PTRMSGTYPE_CACHED), pad2Octets <ignored>",
RDP_POINTER_CACHED);
}
out_uint16_le(s, cache_idx); /* cache_idx */
@ -868,15 +944,20 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx)
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
{
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_CACHEDPOINTERATTRIBUTE "
"cachedPointerUpdateData.cacheIndex %d", cache_idx);
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
FASTPATH_UPDATETYPE_CACHED) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_set_pointer: xrdp_rdp_send_fastpath failed");
free_stream(s);
return 1;
}
}
else
{
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_CACHEDPOINTERATTRIBUTE "
"cacheIndex %d", cache_idx);
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
RDP_DATA_PDU_POINTER);
}
@ -1084,12 +1165,14 @@ libxrdp_reset(struct xrdp_session *session,
}
else
{
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: session->client_info is NULL");
return 1;
}
/* this will send any lingering orders */
if (xrdp_orders_reset((struct xrdp_orders *)session->orders) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_orders_reset failed");
return 1;
}
@ -1101,12 +1184,14 @@ libxrdp_reset(struct xrdp_session *session,
session->check_for_app_input = 0;
if (xrdp_rdp_send_deactivate((struct xrdp_rdp *)session->rdp) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_rdp_send_deactivate failed");
return 1;
}
/* this should do the resizing */
if (xrdp_caps_send_demand_active((struct xrdp_rdp *)session->rdp) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_caps_send_demand_active failed");
return 1;
}
@ -1149,13 +1234,34 @@ libxrdp_orders_send_bitmap3(struct xrdp_session *session,
cache_id, cache_idx, hints);
}
/*****************************************************************************/
int EXPORT_CC
libxrdp_get_channel_count(const struct xrdp_session *session)
{
int count = 0;
const struct xrdp_rdp *rdp = (const struct xrdp_rdp *)session->rdp;
const struct xrdp_mcs *mcs = rdp->sec_layer->mcs_layer;
if (mcs->channel_list == NULL)
{
LOG(LOG_LEVEL_WARNING,
"libxrdp_get_channel_count - No channel initialized");
}
else
{
count = mcs->channel_list->count;
}
return count;
}
/*****************************************************************************/
/* returns error */
/* this function gets the channel name and its flags, index is zero
based. either channel_name or channel_flags can be passed in nil if
they are not needed */
int EXPORT_CC
libxrdp_query_channel(struct xrdp_session *session, int index,
libxrdp_query_channel(struct xrdp_session *session, int channel_id,
char *channel_name, int *channel_flags)
{
int count = 0;
@ -1174,26 +1280,29 @@ libxrdp_query_channel(struct xrdp_session *session, int index,
count = mcs->channel_list->count;
if (index < 0 || index >= count)
if (channel_id < 0 || channel_id >= count)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - Channel out of range %d", index);
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel: Channel index out of range. "
"max channel index %d, received channel index %d",
count, channel_id);
return 1;
}
channel_item = (struct mcs_channel_item *)
list_get_item(mcs->channel_list, index);
list_get_item(mcs->channel_list, channel_id);
if (channel_item == 0)
if (channel_item == NULL)
{
/* this should not happen */
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - channel item is 0");
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - channel item is NULL");
return 1;
}
if (channel_name != 0)
{
g_strncpy(channel_name, channel_item->name, 8);
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - Channel %d name %s", index, channel_name);
LOG(LOG_LEVEL_DEBUG, "libxrdp_query_channel - Channel %d name %s",
channel_id, channel_name);
}
if (channel_flags != 0)
@ -1263,6 +1372,7 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id,
if (xrdp_channel_init(chan, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: xrdp_channel_init failed");
free_stream(s);
return 1;
}
@ -1270,10 +1380,12 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id,
/* here we make a copy of the data */
out_uint8a(s, data, data_len);
s_mark_end(s);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] Virtual Channel PDU "
"data <omitted from log>");
if (xrdp_channel_send(chan, s, channel_id, total_data_len, flags) != 0)
{
LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: error, server channel data NOT sent to client channel");
LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: xrdp_channel_send failed");
free_stream(s);
return 1;
}
@ -1295,15 +1407,20 @@ libxrdp_disable_channel(struct xrdp_session *session, int channel_id,
mcs = rdp->sec_layer->mcs_layer;
if (mcs->channel_list == NULL)
{
LOG(LOG_LEVEL_ERROR, "Channel list is NULL");
return 1;
}
channel_item = (struct mcs_channel_item *)
list_get_item(mcs->channel_list, channel_id);
if (channel_item == NULL)
{
LOG(LOG_LEVEL_ERROR, "Channel item is NULL");
return 1;
}
channel_item->disabled = is_disabled;
LOG(LOG_LEVEL_DEBUG, "%s channel %d (%s)",
(is_disabled ? "Disabling" : "Enabling"), channel_item->chanid,
channel_item->name);
return 1;
}
@ -1524,6 +1641,7 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_fastpath_send_surface:");
if ((session->client_info->use_fast_path & 1) == 0)
{
LOG(LOG_LEVEL_ERROR, "Sending data via fastpath is disabled");
return 1;
}
max_bytes = session->client_info->max_fastpath_frag_bytes;
@ -1537,10 +1655,16 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
cmd_bytes = 10 + 12;
if (data_bytes + rdp_bytes + sec_bytes + cmd_bytes > max_bytes)
{
LOG(LOG_LEVEL_ERROR, "Too much data to send via fastpath. "
"Max fastpath bytes %d, received bytes %d",
max_bytes, (data_bytes + rdp_bytes + sec_bytes + cmd_bytes));
return 1;
}
if (sec_bytes + rdp_bytes + cmd_bytes > pad_bytes)
{
LOG(LOG_LEVEL_ERROR, "Too much header to send via fastpath. "
"Max fastpath header bytes %d, received bytes %d",
pad_bytes, (rdp_bytes + sec_bytes + cmd_bytes));
return 1;
}
g_memset(&ls, 0, sizeof(ls));
@ -1556,6 +1680,13 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
out_uint16_le(s, destTop);
out_uint16_le(s, destRight);
out_uint16_le(s, destBottom);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_SURFCMD_STREAM_SURF_BITS "
"cmdType 0x%4.4x (CMDTYPE_STREAM_SURFACE_BITS), destLeft %d, "
"destTop %d, destRight %d, destBottom %d, "
"bitmapData <see TS_BITMAP_DATA_EX>",
CMDTYPE_STREAM_SURFACE_BITS, destLeft, destTop, destRight,
destBottom);
/* TS_BITMAP_DATA_EX */
out_uint8(s, bpp);
out_uint8(s, 0);
@ -1564,9 +1695,17 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
out_uint16_le(s, width);
out_uint16_le(s, height);
out_uint32_le(s, data_bytes);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding field bitmapData [MS-RDPBCGR] TS_BITMAP_DATA_EX "
"bpp %d, flags 0x00, reserved 0, codecID %d, width %d, "
"height %d, bitmapDataLength %d, exBitmapDataHeader <not present>, "
"bitmapData <omitted from log>",
bpp, codecID, width, height, data_bytes);
/* 4 = FASTPATH_UPDATETYPE_SURFCMDS */
if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0)
{
LOG(LOG_LEVEL_ERROR,
"libxrdp_fastpath_send_surface: xrdp_rdp_send_fastpath failed");
return 1;
}
return 0;
@ -1583,10 +1722,12 @@ libxrdp_fastpath_send_frame_marker(struct xrdp_session *session,
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_fastpath_send_frame_marker:");
if ((session->client_info->use_fast_path & 1) == 0)
{
LOG(LOG_LEVEL_ERROR, "Sending data via fastpath is disabled");
return 1;
}
if (session->client_info->use_frame_acks == 0)
{
LOG(LOG_LEVEL_ERROR, "Fastpath frame acks is disabled");
return 1;
}
rdp = (struct xrdp_rdp *) (session->rdp);
@ -1597,9 +1738,15 @@ libxrdp_fastpath_send_frame_marker(struct xrdp_session *session,
out_uint16_le(s, frame_action);
out_uint32_le(s, frame_id);
s_mark_end(s);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FRAME_MARKER "
"cmdType 0x0004 (CMDTYPE_FRAME_MARKER), frameAction 0x%4.4x, "
"frameId %d", frame_action, frame_id);
/* 4 = FASTPATH_UPDATETYPE_SURFCMDS */
if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0)
{
LOG(LOG_LEVEL_ERROR,
"libxrdp_fastpath_send_frame_marker: xrdp_rdp_send_fastpath failed");
free_stream(s);
return 1;
}
@ -1614,7 +1761,6 @@ libxrdp_send_session_info(struct xrdp_session *session, const char *data,
{
struct xrdp_rdp *rdp;
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_session_info:");
rdp = (struct xrdp_rdp *) (session->rdp);
return xrdp_rdp_send_session_info(rdp, data, data_bytes);
}

View File

@ -33,6 +33,7 @@
#include "file.h"
#include "libxrdpinc.h"
#include "xrdp_client_info.h"
#include "log.h"
/* iso */
@ -549,9 +550,9 @@ xrdp_codec_jpeg_compress(void *handle,
int cy, /* height of area to compress */
int quality, /* higher numbers compress less */
char *out_data, /* dest for jpg image */
int *io_len /* length of out_data and on return */
/* len of compressed data */
);
int *io_len /* length of out_data and on return
len of compressed data */
);
void *
xrdp_jpeg_init(void);
@ -559,7 +560,7 @@ int
xrdp_jpeg_deinit(void *handle);
/* xrdp_channel.c */
struct xrdp_channel*
struct xrdp_channel *
xrdp_channel_create(struct xrdp_sec *owner, struct xrdp_mcs *mcs_layer);
void
xrdp_channel_delete(struct xrdp_channel *self);

View File

@ -203,9 +203,28 @@ int
libxrdp_orders_send_bitmap3(struct xrdp_session *session,
int width, int height, int bpp, char *data,
int cache_id, int cache_idx, int hints);
/**
* Returns the number of channels in the session
*
* This value is one more than the last valid channel ID
*
* @param session RDP session
* @return Number of available channels
*/
int
libxrdp_query_channel(struct xrdp_session *session, int index,
libxrdp_get_channel_count(const struct xrdp_session *session);
int
libxrdp_query_channel(struct xrdp_session *session, int channel_id,
char *channel_name, int *channel_flags);
/**
* Gets the channel ID for the named channel
*
* Channel IDs are in the range 0..(channel_count-1)
*
* @param session RDP session
* @param name name of channel
* @return channel ID, or -1 if the channel cannot be found
*/
int
libxrdp_get_channel_id(struct xrdp_session *session, const char *name);
int

View File

@ -77,7 +77,8 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s,
if (len < 10 + 2)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_general: error");
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
"len 12, remaining %d", len);
return 1;
}
@ -103,6 +104,9 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s,
}
/*****************************************************************************/
/*
* Process [MS-RDPBCGR] TS_ORDER_CAPABILITYSET (2.2.7.1.3) message.
*/
static int
xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
int len)
@ -112,10 +116,10 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
int ex_flags;
int cap_flags;
LOG_DEVEL(LOG_LEVEL_TRACE, "order capabilities");
if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_order: error");
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
"len 84, remaining %d", len);
return 1;
}
in_uint8s(s, 20); /* Terminal desc, pad */
@ -127,33 +131,53 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
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);
LOG_DEVEL(LOG_LEVEL_TRACE, "dest blt-0 %d", order_caps[0]);
LOG_DEVEL(LOG_LEVEL_TRACE, "pat blt-1 %d", order_caps[1]);
LOG_DEVEL(LOG_LEVEL_TRACE, "screen blt-2 %d", order_caps[2]);
LOG_DEVEL(LOG_LEVEL_TRACE, "memblt-3-13 %d %d", order_caps[3], order_caps[13]);
LOG_DEVEL(LOG_LEVEL_TRACE, "triblt-4-14 %d %d", order_caps[4], order_caps[14]);
LOG_DEVEL(LOG_LEVEL_TRACE, "line-8 %d", order_caps[8]);
LOG_DEVEL(LOG_LEVEL_TRACE, "line-9 %d", order_caps[9]);
LOG_DEVEL(LOG_LEVEL_TRACE, "rect-10 %d", order_caps[10]);
LOG_DEVEL(LOG_LEVEL_TRACE, "desksave-11 %d", order_caps[11]);
LOG_DEVEL(LOG_LEVEL_TRACE, "polygon-20 %d", order_caps[20]);
LOG_DEVEL(LOG_LEVEL_TRACE, "polygon2-21 %d", order_caps[21]);
LOG_DEVEL(LOG_LEVEL_TRACE, "polyline-22 %d", order_caps[22]);
LOG_DEVEL(LOG_LEVEL_TRACE, "ellipse-25 %d", order_caps[25]);
LOG_DEVEL(LOG_LEVEL_TRACE, "ellipse2-26 %d", order_caps[26]);
LOG_DEVEL(LOG_LEVEL_TRACE, "text2-27 %d", order_caps[27]);
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "order_caps dump", order_caps, 32);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: terminalDescriptor (ignored as per protocol spec)");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveXGranularity (ignored as per protocol spec)");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveYGranularity (ignored as per protocol spec)");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: maximumOrderLevel (ignored as per protocol spec)");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: numberFonts (ignored as per protocol spec)");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderFlags 0x%4.4x", cap_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 0: DstBlt %d", order_caps[0]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 1: PatBlt %d", order_caps[1]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 2: ScrBlt %d", order_caps[2]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 3,13: MemBlt %d %d", order_caps[3], order_caps[13]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 4,14: Mem3Blt %d %d", order_caps[4], order_caps[14]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 5-6: unused index");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 7: DrawNineGrid %d", order_caps[7]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 8: LineTo %d", order_caps[8]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 9: MultiDrawNineGrid %d", order_caps[9]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 10: unused index");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 11: SaveBitmap %d", order_caps[11]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 12-14: unused index");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 15: MultiDstBlt %d", order_caps[15]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 16: MultiPatBlt %d", order_caps[16]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 17: MultiScrBlt %d", order_caps[17]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 18: MultiOpaqueRect %d", order_caps[18]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 19: FastIndex %d", order_caps[19]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 20: PolygonSC %d", order_caps[20]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 21: PolygonCB %d", order_caps[21]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 22: Polyline %d", order_caps[22]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 23: unused index");
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 24: FastGlyph %d", order_caps[24]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 25: EllipseSC %d", order_caps[25]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 26: EllipseCB %d", order_caps[26]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 27: GlyphIndex %d", order_caps[27]);
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 28-31: unused index");
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: order_caps", order_caps, 32);
in_uint8s(s, 2); /* Text capability flags */
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: textFlags (ignored as per protocol spec)");
/* read extended order support flags */
in_uint16_le(s, ex_flags); /* Ex flags */
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupportExFlags 0x%4.4x", 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)
{
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_order: bitmap cache v3 supported");
LOG_DEVEL(LOG_LEVEL_INFO, "Client Capability: bitmap cache v3 supported");
self->client_info.bitmap_cache_version |= 4;
}
}
@ -161,15 +185,15 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */
self->client_info.desktop_cache = i;
LOG_DEVEL(LOG_LEVEL_TRACE, "desktop cache size %d", i);
in_uint8s(s, 4); /* Unknown */
in_uint8s(s, 4); /* Unknown */
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveSize %d", i);
in_uint8s(s, 4); /* Pad */
in_uint8s(s, 4); /* Pad */
/* check if libpainter should be used for drawing, instead of orders */
if (!(order_caps[TS_NEG_DSTBLT_INDEX] && order_caps[TS_NEG_PATBLT_INDEX] &&
order_caps[TS_NEG_SCRBLT_INDEX] && order_caps[TS_NEG_MEMBLT_INDEX]))
{
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_order: not enough orders supported by client, using painter.");
LOG_DEVEL(LOG_LEVEL_INFO, "Client Capability: not enough orders supported by client, using painter.");
self->client_info.no_orders_supported = 1;
}
@ -186,7 +210,8 @@ xrdp_caps_process_bmpcache(struct xrdp_rdp *self, struct stream *s,
if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_bmpcache: error");
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
"len 36, remaining %d", len);
return 1;
}
self->client_info.bitmap_cache_version |= 1;
@ -229,7 +254,8 @@ xrdp_caps_process_bmpcache2(struct xrdp_rdp *self, struct stream *s,
if (len < 2 + 2 + 4 + 4 + 4)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_bmpcache2: error");
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
"len 16, remaining %d", len);
return 1;
}
self->client_info.bitmap_cache_version |= 2;
@ -271,7 +297,8 @@ xrdp_caps_process_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s,
if (len < 1)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_cache_v3_codec_id: error");
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
"len 1, remaining %d", len);
return 1;
}
in_uint8(s, codec_id);
@ -421,13 +448,24 @@ xrdp_caps_process_rail(struct xrdp_rdp *self, struct stream *s, int len)
if (len < 4)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_rail: error");
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
"len 4, remaining %d", len);
return 1;
}
in_uint32_le(s, i32);
self->client_info.rail_support_level = i32;
LOG(LOG_LEVEL_INFO, "xrdp_process_capset_rail: rail_support_level %d",
self->client_info.rail_support_level);
LOG(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - CAPSTYPE_RAIL "
"RailSupportLevel 0x%8.8x (%s%s%s%s%s%s%s%s)",
self->client_info.rail_support_level,
(self->client_info.rail_support_level & 0x01) ? "TS_RAIL_LEVEL_SUPPORTED " : "",
(self->client_info.rail_support_level & 0x02) ? "TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED " : "",
(self->client_info.rail_support_level & 0x04) ? "TS_RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED " : "",
(self->client_info.rail_support_level & 0x08) ? "TS_RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED " : "",
(self->client_info.rail_support_level & 0x10) ? "TS_RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED " : "",
(self->client_info.rail_support_level & 0x20) ? "TS_RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED " : "",
(self->client_info.rail_support_level & 0x40) ? "TS_RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED " : "",
(self->client_info.rail_support_level & 0x80) ? "TS_RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED " : ""
);
return 0;
}
@ -448,8 +486,8 @@ xrdp_caps_process_window(struct xrdp_rdp *self, struct stream *s, int len)
self->client_info.wnd_num_icon_caches = i32;
in_uint16_le(s, i32);
self->client_info.wnd_num_icon_cache_entries = i32;
LOG(LOG_LEVEL_INFO, "xrdp_process_capset_window wnd_support_level %d "
"wnd_num_icon_caches %d wnd_num_icon_cache_entries %d",
LOG(LOG_LEVEL_INFO, "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);
@ -593,6 +631,7 @@ xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len)
logging in debug mode */
UNUSED_VAR(cmdFlags);
#endif
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_surface_cmds:");
in_uint32_le(s, cmdFlags);
in_uint8s(s, 4); /* reserved */
@ -601,6 +640,9 @@ xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len)
}
/*****************************************************************************/
/*
* Process a [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU (2.2.1.13.2.1) message.
*/
int
xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
{
@ -612,7 +654,6 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
int len;
char *p;
LOG_DEVEL(LOG_LEVEL_TRACE, "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 */
@ -620,118 +661,169 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
in_uint8s(s, source_len);
in_uint16_le(s, num_caps);
in_uint8s(s, 2); /* pad */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU "
"shareID (ignored), originatorID (ignored), lengthSourceDescriptor %d, "
"lengthCombinedCapabilities %d, sourceDescriptor (ignored), "
"numberCapabilities %d", source_len, cap_len, num_caps);
if ((cap_len < 0) || (cap_len > 1024 * 1024))
{
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU "
"lengthCombinedCapabilities %d is too long (> %d)",
cap_len, 1024 * 1024);
return 1;
}
for (index = 0; index < num_caps; index++)
{
p = s->p;
if (!s_check_rem(s, 4))
if (!s_check_rem_and_log(s, 4,
"Parsing [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET"))
{
LOG(LOG_LEVEL_ERROR, "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))
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType %d, lengthCapability %d", type, len);
if (len < 4)
{
LOG(LOG_LEVEL_ERROR,
"Protocol error [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"lengthCapability must be greater than 3, received %d", len);
return 1;
}
if (!s_check_rem_and_log(s, len - 4,
"Parsing [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "))
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_confirm_active: error: len %d, "
"remaining %d", len, (int) (s->end - s->p));
return 1;
}
len -= 4;
switch (type)
{
case CAPSTYPE_GENERAL:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_GENERAL");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_GENERAL");
xrdp_caps_process_general(self, s, len);
break;
case CAPSTYPE_BITMAP:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BITMAP");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_BITMAP - Ignored");
break;
case CAPSTYPE_ORDER:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_ORDER");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_ORDER");
xrdp_caps_process_order(self, s, len);
break;
case CAPSTYPE_BITMAPCACHE:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BMPCACHE");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_BITMAPCACHE");
xrdp_caps_process_bmpcache(self, s, len);
break;
case CAPSTYPE_CONTROL:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_CONTROL");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_CONTROL - Ignored");
break;
case 6:
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = 6");
xrdp_caps_process_cache_v3_codec_id(self, s, len);
break;
case CAPSTYPE_ACTIVATION:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_ACTIVAION");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_ACTIVATION - Ignored");
break;
case CAPSTYPE_POINTER:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_POINTER");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_POINTER");
xrdp_caps_process_pointer(self, s, len);
break;
case CAPSTYPE_SHARE:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_SHARE");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_SHARE - Ignored");
break;
case CAPSTYPE_COLORCACHE:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_COLORCACHE");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_COLORCACHE - Ignored");
break;
case CAPSTYPE_SOUND:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_SOUND");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_SOUND - Ignored");
break;
case CAPSTYPE_INPUT:
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_INPUT");
xrdp_caps_process_input(self, s, len);
break;
case CAPSTYPE_FONT:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_FONT");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_FONT - Ignored");
break;
case CAPSTYPE_BRUSH:
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_BRUSH");
xrdp_caps_process_brushcache(self, s, len);
break;
case CAPSTYPE_GLYPHCACHE:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_GLYPHCACHE");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_GLYPHCACHE");
xrdp_caps_process_glyphcache(self, s, len);
break;
case CAPSTYPE_OFFSCREENCACHE:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_OFFSCREENCACHE");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_OFFSCREENCACHE");
xrdp_caps_process_offscreen_bmpcache(self, s, len);
break;
case CAPSTYPE_BITMAPCACHE_REV2:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BITMAPCACHE_REV2");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_BITMAPCACHE_REV2");
xrdp_caps_process_bmpcache2(self, s, len);
break;
case CAPSTYPE_VIRTUALCHANNEL:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_VIRTUALCHANNEL");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_VIRTUALCHANNEL - Ignored");
break;
case CAPSTYPE_DRAWNINGRIDCACHE:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_DRAWNINGRIDCACHE");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_DRAWNINGRIDCACHE - Ignored");
break;
case CAPSTYPE_DRAWGDIPLUS:
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_DRAWGDIPLUS");
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_DRAWGDIPLUS - Ignored");
break;
case CAPSTYPE_RAIL:
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_RAIL");
xrdp_caps_process_rail(self, s, len);
break;
case CAPSTYPE_WINDOW:
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_WINDOW");
xrdp_caps_process_window(self, s, len);
break;
case CAPSSETTYPE_MULTIFRAGMENTUPDATE:
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSSETTYPE_MULTIFRAGMENTUPDATE");
xrdp_caps_process_multifragmentupdate(self, s, len);
break;
case CAPSETTYPE_SURFACE_COMMANDS:
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSETTYPE_SURFACE_COMMANDS");
xrdp_caps_process_surface_cmds(self, s, len);
break;
case CAPSSETTYPE_BITMAP_CODECS:
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSSETTYPE_BITMAP_CODECS");
xrdp_caps_process_codecs(self, s, len);
break;
case CAPSTYPE_FRAME_ACKNOWLEDGE:
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = CAPSTYPE_FRAME_ACKNOWLEDGE");
xrdp_caps_process_frame_ack(self, s, len);
break;
default:
LOG(LOG_LEVEL_WARNING, "unknown in xrdp_caps_process_confirm_active %d", type);
LOG(LOG_LEVEL_WARNING, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
"capabilitySetType = %d is unknown - Ignored", type);
break;
}
@ -741,7 +833,7 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
if (self->client_info.no_orders_supported &&
(self->client_info.offscreen_support_level != 0))
{
LOG(LOG_LEVEL_WARNING, "xrdp_caps_process_confirm_active: not enough orders "
LOG(LOG_LEVEL_WARNING, "Client Capability: not enough orders "
"supported by client, client wants off screen bitmap but "
"offscreen bitmaps disabled");
self->client_info.offscreen_support_level = 0;
@ -749,7 +841,7 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
self->client_info.offscreen_cache_entries = 0;
}
LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_caps_process_confirm_active");
LOG_DEVEL(LOG_LEVEL_TRACE, "Completed processing received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU");
return 0;
}
/*****************************************************************************/
@ -771,10 +863,10 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
make_stream(s);
init_stream(s, 8192);
LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_caps_send_demand_active");
if (xrdp_rdp_init(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_send_demand_active: xrdp_rdp_init failed");
free_stream(s);
return 1;
}
@ -797,6 +889,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint16_le(s, CAPSTYPE_SHARE_LEN);
out_uint16_le(s, self->mcs_channel);
out_uint16_be(s, 0xb5e2); /* 0x73e1 */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_SHARE "
"channel ID = 0x%x", self->mcs_channel);
/* Output general capability set */
caps_count++;
@ -820,6 +915,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint16_le(s, 0); /* Compression level */
out_uint8(s, 1); /* refreshRectSupport */
out_uint8(s, 1); /* suppressOutputSupport */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_GENERAL TODO");
/* Output bitmap capability set */
caps_count++;
@ -837,11 +934,15 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint16_le(s, 0); /* unknown */
out_uint16_le(s, 0); /* unknown */
out_uint16_le(s, 0); /* pad */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_BITMAP TODO");
/* Output font capability set */
caps_count++;
out_uint16_le(s, CAPSTYPE_FONT);
out_uint16_le(s, CAPSTYPE_FONT_LEN);
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_FONT");
/* Output order capability set */
caps_count++;
@ -895,6 +996,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint32_le(s, 0x0f4240); /* desk save */
out_uint32_le(s, 1); /* ? */
out_uint32_le(s, 0); /* ? */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_ORDER "
"TODO");
/* Output bmpcodecs capability set */
caps_count++;
@ -912,6 +1016,11 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint8(s, 0x01); /* fAllowDynamicFidelity */
out_uint8(s, 0x01); /* fAllowSubsampling */
out_uint8(s, 0x03); /* colorLossLevel */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"NSCODEC "
"fAllowDynamicFidelity = 0x01,"
"fAllowSubsampling = 0x01,"
"colorLossLevel = 0x03");
#if defined(XRDP_RFXCODEC) || defined(XRDP_NEUTRINORDP)
/* remotefx */
codec_caps_count++;
@ -919,12 +1028,16 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint8(s, 0); /* codec id, client sets */
out_uint16_le(s, 4); /* codecPropertiesLength */
out_uint32_le(s, 0); /* reserved */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"REMOTEFX");
/* image remotefx */
codec_caps_count++;
out_uint8a(s, XR_CODEC_GUID_IMAGE_REMOTEFX, 16);
out_uint8(s, 0); /* codec id, client sets */
out_uint16_le(s, 4); /* codecPropertiesLength */
out_uint32_le(s, 0); /* reserved */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"IMAGE_REMOTEFX");
#endif
/* jpeg */
codec_caps_count++;
@ -932,6 +1045,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint8(s, 0); /* codec id, client sets */
out_uint16_le(s, 1); /* codecPropertiesLength */
out_uint8(s, 75); /* jpeg compression ratio */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"JPEG: "
"jpeg compression ratio = 75");
/* calculate and set size and count */
codec_caps_size = (int)(s->p - codec_caps_size_ptr);
codec_caps_size += 2; /* 2 bytes for CAPSTYPE_BMPCODECS above */
@ -945,6 +1061,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint16_le(s, CAPSTYPE_COLORCACHE_LEN);
out_uint16_le(s, 6); /* cache size */
out_uint16_le(s, 0); /* pad */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_COLORCACHE: "
"colorTableCacheSize = 6");
/* Output pointer capability set */
caps_count++;
@ -953,8 +1072,14 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint16_le(s, 1); /* Colour pointer */
out_uint16_le(s, 0x19); /* Cache size */
out_uint16_le(s, 0x19); /* Cache size */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_POINTER: "
"colorPointerFlag = true"
"colorPointerCacheSize = 0x19"
"pointerCacheSize = 0x19");
/* Output input capability set */
/* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/b3bc76ae-9ee5-454f-b197-ede845ca69cc */
caps_count++;
out_uint16_le(s, CAPSTYPE_INPUT);
out_uint16_le(s, CAPSTYPE_INPUT_LEN);
@ -970,6 +1095,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
}
out_uint16_le(s, flags);
out_uint8s(s, 82);
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_INPUT: "
"inputFlags = 0x%x", flags);
if (self->client_info.rail_enable) /* MS-RDPERP 3.3.5.1.4 */
{
@ -980,6 +1108,10 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint32_le(s, 3); /* See: https://msdn.microsoft.com/en-us/library/cc242518.aspx
TS_RAIL_LEVEL_SUPPORTED
TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_RAIL: "
"RailSupportLevel = "
"TS_RAIL_LEVEL_SUPPORTED | TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED");
/* Window List Capability Set */
caps_count++;
@ -988,6 +1120,11 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint32_le(s, TS_WINDOW_LEVEL_SUPPORTED_EX);
out_uint8(s, 3); /* NumIconCaches */
out_uint16_le(s, 12); /* NumIconCacheEntries */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_WINDOW: "
"WndSupportLevel = TS_WINDOW_LEVEL_SUPPORTED_EX, "
"NumIconCaches = 3,"
"NumIconCacheEntries = 12");
}
/* 6 - bitmap cache v3 codecid */
@ -995,6 +1132,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint16_le(s, 0x0006);
out_uint16_le(s, 5);
out_uint8(s, 0); /* client sets */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"0x0006 = 0");
if (self->client_info.use_fast_path & FASTPATH_OUTPUT_SUPPORTED) /* fastpath output on */
{
@ -1003,12 +1142,16 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE);
out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE_LEN);
out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSSETTYPE_MULTIFRAGMENTUPDATE = 3MB");
/* frame acks */
caps_count++;
out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE);
out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE_LEN);
out_uint32_le(s, 2); /* 2 frames in flight */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSTYPE_FRAME_ACKNOWLEDGE = 2 frames");
/* surface commands */
caps_count++;
@ -1018,6 +1161,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
SURFCMDS_FRAMEMARKER |
SURFCMDS_STREAMSUFRACEBITS)); /* cmdFlags */
out_uint32_le(s, 0); /* reserved */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
"CAPSETTYPE_SURFACE_COMMANDS = "
"SURFCMDS_SETSURFACEBITS | SURFCMDS_FRAMEMARKER | SURFCMDS_STREAMSUFRACEBITS");
}
out_uint8s(s, 4); /* pad */
@ -1033,12 +1179,14 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
caps_count_ptr[2] = caps_count >> 16;
caps_count_ptr[3] = caps_count >> 24;
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: sending PDUTYPE_DEMANDACTIVEPDU "
"message with the server's capabilities");
if (xrdp_rdp_send(self, s, PDUTYPE_DEMANDACTIVEPDU) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_caps_send_demand_active: xrdp_rdp_send failed");
free_stream(s);
return 1;
}
LOG_DEVEL(LOG_LEVEL_TRACE, "out (1) xrdp_caps_send_demand_active");
/* send Monitor Layout PDU for dual monitor */
if (self->client_info.monitorCount > 0 &&

View File

@ -43,6 +43,19 @@
#define XRDP_DRDYNVC_STATUS_OPEN 2
#define XRDP_DRDYNVC_STATUS_CLOSE_SENT 3
#define XRDP_DRDYNVC_STATUS_TO_STR(status) \
((status) == XRDP_DRDYNVC_STATUS_CLOSED ? "CLOSED" : \
(status) == XRDP_DRDYNVC_STATUS_OPEN_SENT ? "OPEN_SENT" : \
(status) == XRDP_DRDYNVC_STATUS_OPEN ? "OPEN" : \
(status) == XRDP_DRDYNVC_STATUS_CLOSE_SENT ? "CLOSE_SENT" : \
"unknown" \
)
#define XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id) \
(xrdp_channel_get_item((self), (chan_id)) != NULL \
? xrdp_channel_get_item((self), (chan_id))->name \
: "unknown")
/*****************************************************************************/
/* returns pointer or nil on error */
static struct mcs_channel_item *
@ -52,7 +65,7 @@ xrdp_channel_get_item(struct xrdp_channel *self, int channel_id)
if (self->mcs_layer->channel_list == NULL)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_get_item - No channel initialized");
LOG(LOG_LEVEL_WARNING, "Channel list is NULL, returning NULL");
return NULL ;
}
@ -95,6 +108,7 @@ xrdp_channel_init(struct xrdp_channel *self, struct stream *s)
{
if (xrdp_sec_init(self->sec_layer, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_init: xrdp_sec_init failed");
return 1;
}
@ -115,13 +129,17 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id,
if (channel == NULL)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_send - no such channel");
LOG(LOG_LEVEL_ERROR,
"Request to send a message to non-existent channel_id %d",
channel_id);
return 1;
}
if (channel->disabled)
{
LOG(LOG_LEVEL_WARNING, "xrdp_channel_send, channel disabled");
LOG(LOG_LEVEL_DEBUG,
"Request to send a message to the disabled channel %s (%d)",
channel->name, channel_id);
return 0; /* not an error */
}
@ -145,10 +163,12 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id,
// }
out_uint32_le(s, flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] CHANNEL_PDU_HEADER "
"length %d, flags 0x%8.8x", total_data_len, flags);
if (xrdp_sec_send(self->sec_layer, s, channel->chanid) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_send - failure sending data");
LOG(LOG_LEVEL_ERROR, "xrdp_channel_send: xrdp_sec_send failed");
return 1;
}
@ -183,18 +203,28 @@ xrdp_channel_call_callback(struct xrdp_channel *self, struct stream *s,
}
else
{
LOG(LOG_LEVEL_TRACE, "in xrdp_channel_call_callback, session->callback is nil");
LOG_DEVEL(LOG_LEVEL_WARNING, "session->callback is NULL");
}
}
else
{
LOG(LOG_LEVEL_TRACE, "in xrdp_channel_call_callback, session is nil");
LOG_DEVEL(LOG_LEVEL_WARNING, "session is NULL");
}
return rv;
}
/*****************************************************************************/
/**
* Write a variable length unsigned int (1, 2, or 4 bytes) to the stream.
*
* The number of bytes written is the minimum number of bytes needed to
* represent the value.
*
* @param s the stream to write to
* @param val the value to write
* @return the DYNVC cbId length code for the number of bytes written (see [MS-RDPEDYC] 2.2.2.1)
*/
static int
drdynvc_insert_uint_124(struct stream *s, uint32_t val)
{
@ -220,6 +250,17 @@ drdynvc_insert_uint_124(struct stream *s, uint32_t val)
}
/*****************************************************************************/
/**
* Read a variable length unsigned int (1, 2, or 4 bytes) from the stream.
*
* The number of bytes read is determined by the cbId bit field flag in the
* cmd argument (see [MS-RDPEDYC] 2.2.2.1).
*
* @param s [in] the stream to read from
* @param cmd [in] the cmd byte which contains the cbId bit field flag
* @param chan_id_p [out] a pointer to the value read from the stream
* @return error code
*/
static int
drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
{
@ -229,7 +270,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
cbChId = cmd & 0x03;
if (cbChId == 0)
{
if (!s_check_rem(s, 1))
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPEDYC] channel id"))
{
return 1;
}
@ -237,7 +278,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
}
else if (cbChId == 1)
{
if (!s_check_rem(s, 2))
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPEDYC] channel id"))
{
return 1;
}
@ -245,7 +286,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
}
else
{
if (!s_check_rem(s, 4))
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] channel id"))
{
return 1;
}
@ -256,6 +297,9 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
}
/*****************************************************************************/
/*
* Process a [MS-RDPEDYC] DYNVC_CAPS_RSP message.
*/
static int
drdynvc_process_capability_response(struct xrdp_channel *self,
int cmd, struct stream *s)
@ -264,18 +308,22 @@ drdynvc_process_capability_response(struct xrdp_channel *self,
int cap_version;
int rv;
/* skip padding */
in_uint8s(s, 1);
/* read client's version */
in_uint16_le(s, cap_version);
if ((cap_version != 2) && (cap_version != 3))
if (!s_check_rem_and_log(s, 3, "Parsing [MS-RDPEDYC] DYNVC_CAPS_RSP"))
{
LOG(LOG_LEVEL_ERROR, "drdynvc_process_capability_response: incompatible DVC "
"version %d detected", cap_version);
return 1;
}
LOG(LOG_LEVEL_INFO, "drdynvc_process_capability_response: DVC version %d selected",
cap_version);
in_uint8s(s, 1); /* skip padding */
in_uint16_le(s, cap_version); /* Version */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CAPS_RSP "
"version %d", cap_version);
if ((cap_version != 2) && (cap_version != 3))
{
LOG(LOG_LEVEL_ERROR,
"Dynamic Virtual Channel version %d is not supported",
cap_version);
return 1;
}
self->drdynvc_state = 1;
session = self->sec_layer->rdp_layer->session;
rv = session->callback(session->id, 0x5558, 0, 0, 0, 0);
@ -283,6 +331,9 @@ drdynvc_process_capability_response(struct xrdp_channel *self,
}
/*****************************************************************************/
/*
* Process a [MS-RDPEDYC] DYNVC_CREATE_RSP message.
*/
static int
drdynvc_process_open_channel_response(struct xrdp_channel *self,
int cmd, struct stream *s)
@ -292,22 +343,27 @@ drdynvc_process_open_channel_response(struct xrdp_channel *self,
uint32_t chan_id;
struct xrdp_drdynvc *drdynvc;
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
{
LOG(LOG_LEVEL_ERROR,
"Parsing [MS-RDPEDYC] DYNVC_CREATE_RSP failed");
return 1;
}
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] DYNVC_CREATE_RSP"))
{
return 1;
}
if (!s_check_rem(s, 4))
{
return 1;
}
in_uint32_le(s, creation_status);
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_open_channel_response: chan_id 0x%x "
"creation_status %d", chan_id, creation_status);
session = self->sec_layer->rdp_layer->session;
in_uint32_le(s, creation_status); /* CreationStatus */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CREATE_RSP "
"ChannelId %d, CreationStatus %d", chan_id, creation_status);
if (chan_id > 255)
{
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPEDYC] DYNVC_CREATE_RSP for an "
"invalid channel id. Max allowed 255, received %d", chan_id);
return 1;
}
session = self->sec_layer->rdp_layer->session;
drdynvc = self->drdynvcs + chan_id;
if (creation_status == 0)
{
@ -317,14 +373,26 @@ drdynvc_process_open_channel_response(struct xrdp_channel *self,
{
drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED;
}
LOG_DEVEL(LOG_LEVEL_DEBUG,
"Dynamic Virtual Channel %s (%d) updated: status = %s",
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
chan_id,
XRDP_DRDYNVC_STATUS_TO_STR(drdynvc->status));
if (drdynvc->open_response != NULL)
{
return drdynvc->open_response(session->id, chan_id, creation_status);
}
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
"callback 'open_response' is NULL",
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
chan_id);
return 0;
}
/*****************************************************************************/
/*
* Process a [MS-RDPEDYC] DYNVC_CLOSE message.
*/
static int
drdynvc_process_close_channel_response(struct xrdp_channel *self,
int cmd, struct stream *s)
@ -333,26 +401,45 @@ drdynvc_process_close_channel_response(struct xrdp_channel *self,
uint32_t chan_id;
struct xrdp_drdynvc *drdynvc;
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
{
LOG(LOG_LEVEL_ERROR,
"drdynvc_process_close_channel_response: drdynvc_get_chan_id failed");
return 1;
}
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_close_channel_response: chan_id 0x%x", chan_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CLOSE "
"ChannelId %d", chan_id);
session = self->sec_layer->rdp_layer->session;
if (chan_id > 255)
{
LOG(LOG_LEVEL_ERROR, "Received message for an invalid "
"channel id. channel id %d", chan_id);
return 1;
}
drdynvc = self->drdynvcs + chan_id;
drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED;
LOG_DEVEL(LOG_LEVEL_DEBUG,
"Dynamic Virtual Channel %s (%d) updated: status = %s",
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
chan_id,
XRDP_DRDYNVC_STATUS_TO_STR(drdynvc->status));
if (drdynvc->close_response != NULL)
{
return drdynvc->close_response(session->id, chan_id);
}
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
"callback 'close_response' is NULL",
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
chan_id);
return 0;
}
/*****************************************************************************/
/*
* Process a [MS-RDPEDYC] DYNVC_DATA_FIRST message.
*/
static int
drdynvc_process_data_first(struct xrdp_channel *self,
int cmd, struct stream *s)
@ -364,40 +451,47 @@ drdynvc_process_data_first(struct xrdp_channel *self,
int total_bytes;
struct xrdp_drdynvc *drdynvc;
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
{
LOG(LOG_LEVEL_ERROR,
"Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST failed");
return 1;
}
len = (cmd >> 2) & 0x03;
if (len == 0)
{
if (!s_check_rem(s, 1))
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST"))
{
return 1;
}
in_uint8(s, total_bytes);
in_uint8(s, total_bytes); /* Length */
}
else if (len == 1)
{
if (!s_check_rem(s, 2))
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST"))
{
return 1;
}
in_uint16_le(s, total_bytes);
in_uint16_le(s, total_bytes); /* Length */
}
else
{
if (!s_check_rem(s, 4))
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST"))
{
return 1;
}
in_uint32_le(s, total_bytes);
in_uint32_le(s, total_bytes); /* Length */
}
bytes = (int) (s->end - s->p);
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_data_first: bytes %d total_bytes %d", bytes, total_bytes);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_DATA_FIRST "
"ChannelId %d, Length %d, Data (omitted from the log)",
chan_id, total_bytes);
session = self->sec_layer->rdp_layer->session;
if (chan_id > 255)
{
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPEDYC] DYNVC_DATA_FIRST for an "
"invalid channel id. Max allowed 255, received %d", chan_id);
return 1;
}
drdynvc = self->drdynvcs + chan_id;
@ -406,10 +500,17 @@ drdynvc_process_data_first(struct xrdp_channel *self,
return drdynvc->data_first(session->id, chan_id, s->p,
bytes, total_bytes);
}
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
"callback 'data_first' is NULL",
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
chan_id);
return 0;
}
/*****************************************************************************/
/*
* Process a [MS-RDPEDYC] DYNVC_DATA message.
*/
static int
drdynvc_process_data(struct xrdp_channel *self,
int cmd, struct stream *s)
@ -419,15 +520,20 @@ drdynvc_process_data(struct xrdp_channel *self,
int bytes;
struct xrdp_drdynvc *drdynvc;
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
{
LOG(LOG_LEVEL_ERROR, "drdynvc_process_data: drdynvc_get_chan_id failed");
return 1;
}
bytes = (int) (s->end - s->p);
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_data: bytes %d", bytes);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_DATA "
"ChannelId %d, (re-assembled) Length %d, Data (omitted from the log)",
chan_id, bytes);
session = self->sec_layer->rdp_layer->session;
if (chan_id > 255)
{
LOG(LOG_LEVEL_ERROR, "Received message for an invalid "
"channel id. channel id %d", chan_id);
return 1;
}
drdynvc = self->drdynvcs + chan_id;
@ -435,10 +541,18 @@ drdynvc_process_data(struct xrdp_channel *self,
{
return drdynvc->data(session->id, chan_id, s->p, bytes);
}
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
"callback 'data' is NULL",
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
chan_id);
return 0;
}
/*****************************************************************************/
/**
* Process a [MS-RDPBCGR] 2.2.6.1 Virtual Channel PDU and re-assemble the
* data chunks as needed.
*/
static int
xrdp_channel_process_drdynvc(struct xrdp_channel *self,
struct mcs_channel_item *channel,
@ -451,61 +565,82 @@ xrdp_channel_process_drdynvc(struct xrdp_channel *self,
int rv;
struct stream *ls;
if (!s_check_rem(s, 8))
if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] CHANNEL_PDU_HEADER"))
{
return 1;
}
in_uint32_le(s, total_length);
in_uint32_le(s, flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: total_length %d flags 0x%8.8x",
total_length, flags);
in_uint32_le(s, total_length); /* length */
in_uint32_le(s, flags); /* flags */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] CHANNEL_PDU_HEADER "
"length %d, flags 0x%8.8x", total_length, flags);
ls = NULL;
switch (flags & 3)
{
case 0:
case 0: /* not first chunk and not last chunk */
length = (int) (s->end - s->p);
if (!s_check_rem_out(self->s, length))
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (middle) "
"length %d", length);
if (length > s_rem_out(self->s))
{
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than "
"the remaining chunk buffer size. length %d, remaining %d",
length, s_rem_out(self->s));
return 1;
}
out_uint8a(self->s, s->p, length);
in_uint8s(s, length);
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
in_uint8s(s, length); /* virtualChannelData */
return 0;
case 1:
case 1: /* CHANNEL_FLAG_FIRST */
free_stream(self->s);
make_stream(self->s);
init_stream(self->s, total_length);
length = (int) (s->end - s->p);
if (!s_check_rem_out(self->s, length))
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (first) "
"length %d", length);
if (length > s_rem_out(self->s))
{
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than "
"the remaining chunk buffer size. length %d, remaining %d",
length, s_rem_out(self->s));
return 1;
}
out_uint8a(self->s, s->p, length);
in_uint8s(s, length);
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
in_uint8s(s, length); /* virtualChannelData */
return 0;
case 2:
case 2: /* CHANNEL_FLAG_LAST */
length = (int) (s->end - s->p);
if (!s_check_rem_out(self->s, length))
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (last) "
"length %d", length);
if (length > s_rem_out(self->s))
{
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than "
"the remaining chunk buffer size. length %d, remaining %d",
length, s_rem_out(self->s));
return 1;
}
out_uint8a(self->s, s->p, length);
in_uint8s(s, length);
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
in_uint8s(s, length); /* virtualChannelData */
ls = self->s;
break;
case 3:
case 3: /* CHANNEL_FLAG_FIRST and CHANNEL_FLAG_LAST */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (first and last) "
"length %d", total_length);
ls = s;
break;
default:
LOG(LOG_LEVEL_ERROR, "xrdp_channel_process_drdynvc: error");
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPBCGR] data chunk with "
"unknown flag 0x%8.8x", (int) (flags & 3));
return 1;
}
if (ls == NULL)
{
LOG(LOG_LEVEL_ERROR, "BUG: ls must not be NULL");
return 1;
}
in_uint8(ls, cmd); /* read command */
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: cmd 0x%x", cmd);
in_uint8(ls, cmd); /* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPEDYC] "
"cbId %d, Sp %d, Cmd 0x%2.2x",
(cmd & 0x03), (cmd & 0x0c) >> 2, (cmd & 0xf0) >> 4);
rv = 1;
switch (cmd & 0xf0)
{
@ -525,16 +660,17 @@ xrdp_channel_process_drdynvc(struct xrdp_channel *self,
rv = drdynvc_process_data(self, cmd, s);
break;
default:
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: got unknown "
"command 0x%x", cmd);
LOG(LOG_LEVEL_ERROR, "Received header [MS-RDPEDYC] with "
"unknown command 0x%2.2x", cmd);
break;
}
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: rv %d", rv);
return rv;
}
/*****************************************************************************/
/* returns error */
/* Process a static ([MS-RDPBCGR] 2.2.6) or dynamic (MS-RDPEDYC 2.2.3)
* virtual channel message.
* returns error */
/* This is called from the secure layer to process an incoming non global
channel packet.
'chanid' passed in here is the mcs channel id so it MCS_GLOBAL_CHANNEL
@ -557,12 +693,16 @@ xrdp_channel_process(struct xrdp_channel *self, struct stream *s,
channel = xrdp_channel_get_item(self, channel_id);
if (channel == NULL)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_process, channel not found");
LOG(LOG_LEVEL_ERROR,
"Received a message for an unknown channel id. channel id %d",
chanid);
return 1;
}
if (channel->disabled)
{
LOG(LOG_LEVEL_WARNING, "xrdp_channel_process, channel disabled");
LOG(LOG_LEVEL_WARNING,
"Received a message for the disabled channel %s (%d)",
channel->name, chanid);
return 0; /* not an error */
}
if (channel_id == self->drdynvc_channel_id)
@ -570,14 +710,16 @@ xrdp_channel_process(struct xrdp_channel *self, struct stream *s,
return xrdp_channel_process_drdynvc(self, channel, s);
}
rv = 0;
in_uint32_le(s, length);
in_uint32_le(s, flags);
in_uint32_le(s, length); /* length */
in_uint32_le(s, flags); /* flags */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] CHANNEL_PDU_HEADER "
"length %d, flags 0x%8.8x", length, flags);
rv = xrdp_channel_call_callback(self, s, channel_id, length, flags);
return rv;
}
/*****************************************************************************/
/* drdynvc */
/* Send a [MS-RDPEDYC] DYNVC_CAPS_VERSION2 message */
static int
xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
{
@ -592,11 +734,13 @@ xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
init_stream(s, 8192);
if (xrdp_channel_init(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_channel_drdynvc_send_capability_request: xrdp_channel_init failed");
free_stream(s);
return 1;
}
phold = s->p;
out_uint8(s, 0x50); /* insert cmd */
out_uint8(s, 0x50); /* insert cbId (2 bits), Sp (2 bits), cmd (4 bits) */
out_uint8(s, 0x00); /* insert padding */
out_uint16_le(s, 2); /* insert version */
/* channel priority unused for now */
@ -609,8 +753,13 @@ xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
total_data_len = (int) (s->end - phold);
flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
channel_id = self->drdynvc_channel_id;
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CAPS_VERSION2 "
"cbId 0, Sp 0, Cmd 0x05, Version 2, PriorityCharge0 0, "
"PriorityCharge1 0, PriorityCharge2 0, PriorityCharge3 0");
if (xrdp_channel_send(self, s, channel_id, total_data_len, flags) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_channel_drdynvc_send_capability_request: xrdp_channel_send failed");
free_stream(s);
return 1;
}
@ -627,7 +776,12 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self)
struct mcs_channel_item *ci;
struct mcs_channel_item *dci;
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_drdynvc_start:");
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: drdynvc_channel_id %d", self->drdynvc_channel_id);
if (self->drdynvc_channel_id != -1)
{
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: already started");
return 0;
}
dci = NULL;
count = self->mcs_layer->channel_list->count;
for (index = 0; index < count; index++)
@ -645,12 +799,24 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self)
if (dci != NULL)
{
self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1;
LOG_DEVEL(LOG_LEVEL_DEBUG,
"Initializing Dynamic Virtual Channel with channel id %d",
self->drdynvc_channel_id);
xrdp_channel_drdynvc_send_capability_request(self);
}
else
{
LOG(LOG_LEVEL_WARNING,
"Dynamic Virtual Channel named 'drdynvc' not found, "
"channel not initialized");
}
return 0;
}
/*****************************************************************************/
/*
* Send a [MS-RDPEDYC] DYNVC_CREATE_REQ message to request the creation of a channel.
*/
int
xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
int flags, struct xrdp_drdynvc_procs *procs,
@ -670,33 +836,46 @@ xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
init_stream(s, 8192);
if (xrdp_channel_init(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_channel_drdynvc_open: xrdp_channel_init failed");
free_stream(s);
return 1;
}
cmd_ptr = s->p;
out_uint8(s, 0);
out_uint8(s, 0); /* set later */
ChId = 1;
while (self->drdynvcs[ChId].status != XRDP_DRDYNVC_STATUS_CLOSED)
{
ChId++;
if (ChId > 255)
{
LOG(LOG_LEVEL_ERROR,
"Attempting to create a new channel when the maximum "
"number of channels have already been created. "
"XRDP only supports 255 open channels.");
free_stream(s);
return 1;
}
}
cbChId = drdynvc_insert_uint_124(s, ChId);
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
name_length = g_strlen(name);
out_uint8a(s, name, name_length + 1);
out_uint8a(s, name, name_length + 1); /* ChannelName */
chan_pri = 0;
/* cbId (low 2 bits), Pri (2 bits), Cmd (hi 4 bits) */
cmd_ptr[0] = CMD_DVC_OPEN_CHANNEL | ((chan_pri << 2) & 0x0c) | cbChId;
static_channel_id = self->drdynvc_channel_id;
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
s_mark_end(s);
total_data_len = (int) (s->end - cmd_ptr);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CREATE_REQ "
"cbId %d, Pri %d, Cmd 0x%2.2x, ChannelId %d, ChannelName [%s]",
cbChId, chan_pri, CMD_DVC_OPEN_CHANNEL, ChId, name);
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
static_flags) != 0)
{
LOG(LOG_LEVEL_ERROR,
"Sending [MS-RDPEDYC] DYNVC_CREATE_REQ failed");
free_stream(s);
return 1;
}
@ -711,6 +890,9 @@ xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
}
/*****************************************************************************/
/*
* Send a [MS-RDPEDYC] DYNVC_CLOSE message to request the closing of a channel.
*/
int
xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
{
@ -724,33 +906,48 @@ xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
if ((chan_id < 0) || (chan_id > 255))
{
LOG(LOG_LEVEL_ERROR, "Attempting to close an invalid channel id. "
"channel id %d", chan_id);
return 1;
}
if ((self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN) &&
(self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN_SENT))
{
/* not open */
LOG(LOG_LEVEL_ERROR, "Attempting to close a channel that is not open. "
"channel id %d, channel status %s",
chan_id,
XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status));
return 1;
}
make_stream(s);
init_stream(s, 8192);
if (xrdp_channel_init(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_channel_drdynvc_close: xrdp_channel_init failed");
free_stream(s);
return 1;
}
cmd_ptr = s->p;
out_uint8(s, 0);
out_uint8(s, 0); /* set later */
ChId = chan_id;
cbChId = drdynvc_insert_uint_124(s, ChId);
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
/* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */
cmd_ptr[0] = CMD_DVC_CLOSE_CHANNEL | cbChId;
static_channel_id = self->drdynvc_channel_id;
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
s_mark_end(s);
total_data_len = (int) (s->end - cmd_ptr);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CLOSE "
"cbId %d, Sp 0, Cmd 0x%2.2x, ChannelId %d",
cbChId, CMD_DVC_OPEN_CHANNEL, ChId);
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
static_flags) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_channel_drdynvc_open: xrdp_channel_send failed");
free_stream(s);
return 1;
}
@ -760,6 +957,9 @@ xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
}
/*****************************************************************************/
/*
* Send a [MS-RDPEDYC] DYNVC_DATA_FIRST message.
*/
int
xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
const char *data, int data_bytes,
@ -776,37 +976,53 @@ xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
if ((chan_id < 0) || (chan_id > 255))
{
LOG(LOG_LEVEL_ERROR, "Attempting to send data to an invalid "
"channel id. channel id %d", chan_id);
return 1;
}
if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN)
{
LOG(LOG_LEVEL_ERROR, "Attempting to send data to a channel that "
"is not open. channel id %d, channel status %s",
chan_id,
XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status));
return 1;
}
if (data_bytes > 1590)
{
LOG(LOG_LEVEL_ERROR, "Payload for channel id %d is is too big. "
"data_bytes %d", chan_id, data_bytes);
return 1;
}
make_stream(s);
init_stream(s, 8192);
if (xrdp_channel_init(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_channel_drdynvc_data_first: xrdp_channel_init failed");
free_stream(s);
return 1;
}
cmd_ptr = s->p;
out_uint8(s, 0);
out_uint8(s, 0); /* set later */
ChId = chan_id;
cbChId = drdynvc_insert_uint_124(s, ChId);
cbTotalDataSize = drdynvc_insert_uint_124(s, total_data_bytes);
out_uint8p(s, data, data_bytes);
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
cbTotalDataSize = drdynvc_insert_uint_124(s, total_data_bytes); /* Length */
out_uint8p(s, data, data_bytes); /* Data */
/* cbId (low 2 bits), Len (2 bits), Cmd (hi 4 bits) */
cmd_ptr[0] = CMD_DVC_DATA_FIRST | (cbTotalDataSize << 2) | cbChId;
static_channel_id = self->drdynvc_channel_id;
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
s_mark_end(s);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_DATA_FIRST "
"cbId %d, Len %d, Cmd 0x%2.2x, ChannelId %d, Length %d",
cbChId, cbTotalDataSize, CMD_DVC_DATA_FIRST, ChId, total_data_bytes);
total_data_len = (int) (s->end - cmd_ptr);
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
static_flags) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_channel_drdynvc_data_first: xrdp_channel_send failed");
free_stream(s);
return 1;
}
@ -815,6 +1031,9 @@ xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
}
/*****************************************************************************/
/*
* Send a [MS-RDPEDYC] DYNVC_DATA message.
*/
int
xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id,
const char *data, int data_bytes)
@ -829,36 +1048,52 @@ xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id,
if ((chan_id < 0) || (chan_id > 255))
{
LOG(LOG_LEVEL_ERROR, "Attempting to send data to an invalid "
"channel id. channel id %d", chan_id);
return 1;
}
if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN)
{
LOG(LOG_LEVEL_ERROR, "Attempting to send data to a channel that "
"is not open. channel id %d, channel status %s",
chan_id,
XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status));
return 1;
}
if (data_bytes > 1590)
{
LOG(LOG_LEVEL_ERROR, "Payload for channel id %d is is too big. "
"data_bytes %d", chan_id, data_bytes);
return 1;
}
make_stream(s);
init_stream(s, 8192);
if (xrdp_channel_init(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_channel_drdynvc_data: xrdp_channel_init failed");
free_stream(s);
return 1;
}
cmd_ptr = s->p;
out_uint8(s, 0);
out_uint8(s, 0); /* set later */
ChId = chan_id;
cbChId = drdynvc_insert_uint_124(s, ChId);
out_uint8p(s, data, data_bytes);
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
out_uint8p(s, data, data_bytes); /* Data */
/* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */
cmd_ptr[0] = CMD_DVC_DATA | cbChId;
static_channel_id = self->drdynvc_channel_id;
static_flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
s_mark_end(s);
total_data_len = (int) (s->end - cmd_ptr);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_DATA "
"cbId %d, Sp 0, Cmd 0x%2.2x, ChannelId %d",
cbChId, CMD_DVC_DATA_FIRST, ChId);
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
static_flags) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_channel_drdynvc_data: xrdp_channel_send failed");
free_stream(s);
return 1;
}

View File

@ -30,12 +30,11 @@ xrdp_fastpath_create(struct xrdp_sec *owner, struct trans *trans)
{
struct xrdp_fastpath *self;
LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_fastpath_create");
self = (struct xrdp_fastpath *)g_malloc(sizeof(struct xrdp_fastpath), 1);
self->sec_layer = owner;
self->trans = trans;
self->session = owner->rdp_layer->session;
LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_fastpath_create");
return self;
}
@ -63,13 +62,13 @@ int
xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)
{
int fp_hdr;
int len = 0; /* unused */
int len = 0;
int byte;
char *holdp;
LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_fastpath_recv");
holdp = s->p;
if (!s_check_rem(s, 2))
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_FP_INPUT_PDU"))
{
return 1;
}
@ -84,7 +83,7 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)
byte &= ~(0x80);
len = (byte << 8);
if (!s_check_rem(s, 1))
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_INPUT_PDU length2"))
{
return 1;
}
@ -97,7 +96,10 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)
len = byte;
}
s->next_packet = holdp + len;
LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_fastpath_recv");
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_FP_INPUT_PDU "
"fpInputHeader.action (ignored), fpInputHeader.numEvents %d, "
"fpInputHeader.flags 0x%1.1x, length %d",
self->numEvents, self->secFlags, len);
return 0;
}
@ -134,6 +136,10 @@ xrdp_fastpath_session_callback(struct xrdp_fastpath *self, int msg,
self->session->callback(self->session->id, msg,
param1, param2, param3, param4);
}
else
{
LOG_DEVEL(LOG_LEVEL_WARNING, "Bug: session is NULL");
}
return 0;
}
@ -163,11 +169,14 @@ xrdp_fastpath_process_EVENT_SCANCODE(struct xrdp_fastpath *self,
int code;
flags = 0;
if (!s_check_rem(s, 1))
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_KEYBOARD_EVENT"))
{
return 1;
}
in_uint8(s, code); /* keyCode (1 byte) */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_KEYBOARD_EVENT "
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), "
"keyCode %d", eventFlags, code);
if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE))
{
@ -205,13 +214,16 @@ xrdp_fastpath_process_EVENT_MOUSE(struct xrdp_fastpath *self,
return 1;
}
if (!s_check_rem(s, 2 + 2 + 2))
if (!s_check_rem_and_log(s, 2 + 2 + 2, "Parsing [MS-RDPBCGR] TS_FP_POINTER_EVENT"))
{
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) */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_POINTER_EVENT "
"eventHeader.eventFlags 0x00, eventHeader.eventCode (ignored), "
"pointerFlags 0x%4.4x, xPos %d, yPos %d", pointerFlags, xPos, yPos);
xrdp_fastpath_session_callback(self, RDP_INPUT_MOUSE,
xPos, yPos, pointerFlags, 0);
@ -235,13 +247,18 @@ xrdp_fastpath_process_EVENT_MOUSEX(struct xrdp_fastpath *self,
return 1;
}
if (!s_check_rem(s, 2 + 2 + 2))
if (!s_check_rem_and_log(s, 2 + 2 + 2,
"Parsing [MS-RDPBCGR] TS_FP_POINTERX_EVENT"))
{
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) */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_POINTERX_EVENT "
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), "
"pointerFlags 0x%4.4x, xPos %d, yPos %d",
eventFlags, pointerFlags, xPos, yPos);
xrdp_fastpath_session_callback(self, RDP_INPUT_MOUSEX,
xPos, yPos, pointerFlags, 0);
@ -263,6 +280,10 @@ xrdp_fastpath_process_EVENT_SYNC(struct xrdp_fastpath *self,
* status of the keyboard toggle keys.
*/
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_SYNC_EVENT"
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), ",
eventFlags);
xrdp_fastpath_session_callback(self, RDP_INPUT_SYNCHRONIZE,
eventFlags, 0, 0, 0);
@ -279,11 +300,16 @@ xrdp_fastpath_process_EVENT_UNICODE(struct xrdp_fastpath *self,
int code;
flags = 0;
if (!s_check_rem(s, 2))
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_FP_UNICODE_KEYBOARD_EVENT"))
{
return 1;
}
in_uint16_le(s, code); /* unicode (2 byte) */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_UNICODE_KEYBOARD_EVENT"
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), "
"unicodeCode %d",
eventFlags, code);
if (eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE)
{
flags |= KBD_FLAG_UP;
@ -315,7 +341,7 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self,
/* process fastpath input events */
for (i = 0; i < self->numEvents; i++)
{
if (!s_check_rem(s, 1))
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_INPUT_EVENT eventHeader"))
{
return 1;
}
@ -323,6 +349,9 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self,
eventFlags = (eventHeader & 0x1F);
eventCode = (eventHeader >> 5);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_INPUT_EVENT"
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode 0x%1.1x",
eventFlags, eventCode);
switch (eventCode)
{
@ -367,8 +396,8 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self,
}
break;
default:
LOG(LOG_LEVEL_WARNING, "xrdp_fastpath_process_input_event: unknown "
"eventCode %d", eventCode);
LOG(LOG_LEVEL_ERROR, "xrdp_fastpath_process_input_event: "
"unknown eventCode %d", eventCode);
break;
}
}

View File

@ -17,6 +17,11 @@
* limitations under the License.
*
* iso layer
*
* Note: [ITU-T X.224] and [ISO/IEC 8073] are essentially two specifications
* of the same protocol (see [ITU-T X.224] Appendix I – Differences between
* ITU-T Rec. X.224 (1993) and ISO/IEC 8073:1992). The RDP protocol
* specification [MS-RDPBCGR] makes reference to the [ITU-T X.224] specificaiton.
*/
#if defined(HAVE_CONFIG_H)
@ -36,11 +41,9 @@ xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans)
{
struct xrdp_iso *self;
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_create");
self = (struct xrdp_iso *) g_malloc(sizeof(struct xrdp_iso), 1);
self->mcs_layer = owner;
self->trans = trans;
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_create");
return self;
}
@ -77,8 +80,10 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
!g_file_readable(client_info->key_file))
{
/* certificate or privkey is not readable */
LOG(LOG_LEVEL_WARNING, "No readable certificates or "
"private keys, cannot accept TLS connections");
LOG(LOG_LEVEL_ERROR, "Cannot accept TLS connections because "
"certificate or private key file is not readable. "
"certificate file: [%s], private key file: [%s]",
client_info->certificate, client_info->key_file);
self->failureCode = SSL_CERT_NOT_ON_SERVER;
rv = 1; /* error */
}
@ -89,6 +94,8 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
}
else
{
LOG(LOG_LEVEL_ERROR, "Server requires TLS for security, "
"but the client did not request TLS.");
self->failureCode = SSL_REQUIRED_BY_SERVER;
rv = 1; /* error */
}
@ -116,40 +123,52 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
}
/*****************************************************************************/
/* returns error */
/* Process a [MS-RDPBCGR] RDP_NEG_REQ message.
* returns error
*/
static int
xrdp_iso_process_rdp_neg_req(struct xrdp_iso *self, struct stream *s)
{
int flags;
int len;
if (!s_check_rem(s, 7))
if (!s_check_rem_and_log(s, 7, "Parsing [MS-RDPBCGR] RDP_NEG_REQ"))
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: unexpected end-of-record");
return 1;
}
in_uint8(s, flags);
/* The type field has already been read to determine that this function
should be called */
in_uint8(s, flags); /* flags */
if (flags != 0x0 && flags != 0x8 && flags != 0x1)
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, flags: %x", flags);
LOG(LOG_LEVEL_ERROR,
"Unsupported [MS-RDPBCGR] RDP_NEG_REQ flags: 0x%2.2x", flags);
return 1;
}
in_uint16_le(s, len);
in_uint16_le(s, len); /* length */
if (len != 8)
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, length: %x", len);
LOG(LOG_LEVEL_ERROR,
"Protocol error: [MS-RDPBCGR] RDP_NEG_REQ length must be 8, "
"received %d", len);
return 1;
}
in_uint32_le(s, self->requestedProtocol);
in_uint32_le(s, self->requestedProtocol); /* requestedProtocols */
/* TODO: why is requestedProtocols flag value bigger than 0xb invalid? */
if (self->requestedProtocol > 0xb)
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, requestedProtocol: %x",
self->requestedProtocol);
LOG(LOG_LEVEL_ERROR,
"Unknown requested protocol flag [MS-RDPBCGR] RDP_NEG_REQ, "
"requestedProtocol 0x%8.8x", self->requestedProtocol);
return 1;
}
LOG_DEVEL(LOG_LEVEL_TRACE, "Received struct [MS-RDPBCGR] RDP_NEG_REQ "
"flags 0x%2.2x, length 8, requestedProtocol 0x%8.8x",
flags, self->requestedProtocol);
return 0;
}
@ -163,6 +182,10 @@ xrdp_iso_process_rdp_neg_req(struct xrdp_iso *self, struct stream *s)
* On exit, the TPKT header and the fixed part of the PDU header will have been
* removed from the stream.
*
* @param self
* @param s [in]
* @param code [out]
* @param len [out]
* Returns error
*****************************************************************************/
static int
@ -175,83 +198,110 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len)
if (s != self->trans->in_s)
{
LOG(LOG_LEVEL_WARNING, "xrdp_iso_recv_msg error logic");
LOG(LOG_LEVEL_WARNING,
"Bug: the input stream is not the same stream as the "
"transport input stream");
}
/* TPKT header is 4 bytes, then first 2 bytes of the X.224 CR-TPDU */
if (!s_check_rem(s, 6))
/* [ITU-T T.123] TPKT header is 4 bytes, then first 2 bytes of the X.224 CR-TPDU */
if (!s_check_rem_and_log(s, 6,
"Parsing [ITU-T T.123] TPKT header and [ITU-T X.224] TPDU header"))
{
return 1;
}
in_uint8(s, ver);
in_uint8s(s, 3); /* Skip reserved field, plus length */
in_uint8(s, *len);
in_uint8(s, *code);
/* [ITU-T T.123] TPKT header */
in_uint8(s, ver); /* version */
in_uint8s(s, 3); /* Skip reserved field (1 byte), plus length (2 bytes) */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [ITU-T T.123] TPKT "
"version %d, length (ignored)", ver);
/* [ITU-T X.224] TPDU header */
in_uint8(s, *len); /* LI (length indicator) */
in_uint8(s, *code); /* TPDU code */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [ITU-T X.224] TPDU "
"length indicator %d, TDPU code 0x%2.2x", *len, *code);
if (ver != 3)
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv_msg: bad ver");
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "header", s->data, 4);
LOG(LOG_LEVEL_ERROR,
"Unsupported [ITU-T T.123] TPKT header version: %d", ver);
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "[ITU-T T.123] TPKT header", s->data, 4);
return 1;
}
if (*len == 255)
{
/* X.224 13.2.1 - reserved value */
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv_msg: reserved length encountered");
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "header", s->data, 4);
LOG(LOG_LEVEL_ERROR,
"[ITU-T X.224] TPDU header: unsupported use of reserved length value");
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "[ITU-T X.224] TPDU header", s->data + 4, 4);
return 1;
}
if (*code == ISO_PDU_DT)
{
/* Data PDU : X.224 13.7 */
if (!s_check_rem(s, 1))
/* Data PDU : X.224 13.7 class 0 */
if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T X.224] DT-TPDU (Data) header"))
{
return 1;
}
in_uint8s(s, 1);
in_uint8s(s, 1); /* EOT (End of TSDU Mark) (upper 1 bit) and
TPDU-NR (Data TPDU Number) (lower 7 bits) */
}
else
{
/* Other supported PDUs : X.224 13.x */
if (!s_check_rem(s, 5))
/* Other supported X.224 class 0 PDUs all have 5 bytes remaining
in the fixed header :
CR Connection request (13.3)
CC Connection confirm (13.4)
DR Disconnect request (13.5) */
if (!s_check_rem_and_log(s, 5, "Parsing [ITU-T X.224] Other PDU header"))
{
return 1;
}
in_uint8s(s, 5);
in_uint8s(s, 5); /* DST-REF (2 bytes)
SRC-REF (2 bytes)
[CR, CC] CLASS OPTION (1 byte) or [DR] REASON (1 byte) */
}
return 0;
}
/*****************************************************************************/
/* returns error */
/* Process the header of a [ITU-T X.224] DT-TPDU (Data) message.
*
* returns error
*/
int
xrdp_iso_recv(struct xrdp_iso *self, struct stream *s)
{
int code;
int len;
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_recv");
if (xrdp_iso_recv_msg(self, s, &code, &len) != 0)
{
LOG(LOG_LEVEL_ERROR, " out xrdp_iso_recv xrdp_iso_recv_msg return non zero");
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv: xrdp_iso_recv_msg failed");
return 1;
}
if (code != ISO_PDU_DT || len != 2)
{
LOG(LOG_LEVEL_ERROR, " out xrdp_iso_recv code != ISO_PDU_DT or length != 2");
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv only supports processing "
"[ITU-T X.224] DT-TPDU (Data) headers. Received TPDU header: "
"length indicator %d, TDPU code 0x%2.2x", len, code);
return 1;
}
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_recv");
return 0;
}
/*****************************************************************************/
/*
* Send a [ITU-T X.224] CC-TPDU (Connection Confirm) message with
* [ITU-T T.123] TPKT header.
*
* returns error
*/
static int
xrdp_iso_send_cc(struct xrdp_iso *self)
{
@ -266,35 +316,44 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
init_stream(s, 8192);
holdp = s->p;
/* tpkt */
/* [ITU-T T.123] TPKT header */
out_uint8(s, 3); /* version */
out_uint8(s, 0); /* pad */
out_uint8(s, 0); /* reserved (padding) */
len_ptr = s->p;
out_uint16_be(s, 0); /* length, set later */
/* iso */
/* [ITU-T X.224] CC-TPDU */
len_indicator_ptr = s->p;
out_uint8(s, 0); /* length indicator, set later */
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);
/* rdpNegData */
out_uint16_be(s, 0); /* DST-REF */
out_uint16_be(s, 0x1234); /* SRC-REF */
out_uint8(s, 0); /* CLASS OPTION */
/* [MS-RDPBCGR] 2.2.1.2 rdpNegData */
if (self->rdpNegData)
{
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 */
/* [MS-RDPBCGR] RDP_NEG_FAILURE */
out_uint8(s, RDP_NEG_FAILURE); /* type*/
out_uint8(s, 0); /* flags (none) */
out_uint16_le(s, 8); /* length (must be 8) */
out_uint32_le(s, self->failureCode); /* failureCode */
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding structure [MS-RDPBCGR] RDP_NEG_FAILURE "
"flags 0, length 8, failureCode 0x%8.8x", self->failureCode);
}
else
{
out_uint8(s, RDP_NEG_RSP);
/* [MS-RDPBCGR] RDP_NEG_RSP */
out_uint8(s, RDP_NEG_RSP); /* type*/
//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 */
out_uint16_le(s, 8); /* length (must be 8) */
out_uint32_le(s, self->selectedProtocol); /* selectedProtocol */
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding structure [MS-RDPBCGR] RDP_NEG_RSP "
"flags 0, length 8, selectedProtocol 0x%8.8x",
self->selectedProtocol);
}
}
s_mark_end(s);
@ -305,8 +364,15 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
len_ptr[1] = len;
len_indicator_ptr[0] = len_indicator;
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T T.123] TPKT "
"version 3, length %d", len);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [ITU-T X.224] CC-TPDU (Connection Confirm) "
"length indicator %d, DST-REF 0, SRC-REF 0, CLASS OPTION 0",
len_indicator);
if (trans_write_copy_s(self->trans, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "Sending [ITU-T X.224] CC-TPDU (Connection Confirm) failed");
free_stream(s);
return 1;
}
@ -317,7 +383,7 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
/*****************************************************************************
* Process an X.224 connection request PDU
*
* See MS-RDPCGR v20190923 sections 2.2.1.1 and 3.3.5.3.1.
* See MS-RDPBCGR v20190923 sections 2.2.1.1 and 3.3.5.3.1.
*
* From the latter, in particular:-
* - The length embedded in the TPKT header MUST be examined for
@ -339,22 +405,26 @@ xrdp_iso_incoming(struct xrdp_iso *self)
struct stream *s;
int expected_pdu_len;
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_incoming");
LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: receive connection request");
s = libxrdp_force_read(self->trans);
if (s == NULL)
{
LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: CR-TPDU (Connection Request) failed");
return 1;
}
if (xrdp_iso_recv_msg(self, s, &code, &len) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_recv_msg returned non zero");
LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: CR-TPDU (Connection Request) failed");
return 1;
}
if (code != ISO_PDU_CR)
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming only supports processing "
"[ITU-T X.224] CR-TPDU (Connection Request) headers. "
"Received TPDU header: length indicator %d, TDPU code 0x%2.2x",
len, code);
return 1;
}
@ -369,38 +439,47 @@ xrdp_iso_incoming(struct xrdp_iso *self)
expected_pdu_len = (s->end - s->p) + 6;
if (len != expected_pdu_len)
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: X.224 CR-TPDU length exp %d got %d",
LOG(LOG_LEVEL_ERROR,
"Invalid length indicator in [ITU-T X.224] CR-TPDU (Connection Request). "
"expected %d, received %d",
expected_pdu_len, len);
return 1;
}
/* process connection request */
/* process connection request [MS-RDPBCGR] 2.2.1.1 */
while (s_check_rem(s, 1))
{
in_uint8(s, cc_type);
in_uint8(s, cc_type); /* type or 'C' */
switch (cc_type)
{
default:
LOG_DEVEL(LOG_LEVEL_WARNING,
"Ignoring unknown structure type in [ITU-T X.224] CR-TPDU (Connection Request). "
"type 0x%2.2x", cc_type);
break;
case RDP_NEG_REQ: /* rdpNegReq 1 */
self->rdpNegData = 1;
if (xrdp_iso_process_rdp_neg_req(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_process_rdpNegReq returned non zero");
LOG(LOG_LEVEL_ERROR,
"[ITU-T X.224] Connection Sequence: failed");
return 1;
}
break;
case RDP_CORRELATION_INFO: /* rdpCorrelationInfo 6 */
// TODO
if (!s_check_rem(s, 1 + 2 + 16 + 16))
if (!s_check_rem_and_log(s, 1 + 2 + 16 + 16,
"Parsing [MS-RDPBCGR] RDP_NEG_CORRELATION_INFO"))
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: short correlation info");
return 1;
}
in_uint8s(s, 1 + 2 + 16 + 16);
LOG_DEVEL(LOG_LEVEL_TRACE,
"Received struct [MS-RDPBCGR] RDP_NEG_CORRELATION_INFO "
"(all fields ignored)");
break;
case 'C': /* Cookie */
case 'C': /* Cookie or routingToken */
/* The routingToken and cookie fields are both ASCII
* strings starting with the word 'Cookie: ' and
* ending with CR+LF. We ignore both, so we do
@ -417,6 +496,9 @@ xrdp_iso_incoming(struct xrdp_iso *self)
}
}
}
LOG_DEVEL(LOG_LEVEL_TRACE,
"Received struct [MS-RDPBCGR] routingToken or cookie "
"(ignored)");
break;
}
}
@ -425,13 +507,14 @@ xrdp_iso_incoming(struct xrdp_iso *self)
rv = xrdp_iso_negotiate_security(self);
/* send connection confirm back to client */
LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: send connection confirmation");
if (xrdp_iso_send_cc(self) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_send_cc returned non zero");
LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: send connection confirmation failed");
return 1;
}
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_incoming");
LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: completed");
return rv;
}
@ -446,27 +529,39 @@ xrdp_iso_init(struct xrdp_iso *self, struct stream *s)
}
/*****************************************************************************/
/* returns error */
/* Sends a message with the [ITU-T T.123] TPKT header (T.123 section 8) and
* [ITU-T X.224] DT-TPDU (Data) header (X.224 section 13)
* returns error
*/
int
xrdp_iso_send(struct xrdp_iso *self, struct stream *s)
{
int len;
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_send");
s_pop_layer(s, iso_hdr);
len = (int) (s->end - s->p);
out_uint8(s, 3);
out_uint8(s, 0);
out_uint16_be(s, len);
out_uint8(s, 2);
out_uint8(s, ISO_PDU_DT);
out_uint8(s, 0x80);
/* [ITU-T T.123] TPKT header */
out_uint8(s, 3); /* version */
out_uint8(s, 0); /* reserved (padding) */
out_uint16_be(s, len); /* length */
/* [ITU-T X.224] DT-TPDU (Data) header */
out_uint8(s, 2); /* LI (length indicator) */
out_uint8(s, ISO_PDU_DT); /* TPDU code */
out_uint8(s, 0x80); /* EOT (End of TSDU Mark) (upper 1 bit) and
TPDU-NR (Data TPDU Number) (lower 7 bits) */
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T T.123] TPKT "
"version 3, length %d", len);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T X.224] DT-TPDU (Data) "
"length indicator 2, TPDU code 0x%2.2x, EOT 1, TPDU-NR 0x00",
ISO_PDU_DT);
if (trans_write_copy_s(self->trans, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_iso_send: trans_write_copy_s failed");
return 1;
}
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_send");
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -969,6 +969,10 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
{
/* compressed data longer than uncompressed data */
/* give up */
LOG_DEVEL(LOG_LEVEL_DEBUG, "Compression algorithim produced a compressed "
"buffer which is larger than the uncompressed buffer. "
"compression ratio %f, flags 0x%x",
(float) len / (float) opb_index, enc->flags);
enc->historyOffset = 0;
g_memset(hash_table, 0, enc->buf_len * 2);
g_memset(enc->historyBuffer, 0, enc->buf_len);
@ -982,10 +986,10 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
enc->flags |= enc->flagsHold;
enc->flagsHold = 0;
LOG_DEVEL(LOG_LEVEL_TRACE, "\n");
LOG_DEVEL(LOG_LEVEL_TRACE, "compression ratio: %f", (float) len / (float) enc->bytes_in_opb);
LOG_DEVEL(LOG_LEVEL_TRACE, "Compression successful. compression ratio %f, "
"flags 0x%x, bytes_in_opb %d, historyOffset %d, uncompressed len %d",
(float) len / (float) enc->bytes_in_opb, enc->flags,
enc->bytes_in_opb, enc->historyOffset, len);
return 1;
}

View File

@ -83,6 +83,7 @@ xrdp_orders_reset(struct xrdp_orders *self)
{
if (xrdp_orders_force_send(self) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_orders_reset: xrdp_orders_force_send failed");
return 1;
}
g_free(self->orders_state.text_data);
@ -109,23 +110,29 @@ xrdp_orders_init(struct xrdp_orders *self)
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_orders_init: fastpath");
if (xrdp_rdp_init_fastpath(self->rdp_layer, self->out_s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_orders_init: xrdp_rdp_init_fastpath failed");
return 1;
}
self->order_count_ptr = self->out_s->p;
out_uint8s(self->out_s, 2); /* number of orders, set later */
// LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] TODO");
}
else
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_orders_init: slowpath");
if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_orders_init: xrdp_rdp_init_data failed");
return 1;
}
out_uint16_le(self->out_s, RDP_UPDATE_ORDERS);
out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); /* updateType */
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 */
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] TS_UPDATE_ORDERS_PDU_DATA "
"updateType %d (UPDATETYPE_ORDERS), pad2OctetsA <ignored>, "
"numberOrders <to be set later>, pad2OctetsB <ignored>",
RDP_UPDATE_ORDERS);
}
}
return 0;
@ -154,6 +161,8 @@ xrdp_orders_send(struct xrdp_orders *self)
if (xrdp_rdp_send_fastpath(self->rdp_layer,
self->out_s, 0) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_orders_send: xrdp_rdp_send_fastpath failed");
rv = 1;
}
}
@ -162,6 +171,8 @@ xrdp_orders_send(struct xrdp_orders *self)
if (xrdp_rdp_send_data(self->rdp_layer, self->out_s,
RDP_DATA_PDU_UPDATE) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_orders_send: xrdp_rdp_send_data failed");
rv = 1;
}
}
@ -225,6 +236,9 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size)
{
if (max_size > max_order_size)
{
LOG(LOG_LEVEL_ERROR, "Requested orders max_size (%d) "
"is greater than the client connection max_size (%d)",
max_size, max_order_size);
return 1;
}
else
@ -237,7 +251,8 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size)
size = (int)(self->out_s->p - self->order_count_ptr);
if (size < 0)
{
LOG(LOG_LEVEL_ERROR, "error in xrdp_orders_check, size too small: %d bytes", size);
LOG(LOG_LEVEL_ERROR, "Bug: order data length cannot be negative. "
"Found length %d bytes", size);
return 1;
}
if (size > max_order_size)
@ -245,7 +260,9 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size)
/* this suggests someone calls this function without passing the
correct max_size so we end up putting more into the buffer
than we indicate we can */
LOG(LOG_LEVEL_WARNING, "error in xrdp_orders_check, size too big: %d bytes", size);
LOG(LOG_LEVEL_WARNING, "Ignoring Bug: order data length "
"is larger than maximum length. Expected %d, actual %d",
max_order_size, size);
/* We where getting called with size already greater than
max_order_size
Which I suspect was because the sending of text did not include
@ -2175,15 +2192,23 @@ xrdp_orders_send_palette(struct xrdp_orders *self, int *palette,
if (xrdp_orders_check(self, 2000) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_orders_send_palette: xrdp_orders_check failed");
return 1;
}
self->order_count++;
order_flags = TS_STANDARD | TS_SECONDARY;
out_uint8(self->out_s, order_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] DRAWING_ORDER "
"controlFlags 0x%2.2x (TS_STANDARD | TS_SECONDARY)", order_flags);
len = 1027 - 7; /* length after type minus 7 */
out_uint16_le(self->out_s, len);
out_uint16_le(self->out_s, 0); /* flags */
out_uint8(self->out_s, TS_CACHE_COLOR_TABLE); /* type */
out_uint16_le(self->out_s, len); /* orderLength */
out_uint16_le(self->out_s, 0); /* extraFlags */
out_uint8(self->out_s, TS_CACHE_COLOR_TABLE); /* orderType */
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] SECONDARY_DRAWING_ORDER_HEADER "
"orderLength %d, extraFlags 0x0000, orderType 0x%2.2x (TS_CACHE_COLOR_TABLE)",
len, TS_CACHE_COLOR_TABLE);
out_uint8(self->out_s, cache_id);
out_uint16_le(self->out_s, 256); /* num colors */
@ -2194,7 +2219,9 @@ xrdp_orders_send_palette(struct xrdp_orders *self, int *palette,
out_uint8(self->out_s, palette[i] >> 16);
out_uint8(self->out_s, 0);
}
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPEGDI] CACHE_COLOR_TABLE_ORDER "
"cacheIndex %d, numberColors 256, colorTable <omitted from log>",
cache_id);
return 0;
}

View File

@ -42,12 +42,19 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id)
order_size = 11;
if (xrdp_orders_check(self, order_size) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_orders_send_window_delete: xrdp_orders_check failed");
return 1;
}
self->order_count++;
order_flags = TS_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
(order_flags & 0x3), (order_flags >> 2));
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
@ -55,6 +62,12 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id)
out_uint32_le(self->out_s, field_present_flags);
/* windowId (4 bytes) */
out_uint32_le(self->out_s, window_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
"OrderSize %d, "
"FieldsPresentFlags 0x%8.8x (WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_DELETED), "
"WindowId 0x%8.8x",
order_size, field_present_flags, window_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Deleted Window");
return 0;
}
@ -75,12 +88,19 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self,
order_size = 14;
if (xrdp_orders_check(self, order_size) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_orders_send_window_cached_icon: xrdp_orders_check failed");
return 1;
}
self->order_count++;
order_flags = TS_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
(order_flags & 0x3), (order_flags >> 2));
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
@ -89,10 +109,17 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self,
out_uint32_le(self->out_s, field_present_flags);
/* windowId (4 bytes) */
out_uint32_le(self->out_s, window_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x",
order_size, field_present_flags, window_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Cached Icon");
/* CacheEntry (2 bytes) */
out_uint16_le(self->out_s, cache_entry);
/* CacheId (1 byte) */
out_uint8(self->out_s, cache_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order field [MS-RDPERP] TS_CACHED_ICON_INFO "
"CacheEntry %d, CacheId %d", cache_entry, cache_id);
return 0;
}
@ -134,6 +161,18 @@ xrdp_orders_send_ts_icon(struct stream *s, int cache_entry, int cache_id,
}
out_uint8p(s, icon_info->data, icon_info->data_bytes);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order fields [MS-RDPERP] TS_ICON_INFO "
"CacheEntry %d, CacheId %d, Bpp %d, Width %d, Height %d, "
"CbColorTable <%s>, "
"CbBitsMask %d, CbBitsColor %d, BitsMask <omitted from log>, "
"ColorTable <%s>, "
"BitsColor <omitted from log>",
cache_entry, cache_id, icon_info->bpp, icon_info->width,
icon_info->height,
(use_cmap ? "present, omitted from log" : "not present"),
icon_info->mask_bytes, icon_info->data_bytes,
(use_cmap ? "present, omitted from log" : "not present")
);
return 0;
}
@ -169,12 +208,19 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self,
if (xrdp_orders_check(self, order_size) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_orders_send_window_icon: xrdp_orders_check failed");
return 1;
}
self->order_count++;
order_flags = TS_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
(order_flags & 0x3), (order_flags >> 2));
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
@ -183,6 +229,10 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self,
out_uint32_le(self->out_s, field_present_flags);
/* windowId (4 bytes) */
out_uint32_le(self->out_s, window_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x",
order_size, field_present_flags, window_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Window Icon");
xrdp_orders_send_ts_icon(self->out_s, cache_entry, cache_id, icon_info);
@ -372,23 +422,36 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
if (xrdp_orders_check(self, order_size) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_orders_send_window_new_update: xrdp_orders_check failed");
return 1;
}
self->order_count++;
order_flags = TS_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
(order_flags & 0x3), (order_flags >> 2));
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
out_uint32_le(self->out_s, field_present_flags);
/* windowId (4 bytes) */
out_uint32_le(self->out_s, window_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x",
order_size, field_present_flags, window_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] New or Existing Window (TS_WINDOW_INFO)");
if (field_present_flags & WINDOW_ORDER_FIELD_OWNER)
{
/* ownerWindowId (4 bytes) */
out_uint32_le(self->out_s, window_state->owner_window_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"OwnerWindowId 0x%8.8x", window_state->owner_window_id);
}
if (field_present_flags & WINDOW_ORDER_FIELD_STYLE)
@ -397,18 +460,28 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
out_uint32_le(self->out_s, window_state->style);
/* extendedStyle (4 bytes) */
out_uint32_le(self->out_s, window_state->extended_style);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"Style 0x%8.8x, ExtendedStyle 0x%8.8x",
window_state->style, window_state->extended_style);
}
if (field_present_flags & WINDOW_ORDER_FIELD_SHOW)
{
/* showState (1 byte) */
out_uint8(self->out_s, window_state->show_state);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"ShowState 0x%2.2x", window_state->show_state);
}
if (field_present_flags & WINDOW_ORDER_FIELD_TITLE)
{
/* titleInfo */
xrdp_orders_send_as_unicode(self->out_s, window_state->title_info);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"TitleInfo %s", window_state->title_info);
}
if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
@ -417,26 +490,61 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
out_uint32_le(self->out_s, window_state->client_offset_x);
/* clientOffsetY (4 bytes) */
out_uint32_le(self->out_s, window_state->client_offset_y);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"ClientOffsetX %d, ClientOffsetY %d",
window_state->client_offset_x, window_state->client_offset_y);
}
/* TODO: The [MS-RDPERP] spec says that:
* The ClientAreaWidth and ClientAreaHeight field only appears if the WndSupportLevel field of the
* Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX
* (as specified in [MS-RDPERP] section 2.2.1.1.2)
*/
if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
{
/* clientAreaWidth (4 bytes) */
out_uint32_le(self->out_s, window_state->client_area_width);
/* clientAreaHeight (4 bytes) */
out_uint32_le(self->out_s, window_state->client_area_height);
}
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"ClientAreaWidth %d, ClientAreaHeight %d",
window_state->client_area_width, window_state->client_area_height);
}
/* TODO: The [MS-RDPERP] spec section 2.2.1.3.1.2.1 has the following additional fields:
* WindowLeftResizeMargin (optional)
* WindowRightResizeMargin (optional)
* WindowTopResizeMargin (optional)
* WindowBottomResizeMargin (optional)
*/
/* TODO: The [MS-RDPERP] spec says that:
* The RPContent field only appears if the WndSupportLevel field of the
* Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX
* (as specified in [MS-RDPERP] section 2.2.1.1.2)
*/
if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT)
{
/* RPContent (1 byte) */
out_uint8(self->out_s, window_state->rp_content);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"RPContent 0x%2.2x", window_state->rp_content);
}
/* TODO: The [MS-RDPERP] spec says that:
* The RootParentHandle field only appears if the WndSupportLevel field of the
* Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX
* (as specified in [MS-RDPERP] section 2.2.1.1.2)
*/
if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT)
{
/* rootParentHandle (4 bytes) */
out_uint32_le(self->out_s, window_state->root_parent_handle);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"RootParentHandle 0x%8.8x", window_state->root_parent_handle);
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET)
@ -445,6 +553,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
out_uint32_le(self->out_s, window_state->window_offset_x);
/* windowOffsetY (4 bytes) */
out_uint32_le(self->out_s, window_state->window_offset_y);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"WindowOffsetX %d, WindowOffsetY %d",
window_state->window_offset_x, window_state->window_offset_y);
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
@ -453,6 +565,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
out_uint32_le(self->out_s, window_state->window_client_delta_x);
/* windowClientDeltaY (4 bytes) */
out_uint32_le(self->out_s, window_state->window_client_delta_y);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"WindowClientDeltaX %d, WindowClientDeltaY %d",
window_state->window_client_delta_x, window_state->window_client_delta_y);
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE)
@ -461,6 +577,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
out_uint32_le(self->out_s, window_state->window_width);
/* windowHeight (4 bytes) */
out_uint32_le(self->out_s, window_state->window_height);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"WindowWidth %d, WindowHeight %d",
window_state->window_width, window_state->window_height);
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS)
@ -475,6 +595,9 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
out_uint16_le(self->out_s, window_state->window_rects[index].right);
out_uint16_le(self->out_s, window_state->window_rects[index].bottom);
}
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"NumWindowRects %d, WindowRects <omitted from log>",
window_state->num_window_rects);
}
if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET)
@ -483,6 +606,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
out_uint32_le(self->out_s, window_state->visible_offset_x);
/* visibleOffsetY (4 bytes) */
out_uint32_le(self->out_s, window_state->visible_offset_y);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"VisibleOffsetX %d, VisibleOffsetY %d",
window_state->visible_offset_x, window_state->visible_offset_y);
}
if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY)
@ -497,7 +624,17 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
out_uint16_le(self->out_s, window_state->visibility_rects[index].right);
out_uint16_le(self->out_s, window_state->visibility_rects[index].bottom);
}
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
"NumVisibilityRects %d, VisibilityRects <omitted from log>",
window_state->num_visibility_rects);
}
/* TODO: The [MS-RDPERP] spec section 2.2.1.3.1.2.1 has the following additional fields:
* OverlayDescription (optional, variable)
* TaskbarButton (optional)
* EnforceServerZOrder (optional)
* AppBarState (optional)
* AppBarEdge (optional)
*/
return 0;
}
@ -516,12 +653,19 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id,
order_size = 15;
if (xrdp_orders_check(self, order_size) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_orders_send_notify_delete: xrdp_orders_check failed");
return 1;
}
self->order_count++;
order_flags = TS_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
(order_flags & 0x3), (order_flags >> 2));
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
@ -531,6 +675,11 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id,
out_uint32_le(self->out_s, window_id);
/* notifyIconId (4 bytes) */
out_uint32_le(self->out_s, notify_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_NOTIFYICON_ORDER_HEADER "
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x, NotifyIconId 0x%8.8x",
order_size, field_present_flags, window_id, notify_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Deleted Notification Icons");
return 0;
}
@ -610,12 +759,19 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
if (xrdp_orders_check(self, order_size) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_orders_send_notify_new_update: xrdp_orders_check failed");
return 1;
}
self->order_count++;
order_flags = TS_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
(order_flags & 0x3), (order_flags >> 2));
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
@ -624,17 +780,27 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
out_uint32_le(self->out_s, window_id);
/* notifyIconId (4 bytes) */
out_uint32_le(self->out_s, notify_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_NOTIFYICON_ORDER_HEADER "
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x, NotifyIconId 0x%8.8x",
order_size, field_present_flags, window_id, notify_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] New or Existing Notification Icons");
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
{
/* Version (4 bytes) */
out_uint32_le(self->out_s, notify_state->version);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
"Version %d", notify_state->version);
}
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
{
/* ToolTip (variable) UNICODE_STRING */
xrdp_orders_send_as_unicode(self->out_s, notify_state->tool_tip);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
"ToolTip %s", notify_state->tool_tip);
}
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
@ -644,12 +810,20 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
out_uint32_le(self->out_s, notify_state->infotip.flags);
xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.text);
xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.title);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] TS_NOTIFY_ICON_INFOTIP "
"Timeout %d, InfoFlags 0x%8.8x, InfoTipText %s, Title %s",
notify_state->infotip.timeout, notify_state->infotip.flags,
notify_state->infotip.text, notify_state->infotip.title);
}
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
{
/* State (4 bytes) */
out_uint32_le(self->out_s, notify_state->state);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
"State %d", notify_state->state);
}
if (field_present_flags & WINDOW_ORDER_ICON)
@ -666,6 +840,10 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
out_uint16_le(self->out_s, notify_state->icon_cache_entry);
/* CacheId (1 byte) */
out_uint8(self->out_s, notify_state->icon_cache_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order field [MS-RDPERP] TS_CACHED_ICON_INFO "
"CacheEntry %d, CacheId %d",
notify_state->icon_cache_entry, notify_state->icon_cache_id);
}
return 0;
@ -704,21 +882,37 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self,
if (xrdp_orders_check(self, order_size) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_orders_send_monitored_desktop: xrdp_orders_check failed");
return 1;
}
self->order_count++;
order_flags = TS_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
(order_flags & 0x3), (order_flags >> 2));
out_uint8(self->out_s, order_flags);
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
out_uint32_le(self->out_s, field_present_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_DESKTOP_ORDER_HEADER "
"OrderSize %d, FieldsPresentFlags 0x%8.8x",
order_size, field_present_flags);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] %s",
((field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_NONE) ?
"Non-Monitored Desktop" : "Actively Monitored Desktop"));
if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
{
/* ActiveWindowId (4 bytes) */
out_uint32_le(self->out_s, mdo->active_window_id);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
"ActiveWindowId 0x%8.8x", mdo->active_window_id);
}
if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
@ -731,6 +925,10 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self,
{
out_uint32_le(self->out_s, mdo->window_ids[index]);
}
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
"NumWindowIds %d, WindowIds <omitted from log>",
mdo->num_window_ids);
}
return 0;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

17
mc/mc.c
View File

@ -23,17 +23,18 @@
#endif
#include "mc.h"
#include "log.h"
/*****************************************************************************/
/* return error */
int
lib_mod_start(struct mod *mod, int w, int h, int bpp)
{
LIB_DEBUG(mod, "in lib_mod_start");
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_start");
mod->width = w;
mod->height = h;
mod->bpp = bpp;
LIB_DEBUG(mod, "out lib_mod_start");
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_start");
return 0;
}
@ -42,8 +43,8 @@ lib_mod_start(struct mod *mod, int w, int h, int bpp)
int
lib_mod_connect(struct mod *mod)
{
LIB_DEBUG(mod, "in lib_mod_connect");
LIB_DEBUG(mod, "out lib_mod_connect");
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_connect");
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_connect");
return 0;
}
@ -53,8 +54,8 @@ int
lib_mod_event(struct mod *mod, int msg, long param1, long param2,
long param3, long param4)
{
LIB_DEBUG(mod, "in lib_mod_event");
LIB_DEBUG(mod, "out lib_mod_event");
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_event");
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_event");
return 0;
}
@ -63,8 +64,8 @@ lib_mod_event(struct mod *mod, int msg, long param1, long param2,
int
lib_mod_signal(struct mod *mod)
{
LIB_DEBUG(mod, "in lib_mod_signal");
LIB_DEBUG(mod, "out lib_mod_signal");
LOG_DEVEL(LOG_LEVEL_TRACE, "in lib_mod_signal");
LOG_DEVEL(LOG_LEVEL_TRACE, "out lib_mod_signal");
return 0;
}

134
mc/mc.h
View File

@ -30,73 +30,73 @@ struct source_info;
struct mod
{
int size; /* size of this struct */
int version; /* internal version */
/* client functions */
int (*mod_start)(struct mod* v, int w, int h, int bpp);
int (*mod_connect)(struct mod* v);
int (*mod_event)(struct mod* v, int msg, long param1, long param2,
long param3, long param4);
int (*mod_signal)(struct mod* v);
int (*mod_end)(struct mod* v);
int (*mod_set_param)(struct mod *v, const char *name, const char *value);
int (*mod_session_change)(struct mod* v, int, int);
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);
tintptr mod_dumby[100 - 9]; /* align, 100 minus the number of mod
int size; /* size of this struct */
int version; /* internal version */
/* client functions */
int (*mod_start)(struct mod *v, int w, int h, int bpp);
int (*mod_connect)(struct mod *v);
int (*mod_event)(struct mod *v, int msg, long param1, long param2,
long param3, long param4);
int (*mod_signal)(struct mod *v);
int (*mod_end)(struct mod *v);
int (*mod_set_param)(struct mod *v, const char *name, const char *value);
int (*mod_session_change)(struct mod *v, int, int);
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);
tintptr mod_dumby[100 - 9]; /* align, 100 minus the number of mod
functions above */
/* server functions */
int (*server_begin_update)(struct mod* v);
int (*server_end_update)(struct mod* v);
int (*server_fill_rect)(struct mod* v, int x, int y, int cx, int cy);
int (*server_screen_blt)(struct mod* v, int x, int y, int cx, int cy,
int srcx, int srcy);
int (*server_paint_rect)(struct mod* v, int x, int y, int cx, int cy,
char* data, int width, int height, int srcx, int srcy);
int (*server_set_cursor)(struct mod* v, int x, int y, char* data, char* mask);
int (*server_palette)(struct mod* v, int* palette);
int (*server_msg)(struct mod* v, const char* msg, int code);
int (*server_is_term)(struct mod* v);
int (*server_set_clip)(struct mod* v, int x, int y, int cx, int cy);
int (*server_reset_clip)(struct mod* v);
int (*server_set_fgcolor)(struct mod* v, int fgcolor);
int (*server_set_bgcolor)(struct mod* v, int bgcolor);
int (*server_set_opcode)(struct mod* v, int opcode);
int (*server_set_mixmode)(struct mod* v, int mixmode);
int (*server_set_brush)(struct mod* v, int x_origin, int y_origin,
int style, char* pattern);
int (*server_set_pen)(struct mod* v, int style,
int width);
int (*server_draw_line)(struct mod* v, int x1, int y1, int x2, int y2);
int (*server_add_char)(struct mod* v, int font, int character,
int offset, int baseline,
int width, int height, char* data);
int (*server_draw_text)(struct mod* v, int font,
int flags, int mixmode, 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);
int (*server_reset)(struct mod* v, int width, int height, int bpp);
int (*server_query_channel)(struct mod* v, int index,
char* channel_name,
int* channel_flags);
int (*server_get_channel_id)(struct mod* v, const char *name);
int (*server_send_to_channel)(struct mod* v, int channel_id,
char* data, int data_len,
int total_data_len, int flags);
int (*server_bell_trigger)(struct mod* v);
tintptr server_dumby[100 - 25]; /* align, 100 minus the number of server
/* server functions */
int (*server_begin_update)(struct mod *v);
int (*server_end_update)(struct mod *v);
int (*server_fill_rect)(struct mod *v, int x, int y, int cx, int cy);
int (*server_screen_blt)(struct mod *v, int x, int y, int cx, int cy,
int srcx, int srcy);
int (*server_paint_rect)(struct mod *v, int x, int y, int cx, int cy,
char *data, int width, int height, int srcx, int srcy);
int (*server_set_cursor)(struct mod *v, int x, int y, char *data, char *mask);
int (*server_palette)(struct mod *v, int *palette);
int (*server_msg)(struct mod *v, const char *msg, int code);
int (*server_is_term)(struct mod *v);
int (*server_set_clip)(struct mod *v, int x, int y, int cx, int cy);
int (*server_reset_clip)(struct mod *v);
int (*server_set_fgcolor)(struct mod *v, int fgcolor);
int (*server_set_bgcolor)(struct mod *v, int bgcolor);
int (*server_set_opcode)(struct mod *v, int opcode);
int (*server_set_mixmode)(struct mod *v, int mixmode);
int (*server_set_brush)(struct mod *v, int x_origin, int y_origin,
int style, char *pattern);
int (*server_set_pen)(struct mod *v, int style,
int width);
int (*server_draw_line)(struct mod *v, int x1, int y1, int x2, int y2);
int (*server_add_char)(struct mod *v, int font, int character,
int offset, int baseline,
int width, int height, char *data);
int (*server_draw_text)(struct mod *v, int font,
int flags, int mixmode, 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);
int (*server_reset)(struct mod *v, int width, int height, int bpp);
int (*server_query_channel)(struct mod *v, int index,
char *channel_name,
int *channel_flags);
int (*server_get_channel_id)(struct mod *v, const char *name);
int (*server_send_to_channel)(struct mod *v, int channel_id,
char *data, int data_len,
int total_data_len, int flags);
int (*server_bell_trigger)(struct mod *v);
tintptr server_dumby[100 - 25]; /* align, 100 minus the number of server
functions above */
/* common */
tintptr handle; /* pointer to self as long */
tintptr wm;
tintptr painter;
struct source_info *si;
/* mod data */
int sck;
int width;
int height;
int bpp;
/* common */
tintptr handle; /* pointer to self as long */
tintptr wm;
tintptr painter;
struct source_info *si;
/* mod data */
int sck;
int width;
int height;
int bpp;
};

View File

@ -239,8 +239,8 @@ convert_bitmap(int in_bpp, int out_bpp, char *bmpdata,
return out;
}
g_writeln("convert_bitmap: error unknown conversion from %d to %d",
in_bpp, out_bpp);
LOG(LOG_LEVEL_WARNING, "convert_bitmap: error unknown conversion from %d to %d",
in_bpp, out_bpp);
return 0;
}
@ -341,7 +341,7 @@ convert_color(int in_bpp, int out_bpp, int in_color, int *palette)
return in_color;
}
g_writeln("convert_color: error unknown conversion from %d to %d",
in_bpp, out_bpp);
LOG(LOG_LEVEL_WARNING, "convert_color: error unknown conversion from %d to %d",
in_bpp, out_bpp);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -79,11 +79,16 @@ 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);
int (*mod_frame_ack)(struct mod* mod, int flags, int frame_id);
int (*mod_suppress_output)(struct mod* mod, int suppress,
int left, int top, int right, int bottom);
tintptr mod_dumby[100 - 11]; /* align, 100 minus the number of mod
functions above */
int (*mod_frame_ack)(struct mod *mod, int flags, int frame_id);
int (*mod_suppress_output)(struct mod *mod, int suppress,
int left, int top, int right, int bottom);
int (*mod_server_monitor_resize)(struct mod *mod,
int width, int height);
int (*mod_server_monitor_full_invalidate)(struct mod *mod,
int width, int height);
int (*mod_server_version_message)(struct mod *mod);
tintptr mod_dumby[100 - 14]; /* align, 100 minus the number of mod
functions above */
/* server functions */
int (*server_begin_update)(struct mod *v);
int (*server_end_update)(struct mod *v);
@ -157,27 +162,27 @@ struct mod
int flags);
int (*server_set_pointer_ex)(struct mod *mod, int x, int y, char *data,
char *mask, int bpp);
int (*server_add_char_alpha)(struct mod* mod, int font, int character,
int (*server_add_char_alpha)(struct mod *mod, int font, int character,
int offset, int baseline,
int width, int height, char* data);
int (*server_create_os_surface_bpp)(struct mod* v, int rdpindex,
int width, int height, char *data);
int (*server_create_os_surface_bpp)(struct mod *v, int rdpindex,
int width, int height, int bpp);
int (*server_paint_rect_bpp)(struct mod* v, int x, int y, int cx, int cy,
char* data, int width, int height,
int (*server_paint_rect_bpp)(struct mod *v, int x, int y, int cx, int cy,
char *data, int width, int height,
int srcx, int srcy, int bpp);
int (*server_composite)(struct mod* v, int srcidx, int srcformat,
int srcwidth, int srcrepeat, int* srctransform,
int (*server_composite)(struct mod *v, int srcidx, int srcformat,
int srcwidth, 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);
int (*server_paint_rects)(struct mod* v,
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, int frame_id);
int (*server_session_info)(struct mod* v, const char *data,
int (*server_session_info)(struct mod *v, const char *data,
int data_bytes);
tintptr server_dumby[100 - 44]; /* align, 100 minus the number of server
functions above */

View File

@ -129,6 +129,12 @@ fi
make_args="FILESDIR=$FILESDIR PREFIX=$FILESDIR CFGDIR=$FILESDIR"
;;
*) make_args="FILESDIR=$FILESDIR PREFIX=$FILESDIR USE_Z3=yes"
# Check that the Z3 development files appear to be installed
# before trying to create z3_version.h. Otherwise we may
# mislead the user as to what needs to be done.
if [ ! -f /usr/include/z3.h ]; then
echo "** libz3-dev (or equivalent) does not appear to be installed" >&2
fi
if [ ! -f /usr/include/z3_version.h ]; then
create_z3_version_h
fi

View File

@ -1,21 +1,19 @@
#!/bin/sh
set -eufx
FEATURE_SET="$1"
ARCH="$2"
shift
shift
FEATURE_SET=min
ARCH=amd64
if [ $# -ge 1 ]; then
FEATURE_SET="$1"
shift
fi
if [ $# -ge 1 ]; then
ARCH="$1"
shift
fi
APT_EXTRA_ARGS="$@"
if [ -z "$FEATURE_SET" ]; then
FEATURE_SET=min
fi
if [ -z "$ARCH" ]; then
ARCH=amd64
fi
# common build tools for all architectures and feature sets
PACKAGES=" \
autoconf \
@ -26,7 +24,8 @@ PACKAGES=" \
libtool \
make \
nasm \
pkg-config\
pkg-config \
check \
"
case "$ARCH"
@ -77,7 +76,6 @@ in
libxfixes-dev:i386 \
libxrandr-dev:i386 \
libxrender-dev:i386 \
openssl:i386 \
libfuse-dev:i386"
dpkg --add-architecture i386

View File

@ -15,10 +15,6 @@ if XRDP_DEBUG
AM_CPPFLAGS += -DXRDP_DEBUG
endif
if SESMAN_NOPAM
AUTH_C = verify_user.c
AUTH_LIB = -lcrypt
else
if SESMAN_BSD
AUTH_C = verify_user_bsd.c
AUTH_LIB =
@ -31,6 +27,10 @@ if SESMAN_KERBEROS
AUTH_C = verify_user_kerberos.c
AUTH_LIB = -lkrb5
else
if SESMAN_NOPAM
AUTH_C = verify_user.c
AUTH_LIB = -lcrypt
else
AUTH_C = verify_user_pam.c
AUTH_LIB = -lpam
endif

View File

@ -18,7 +18,7 @@ endif
CHANSRV_EXTRA_LIBS =
if XRDP_FUSE
AM_CPPFLAGS += -DXRDP_FUSE $(FUSE_CFLAGS)
AM_CPPFLAGS += -DXRDP_FUSE $(FUSE_CFLAGS) -DFUSE_USE_VERSION=26
CHANSRV_EXTRA_LIBS += $(FUSE_LIBS)
endif

View File

@ -61,7 +61,7 @@ static tbus g_thread_done_event = 0;
struct config_chansrv *g_cfg = NULL;
int g_display_num = 0;
int g_display_num = -1;
int g_cliprdr_chan_id = -1; /* cliprdr */
int g_rdpsnd_chan_id = -1; /* rdpsnd */
int g_rdpdr_chan_id = -1; /* rdpdr */
@ -1557,65 +1557,6 @@ x_server_fatal_handler(void)
exit(0);
}
/*****************************************************************************/
static int
get_display_num_from_display(char *display_text)
{
int index;
int mode;
int host_index;
int disp_index;
int scre_index;
char host[256];
char disp[256];
char scre[256];
g_memset(host, 0, 256);
g_memset(disp, 0, 256);
g_memset(scre, 0, 256);
index = 0;
host_index = 0;
disp_index = 0;
scre_index = 0;
mode = 0;
while (display_text[index] != 0)
{
if (display_text[index] == ':')
{
mode = 1;
}
else if (display_text[index] == '.')
{
mode = 2;
}
else if (mode == 0)
{
host[host_index] = display_text[index];
host_index++;
}
else if (mode == 1)
{
disp[disp_index] = display_text[index];
disp_index++;
}
else if (mode == 2)
{
scre[scre_index] = display_text[index];
scre_index++;
}
index++;
}
host[host_index] = 0;
disp[disp_index] = 0;
scre[scre_index] = 0;
g_display_num = g_atoi(disp);
return 0;
}
/*****************************************************************************/
int
main_cleanup(void)
@ -1728,7 +1669,7 @@ main(int argc, char **argv)
char text[256];
const char *config_path;
char log_path[256];
char *display_text;
const char *display_text;
char log_file[256];
enum logReturns error;
struct log_config *logconfig;
@ -1743,6 +1684,21 @@ main(int argc, char **argv)
return 1;
}
display_text = g_getenv("DISPLAY");
if (display_text == NULL)
{
g_writeln("DISPLAY is not set");
main_cleanup();
return 1;
}
g_display_num = g_get_display_num_from_display(display_text);
if (g_display_num < 0)
{
g_writeln("Unable to get display from DISPLAY='%s'", display_text);
main_cleanup();
return 1;
}
/*
* The user is unable at present to override the sysadmin-provided
* sesman.ini location */
@ -1755,11 +1711,6 @@ main(int argc, char **argv)
config_dump(g_cfg);
pid = g_getpid();
display_text = g_getenv("DISPLAY");
if (display_text != NULL)
{
get_display_num_from_display(display_text);
}
/* starting logging subsystem */
g_snprintf(log_file, 255, "%s/xrdp-chansrv.%d.log", log_path, g_display_num);
@ -1813,13 +1764,6 @@ main(int argc, char **argv)
LOG_DEVEL(LOG_LEVEL_INFO, "main: DISPLAY env var set to %s", display_text);
if (g_display_num == 0)
{
LOG_DEVEL(LOG_LEVEL_ERROR, "main: error, display is zero");
main_cleanup();
return 1;
}
LOG_DEVEL(LOG_LEVEL_INFO, "main: using DISPLAY %d", g_display_num);
g_snprintf(text, 255, "xrdp_chansrv_%8.8x_main_term", pid);
g_term_event = g_create_wait_obj(text);

View File

@ -130,7 +130,12 @@ void xfuse_devredir_cb_file_close(struct state_close *fip)
** **
******************************************************************************/
#define FUSE_USE_VERSION 26
/* FUSE_USE_VERSION must be defined globally for other parts of
* xrdp-chansrv which include <fuse_lowlevel.h> for definitions. Check
* it's actually defined here */
#ifndef FUSE_USE_VERSION
#error Define FUSE_USE_VERSION in the make system and recompile
#endif
#include <fuse_lowlevel.h>
#include <stdio.h>
@ -789,7 +794,7 @@ xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex)
if (g_xfs == NULL)
{
LOG_DEVEL(LOG_LEVEL_ERROR,
"xfuse_add_clip_dir_item() called with no filesystem")
"xfuse_add_clip_dir_item() called with no filesystem");
}
else
{

View File

@ -273,7 +273,11 @@ xfs_create_xfs_fs(mode_t umask, uid_t uid, gid_t gid)
xfs->free_list = NULL;
xfs->generation = 1;
/* xfs->inode_table check should be superfluous here, but it
* prevents cppcheck 2.2/2.3 generating a false positive nullPointer
* report */
if (!grow_xfs(xfs, INODE_TABLE_ALLOCATION_INITIAL) ||
xfs->inode_table == NULL ||
(xino1 = g_new0(XFS_INODE_ALL, 1)) == NULL ||
(xino2 = g_new0(XFS_INODE_ALL, 1)) == NULL)
{

View File

@ -11,6 +11,8 @@
#include <sys/un.h>
#include <sys/stat.h>
#include "string_calls.h"
#define PCSC_API
typedef unsigned char BYTE;
@ -153,66 +155,6 @@ lhexdump(void *p, int len)
}
}
/*****************************************************************************/
static int
get_display_num_from_display(const char *display_text)
{
int rv;
int index;
int mode;
int host_index;
int disp_index;
int scre_index;
char host[256];
char disp[256];
char scre[256];
memset(host, 0, 256);
memset(disp, 0, 256);
memset(scre, 0, 256);
index = 0;
host_index = 0;
disp_index = 0;
scre_index = 0;
mode = 0;
while (display_text[index] != 0)
{
if (display_text[index] == ':')
{
mode = 1;
}
else if (display_text[index] == '.')
{
mode = 2;
}
else if (mode == 0)
{
host[host_index] = display_text[index];
host_index++;
}
else if (mode == 1)
{
disp[disp_index] = display_text[index];
disp_index++;
}
else if (mode == 2)
{
scre[scre_index] = display_text[index];
scre_index++;
}
index++;
}
host[host_index] = 0;
disp[disp_index] = 0;
scre[scre_index] = 0;
LLOGLN(10, ("get_display_num_from_display: host [%s] disp [%s] scre [%s]",
host, disp, scre));
rv = atoi(disp);
return rv;
}
/*****************************************************************************/
static int
connect_to_chansrv(void)
@ -252,11 +194,11 @@ connect_to_chansrv(void)
LLOGLN(0, ("connect_to_chansrv: error, home not set"));
return 1;
}
dis = get_display_num_from_display(xrdp_display);
if (dis < 10)
dis = g_get_display_num_from_display(xrdp_display);
if (dis < 0)
{
/* DISPLAY must be > 9 */
LLOGLN(0, ("connect_to_chansrv: error, display not > 9 %d", dis));
LLOGLN(0, ("connect_to_chansrv: error, don't understand DISPLAY='%s'",
xrdp_display));
return 1;
}
g_sck = socket(PF_LOCAL, SOCK_STREAM, 0);

View File

@ -41,6 +41,7 @@ struct sesman_startup_params
int no_daemon;
int help;
int version;
int dump_config;
};
int g_sck;
@ -127,6 +128,10 @@ sesman_process_params(int argc, char **argv,
{
startup_params->version = 1;
}
else if (nocase_matches(option, "--dump-config", NULL))
{
startup_params->dump_config = 1;
}
else if (nocase_matches(option, "-c", "--config", NULL))
{
index++;
@ -305,11 +310,12 @@ static void
print_help(void)
{
g_printf("Usage: xrdp-sesman [options]\n");
g_printf(" -k, --kill shut down xrdp-sesman\n");
g_printf(" -h, --help show help\n");
g_printf(" -v, --version show version\n");
g_printf(" -n, --nodaemon don't fork into background\n");
g_printf(" -c, --config specify new path to sesman.ini\n");
g_printf(" -k, --kill shut down xrdp-sesman\n");
g_printf(" -h, --help show help\n");
g_printf(" -v, --version show version\n");
g_printf(" -n, --nodaemon don't fork into background\n");
g_printf(" -c, --config specify new path to sesman.ini\n");
g_writeln(" --dump-config display config on stdout on startup");
g_deinit();
}
@ -415,12 +421,6 @@ main(int argc, char **argv)
g_exit(kill_running_sesman(pid_file));
}
daemon = !startup_params.no_daemon;
if (!daemon)
{
g_printf("starting sesman in foreground...\n");
}
if (g_file_exist(pid_file))
{
g_printf("xrdp-sesman is already running.\n");
@ -440,15 +440,14 @@ main(int argc, char **argv)
g_exit(1);
}
/* not to spit on the console, show config summary only when running
* in foreground */
if (!daemon)
if (startup_params.dump_config)
{
config_dump(g_cfg);
}
/* starting logging subsystem */
log_error = log_start(startup_params.sesman_ini, "xrdp-sesman");
log_error = log_start(startup_params.sesman_ini, "xrdp-sesman",
startup_params.dump_config);
if (log_error != LOG_STARTUP_OK)
{
@ -481,6 +480,7 @@ main(int argc, char **argv)
LOG(LOG_LEVEL_TRACE, " reconnect_sh = %s", g_cfg->reconnect_sh);
LOG(LOG_LEVEL_TRACE, " auth_file_path = %s", g_cfg->auth_file_path);
daemon = !startup_params.no_daemon;
if (daemon)
{
/* not to spit on the console, shut up stdout/stderr before anything's logged */

View File

@ -116,23 +116,19 @@ session_get_bydata(const char *name, int width, int height, int bpp, int type,
return 0;
}
#if 0
LOG(LOG_LEVEL_INFO,
LOG(LOG_LEVEL_DEBUG,
"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(LOG_LEVEL_INFO,
LOG(LOG_LEVEL_DEBUG,
"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 (g_strncmp(name, tmp->item->name, 255) == 0 &&
(!(policy & SESMAN_CFG_SESS_POLICY_D) ||
@ -173,12 +169,14 @@ x_server_running_check_ports(int display)
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, "/tmp/.X%d-lock", display);
x_running = g_file_exist(text);
}
if (!x_running) /* check 59xx */
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
if ((sck = g_tcp_socket()) != -1)
{
g_sprintf(text, "59%2.2d", display);
@ -189,6 +187,7 @@ x_server_running_check_ports(int display)
if (!x_running) /* check 60xx */
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
if ((sck = g_tcp_socket()) != -1)
{
g_sprintf(text, "60%2.2d", display);
@ -199,6 +198,7 @@ x_server_running_check_ports(int display)
if (!x_running) /* check 62xx */
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
if ((sck = g_tcp_socket()) != -1)
{
g_sprintf(text, "62%2.2d", display);
@ -209,34 +209,44 @@ x_server_running_check_ports(int display)
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, XRDP_CHANSRV_STR, display);
x_running = g_file_exist(text);
}
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, CHANSRV_PORT_OUT_STR, display);
x_running = g_file_exist(text);
}
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, CHANSRV_PORT_IN_STR, display);
x_running = g_file_exist(text);
}
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, CHANSRV_API_STR, display);
x_running = g_file_exist(text);
}
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, XRDP_X11RDP_STR, display);
x_running = g_file_exist(text);
}
if (x_running)
{
LOG(LOG_LEVEL_INFO, "Found X server running at %s", text);
}
return x_running;
}
@ -259,10 +269,20 @@ x_server_running(int display)
if (!x_running)
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
g_sprintf(text, "/tmp/.X%d-lock", display);
x_running = g_file_exist(text);
}
if (x_running)
{
LOG(LOG_LEVEL_INFO, "Found X server running at %s", text);
}
else
{
LOG(LOG_LEVEL_DEBUG, "Did not find a running X server at %s", text);
}
return x_running;
}
@ -314,7 +334,9 @@ session_get_avail_display_from_chain(void)
display++;
}
LOG(LOG_LEVEL_ERROR, "X server -- no display in range is available");
LOG(LOG_LEVEL_ERROR, "X server -- no display in range (%d to %d) is available",
g_cfg->sess.x11_display_offset,
g_cfg->sess.x11_display_offset + g_cfg->sess.max_sessions);
return 0;
}
@ -328,14 +350,16 @@ wait_for_xserver(int display)
/* wait up to 10 secs for x server to start */
i = 0;
LOG(LOG_LEVEL_DEBUG, "Waiting for X server to start on display %d", display);
while (!x_server_running(display))
{
i++;
if (i > 40)
{
LOG(LOG_LEVEL_ERROR,
"X server for display %d startup timeout",
LOG(LOG_LEVEL_WARNING,
"Timed out waiting for X server on display %d to startup",
display);
break;
}
@ -357,13 +381,16 @@ session_start_chansrv(char *username, int display)
chansrv_pid = g_fork();
if (chansrv_pid == 0)
{
LOG(LOG_LEVEL_INFO,
"Starting the xrdp channel server for display %d", display);
chansrv_params = list_create();
chansrv_params->auto_free = 1;
/* building parameters */
g_snprintf(exe_path, sizeof(exe_path), "%s/xrdp-chansrv",
XRDP_SBIN_PATH);
list_add_item(chansrv_params, (intptr_t) g_strdup(exe_path));
list_add_item(chansrv_params, 0); /* mandatory */
@ -373,9 +400,8 @@ session_start_chansrv(char *username, int display)
/* executing chansrv */
g_execvp(exe_path, (char **) (chansrv_params->items));
/* should not get here */
LOG(LOG_LEVEL_ALWAYS, "error starting chansrv "
"- user %s - pid %d", username, g_getpid());
list_delete(chansrv_params);
g_exit(1);
}
@ -390,13 +416,12 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
{
int display = 0;
int pid = 0;
int i = 0;
char geometry[32];
char depth[32];
char screen[32]; /* display number */
char text[256];
char execvpparams[2048];
char *xserver; /* absolute/relative path to Xorg/X11rdp/Xvnc */
char *xserver = NULL; /* absolute/relative path to Xorg/X11rdp/Xvnc */
char *passwd_file;
char **pp1 = (char **)NULL;
struct session_chain *temp = (struct session_chain *)NULL;
@ -421,7 +446,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
/* check to limit concurrent sessions */
if (g_session_count >= g_cfg->sess.max_sessions)
{
LOG(LOG_LEVEL_INFO, "max concurrent session limit "
LOG(LOG_LEVEL_ERROR, "max concurrent session limit "
"exceeded. login for user %s denied", s->username);
return 0;
}
@ -430,8 +455,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
if (temp == 0)
{
LOG(LOG_LEVEL_ERROR, "cannot create new chain "
"element - user %s", s->username);
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
"chain element - user %s", s->username);
return 0;
}
@ -440,7 +465,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
if (temp->item == 0)
{
g_free(temp);
LOG(LOG_LEVEL_ERROR, "cannot create new session "
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
"item - user %s", s->username);
return 0;
}
@ -459,11 +484,16 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
if (pid == -1)
{
LOG(LOG_LEVEL_ERROR,
"[session start] (display %d): Failed to fork for scp with "
"errno: %d, description: %s",
display, g_get_errno(), g_get_strerror());
}
else if (pid == 0)
{
LOG(LOG_LEVEL_INFO, "calling auth_start_session from pid %d",
g_getpid());
LOG(LOG_LEVEL_INFO,
"[session start] (display %d): calling auth_start_session from pid %d",
display, g_getpid());
auth_start_session(data, display);
g_delete_wait_obj(g_term_event);
g_tcp_close(g_sck);
@ -494,15 +524,16 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
*/
if (g_setsid() < 0)
{
LOG(LOG_LEVEL_ERROR,
"setsid failed - pid %d", g_getpid());
LOG(LOG_LEVEL_WARNING,
"[session start] (display %d): setsid failed - pid %d",
display, g_getpid());
}
if (g_setlogin(s->username) < 0)
{
LOG(LOG_LEVEL_ERROR,
"setlogin failed for user %s - pid %d", s->username,
g_getpid());
LOG(LOG_LEVEL_WARNING,
"[session start] (display %d): setlogin failed for user %s - pid %d",
display, s->username, g_getpid());
}
}
@ -521,6 +552,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
child forks wm, and waits, todo */
if (window_manager_pid == -1)
{
LOG(LOG_LEVEL_ERROR,
"Failed to fork for the window manager on display %d", display);
}
else if (window_manager_pid == 0)
{
@ -540,79 +573,74 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
g_set_current_dir(s->directory);
}
}
if (s->program != 0)
if (s->program != 0 && s->program[0] != 0)
{
if (s->program[0] != 0)
if (g_strchr(s->program, ' ') != 0 || g_strchr(s->program, '\t') != 0)
{
LOG(LOG_LEVEL_DEBUG,
"starting program with parameters: %s ",
s->program);
if (g_strchr(s->program, ' ') != 0 || g_strchr(s->program, '\t') != 0)
{
const char *params[] = {"sh", "-c", s->program, NULL};
g_execvp("/bin/sh", (char **)params);
}
else
{
g_execlp3(s->program, s->program, 0);
}
LOG(LOG_LEVEL_ALWAYS,
"error starting program %s for user %s - pid %d",
s->program, s->username, g_getpid());
LOG(LOG_LEVEL_INFO,
"Starting user requested window manager on "
"display %d with embeded arguments using a shell: %s",
display, s->program);
const char *params[] = {"sh", "-c", s->program, NULL};
g_execvp("/bin/sh", (char **)params);
}
else
{
LOG(LOG_LEVEL_INFO,
"Starting user requested window manager on "
"display %d: %s", display, s->program);
g_execlp3(s->program, s->program, 0);
}
}
else
{
LOG(LOG_LEVEL_DEBUG, "The user session on display %d did "
"not request a specific window manager", display);
}
/* try to execute user window manager if enabled */
if (g_cfg->enable_user_wm)
{
g_sprintf(text, "%s/%s", g_getenv("HOME"), g_cfg->user_wm);
if (g_file_exist(text))
{
LOG(LOG_LEVEL_INFO,
"Starting window manager on display %d"
"from user home directory: %s", display, text);
g_execlp3(text, g_cfg->user_wm, 0);
LOG(LOG_LEVEL_ALWAYS, "error starting user "
"wm for user %s - pid %d", s->username, g_getpid());
/* logging parameters */
LOG(LOG_LEVEL_DEBUG, "errno: %d, "
"description: %s", g_get_errno(), g_get_strerror());
LOG(LOG_LEVEL_DEBUG, "execlp3 parameter "
"list:");
LOG(LOG_LEVEL_DEBUG, " argv[0] = %s",
}
else
{
LOG(LOG_LEVEL_DEBUG,
"The user home directory window manager configuration "
"is enabled but window manager program does not exist: %s",
text);
LOG(LOG_LEVEL_DEBUG, " argv[1] = %s",
g_cfg->user_wm);
}
}
/* if we're here something happened to g_execlp3
so we try running the default window manager */
LOG(LOG_LEVEL_INFO,
"Starting the default window manager on display %d: %s",
display, g_cfg->default_wm);
g_execlp3(g_cfg->default_wm, g_cfg->default_wm, 0);
LOG(LOG_LEVEL_ALWAYS, "error starting default "
"wm for user %s - pid %d", s->username, g_getpid());
/* logging parameters */
LOG(LOG_LEVEL_DEBUG, "errno: %d, description: "
"%s", g_get_errno(), g_get_strerror());
LOG(LOG_LEVEL_DEBUG, "execlp3 parameter list:");
LOG(LOG_LEVEL_DEBUG, " argv[0] = %s",
g_cfg->default_wm);
LOG(LOG_LEVEL_DEBUG, " argv[1] = %s",
g_cfg->default_wm);
/* still a problem starting window manager just start xterm */
LOG(LOG_LEVEL_WARNING,
"No window manager on display %d started, "
"so falling back to starting xterm for user debugging",
display);
g_execlp3("xterm", "xterm", 0);
/* should not get here */
LOG(LOG_LEVEL_ALWAYS, "error starting xterm "
"for user %s - pid %d", s->username, g_getpid());
/* logging parameters */
LOG(LOG_LEVEL_DEBUG, "errno: %d, description: "
"%s", g_get_errno(), g_get_strerror());
}
else
{
LOG(LOG_LEVEL_ERROR, "another Xserver might "
"already be active on display %d - see log", display);
LOG(LOG_LEVEL_ERROR,
"There is no X server active on display %d", display);
}
LOG(LOG_LEVEL_DEBUG, "aborting connection...");
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting to start "
"the window manager on display %d, aborting connection",
display);
g_exit(0);
}
else
@ -621,6 +649,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
child becomes X */
if (display_pid == -1)
{
LOG(LOG_LEVEL_ERROR,
"Failed to fork for the X server on display %d", display);
}
else if (display_pid == 0) /* child */
{
@ -641,7 +671,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
g_cfg->env_values);
}
/* setting Xserver environment variables */
g_snprintf(text, 255, "%d", g_cfg->sess.max_idle_time);
g_setenv("XRDP_SESMAN_MAX_IDLE_TIME", text, 1);
g_snprintf(text, 255, "%d", g_cfg->sess.max_disc_time);
@ -663,6 +693,13 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
/* Add the entry in XAUTHORITY file or exit if error */
if (add_xauth_cookie(display, authfile) != 0)
{
LOG(LOG_LEVEL_ERROR,
"Error setting the xauth cookie for display %d in file %s",
display, authfile);
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting to start "
"the X server on display %d, aborting connection",
display);
g_exit(1);
}
@ -678,8 +715,9 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0)
{
LOG(LOG_LEVEL_WARNING,
"Failed to disable setuid on X server: %s",
g_get_strerror());
"[session start] (display %d): Failed to disable "
"setuid on X server: %s",
display, g_get_strerror());
}
#endif
@ -703,17 +741,12 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
pp1 = (char **) xserver_params->items;
LOG(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048));
/* some args are passed via env vars */
g_sprintf(geometry, "%d", s->width);
g_setenv("XRDP_START_WIDTH", geometry, 1);
g_sprintf(geometry, "%d", s->height);
g_setenv("XRDP_START_HEIGHT", geometry, 1);
/* fire up Xorg */
g_execvp(xserver, pp1);
}
else if (type == SESMAN_SESSION_TYPE_XVNC)
{
@ -748,8 +781,6 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
/* make sure it ends with a zero */
list_add_item(xserver_params, 0);
pp1 = (char **)xserver_params->items;
LOG(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048));
g_execvp(xserver, pp1);
}
else if (type == SESMAN_SESSION_TYPE_XRDP)
{
@ -777,72 +808,105 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
/* make sure it ends with a zero */
list_add_item(xserver_params, 0);
pp1 = (char **)xserver_params->items;
LOG(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048));
g_execvp(xserver, pp1);
}
else
{
LOG(LOG_LEVEL_ALWAYS, "bad session type - "
"user %s - pid %d", s->username, g_getpid());
LOG(LOG_LEVEL_ERROR, "Unknown session type: %d", type);
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
"to start the X server on display %d, aborting connection",
display);
g_exit(1);
}
/* fire up X server */
LOG(LOG_LEVEL_INFO, "Starting X server on display %d: %s",
display, dumpItemsToString(xserver_params, execvpparams, 2048));
g_execvp(xserver, pp1);
/* should not get here */
LOG(LOG_LEVEL_ALWAYS, "error starting X server "
"- user %s - pid %d", s->username, g_getpid());
/* logging parameters */
LOG(LOG_LEVEL_DEBUG, "errno: %d, description: "
"%s", g_get_errno(), g_get_strerror());
LOG(LOG_LEVEL_DEBUG, "execve parameter list size: "
"%d", (xserver_params)->count);
for (i = 0; i < (xserver_params->count); i++)
{
LOG(LOG_LEVEL_DEBUG, " argv[%d] = %s",
i, (char *)list_get_item(xserver_params, i));
}
LOG(LOG_LEVEL_ERROR,
"Error starting X server on display %d", display);
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
"to start the X server on display %d, aborting connection",
display);
list_delete(xserver_params);
g_exit(1);
}
else
{
int wm_wait_time;
struct exit_status wm_exit_status;
struct exit_status xserver_exit_status;
struct exit_status chansrv_exit_status;
wait_for_xserver(display);
chansrv_pid = session_start_chansrv(s->username, display);
LOG(LOG_LEVEL_INFO,
"Session started successfully for user %s on display %d",
s->username, display);
/* Monitor the amount of time we wait for the
* window manager. This is approximately how long the window
* manager was running for */
LOG(LOG_LEVEL_INFO, "waiting for window manager "
"(pid %d) to exit", window_manager_pid);
LOG(LOG_LEVEL_INFO, "Session in progress on display %d, waiting "
"until the window manager (pid %d) exits to end the session",
display, window_manager_pid);
wm_wait_time = g_time1();
g_waitpid(window_manager_pid);
wm_exit_status = g_waitpid_status(window_manager_pid);
wm_wait_time = g_time1() - wm_wait_time;
if (wm_exit_status.exit_code > 0)
{
LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) "
"exited with non-zero exit code %d and signal %d. This "
"could indicate a window manager config problem",
window_manager_pid, display, wm_exit_status.exit_code,
wm_exit_status.signal_no);
}
if (wm_wait_time < 10)
{
/* This could be a config issue. Log a significant error */
LOG(LOG_LEVEL_ALWAYS, "window manager exited quickly "
"(%d secs). Window manager config problem?",
wm_wait_time);
LOG(LOG_LEVEL_WARNING, "Window manager (pid %d, display %d) "
"exited quickly (%d secs). This could indicate a window "
"manager config problem",
window_manager_pid, display, wm_wait_time);
}
else
{
LOG(LOG_LEVEL_INFO, "window manager (pid %d) was running "
"for approximately %d seconds.",
window_manager_pid, wm_wait_time);
LOG(LOG_LEVEL_DEBUG, "Window manager (pid %d, display %d) "
"was running for %d seconds.",
window_manager_pid, display, wm_wait_time);
}
LOG(LOG_LEVEL_INFO, "Cleaning up session. Calling "
"auth_stop_session and auth_end from pid %d", g_getpid());
LOG(LOG_LEVEL_INFO,
"Calling auth_stop_session and auth_end from pid %d",
g_getpid());
auth_stop_session(data);
auth_end(data);
LOG(LOG_LEVEL_INFO,
"Terminating X server (pid %d) on display %d",
display_pid, display);
g_sigterm(display_pid);
LOG(LOG_LEVEL_INFO, "Terminating the xrdp channel server (pid %d) "
"on display %d", chansrv_pid, display);
g_sigterm(chansrv_pid);
/* make sure socket cleanup happen after child process exit */
g_waitpid(display_pid);
g_waitpid(chansrv_pid);
xserver_exit_status = g_waitpid_status(display_pid);
LOG(LOG_LEVEL_INFO,
"X server on display %d (pid %d) returned exit code %d "
"and signal number %d",
display, display_pid, xserver_exit_status.exit_code,
xserver_exit_status.signal_no);
chansrv_exit_status = g_waitpid_status(chansrv_pid);
LOG(LOG_LEVEL_INFO,
"xrdp channel server for display %d (pid %d) "
"exit code %d and signal number %d",
display, chansrv_pid, chansrv_exit_status.exit_code,
chansrv_exit_status.signal_no);
cleanup_sockets(display);
g_deinit();
@ -852,6 +916,10 @@ session_start_fork(tbus data, tui8 type, struct SCP_CONNECTION *c,
}
else
{
LOG(LOG_LEVEL_INFO, "Starting session: session_pid %d, "
"display :%d.0, width %d, height %d, bpp %d, client ip %s, "
"user name %s",
pid, display, s->width, s->height, s->bpp, s->client_ip, s->username);
temp->item->pid = pid;
temp->item->display = display;
temp->item->width = s->width;
@ -898,6 +966,7 @@ session_reconnect_fork(int display, char *username, long data)
if (pid == -1)
{
LOG(LOG_LEVEL_ERROR, "Failed to fork for session reconnection script");
}
else if (pid == 0)
{
@ -910,9 +979,25 @@ session_reconnect_fork(int display, char *username, long data)
if (g_file_exist(g_cfg->reconnect_sh))
{
LOG(LOG_LEVEL_INFO,
"Starting session reconnection script on display %d: %s",
display, g_cfg->reconnect_sh);
g_execlp3(g_cfg->reconnect_sh, g_cfg->reconnect_sh, 0);
/* should not get here */
LOG(LOG_LEVEL_ERROR,
"Error starting session reconnection script on display %d: %s",
display, g_cfg->reconnect_sh);
}
else
{
LOG(LOG_LEVEL_WARNING,
"Session reconnection script file does not exist: %s",
g_cfg->reconnect_sh);
}
/* TODO: why is this existing with a success error code when the
reconnect script failed to be executed? */
g_exit(0);
}
@ -972,7 +1057,9 @@ session_kill(int pid)
if (tmp->item->pid == pid)
{
/* deleting the session */
LOG(LOG_LEVEL_INFO, "++ terminated session: username %s, display :%d.0, session_pid %d, ip %s", tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip);
LOG(LOG_LEVEL_INFO,
"++ terminated session: username %s, display :%d.0, session_pid %d, ip %s",
tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->client_ip);
g_free(tmp->item);
if (prev == 0)
@ -1011,8 +1098,7 @@ session_sigkill_all(void)
{
if (tmp->item == 0)
{
LOG(LOG_LEVEL_ERROR, "found null session "
"descriptor!");
LOG(LOG_LEVEL_ERROR, "found null session descriptor!");
}
else
{
@ -1045,8 +1131,7 @@ session_get_bypid(int pid)
{
if (tmp->item == 0)
{
LOG(LOG_LEVEL_ERROR, "session descriptor for "
"pid %d is null!", pid);
LOG(LOG_LEVEL_ERROR, "session descriptor for pid %d is null!", pid);
g_free(dummy);
return 0;
}
@ -1078,15 +1163,14 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
tmp = g_sessions;
LOG(LOG_LEVEL_DEBUG, "searching for session by user: %s", user);
while (tmp != 0)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "user: %s", user);
if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "session_get_byuser: status=%d, flags=%d, "
"result=%d", (tmp->item->status), flags,
((tmp->item->status) & flags));
LOG(LOG_LEVEL_DEBUG, "session_get_byuser: status=%d, flags=%d, "
"result=%d", (tmp->item->status), flags,
((tmp->item->status) & flags));
if ((tmp->item->status) & flags)
{
@ -1169,7 +1253,7 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
int
cleanup_sockets(int display)
{
LOG(LOG_LEVEL_DEBUG, "cleanup_sockets:");
LOG(LOG_LEVEL_INFO, "cleanup_sockets:");
char file[256];
int error;

View File

@ -92,7 +92,7 @@ sig_sesman_reload_cfg(int sig)
g_cfg = cfg;
/* start again logging subsystem */
error = log_start(g_cfg->sesman_ini, "xrdp-sesman");
error = log_start(g_cfg->sesman_ini, "xrdp-sesman", 0);
if (error != LOG_STARTUP_OK)
{

View File

@ -38,6 +38,9 @@ xrdp_sesadmin_SOURCES = \
xrdp_dis_SOURCES = \
dis.c
xrdp_dis_LDADD = \
$(top_builddir)/common/libcommon.la
xrdp_xcon_SOURCES = \
xcon.c

View File

@ -29,6 +29,7 @@
#include <errno.h>
#include "xrdp_sockets.h"
#include "string_calls.h"
int main(int argc, char **argv)
{
@ -36,7 +37,6 @@ int main(int argc, char **argv)
int dis;
struct sockaddr_un sa;
size_t len;
char *p;
char *display;
if (argc != 1)
@ -54,7 +54,12 @@ int main(int argc, char **argv)
return 1;
}
dis = strtol(display + 1, &p, 10);
dis = g_get_display_num_from_display(display);
if (dis < 0)
{
printf("Can't parse DISPLAY='%s'\n", display);
return 1;
}
memset(&sa, 0, sizeof(sa));
sa.sun_family = AF_UNIX;
sprintf(sa.sun_path, XRDP_DISCONNECT_STR, dis);

View File

@ -29,6 +29,7 @@
#endif
#include "sesman.h"
#include "string_calls.h"
#include <stdio.h>
#include <string.h>

View File

@ -30,6 +30,7 @@
#include "arch.h"
#include "os_calls.h"
#include "string_calls.h"
#include <krb5.h>

View File

@ -30,6 +30,7 @@
#include "arch.h"
#include "os_calls.h"
#include "string_calls.h"
#include <security/pam_userpass.h>

1
tests/.gitignore vendored
View File

@ -1 +0,0 @@
!Makefile

7
tests/Makefile.am Normal file
View File

@ -0,0 +1,7 @@
EXTRA_DIST = \
readme.txt
SUBDIRS = \
common \
memtest

26
tests/common/Makefile.am Normal file
View File

@ -0,0 +1,26 @@
AM_CPPFLAGS = \
-I$(top_builddir) \
-I$(top_srcdir)/common
if XRDP_DEBUG
AM_CPPFLAGS += -DXRDP_DEBUG
endif
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(top_srcdir)/tap-driver.sh
TESTS = test_common
check_PROGRAMS = test_common
test_common_SOURCES = \
test_common.h \
test_common_main.c \
test_string_calls.c
test_common_CFLAGS = \
@CHECK_CFLAGS@
test_common_LDADD = \
$(top_builddir)/common/libcommon.la \
@CHECK_LIBS@

View File

@ -0,0 +1,9 @@
#ifndef TEST_COMMON_H
#define TEST_COMMON_H
#include <check.h>
Suite *make_suite_test_string(void);
#endif /* TEST_COMMON_H */

View File

@ -0,0 +1,23 @@
#if defined(HAVE_CONFIG_H)
#include "config_ac.h"
#endif
#include <stdlib.h>
#include <check.h>
#include "test_common.h"
int main (void)
{
int number_failed;
SRunner *sr;
sr = srunner_create (make_suite_test_string());
// srunner_add_suite(sr, make_list_suite());
srunner_set_tap(sr, "-");
srunner_run_all (sr, CK_ENV);
number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -0,0 +1,240 @@
#if defined(HAVE_CONFIG_H)
#include "config_ac.h"
#endif
#include "test_common.h"
#include "string_calls.h"
#define RESULT_LEN 1024
START_TEST(test_strnjoin__when_src_is_null__returns_empty_string)
{
/* setup */
const char **src = NULL;
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, " ", src, 0);
/* verify */
ck_assert_str_eq(result, "");
}
END_TEST
START_TEST(test_strnjoin__when_src_has_null_item__returns_joined_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, NULL };
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, " ", src, 2);
/* verify */
ck_assert_str_eq(result, "test_value ");
}
END_TEST
START_TEST(test_strnjoin__when_src_has_one_item__returns_copied_source_string)
{
/* setup */
const char *expected_value = "test_value";
const char *src[] = { expected_value };
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, " ", src, 1);
/* verify */
ck_assert_str_eq(result, expected_value);
}
END_TEST
START_TEST(test_strnjoin__when_src_has_two_items__returns_joined_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, test_value };
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, " ", src, 2);
/* verify */
ck_assert_str_eq(result, "test_value test_value");
}
END_TEST
START_TEST(test_strnjoin__when_joiner_is_empty_string__returns_joined_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, test_value };
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, "", src, 2);
/* verify */
ck_assert_str_eq(result, "test_valuetest_value");
}
END_TEST
START_TEST(test_strnjoin__when_joiner_is_NULL__returns_joined_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, test_value };
char result[RESULT_LEN];
result[0] = '\0';
/* test */
g_strnjoin(result, RESULT_LEN, NULL, src, 2);
/* verify */
ck_assert_str_eq(result, "test_valuetest_value");
}
END_TEST
START_TEST(test_strnjoin__when_destination_is_NULL__returns_NULL)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value };
char *result = NULL;
/* test */
g_strnjoin(result, 0, " ", src, 1);
/* verify */
ck_assert_ptr_eq(result, NULL);
}
END_TEST
START_TEST(test_strnjoin__when_destination_is_shorter_than_src__returns_partial_src_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value };
char result[5];
result[0] = '\0';
/* test */
g_strnjoin(result, 5, " ", src, 1);
/* verify */
ck_assert_str_eq(result, "test");
}
END_TEST
START_TEST(test_strnjoin__when_destination_is_shorter_than_src_plus_joiner__returns_partial_joined_string)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, test_value};
char result[16];
result[0] = '\0';
/* test */
g_strnjoin(result, 16, " joiner ", src, 2);
/* verify */
ck_assert_str_eq(result, "test_value join");
}
END_TEST
START_TEST(test_strnjoin__when_destination_has_contents__returns_joined_string_with_content_overwritten)
{
/* setup */
const char *test_value = "test_value";
const char *src[] = { test_value, test_value};
char result[RESULT_LEN] = "1234567890";
/* test */
g_strnjoin(result, RESULT_LEN, " ", src, 2);
/* verify */
ck_assert_str_eq(result, "test_value test_value");
}
END_TEST
START_TEST(test_strnjoin__when_always__then_doesnt_write_beyond_end_of_destination)
{
/* setup */
const char *src[] = { "a","b","c"};
char result[5+1+1]; /* a-b-c + term null + guard value */
/* test */
result[6] = '\x7f';
g_strnjoin(result, 5 + 1, "-", src, 3);
/* verify */
ck_assert_int_eq(result[6], '\x7f');
}
END_TEST
/******************************************************************************/
Suite *
make_suite_test_string(void)
{
Suite *s;
TCase *tc_strnjoin;
s = suite_create("String");
tc_strnjoin = tcase_create("strnjoin");
suite_add_tcase(s, tc_strnjoin);
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_is_null__returns_empty_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_has_null_item__returns_joined_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_has_one_item__returns_copied_source_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_src_has_two_items__returns_joined_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_joiner_is_empty_string__returns_joined_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_joiner_is_NULL__returns_joined_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_is_NULL__returns_NULL);
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_is_shorter_than_src__returns_partial_src_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_is_shorter_than_src_plus_joiner__returns_partial_joined_string);
tcase_add_test(tc_strnjoin, test_strnjoin__when_destination_has_contents__returns_joined_string_with_content_overwritten);
tcase_add_test(tc_strnjoin, test_strnjoin__when_always__then_doesnt_write_beyond_end_of_destination);
return s;
}

View File

@ -1,13 +0,0 @@
OBJS = libmem.o memtest.o
#CFLAGS = -O2 -Wall
CFLAGS = -g
all: memtest
memtest: $(OBJS)
$(CC) -o memtest $(OBJS)
clean:
rm -f $(OBJS) librdp.a

21
tests/memtest/Makefile.am Normal file
View File

@ -0,0 +1,21 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/common
if XRDP_DEBUG
AM_CPPFLAGS += -DXRDP_DEBUG
endif
check_PROGRAMS = \
memtest
memtest_SOURCES = \
libmem.h \
libmem.c \
memtest.c
memtest_LDADD = \
$(top_builddir)/common/libcommon.la
TESTS = \
memtest

View File

@ -1,414 +1,411 @@
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
#define ALIGN_BY 32
#define ALIGN_BY_M1 (ALIGN_BY - 1)
#define ALIGN(_in) (((_in) + ALIGN_BY_M1) & (~ALIGN_BY_M1))
#define LLOG_LEVEL 1
#define LLOGLN(_log_level, _params) \
do { \
if (_log_level < LLOG_LEVEL) \
{ \
printf _params ; \
printf ("\n") ; \
} \
} while (0)
struct mem_item
{
unsigned int addr;
int bytes;
struct mem_item* next;
struct mem_item* prev;
unsigned int addr;
int bytes;
struct mem_item *next;
struct mem_item *prev;
};
struct mem_info
{
unsigned int addr;
int bytes;
int flags;
struct mem_item* free_head;
struct mem_item* free_tail;
struct mem_item* used_head;
struct mem_item* used_tail;
int total_bytes;
unsigned int addr;
int bytes;
int flags;
struct mem_item *free_head;
struct mem_item *free_tail;
struct mem_item *used_head;
struct mem_item *used_tail;
int total_bytes;
};
/*****************************************************************************/
static int
libmem_free_mem_item(struct mem_info* self, struct mem_item* mi)
libmem_free_mem_item(struct mem_info *self, struct mem_item *mi)
{
if (self == 0 || mi == 0)
{
if (self == 0 || mi == 0)
{
return 0;
}
if (mi->prev != 0)
{
mi->prev->next = mi->next;
}
if (mi->next != 0)
{
mi->next->prev = mi->prev;
}
if (mi == self->free_head)
{
self->free_head = mi->next;
}
if (mi == self->free_tail)
{
self->free_tail = mi->prev;
}
if (mi == self->used_head)
{
self->used_head = mi->next;
}
if (mi == self->used_tail)
{
self->used_tail = mi->prev;
}
free(mi);
return 0;
}
if (mi->prev != 0)
{
mi->prev->next = mi->next;
}
if (mi->next != 0)
{
mi->next->prev = mi->prev;
}
if (mi == self->free_head)
{
self->free_head = mi->next;
}
if (mi == self->free_tail)
{
self->free_tail = mi->prev;
}
if (mi == self->used_head)
{
self->used_head = mi->next;
}
if (mi == self->used_tail)
{
self->used_tail = mi->prev;
}
free(mi);
return 0;
}
/*****************************************************************************/
void*
void *
libmem_init(unsigned int addr, int bytes)
{
struct mem_info* self;
struct mem_item* mi;
struct mem_info *self;
struct mem_item *mi;
self = (struct mem_info*)malloc(sizeof(struct mem_info));
memset(self, 0, sizeof(struct mem_info));
self->addr = addr;
self->bytes = bytes;
//self->flags = 1;
mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(mi, 0, sizeof(struct mem_item));
mi->addr = addr;
mi->bytes = bytes;
self->free_head = mi;
self->free_tail = mi;
return self;
self = (struct mem_info *)malloc(sizeof(struct mem_info));
memset(self, 0, sizeof(struct mem_info));
self->addr = addr;
self->bytes = bytes;
//self->flags = 1;
mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(mi, 0, sizeof(struct mem_item));
mi->addr = addr;
mi->bytes = bytes;
self->free_head = mi;
self->free_tail = mi;
return self;
}
/*****************************************************************************/
void
libmem_deinit(void* aself)
libmem_deinit(void *aself)
{
struct mem_info* self;
struct mem_info *self;
self = (struct mem_info*)aself;
if (self == 0)
{
return;
}
while (self->free_head != 0)
{
libmem_free_mem_item(self, self->free_head);
}
while (self->used_head != 0)
{
libmem_free_mem_item(self, self->used_head);
}
free(self);
self = (struct mem_info *)aself;
if (self == 0)
{
return;
}
while (self->free_head != 0)
{
libmem_free_mem_item(self, self->free_head);
}
while (self->used_head != 0)
{
libmem_free_mem_item(self, self->used_head);
}
free(self);
}
/****************************************************************************/
static int
libmem_add_used_item(struct mem_info* self, unsigned int addr, int bytes)
libmem_add_used_item(struct mem_info *self, unsigned int addr, int bytes)
{
struct mem_item* mi;
struct mem_item* new_mi;
int added;
struct mem_item *mi;
struct mem_item *new_mi;
int added;
if (self == 0 || addr == 0)
{
return 1;
}
if (self->used_head == 0)
{
/* add first item */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->used_head = new_mi;
self->used_tail = new_mi;
return 0;
}
added = 0;
mi = self->used_head;
while (mi != 0)
{
if (mi->addr > addr)
if (self == 0 || addr == 0)
{
/* add before */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
new_mi->prev = mi->prev;
new_mi->next = mi;
if (mi->prev != 0)
{
mi->prev->next = new_mi;
}
mi->prev = new_mi;
if (self->used_head == mi)
{
return 1;
}
if (self->used_head == 0)
{
/* add first item */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->used_head = new_mi;
}
added = 1;
break;
self->used_tail = new_mi;
return 0;
}
mi = mi->next;
}
if (!added)
{
/* add last */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->used_tail->next = new_mi;
new_mi->prev = self->used_tail;
self->used_tail = new_mi;
}
return 0;
added = 0;
mi = self->used_head;
while (mi != 0)
{
if (mi->addr > addr)
{
/* add before */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
new_mi->prev = mi->prev;
new_mi->next = mi;
if (mi->prev != 0)
{
mi->prev->next = new_mi;
}
mi->prev = new_mi;
if (self->used_head == mi)
{
self->used_head = new_mi;
}
added = 1;
break;
}
mi = mi->next;
}
if (!added)
{
/* add last */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->used_tail->next = new_mi;
new_mi->prev = self->used_tail;
self->used_tail = new_mi;
}
return 0;
}
/****************************************************************************/
static int
libmem_add_free_item(struct mem_info* self, unsigned int addr, int bytes)
libmem_add_free_item(struct mem_info *self, unsigned int addr, int bytes)
{
struct mem_item* mi;
struct mem_item* new_mi;
int added;
struct mem_item *mi;
struct mem_item *new_mi;
int added;
if (self == 0 || addr == 0)
{
return 1;
}
if (self->free_head == 0)
{
/* add first item */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->free_head = new_mi;
self->free_tail = new_mi;
return 0;
}
added = 0;
mi = self->free_head;
while (mi != 0)
{
if (mi->addr > addr)
if (self == 0 || addr == 0)
{
if (mi->prev != 0)
{
if (mi->prev->addr + mi->prev->bytes == addr)
{
/* don't need to add, just make prev bigger */
mi->prev->bytes += bytes;
if (mi->prev->addr + mi->prev->bytes == mi->addr)
{
/* here we can remove one */
mi->prev->bytes += mi->bytes;
libmem_free_mem_item(self, mi);
}
return 0;
}
}
if (addr + bytes == mi->addr)
{
/* don't need to add here either */
mi->addr = addr;
mi->bytes += bytes;
return 0;
}
/* add before */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
new_mi->prev = mi->prev;
new_mi->next = mi;
if (mi->prev != 0)
{
mi->prev->next = new_mi;
}
mi->prev = new_mi;
if (self->free_head == mi)
{
self->free_head = new_mi;
}
added = 1;
break;
return 1;
}
mi = mi->next;
}
if (!added)
{
/* add last */
new_mi = (struct mem_item*)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->free_tail->next = new_mi;
new_mi->prev = self->free_tail;
self->free_tail = new_mi;
}
return 0;
if (self->free_head == 0)
{
/* add first item */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->free_head = new_mi;
self->free_tail = new_mi;
return 0;
}
added = 0;
mi = self->free_head;
while (mi != 0)
{
if (mi->addr > addr)
{
if (mi->prev != 0)
{
if (mi->prev->addr + mi->prev->bytes == addr)
{
/* don't need to add, just make prev bigger */
mi->prev->bytes += bytes;
if (mi->prev->addr + mi->prev->bytes == mi->addr)
{
/* here we can remove one */
mi->prev->bytes += mi->bytes;
libmem_free_mem_item(self, mi);
}
return 0;
}
}
if (addr + bytes == mi->addr)
{
/* don't need to add here either */
mi->addr = addr;
mi->bytes += bytes;
return 0;
}
/* add before */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
new_mi->prev = mi->prev;
new_mi->next = mi;
if (mi->prev != 0)
{
mi->prev->next = new_mi;
}
mi->prev = new_mi;
if (self->free_head == mi)
{
self->free_head = new_mi;
}
added = 1;
break;
}
mi = mi->next;
}
if (!added)
{
/* add last */
new_mi = (struct mem_item *)malloc(sizeof(struct mem_item));
memset(new_mi, 0, sizeof(struct mem_item));
new_mi->addr = addr;
new_mi->bytes = bytes;
self->free_tail->next = new_mi;
new_mi->prev = self->free_tail;
self->free_tail = new_mi;
}
return 0;
}
/*****************************************************************************/
static int
libmem_print(struct mem_info* self)
libmem_print(struct mem_info *self)
{
struct mem_item* mi;
struct mem_item *mi;
LLOGLN(0, ("libmem_print:"));
LLOGLN(0, (" used_head %p", self->used_head));
LLOGLN(0, (" used_tail %p", self->used_tail));
mi = self->used_head;
if (mi != 0)
{
LLOGLN(0, (" used list"));
while (mi != 0)
LOG_DEVEL(LOG_LEVEL_DEBUG, "libmem_print:");
LOG_DEVEL(LOG_LEVEL_DEBUG, " used_head %p", self->used_head);
LOG_DEVEL(LOG_LEVEL_DEBUG, " used_tail %p", self->used_tail);
mi = self->used_head;
if (mi != 0)
{
LLOGLN(0, (" ptr %p prev %p next %p addr 0x%8.8x bytes %d",
mi, mi->prev, mi->next, mi->addr, mi->bytes));
mi = mi->next;
LOG_DEVEL(LOG_LEVEL_DEBUG, " used list");
while (mi != 0)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, " ptr %p prev %p next %p addr 0x%8.8x bytes %d",
mi, mi->prev, mi->next, mi->addr, mi->bytes);
mi = mi->next;
}
}
}
LLOGLN(0, (" free_head %p", self->free_head));
LLOGLN(0, (" free_tail %p", self->free_tail));
mi = self->free_head;
if (mi != 0)
{
LLOGLN(0, (" free list"));
while (mi != 0)
LOG_DEVEL(LOG_LEVEL_DEBUG, " free_head %p", self->free_head);
LOG_DEVEL(LOG_LEVEL_DEBUG, " free_tail %p", self->free_tail);
mi = self->free_head;
if (mi != 0)
{
LLOGLN(0, (" ptr %p prev %p next %p addr 0x%8.8x bytes %d",
mi, mi->prev, mi->next, mi->addr, mi->bytes));
mi = mi->next;
LOG_DEVEL(LOG_LEVEL_DEBUG, " free list");
while (mi != 0)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, " ptr %p prev %p next %p addr 0x%8.8x bytes %d",
mi, mi->prev, mi->next, mi->addr, mi->bytes);
mi = mi->next;
}
}
}
return 0;
return 0;
}
/*****************************************************************************/
unsigned int
libmem_alloc(void* obj, int bytes)
libmem_alloc(void *obj, int bytes)
{
struct mem_info* self;
struct mem_item* mi;
unsigned int addr;
struct mem_info *self;
struct mem_item *mi;
unsigned int addr;
if (bytes < 1)
{
if (bytes < 1)
{
return 0;
}
bytes = ALIGN(bytes);
self = (struct mem_info *)obj;
addr = 0;
mi = self->free_head;
while (mi != 0)
{
if (bytes <= mi->bytes)
{
addr = mi->addr;
mi->bytes -= bytes;
mi->addr += bytes;
if (mi->bytes < 1)
{
libmem_free_mem_item(self, mi);
}
break;
}
mi = mi->next;
}
if (addr != 0)
{
self->total_bytes += bytes;
libmem_add_used_item(self, addr, bytes);
if (self->flags & 1)
{
libmem_print(self);
}
}
else
{
LOG_DEVEL(LOG_LEVEL_ERROR, "libmem_alloc: error");
}
return addr;
}
/*****************************************************************************/
int
libmem_free(void *obj, unsigned int addr)
{
struct mem_info *self;
struct mem_item *mi;
if (addr == 0)
{
return 0;
}
self = (struct mem_info *)obj;
mi = self->used_tail;
while (mi != 0)
{
if (mi->addr == addr)
{
self->total_bytes -= mi->bytes;
libmem_add_free_item(self, mi->addr, mi->bytes);
libmem_free_mem_item(self, mi);
if (self->flags & 1)
{
libmem_print(self);
}
return 0;
}
mi = mi->prev;
}
LOG_DEVEL(LOG_LEVEL_ERROR, "libmem_free: error");
return 1;
}
/*****************************************************************************/
int
libmem_set_flags(void *obj, int flags)
{
struct mem_info *self;
self = (struct mem_info *)obj;
self->flags |= flags;
return 0;
}
bytes = ALIGN(bytes);
self = (struct mem_info*)obj;
addr = 0;
mi = self->free_head;
while (mi != 0)
{
if (bytes <= mi->bytes)
{
addr = mi->addr;
mi->bytes -= bytes;
mi->addr += bytes;
if (mi->bytes < 1)
{
libmem_free_mem_item(self, mi);
}
break;
}
mi = mi->next;
}
if (addr != 0)
{
self->total_bytes += bytes;
libmem_add_used_item(self, addr, bytes);
if (self->flags & 1)
{
libmem_print(self);
}
}
else
{
LLOGLN(0, ("libmem_alloc: error"));
}
return addr;
}
/*****************************************************************************/
int
libmem_free(void* obj, unsigned int addr)
libmem_clear_flags(void *obj, int flags)
{
struct mem_info* self;
struct mem_item* mi;
struct mem_info *self;
if (addr == 0)
{
self = (struct mem_info *)obj;
self->flags &= ~flags;
return 0;
}
self = (struct mem_info*)obj;
mi = self->used_tail;
while (mi != 0)
{
if (mi->addr == addr)
{
self->total_bytes -= mi->bytes;
libmem_add_free_item(self, mi->addr, mi->bytes);
libmem_free_mem_item(self, mi);
if (self->flags & 1)
{
libmem_print(self);
}
return 0;
}
mi = mi->prev;
}
LLOGLN(0, ("libmem_free: error"));
return 1;
}
/*****************************************************************************/
int
libmem_set_flags(void* obj, int flags)
libmem_get_alloced_bytes(void *obj)
{
struct mem_info* self;
struct mem_info *self;
self = (struct mem_info*)obj;
self->flags |= flags;
return 0;
}
/*****************************************************************************/
int
libmem_clear_flags(void* obj, int flags)
{
struct mem_info* self;
self = (struct mem_info*)obj;
self->flags &= ~flags;
return 0;
}
/*****************************************************************************/
int
libmem_get_alloced_bytes(void* obj)
{
struct mem_info* self;
self = (struct mem_info*)obj;
return self->total_bytes;
self = (struct mem_info *)obj;
return self->total_bytes;
}

View File

@ -2,19 +2,19 @@
#ifndef _LIBMEM_C
#define _LIBMEM_C
void*
void *
libmem_init(unsigned int addr, int bytes);
void
libmem_deinit(void* aself);
libmem_deinit(void *aself);
unsigned int
libmem_alloc(void* obj, int bytes);
libmem_alloc(void *obj, int bytes);
int
libmem_free(void* obj, unsigned int addr);
libmem_free(void *obj, unsigned int addr);
int
libmem_set_flags(void* obj, int flags);
libmem_set_flags(void *obj, int flags);
int
libmem_clear_flags(void* obj, int flags);
libmem_clear_flags(void *obj, int flags);
int
libmem_get_alloced_bytes(void* obj);
libmem_get_alloced_bytes(void *obj);
#endif

View File

@ -1,60 +1,72 @@
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "libmem.h"
#include "log.h"
int main(int argc, char** argv)
int main(int argc, char **argv)
{
void* obj;
unsigned int addr1;
unsigned int addr2;
unsigned int addr3;
unsigned int addr4;
unsigned int addr5;
int index;
int rd;
void *obj;
unsigned int addr1;
unsigned int addr2;
unsigned int addr3;
unsigned int addr4;
unsigned int addr5;
int index;
int rd;
struct log_config *config;
srand(time(0));
obj = libmem_init(0x80000000, 64 * 1024 * 1024);
for (index = 0; index < 256; index++)
{
rd = rand() & 0xffff;
printf("1 rd %d\n", rd);
addr1 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("2 rd %d\n", rd);
addr2 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("3 rd %d\n", rd);
addr3 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("4 rd %d\n", rd);
addr4 = libmem_alloc(obj, rd);
addr5 = libmem_alloc(obj, rd);
libmem_free(obj, addr1);
printf("5\n");
addr1 = libmem_alloc(obj, 64);
printf("6\n");
libmem_free(obj, addr3);
printf("7\n");
addr3 = libmem_alloc(obj, 64 * 1024);
libmem_free(obj, addr5);
addr5 = libmem_alloc(obj, 64 * 1024);
printf("8\n");
libmem_free(obj, addr1);
printf("9\n");
libmem_free(obj, addr2);
printf("10\n");
libmem_free(obj, addr3);
libmem_free(obj, addr4);
if (index == 255)
config = log_config_init_for_console(LOG_LEVEL_DEBUG, NULL);
log_start_from_param(config);
log_config_free(config);
srand(time(0));
obj = libmem_init(0x80000000, 64 * 1024 * 1024);
for (index = 0; index < 256; index++)
{
libmem_set_flags(obj, 1);
rd = rand() & 0xffff;
printf("1 rd %d\n", rd);
addr1 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("2 rd %d\n", rd);
addr2 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("3 rd %d\n", rd);
addr3 = libmem_alloc(obj, rd);
rd = rand() & 0xffff;
printf("4 rd %d\n", rd);
addr4 = libmem_alloc(obj, rd);
addr5 = libmem_alloc(obj, rd);
libmem_free(obj, addr1);
printf("5\n");
addr1 = libmem_alloc(obj, 64);
printf("6\n");
libmem_free(obj, addr3);
printf("7\n");
addr3 = libmem_alloc(obj, 64 * 1024);
libmem_free(obj, addr5);
addr5 = libmem_alloc(obj, 64 * 1024);
printf("8\n");
libmem_free(obj, addr1);
printf("9\n");
libmem_free(obj, addr2);
printf("10\n");
libmem_free(obj, addr3);
libmem_free(obj, addr4);
if (index == 255)
{
libmem_set_flags(obj, 1);
}
libmem_free(obj, addr5);
}
libmem_free(obj, addr5);
}
libmem_deinit(obj);
return 0;
libmem_deinit(obj);
log_end();
return 0;
}

View File

@ -1,13 +0,0 @@
CFLAGS = -O2 -Wall
LDFLAGS =
OBJS = main.o
LIBS = -ldl
all: tcp_proxy
tcp_proxy: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o tcp_proxy $(OBJS) $(LIBS)
.PHONY clean:
rm -f $(OBJS) tcp_proxy

View File

@ -1,701 +0,0 @@
/**
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <locale.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int g_loc_io_count = 0; // bytes read from local port
int g_rem_io_count = 0; // bytes read from remote port
static int g_terminated = 0;
static char g_buf[1024 * 32];
typedef unsigned short tui16;
/*****************************************************************************/
static void
g_memset(void *ptr, int val, int size)
{
memset(ptr, val, size);
}
/*****************************************************************************/
static void
g_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stdout, format, ap);
va_end(ap);
}
/*****************************************************************************/
static void
g_writeln(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stdout, format, ap);
va_end(ap);
g_printf("\n");
}
/*****************************************************************************/
static void
g_hexdump(char *p, int len)
{
unsigned char *line;
int i;
int thisline;
int offset;
line = (unsigned char *)p;
offset = 0;
while (offset < len)
{
g_printf("%04x ", offset);
thisline = len - offset;
if (thisline > 16)
{
thisline = 16;
}
for (i = 0; i < thisline; i++)
{
g_printf("%02x ", line[i]);
}
for (; i < 16; i++)
{
g_printf(" ");
}
for (i = 0; i < thisline; i++)
{
g_printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
}
g_writeln("%s", "");
offset += thisline;
line += thisline;
}
}
/*****************************************************************************/
static int
g_tcp_socket(void)
{
int rv;
int option_value;
socklen_t option_len;
rv = (int)socket(AF_INET, SOCK_STREAM, 0);
if (rv < 0)
{
return -1;
}
option_len = sizeof(option_value);
if (getsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value,
&option_len) == 0)
{
if (option_value == 0)
{
option_value = 1;
option_len = sizeof(option_value);
setsockopt(rv, SOL_SOCKET, SO_REUSEADDR, (char *)&option_value,
option_len);
}
}
option_len = sizeof(option_value);
if (getsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value,
&option_len) == 0)
{
if (option_value < (1024 * 32))
{
option_value = 1024 * 32;
option_len = sizeof(option_value);
setsockopt(rv, SOL_SOCKET, SO_SNDBUF, (char *)&option_value,
option_len);
}
}
return rv;
}
/*****************************************************************************/
static int
g_tcp_set_non_blocking(int sck)
{
unsigned long i;
i = fcntl(sck, F_GETFL);
i = i | O_NONBLOCK;
fcntl(sck, F_SETFL, i);
return 0;
}
/*****************************************************************************/
static int
g_tcp_bind(int sck, const char* port)
{
struct sockaddr_in s;
memset(&s, 0, sizeof(struct sockaddr_in));
s.sin_family = AF_INET;
s.sin_port = htons((tui16)atoi(port));
s.sin_addr.s_addr = INADDR_ANY;
return bind(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
}
/*****************************************************************************/
static int
g_tcp_listen(int sck)
{
return listen(sck, 2);
}
/*****************************************************************************/
static int
g_tcp_select(int sck1, int sck2)
{
fd_set rfds;
struct timeval time;
int max = 0;
int rv = 0;
g_memset(&rfds, 0, sizeof(fd_set));
g_memset(&time, 0, sizeof(struct timeval));
time.tv_sec = 0;
time.tv_usec = 0;
FD_ZERO(&rfds);
if (sck1 > 0)
{
FD_SET(((unsigned int)sck1), &rfds);
}
if (sck2 > 0)
{
FD_SET(((unsigned int)sck2), &rfds);
}
max = sck1;
if (sck2 > max)
{
max = sck2;
}
rv = select(max + 1, &rfds, 0, 0, &time);
if (rv > 0)
{
rv = 0;
if (FD_ISSET(((unsigned int)sck1), &rfds))
{
rv = rv | 1;
}
if (FD_ISSET(((unsigned int)sck2), &rfds))
{
rv = rv | 2;
}
}
else
{
rv = 0;
}
return rv;
}
/*****************************************************************************/
static int
g_tcp_recv(int sck, void *ptr, int len, int flags)
{
return recv(sck, ptr, len, flags);
}
/*****************************************************************************/
static void
g_tcp_close(int sck)
{
if (sck == 0)
{
return;
}
close(sck);
}
/*****************************************************************************/
static int
g_tcp_send(int sck, const void *ptr, int len, int flags)
{
return send(sck, ptr, len, flags);
}
/*****************************************************************************/
void
g_sleep(int msecs)
{
usleep(msecs * 1000);
}
/*****************************************************************************/
static int
g_tcp_last_error_would_block(int sck)
{
return (errno == EWOULDBLOCK) || (errno == EAGAIN) || (errno == EINPROGRESS);
}
/*****************************************************************************/
static int
g_tcp_accept(int sck)
{
int ret ;
struct sockaddr_in s;
unsigned int i;
i = sizeof(struct sockaddr_in);
memset(&s, 0, i);
ret = accept(sck, (struct sockaddr *)&s, &i);
return ret ;
}
/*****************************************************************************/
static int
g_tcp_connect(int sck, const char* address, const char* port)
{
struct sockaddr_in s;
struct hostent* h;
g_memset(&s, 0, sizeof(struct sockaddr_in));
s.sin_family = AF_INET;
s.sin_port = htons((tui16)atoi(port));
s.sin_addr.s_addr = inet_addr(address);
if (s.sin_addr.s_addr == INADDR_NONE)
{
h = gethostbyname(address);
if (h != 0)
{
if (h->h_name != 0)
{
if (h->h_addr_list != 0)
{
if ((*(h->h_addr_list)) != 0)
{
s.sin_addr.s_addr = *((int*)(*(h->h_addr_list)));
}
}
}
}
}
return connect(sck, (struct sockaddr*)&s, sizeof(struct sockaddr_in));
}
/*****************************************************************************/
static int
g_tcp_socket_ok(int sck)
{
int opt;
socklen_t opt_len = sizeof(opt);
if (getsockopt(sck, SOL_SOCKET, SO_ERROR, (char *)(&opt), &opt_len) == 0)
{
if (opt == 0)
{
return 1;
}
}
return 0;
}
/*****************************************************************************/
static void
g_init(const char *app_name)
{
setlocale(LC_CTYPE, "");
}
/*****************************************************************************/
static void
g_deinit(void)
{
}
/*****************************************************************************/
static int
g_tcp_can_send(int sck, int millis)
{
fd_set wfds;
struct timeval time;
int rv;
time.tv_sec = millis / 1000;
time.tv_usec = (millis * 1000) % 1000000;
FD_ZERO(&wfds);
if (sck > 0)
{
FD_SET(((unsigned int)sck), &wfds);
rv = select(sck + 1, 0, &wfds, 0, &time);
if (rv > 0)
{
return g_tcp_socket_ok(sck);
}
}
return 0;
}
/*****************************************************************************/
static void
g_signal_user_interrupt(void (*func)(int))
{
signal(SIGINT, func);
}
/*****************************************************************************/
static void
g_signal_terminate(void (*func)(int))
{
signal(SIGTERM, func);
}
/*****************************************************************************/
static void
g_signal_usr1(void (*func)(int))
{
signal(SIGUSR1, func);
}
/*****************************************************************************/
static int
g_strcasecmp(const char *c1, const char *c2)
{
return strcasecmp(c1, c2);
}
/*****************************************************************************/
static int
main_loop(char *local_port, char *remote_ip, char *remote_port, int hexdump)
{
int lis_sck;
int acc_sck;
int con_sck;
int sel;
int count;
int sent;
int error;
int i;
int acc_to_con;
int con_to_acc;
acc_to_con = 0;
con_to_acc = 0;
acc_sck = 0;
/* create the listening socket and setup options */
lis_sck = g_tcp_socket();
g_tcp_set_non_blocking(lis_sck);
error = g_tcp_bind(lis_sck, local_port);
if (error != 0)
{
g_writeln("bind failed");
}
/* listen for an incoming connection */
if (error == 0)
{
error = g_tcp_listen(lis_sck);
if (error == 0)
{
g_writeln("listening for connection");
}
}
/* accept an incoming connection */
if (error == 0)
{
while ((!g_terminated) && (error == 0))
{
acc_sck = g_tcp_accept(lis_sck);
if ((acc_sck == -1) && g_tcp_last_error_would_block(lis_sck))
{
g_sleep(100);
}
else if (acc_sck == -1)
{
error = 1;
}
else
{
break;
}
}
if (error == 0)
{
error = g_terminated;
}
/* stop listening */
g_tcp_close(lis_sck);
lis_sck = 0;
if (error == 0)
{
g_writeln("got connection");
}
}
/* connect outgoing socket */
con_sck = 0;
if (error == 0)
{
con_sck = g_tcp_socket();
g_tcp_set_non_blocking(con_sck);
error = g_tcp_connect(con_sck, remote_ip, remote_port);
if ((error == -1) && g_tcp_last_error_would_block(con_sck))
{
error = 0;
i = 0;
while ((!g_tcp_can_send(con_sck, 100)) && (!g_terminated) && (i < 100))
{
g_sleep(100);
i++;
}
if (i > 99)
{
g_writeln("timeout connecting");
error = 1;
}
if (g_terminated)
{
error = 1;
}
}
if ((error != 0) && (!g_terminated))
{
g_writeln("error connecting to remote\r\n");
}
}
while ((!g_terminated) && (error == 0))
{
sel = g_tcp_select(con_sck, acc_sck);
if (sel == 0)
{
g_sleep(10);
continue;
}
if (sel & 1)
{
// can read from con_sck w/o blocking
count = g_tcp_recv(con_sck, g_buf, 1024 * 16, 0);
error = count < 1;
if (error == 0)
{
g_loc_io_count += count;
con_to_acc += count;
if (hexdump)
{
g_writeln("from remove, the socket from connect");
g_hexdump(g_buf, count);
}
#if 0
g_writeln("local_io_count: %d\tremote_io_count: %d",
g_loc_io_count, g_rem_io_count);
#endif
sent = 0;
while ((sent < count) && (error == 0) && (!g_terminated))
{
i = g_tcp_send(acc_sck, g_buf + sent, count - sent, 0);
if ((i == -1) && g_tcp_last_error_would_block(acc_sck))
{
g_tcp_can_send(acc_sck, 1000);
}
else if (i < 1)
{
error = 1;
}
else
{
sent += i;
}
}
}
}
if (sel & 2)
{
// can read from acc_sck w/o blocking
count = g_tcp_recv(acc_sck, g_buf, 1024 * 16, 0);
error = count < 1;
if (error == 0)
{
g_rem_io_count += count;
acc_to_con += count;
if (hexdump)
{
g_writeln("from accepted, the socket from accept");
g_hexdump(g_buf, count);
}
#if 0
g_writeln("local_io_count: %d\tremote_io_count: %d",
g_loc_io_count, g_rem_io_count);
#endif
sent = 0;
while ((sent < count) && (error == 0) && (!g_terminated))
{
i = g_tcp_send(con_sck, g_buf + sent, count - sent, 0);
if ((i == -1) && g_tcp_last_error_would_block(con_sck))
{
g_tcp_can_send(con_sck, 1000);
}
else if (i < 1)
{
error = 1;
}
else
{
sent += i;
}
}
}
}
}
g_tcp_close(lis_sck);
g_tcp_close(con_sck);
g_tcp_close(acc_sck);
g_writeln("acc_to_con %d", acc_to_con);
g_writeln("con_to_acc %d", con_to_acc);
return 0;
}
/*****************************************************************************/
static int
usage(void)
{
g_writeln("tcp_proxy <local-port> <remote-ip> <remote-port> [dump]");
return 0;
}
/*****************************************************************************/
void
proxy_shutdown(int sig)
{
g_writeln("shutting down");
g_terminated = 1;
}
void
clear_counters(int sig)
{
g_writeln("cleared counters at: local_io_count: %d remote_io_count: %d",
g_loc_io_count, g_rem_io_count);
g_loc_io_count = 0;
g_rem_io_count = 0;
}
/*****************************************************************************/
int
main(int argc, char **argv)
{
int dump;
if (argc < 4)
{
usage();
return 0;
}
g_init("tcp_proxy");
g_signal_user_interrupt(proxy_shutdown); /* SIGINT */
g_signal_usr1(clear_counters); /* SIGUSR1 */
g_signal_terminate(proxy_shutdown); /* SIGTERM */
if (argc < 5)
{
while (!g_terminated)
{
g_loc_io_count = 0;
g_rem_io_count = 0;
main_loop(argv[1], argv[2], argv[3], 0);
}
}
else
{
dump = g_strcasecmp(argv[4], "dump") == 0;
while (!g_terminated)
{
main_loop(argv[1], argv[2], argv[3], dump);
}
}
g_deinit();
return 0;
}

3
tools/Makefile.am Normal file
View File

@ -0,0 +1,3 @@
SUBDIRS = \
devel

6
tools/devel/Makefile.am Normal file
View File

@ -0,0 +1,6 @@
EXTRA_DIST = \
gtcp_proxy
SUBDIRS = \
tcp_proxy

View File

@ -332,7 +332,9 @@ static void *tcp_proxy(void *arg)
for (i = 0; i < 100; i++)
{
if (tcp_can_send(con_skt, 100))
{
break;
}
usleep(100);
}
@ -452,7 +454,9 @@ static void show_msg(int not_main_window, int style,
GtkWidget *dialog;
if (not_main_window)
{
gdk_threads_enter();
}
dialog = gtk_message_dialog_new(GTK_WINDOW(NULL),
GTK_DIALOG_DESTROY_WITH_PARENT,
@ -465,7 +469,9 @@ static void show_msg(int not_main_window, int style,
gtk_widget_destroy(dialog);
if (not_main_window)
{
gdk_threads_leave();
}
}
/**
@ -475,12 +481,16 @@ static void show_msg(int not_main_window, int style,
static void show_status(int not_main_thread, char *msg)
{
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_statusbar_push(GTK_STATUSBAR(g_statusbar), CONTEXT_ID, msg);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@ -490,12 +500,16 @@ static void show_status(int not_main_thread, char *msg)
static void clear_status(int not_main_thread)
{
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_statusbar_remove_all(GTK_STATUSBAR(g_statusbar), CONTEXT_ID);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@ -505,12 +519,16 @@ static void clear_status(int not_main_thread)
static void enable_btn_start(int not_main_thread)
{
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_widget_set_sensitive(GTK_WIDGET(g_btn_start), TRUE);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@ -520,12 +538,16 @@ static void enable_btn_start(int not_main_thread)
static void disable_btn_start(int not_main_thread)
{
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_widget_set_sensitive(GTK_WIDGET(g_btn_start), FALSE);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@ -569,12 +591,16 @@ static void show_loc_port_stats(int not_main_thread, int count)
sprintf(buf, "%d", count);
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_entry_set_text(GTK_ENTRY(g_tbx_loc_stats), buf);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**
@ -588,12 +614,16 @@ static void show_rem_port_stats(int not_main_thread, int count)
sprintf(buf, "%d", count);
if (not_main_thread)
{
gdk_threads_enter();
}
gtk_entry_set_text(GTK_ENTRY(g_tbx_rem_stats), buf);
if (not_main_thread)
{
gdk_threads_leave();
}
}
/**

View File

@ -30,7 +30,9 @@ int tcp_socket_create(void)
/* in win32 a socket is an unsigned int, in linux, it's an int */
if ((rv = (int) socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
return -1;
}
option_len = sizeof(option_value);
@ -157,7 +159,9 @@ int tcp_last_error_would_block()
void tcp_close(int skt)
{
if (skt <= 0)
{
return;
}
#if defined(_WIN32)
closesocket(skt);
@ -180,7 +184,9 @@ int tcp_socket(void)
/* in win32 a socket is an unsigned int, in linux, it's an int */
if ((rv = (int) socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
return -1;
}
option_len = sizeof(option_value);
@ -295,7 +301,9 @@ int tcp_socket_ok(int skt)
if (getsockopt(skt, SOL_SOCKET, SO_ERROR, (char *) (&opt), &opt_len) == 0)
{
if (opt == 0)
{
return 1;
}
}
return 0;
@ -323,15 +331,21 @@ int tcp_select(int sck1, int sck2)
FD_ZERO(&rfds);
if (sck1 > 0)
{
FD_SET(((unsigned int) sck1), &rfds);
}
if (sck2 > 0)
{
FD_SET(((unsigned int) sck2), &rfds);
}
max = sck1;
if (sck2 > max)
{
max = sck2;
}
rv = select(max + 1, &rfds, 0, 0, &time);
@ -340,10 +354,14 @@ int tcp_select(int sck1, int sck2)
rv = 0;
if (FD_ISSET(((unsigned int) sck1), &rfds))
{
rv = rv | 1;
}
if (FD_ISSET(((unsigned int)sck2), &rfds))
{
rv = rv | 2;
}
}
else
{

Some files were not shown because too many files have changed in this diff Show More