Compare commits

...

227 Commits
devel ... v0.9

Author SHA1 Message Date
metalefty
2d78ee852c
Merge pull request #2958 from metalefty/v0.9-cherry-pick
[v0.9] cherry picks
2024-03-21 16:56:05 +09:00
metalefty
8948b95528
Merge branch 'v0.9' into v0.9-cherry-pick 2024-03-21 16:55:35 +09:00
metalefty
d7b7a3c231
Merge pull request #2995 from metalefty/v0.9-release
Release v0.9.25.1
2024-03-13 18:19:00 +09:00
Koichiro Iwao
41c79932c8 Bump version to v0.9.25.1 2024-03-13 13:30:06 +09:00
Koichiro Iwao
999dc3f968 Update NEWS for v0.9.25.1 2024-03-13 13:29:43 +09:00
metalefty
b913f0d4de
Merge pull request #2994 from metalefty/v0.9-vnc-scroll
[v0.9] Disable touch events on Xvnc Session
2024-03-13 13:21:39 +09:00
Koichiro Iwao
82bf205ef5 Remove XRDP_SESSION_CODE which is no longer used 2024-03-13 09:47:02 +09:00
sefler
14c21566dc Disabel touch events on XVNC session
Fixes:  #2993

(cherry picked from commit e97a66593b)
2024-03-13 09:42:44 +09:00
metalefty
18cb6ef0f1
Merge pull request #2988 from metalefty/v0.9-release
Release v0.9.25
2024-03-11 22:45:19 +09:00
Koichiro Iwao
a74747f162 Bump version to v0.9.25 2024-03-11 21:14:25 +09:00
Koichiro Iwao
318eba1c4b Update NEWS for v0.9.25 2024-03-11 21:14:25 +09:00
rowlap
aa05ddcf89 Remove duplicate DEBUG output
allow_multimon and new_cursors are printed twice

(cherry picked from commit bf81557cdc)
2024-03-06 17:19:27 +09:00
rowlap
8f970ca670 Remove tcutils channel from xrdp.ini
According to #1943 tcutils was removed, so update the channel section to match.

(cherry picked from commit 2a0c2a612f)
2024-02-27 22:33:57 +09:00
Koichiro Iwao
2de41e0e00 Migrate github actions to Node 20
Hand-apply of #2955, 4ba025b.
2024-02-26 19:08:34 +09:00
Derek Schrock
ba2202ef91 Fall back to IPv4 if IPv6 capable but don't have an IPv6 address set
When xrdp is built with IPv6 support it will only fall back to IPv4 if
IPv6 is not supported (EAFNOSUPPORT).  However, if the system is IPv6
capable but doesn't have an IPv6 address set (at least inside a FreeBSD
jail) EPROTONOSUPPORT is returned from socket().

(cherry picked from commit 5afbca4954)
2024-02-26 19:05:30 +09:00
Koichiro Iwao
84a747c42d Bump copyright year and make easier to bump
(cherry picked from commit ae249c6755)
2024-02-21 21:42:34 +09:00
metalefty
a56f088f4b
Merge pull request #2948 from metalefty/v0.9-inertial-scrolling
[v0.9] Backport touchpad intertial scrolling
2024-02-19 11:57:43 +09:00
metalefty
4114133bdb
Merge pull request #2947 from metalefty/v0.9-codec
[v0.9] Just log Image RemoteFX codec
2024-02-17 00:20:48 +09:00
sefler
34819ac504 Backport touchpad intertial scrolling 2024-02-15 17:40:57 +09:00
Koichiro Iwao
3ebbcdcb47 Just log Image RemoteFX codec 2024-02-15 13:37:09 +09:00
matt335672
ccee5af1f4
Merge pull request #2903 from matt335672/v0_9_test_suite_add_timeouts
[V0.9] test suite add timeouts
2024-01-07 14:29:10 +00:00
matt335672
64d36e078a Increase back-stop timeouts for some tests
The Debian build farm has a number of older and slower machines
which need to run the xrdp test suite.

On these platforms, we occasionally get timeouts where machine load is
high. This results in duplicate issues being raised. It is not obvious
that the issues are duplicates, which wastes time all round.

This commit splits up some test cases into multiple cases and
adds larger timeouts for those cases that are CPU-intensive.
2024-01-04 15:22:34 +00:00
matt335672
2314ebe11d
Merge pull request #2897 from matt335672/v0_9_update_to_freebsd_13
[V0.9] Bump CI version of FreeBSD to 13.2
2024-01-02 11:06:34 +00:00
matt335672
b32a53bf94 Bump CI version of FreeBSD to 13.2 2024-01-02 10:38:04 +00:00
metalefty
85c863dba6
Merge pull request #2892 from metalefty/v0.9-release
Release v0.9.24
2023-12-30 22:05:13 +09:00
Koichiro Iwao
0f6b6e5aae Bump version to v0.9.24 2023-12-30 21:25:12 +09:00
Koichiro Iwao
5d15e44e96 Update NEWS for v0.9.24 2023-12-30 21:24:33 +09:00
matt335672
e775881c1b
Merge pull request #2887 from matt335672/v0_9_cppcheck_2_13
[V0.9] Bump cppcheck to v2.13.0
2023-12-23 14:21:20 +00:00
matt335672
0f3ca051cb Bump cppchck to v2.13.0 2023-12-23 13:38:54 +00:00
matt335672
111ee54453
Merge pull request #2860 from naruhito/neutrinordp-proxy-sidebutton-click
Update xrdp-neutrinordp.c to support side button (forward/back) click
2023-11-27 15:08:31 +00:00
Naruhito
ca049dcf24 Proxy extended mouse button 8, 9 events
https://github.com/neutrinolabs/xrdp/pull/2860#issuecomment-1818705074
2023-11-27 20:53:50 +09:00
matt335672
b610b41165
Merge pull request #2839 from matt335672/v0_9_fix_devredir_ordering
Fix message ordering in devredir
2023-10-26 15:37:11 +01:00
matt335672
6500949a18 Fix message ordering in devredir
The drive redirector is not compliant with the message ordering
in [MS-RDPEFS], causing FreeRDP 2.11.2 ro fail on redirecting drives.
2023-10-26 15:19:09 +01:00
matt335672
b782340456
Merge pull request #2830 from matt335672/v0_9_cppcheck-inc
[V0.9] updated Cppcheck to 2.12.1 / provide more includes to Cppcheck
2023-10-18 10:42:15 +01:00
firewave
2c0749d2cb bumped Cppcheck to 2.12.1
- build Cppcheck with matchcompiler for improved performance
- build Cppcheck with Boost for improved ValueFlow performance
2023-10-18 10:14:41 +01:00
firewave
90c7e72656 provide more includes to Cppcheck
- added (temporary) suppression of Cppcheck `shiftTooManyBits` false positives in `libxrdp/xrdp_mppc_enc.c`
- fix Cppcheck `nullPointerRedundantCheck` in `sesman/chansrv/clipboard.c`
2023-10-18 10:14:06 +01:00
matt335672
66c668c44b
Merge pull request #2826 from metalefty/v0.9-no-c99
Cherry-pick downstream patch from EPEL
2023-10-12 10:19:40 +01:00
Koichiro Iwao
37f206d2c8 Cherry-pick downstream patch from EPEL
Same as #2715

Obtained from: https://src.fedoraproject.org/rpms/xrdp/blob/014fe42/f/xrdp-0.9.22.1-no-c99.patch
2023-10-12 14:27:39 +09:00
matt335672
4e713c884f
Merge pull request #2824 from matt335672/v0_9_remove_ss_clipboard_code
[v0.9] remove ss clipboard code
2023-10-11 11:18:50 +01:00
matt335672
f6fa3fc5ba Remove client-server shortcut paste code
When significant amounts of data is coming from the client in a
fragmented CLIPRDR_DATA_RESPONSE PDU, this code provides a way to
start copying it to a requesting client before it is all read.

The only advantage of this code is to provide a slight speedup
before a paste is visible on the server.

There are significant problems with this code. Notably, it is
very difficult to parse Unicode text coming through this route. Each
UTF-16 character can occupy up to 4 bytes, and a fragmentation
boundary could occur at any point within a UTF-16 character.
2023-10-11 10:41:34 +01:00
matt335672
7603c5791b
Merge pull request #2817 from matt335672/v0_9_groups_patch
[V0.9] groups patch
2023-10-06 11:11:32 +01:00
matt335672
e6bc4db423 access_login_allowed: Remove primary group check
This check is now performed within g_check_user_in_group()
2023-10-06 10:56:14 +01:00
matt335672
8323e80668 Add getgrouplist() support to os_calls
On enterprise systems, using getgrouplist() (if available)
is more efficient than iterating over the members of the group,
and is also more likely to work
2023-10-06 10:52:08 +01:00
matt335672
1658d71ee3 Add getgrouplist() detection functionality
Defines the macro HAVE_GETGROUPLIST if getgrouplist() is
available, and defines the type passed to the GID array as
GETGROUPS_T
2023-10-06 10:51:43 +01:00
metalefty
1b49f82e39
Merge pull request #2808 from metalefty/v0.9-release
Release v0.9.23.1
2023-09-28 02:55:42 +09:00
Koichiro Iwao
82dbfa338a Bump version to v0.9.23.1 2023-09-27 21:12:15 +09:00
Koichiro Iwao
2b9b84fb81 Update NEWS for v0.9.23.1 2023-09-27 21:11:14 +09:00
metalefty
fd25fc546a
Merge pull request from GHSA-2hjx-rm4f-r9hw
[V0.9] CVE-2023-42822
2023-09-27 17:37:24 +09:00
matt335672
58c9c1f06a CVE-2023-42822
- font_items in struct xrdp_font renamed to chars to catch all
  accesses to it. This name is consistent with the type of
  the array elements (struct xrdp_font_char).
- Additional fields added to struct xrdp_font to allow for range
  checking and for a default character to be provided
- Additional checks and logic added to xrdp_font_create()
- New macro XRDP_FONT_GET_CHAR() added to perform checked access
  to chars field in struct xrdp_font
2023-09-25 14:02:30 +01:00
matt335672
4db9323413
Merge pull request #2784 from matt335672/v0_9_z3
Cppcheck 2.8 removed the dependency on z3
2023-09-04 10:33:36 +01:00
firewave
8f311633e9 Cppcheck 2.8 removed the dependency on z3 2023-09-04 10:15:25 +01:00
metalefty
4c3dd94dde
Merge pull request #2779 from metalefty/v0.9-release
Release v0.9.23
2023-08-31 11:26:29 +09:00
Koichiro Iwao
6c068fbb95 Bump version to v0.9.23 2023-08-31 10:45:26 +09:00
Koichiro Iwao
7b08610742 Update NEWS for v0.9.23 2023-08-31 10:45:22 +09:00
metalefty
8c5b7cdff3
Merge pull request from GHSA-f489-557v-47jq
[v0.9] Check auth_start_session() result
2023-08-24 10:14:48 +09:00
matt335672
322d11b431 [v0.9] Check auth_start_session() result 2023-08-19 13:26:44 +01:00
matt335672
469a89cf53
Merge pull request #2767 from matt335672/v0_9_clipboard_updates
V0 9 clipboard updates
2023-08-09 14:39:54 +01:00
matt335672
722fe7d74f clipboard: Fix TODO action in clipboard_common.h
Use the official Windows clipboard format names where appropriate

Replace g_file_format_id with g_file_group_descriptor_format_id
as the latter name is more descriptive of what is described in
[MS-ECLIP]
2023-08-08 09:46:20 +01:00
matt335672
15f730524e clipboard: Only advertise text to X11 clients if it is available 2023-08-08 09:46:13 +01:00
matt335672
680bba8a02 clipboard: Tell the X11 client if a selection is unavailable 2023-08-08 09:46:05 +01:00
matt335672
011009681e
Merge pull request #2738 from matt335672/v0_9_bump_cppcheck_to_2_11
[V0.9] bump cppcheck to 2 11
2023-06-23 17:17:16 +01:00
matt335672
946f86f611 Use all available CPUs to build cppcheck 2023-06-23 17:05:43 +01:00
matt335672
7e514bf339 Bump cppcheck to v2.11
This fixes the following errors:-

sesman/tools/authtest.c:64:14: error: syntax error [syntaxError]
    g_printf("xrdp auth module tester v" PACKAGE_VERSION "\n");
             ^
sesman/tools/sesrun.c:165:14: error: syntax error [syntaxError]
    g_printf("xrdp session starter v" PACKAGE_VERSION "\n");
             ^
vrplayer/decoder.h:35:12: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
    public slots:
           ^
vrplayer/playaudio.h:45:12: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
    public slots:
           ^
vrplayer/dlgabout.h:22:13: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
    private slots:
            ^
vrplayer/playvideo.h:49:12: error: There is an unknown macro here somewhere. Configuration is required. If slots is a macro then please configure it. [unknownMacro]
    public slots:
           ^
Additionally, cppcheck now makes use of all available CPUs
2023-06-23 17:05:21 +01:00
matt335672
27ea401e43
Merge pull request #2712 from matt335672/v0_9_allow_long_strings_in_pam_env
[0.9] Remove size limit for PAM environment variables
2023-06-01 15:34:17 +01:00
matt335672
3d2b3b89f4 Remove size limit for PAM environment variables
The current logic in auth_set_env() for PAM environments only allows
environment variables to be around 256 characters in length.
2023-05-31 16:30:58 +01:00
metalefty
f1fa6bbc19
Merge pull request #2703 from metalefty/v0.9-tarball-script
Add script to make release tarball
2023-05-26 23:50:19 +09:00
Koichiro IWAO
6954ab0972 Fix usage comment 2023-05-26 23:32:02 +09:00
Koichiro IWAO
7efcd9280c Reduce prompt timeout 2023-05-26 23:27:20 +09:00
Koichiro IWAO
b3dba2bad4 Add script to make release tarball
to avoid mistake in release procedure.
2023-05-26 18:39:46 +09:00
metalefty
b26ca93176
Merge pull request #2694 from metalefty/v0.9-release
Update NEWS and bump version to v0.9.22.1
2023-05-22 23:41:56 +09:00
Koichiro IWAO
d2a55d9203
Update NEWS and bump version to v0.9.22.1 2023-05-22 23:11:48 +09:00
metalefty
2f214c8452
Merge pull request #2658 from metalefty/v0.9-release
v0.9 release
2023-05-07 15:14:46 +09:00
Koichiro IWAO
71594b5114
Bump version for v0.9.22 2023-05-07 15:03:13 +09:00
Koichiro IWAO
1b3be3e641 Update NEWS for v0.9.22 2023-05-07 15:03:05 +09:00
matt335672
6c9f7f8434
Merge pull request #2653 from matt335672/v0_9_allow_longer_user_wm_str
[V0.9] Allow longer UserWindowManager strings
2023-05-02 12:10:40 +01:00
matt335672
a58c895d1b Allow longer UserWindowManager strings
The UserWindowManager is limited to 31 characters. There appears
to be no good reason for this.
2023-05-02 12:06:30 +01:00
matt335672
929d072622
Merge pull request #2650 from matt335672/v0_9_unnecessary_check_h
[V0.9] Remove unnecessary check h
2023-04-28 10:41:46 +01:00
Jat
4bc8701631 remove unnecessary include check.h 2023-04-28 10:23:26 +01:00
matt335672
d9580dee01
Merge pull request #2634 from lennartS/v0.9_shell
sesman: Prevent the use of 'alternate shell'
2023-04-19 09:58:15 +01:00
Lennart Sauerbeck
d4ea314ac2 sesman: Prevent the use of 'alternate shell'
By setting the new config value 'AllowAlternateShell' to 'no' it is now
possible to prevent the use of an alternate shell, which can be set by
the connecting user.
The default remains unchanged and any shell is allowed if the config
value is not specified. It can also be set explicitly to 'yes' to achieve
the same outcome.

Fixes: #850
2023-04-17 22:34:19 +02:00
matt335672
d7c3809ce8
Merge pull request #2622 from matt335672/v0_9_cirrus_freebsd_update
[V0.9] Bump FreeBSD image to 12.4
2023-03-31 12:11:27 +01:00
matt335672
a046aeea3f Bump FreeBSD image to 12.4 2023-03-31 12:03:14 +01:00
matt335672
bd43e80ef4
Merge pull request #2612 from matt335672/v0_9_unwrap_mem_calls
[v0.9] common: change g_malloc, g_free, g_memset, and g_memcpy to macros
2023-03-28 10:31:40 +01:00
Jay Sorg
d0cd397fee common: change g_malloc, g_free, g_memset, and g_memcpy to macros 2023-03-28 10:14:55 +01:00
matt335672
0525e4fbf4
Merge pull request #2611 from matt335672/v0_9_pcsc_stack_fix
chansrv: don't free item on stack
2023-03-27 10:23:34 +01:00
Jay Sorg
bd63675a75 chansrv: don't free item on stack 2023-03-27 10:11:23 +01:00
matt335672
35bc862775
Merge pull request #2582 from metalefty/v0.9-cherry-pick
[v0.9] sesman: fix help message alignment
2023-03-08 10:42:44 +00:00
Koichiro IWAO
f4e909c071 sesman: fix help message alignment 2023-03-08 13:07:33 +09:00
matt335672
df32336c76
Merge pull request #2577 from matt335672/v0_9_fix_list_insert_bug
[V0.9] Fix regression in list module
2023-03-06 18:00:50 +00:00
matt335672
8810d46ff1 Fix regression in list module 2023-03-06 17:47:48 +00:00
matt335672
affc40b8f0
Merge pull request #2574 from metalefty/v0.9-cherry-pick
[v0.9] Fix potential null dereference
2023-03-06 14:41:14 +00:00
Zhipeng Xue
689950d953 Fix potential null dereference 2023-03-06 23:01:22 +09:00
metalefty
a564bbbe5d
Merge pull request #2566 from matt335672/v0_9_pam_d_configurable
Make pam.d directory configurable
2023-02-28 10:02:49 +09:00
Yifan J
44efa5db5b Make pam.d directory configurable 2023-02-27 10:49:08 +00:00
metalefty
00d9b29fcc
Merge pull request #2554 from metalefty/v0.9-cherry-pick
[v0.9] cherry-pick sound related improvements
2023-02-20 09:18:21 +09:00
Koichiro IWAO
3080439fa9 chansrv/audin: return UNKNOWN when undefined value
is passed to audin_wave_format_tag_to_str.
2023-02-17 10:52:55 +09:00
Koichiro IWAO
2350267f49 chansrv/audin,sound: record index of formats array
It helps to know which audio format is in use.
2023-02-17 10:52:48 +09:00
Koichiro IWAO
cde22e3b4d chansrv/audin: record audin (microphone redirection) audio formats 2023-02-17 10:52:41 +09:00
Koichiro IWAO
b765304a43 chansrv/sound: adjust log level and record wFormatTag as string
These log levels are unintendedly decreased during logging reworking.

Recording audio formats are useful to know which format is used in
current RDP session.
2023-02-17 10:52:34 +09:00
Koichiro IWAO
58921a972e chansrv: add a utility function to convert wFormatTag into string 2023-02-17 10:52:26 +09:00
Hiero32
46b4ee2e95 sound: fix noise between two playbacks for mp3/aac (#2519)
* sound: fix noise between two playbacks for mp3/aac
* fix sound stuttered on skip operation of vlc
2023-02-17 10:49:40 +09:00
matt335672
2e5dd686dc
Merge pull request #2548 from matt335672/v0_9_list_improvements
V0 9 list improvements
2023-02-13 14:34:18 +00:00
matt335672
7198f58d6f Add simple list test cases 2023-02-11 14:52:23 +00:00
matt335672
152c31ca89 Add memory allocation checking to the list module
The list module lacks memory allocation checking, and
consequently can coredump on list_create() or
list_add_item().
2023-02-10 14:34:22 +00:00
matt335672
1faca4c1f7
Merge pull request #2521 from matt335672/v0_9_cppcheck_2_10
Bump cppcheck version to 2.10
2023-01-29 16:17:40 +00:00
matt335672
2d66b2f8d4 Bump cppcheck version to 2.10 2023-01-29 16:00:21 +00:00
matt335672
f31fee3052
Merge pull request #2508 from matt335672/v0_9_otaconix_patch_1
[V0.9] Tiny fix in pseudocode description of startwm.sh
2023-01-18 15:29:34 +00:00
matt335672
1e1eeec140
Merge pull request #2507 from matt335672/v0_9_check_pcsc_sock_create_err
[V0.9] Don't try to listen on the scard socket if it isn't there
2023-01-18 15:29:01 +00:00
matt335672
cae8215f3f
Merge pull request #2509 from matt335672/v0_9_no_pwd_no_autologin
[V0.9] Disable autologon for empty passwords
2023-01-18 15:28:34 +00:00
matt335672
ba4c9b9893 Disable autologon for empty passwords
Although there is nothing in the specification to prevent automatic
logons with empty passwords, this is not a secure default.

The autologon flag INFO_AUTOLOGON ([MS-RDPBCGR] 2.2.1.11.1.1) is now
ignored for empty passwords.
2023-01-18 15:08:38 +00:00
otaconix
a80e66e2d2 Tiny fix in pseudocode description of startwm.sh
I realize there's not much value in this PR, but I noticed this, so I thought I'd fix it 🙂
2023-01-18 15:07:10 +00:00
matt335672
6aac2e942d Don't try to listen on the scard socket if it isn't there
If the scard local socket can't be created, there's no point
in trying to listen on it. This will just fill the chansrv log
file with errors.
2023-01-18 14:40:02 +00:00
metalefty
d459047924
Merge pull request #2470 from metalefty/v0.9-release
Release v0.9.21.1
2022-12-13 17:59:38 +09:00
Koichiro IWAO
9eedaf9fa2 Bump version to v0.9.21.1 2022-12-13 17:47:10 +09:00
Koichiro IWAO
28a39a5d9f Update NEWS for v0.9.21.1 2022-12-13 17:46:54 +09:00
Koichiro IWAO
6308e23e1f gitignore: add some build artifacts 2022-12-13 10:00:00 +09:00
metalefty
75556d2a69
Merge pull request #2468 from matt335672/v0_9_fix_slackbuild_missing_file
Add xrdp-sesman.system to distributed files
2022-12-13 09:05:18 +09:00
matt335672
19da7a92eb Add xrdp-sesman.system to distributed files
Distributed file list also now sorted for ease of checking
2022-12-12 19:43:08 +00:00
metalefty
83a4d55b14
Merge pull request #2464 from metalefty/v0.9-release
Release v0.9.21
2022-12-10 21:14:26 +09:00
Koichiro IWAO
a4e83996db Bump version to v0.9.21 2022-12-10 21:08:48 +09:00
Koichiro IWAO
07605c7d65 Update NEWS for v0.9.21 2022-12-10 21:08:48 +09:00
matt335672
faa7021a0b
Merge pull request #2462 from matt335672/fix_devredir
Remove double '!' from test
2022-12-09 18:19:39 +00:00
matt335672
814d56317c Remove double '!' from test
Commit 7ad7b05261 introduced a regression
which prevented remote drives being accessible. I picked it up in testing,
but then failed to commit the change.
2022-12-09 18:12:25 +00:00
matt335672
fbf374c8b0
Merge pull request #2461 from metalefty/ci-fix
Fix CI failure after 8484767
2022-12-09 17:21:49 +00:00
metalefty
36c54d9776
Merge pull request #2460 from matt335672/v0_9_pcscd_sock_permissions
Set permissions on pcsc socket dir to owner only
2022-12-10 00:12:02 +09:00
Koichiro IWAO
2f1196bdc4 Fix CI failure after 8484767
libscp_v0.c:228:52: error: comparison of integer expressions of different signedness: ‘int’ and ‘unsigned int’ [-Werror=sign-compare]
  228 |         if ((trans->in_s->end - trans->in_s->data) < trans->header_size)
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
2022-12-09 23:21:26 +09:00
metalefty
b442abe467
Merge pull request from GHSA-2f49-wwpm-78pj
CVE-2022-23478
2022-12-09 22:12:51 +09:00
metalefty
de1352183a
Merge pull request from GHSA-56pq-2pm9-7fhm
CVE-2022-23482
2022-12-09 22:12:28 +09:00
metalefty
6a64039773
Merge pull request from GHSA-59wp-3wq6-jh5v
CVE-2022-23493
2022-12-09 22:12:14 +09:00
metalefty
7c7cc2523a
Merge pull request from GHSA-hm75-9jcg-p7hq
CVE-2022-23481
2022-12-09 22:11:57 +09:00
metalefty
a1484cd0a1
Merge pull request from GHSA-38rw-9ch2-fcxq
CVE-2022-23483
2022-12-09 22:11:40 +09:00
metalefty
a8bb8959c3
Merge pull request from GHSA-rqfx-5fv8-q9c6
CVE-2022-23484
2022-12-09 22:11:25 +09:00
metalefty
8484767250
Merge pull request from GHSA-pgx2-3fjj-fqqh
CVE-2022-23479
2022-12-09 22:10:58 +09:00
metalefty
0418502eb3
Merge pull request from GHSA-3jmx-f6hv-95wg
CVE-2022-23480
2022-12-09 22:10:33 +09:00
metalefty
09e1a0561e
Merge pull request from GHSA-hqw2-jx2c-wrr2
Prevent buffer overflow for oversized audio format from client
2022-12-09 22:10:10 +09:00
metalefty
7c71a4f560
Merge pull request from GHSA-8c2f-mw8m-qpx6
Login window - replace g_sprintf() withl g_snprintf() calls
2022-12-09 22:09:34 +09:00
matt335672
413678ef3d Set permissions on pcsc socket dir to owner only
There is no reason for any user other than the current one to be able
to communicate with the remote smartcard.
2022-12-09 11:57:46 +00:00
matt335672
e0578b5621
Merge pull request #2457 from metalefty/v0.9-cherry-pick
[v0.9] cherry-pick for v0.9.21
2022-12-09 10:42:03 +00:00
matt335672
030db5524b CVE-2022-23493
Check chansrv channel ID on a channel close

Prevent OOB read if an invalid channel ID is sent.
2022-12-09 10:30:49 +00:00
Koichiro IWAO
4256d84676 vnc: add mouse button 6, 7, 8 support
(cherry picked from commit 2b0c903afe)
2022-12-09 17:01:15 +09:00
Koichiro IWAO
6e0c496564 vnc: Constify existing use of magic numbers
(cherry picked from commit 70bc5ea092)
2022-12-09 17:00:59 +09:00
Mosakuji Hokuto
70e14f760e Update pamdir_suse to accommodate with TW pam.d move (#2413)
On newer builds of openSUSE tumbleweed the path of pam.d has moved from
/usr/etc/pam.d to /usr/lib/pam.d, which prevents install script to
correctly guess pam rules. Updating path in mkpamrules solves the
problem.

(cherry picked from commit 4ff968bc98)
2022-12-09 17:00:29 +09:00
matt335672
ba2b9fc606 Changes to cope with trans->header_size being unsigned 2022-12-08 14:41:19 +00:00
matt335672
60864014b7 CVE-2022-23479
Detect attempts to overflow input buffer

If application code hasn't properly sanitised the header_size
for a transport, it is possible for read requests to be issued
which overflow the input buffer. This change detects this
at a low level and bounces the read request.
2022-12-08 14:41:19 +00:00
matt335672
191ed3e3fa Remove unused g_full_name_for_filesystem
Not only was this unused, the way it was read could lead to a
buffer overflow (CVE-2022-23480)
2022-12-08 14:13:48 +00:00
matt335672
c2c6efb1d3 CVE-2022-23484
Add check for RAIL window text size
2022-12-08 10:43:42 +00:00
matt335672
35cca701c7 CVE-2022-23483
Sanitise channel data being passed from application

Avoids OOB read if the size field is incorrect.
2022-12-08 10:41:30 +00:00
matt335672
bb9766c79f CVE-2022-23482
Check minimum length of TS_UD_CS_CORE message
2022-12-08 10:38:58 +00:00
matt335672
c77e974080 CVE-2022-23481
Add length checks to client confirm active PDU parsing
2022-12-08 10:37:57 +00:00
matt335672
7ad7b05261 CVE-2022-23480
Added length checking to redirector response parsing
2022-12-08 10:36:40 +00:00
matt335672
6cb54a1c26 CVE-2022-23478
Fix potential OOB write if invalid chansrv channel opened

Also removed an unnecessary dynamic memory allocation
2022-12-08 10:31:10 +00:00
matt335672
d49f269af8 CVE-2022-23477
Prevent buffer overflow for oversized audio format from client
2022-12-08 10:26:08 +00:00
matt335672
43cf272b11 CVE-2022-23468
Login window - replace g_sprintf() withl g_snprintf() calls
2022-12-07 14:45:36 +00:00
matt335672
da521b27f9
Merge pull request #2439 from matt335672/v0_9_remove_passwd_from_auth_info
[V0.9] Remove unnecesssary data from struct auth_info
2022-11-29 08:41:29 +00:00
matt335672
4a8e5d3493 Clear password when session ends
Any password stored in SCP_SESSION is now cleared before storage
is returned to the heap
2022-11-28 10:44:09 +00:00
matt335672
56a7c3efdd Remove unnecessary data from struct t_auth_info
8fc5610dad back-ported to v0.9
2022-11-28 10:20:58 +00:00
matt335672
5bf82ed54c
Merge pull request #2395 from matt335672/update_actions
[v0.9] Update github actions to address warnings
2022-10-20 16:08:38 +01:00
matt335672
ffaf8c2cc4 Add casts required for C++ CI and OpenSSL 3.x 2022-10-20 15:02:00 +01:00
matt335672
af6f777697 Update legacy OS from 18.04 to 20.04
Since Ubuntu 20.04 supports less i386 functionality than 18.04,
it has been necessary to use a smaller set of compile options,
resulting in less compile coverage.
2022-10-20 15:02:00 +01:00
matt335672
2776ffc280 Update OS_VERSION environmental hack 2022-10-20 15:00:32 +01:00
matt335672
d94a7388c8 Update github actions version for node.js 16 2022-10-20 15:00:32 +01:00
metalefty
e101d6baf6
Merge pull request #2367 from metalefty/v0.9-release
Bump version to v0.9.20
2022-09-15 14:39:07 +09:00
Koichiro IWAO
75fab21415 Bump version to v0.9.20 2022-09-15 14:23:20 +09:00
metalefty
4770a7c923
Merge pull request #2360 from metalefty/v0.9-cherry-pick
[v0.9] cherry-pick from devel for v0.9.20
2022-09-11 14:39:05 +09:00
a1346054
6acf8398dd fix typos
(cherry picked from commit 7fe18cc1c0)
2022-09-11 11:47:11 +09:00
a1346054
1a3a9bb479 remove executable bit from text files
(cherry picked from commit 5ff68740e5)
2022-09-11 10:50:43 +09:00
a1346054
63f16d229a improve test logic
(cherry picked from commit 0c942feaff)
2022-09-11 10:48:27 +09:00
a1346054
2857c39d0a fix some shellcheck warnings
(cherry picked from commit 59f8d9fe07)
2022-09-11 10:48:17 +09:00
Khem Raj
d64be8a1cd mark count with unused attribute
This may throw a warning with clang-15+ when devel logs are disabled
Fixes
../../../xrdp-0.9.19/sesman/chansrv/chansrv.c:198:9: error: variable 'count' set but not used [-Werror,-Wunused-but-set-variable]

Signed-off-by: Khem Raj <raj.khem@gmail.com>
(cherry picked from commit fc2d61e0c8)
2022-09-11 10:47:56 +09:00
Koichiro IWAO
44e9982119 sesman: fix spacing in log
[20220301-18:25:01] [INFO ] Starting window manager on display 12from user home directory: /home/user/startwm.sh
                                                                ^^

(cherry picked from commit 2c25e60abc)
2022-09-11 10:46:54 +09:00
matt335672
676c3ed00e Add xrdpapi/simple.c to the CI
(cherry picked from commit dabd049ad2)
2022-09-11 10:45:00 +09:00
matt335672
8dfc28409d Update xrdpapi/simple.c for new logging
(cherry picked from commit 58573c4110)
2022-09-11 10:43:49 +09:00
metalefty
9b34a96f98
Merge pull request #2351 from matt335672/v09_cppcheck_v29
[v0.9] Bump cppcheck version to 2.9
2022-08-31 09:14:47 +09:00
matt335672
29d03d8710 Bump cppcheck version to 2.9 2022-08-30 11:00:13 +01:00
matt335672
3161d223b1
Merge pull request #2349 from metalefty/v0.9-sesman-ini
v0.9: sesman.ini: mention FreeBSD Xorg path
2022-08-27 12:07:04 +01:00
Koichiro IWAO
c5e0e4962c sesman.ini: mention FreeBSD Xorg path 2022-08-26 14:11:17 +09:00
metalefty
3e44629184
Merge pull request #2292 from Nexarian/backport_mstsc_resize_fix_to_v0.9
Backport MSTSC resize fix.
2022-08-22 15:32:00 +09:00
Christopher Pitstick
326f4660ce Fixing astyle error. 2022-07-09 21:13:01 -04:00
Christopher Pitstick
a07da5b38d Backporting already this size fix. 2022-07-09 19:39:36 -04:00
Christopher Pitstick
4a6f0030f1 Backport MSTSC resize fix.
Ports https://github.com/neutrinolabs/xrdp/pull/2291 to v0.9
2022-06-26 23:34:59 -04:00
metalefty
4a87550028
Merge pull request #2273 from matt335672/wyse_thin_client_0.9
Improve RDS compatibility
2022-05-19 09:28:43 +09:00
matt335672
d602020f96 Bump FreeBSD CI version to 12.3 2022-05-19 09:19:04 +09:00
matt335672
87cbab2148 Open log in sesman before reading config 2022-05-19 09:18:41 +09:00
matt335672
ce24eaa641 Relaxed Channel Join PDU requirements for non-TLS
Windows 10 RDS is quite relaxed about missing channel join PDUs,
whereas we have to adhere quite tightly to the specification to
make sure we get a TLS "Client hello" where appropriate. This makes
us incompatible with older RDP clients. For example, the Wyse sx0
thin client does not send a channel join PDU for the user channel.
Older, non-TLS versions of xrdp supported these devices.

This commit re-implements the xrdp v0.6.1 behaviour for non-TLS
connections only, allowing system administrators to use these devices
on trusted networks. These devices are in any case too old to
establish a modern TLS connection.
2022-05-18 12:12:08 +01:00
matt335672
fc510d5ff6 Log connected client version 2022-05-18 12:11:50 +01:00
matt335672
e5a0d40839 Send MS-compatible user channel
The Windows 10 RDS sets the user channel ID to be one more than the
ID of the last allocated static virtual channel. Currently we set it to
1002 (0x03ea) which is allocated to the server channel. This change
makes xrdp emulate RDS more closely.
2022-05-18 12:09:52 +01:00
matt335672
aa00974a6c Update channel logging 2022-05-18 12:09:42 +01:00
Koichiro IWAO
8290e59a01 Merge branch 'devel' into v0.9 2022-03-17 15:20:14 +09:00
metalefty
7e6194504e
Merge pull request #2139 from metalefty/release
Release v0.9.18.1
2022-02-07 22:23:56 +09:00
Koichiro IWAO
b160f84062 Bump version to v0.9.18.1 2022-02-07 16:57:43 +09:00
Koichiro IWAO
e19b877d7b Update NEWS for v0.9.18.1 2022-02-07 16:57:43 +09:00
matt335672
057f5955c3 Add lower bound to sesman data input size check
(cherry picked from commit eb4a8e342d)
2022-02-07 16:11:26 +09:00
Koichiro IWAO
cb1d034fde Merge branch 'devel' into v0.9 2022-02-07 15:12:23 +09:00
Koichiro IWAO
220783fb92 Merge branch 'devel' into v0.9 2022-02-07 15:11:46 +09:00
Koichiro IWAO
d868b05273 Merge branch 'devel' into v0.9 2021-04-30 21:01:27 +09:00
Koichiro IWAO
fc3d2838a5 Merge branch 'devel' into v0.9 2020-12-28 23:03:43 +09:00
Koichiro IWAO
8faaa57cd7 Merge branch 'devel' into v0.9 2020-08-31 16:07:07 +09:00
metalefty
a9d4130d20
Merge pull request #1624 from metalefty/v0.9-CVE-2020-4044
Release v0.9.13.1
2020-06-30 15:21:29 +09:00
Koichiro IWAO
9c508cda0f
bump version to v0.9.13.1 2020-06-30 15:01:55 +09:00
Koichiro IWAO
5c74b1a856
Update NEWS for v0.9.13.1 2020-06-30 15:00:24 +09:00
matt335672
cfd653c6e5
Fixed CVE-2020-4044 CI errors 2020-06-30 11:59:58 +09:00
matt335672
ba2f727c9a
Fix for CVE-2020-4044
Reported by: Ashley Newson
2020-06-30 11:59:41 +09:00
Koichiro IWAO
0a068311b1
Merge branch 'devel' into v0.9 2020-03-11 13:30:33 +09:00
Koichiro IWAO
6294649d13
Merge branch 'devel' into v0.9 2020-03-11 13:29:20 +09:00
Koichiro IWAO
8e6af639e8
Merge branch 'devel' into v0.9 2019-12-28 21:30:26 +09:00
Koichiro IWAO
f2bd1af772
Merge branch 'devel' into v0.9 2019-12-28 21:15:39 +09:00
Koichiro IWAO
0b17739da0
Merge branch 'devel' into v0.9 2019-08-20 00:38:17 +09:00
Koichiro IWAO
21ff90a89b
Merge branch 'devel' into v0.9 2019-08-20 00:35:10 +09:00
Koichiro IWAO
e70d783524 Merge branch 'devel' into v0.9 2019-04-18 14:40:38 +09:00
Koichiro IWAO
9e8fbf2d5a
Merge branch 'devel' into v0.9 2019-04-18 11:26:55 +09:00
Koichiro IWAO
164e45b6d1
Merge branch 'devel' into v0.9 2018-12-25 13:42:40 +09:00
Koichiro IWAO
a0edfad3df
Merge branch 'devel' into v0.9 2018-09-25 15:10:32 +09:00
Koichiro IWAO
43eb262643
Merge branch 'devel' into v0.9 2018-06-29 17:03:06 +09:00
Koichiro IWAO
32ff7f8956
Merge branch 'devel' into v0.9 2018-03-26 14:58:36 +09:00
Koichiro IWAO
5c622f51a4
Merge branch 'devel' into v0.9 2018-01-09 15:22:53 +09:00
Koichiro IWAO
776519af61 Merge branch 'devel' into v0.9 2017-09-28 11:31:13 +09:00
Koichiro IWAO
94e82d08cd Release v0.9.3.1 2017-08-16 13:57:35 +09:00
Koichiro IWAO
adb381a61c instfiles: don't include generated *.services files in distribution
Solves #848.
Pointed out by: Fuminobu TAKEYAMA (@ftake)
2017-08-16 13:44:51 +09:00
Koichiro IWAO
c222335be9 Merge branch 'devel' into v0.9 2017-07-14 21:40:31 +09:00
Koichiro IWAO
28a1e42f98 Merge branch 'devel' into v0.9 2017-07-13 14:35:21 +09:00
Koichiro IWAO
f24aa9b8c5 Merge branch 'devel' into v0.9 2017-07-06 18:22:59 +09:00
Koichiro IWAO
66e3cf5b45 travis: enable build test on v0.9 branch
it is the latest stable branch.
2017-07-06 12:30:25 +09:00
Koichiro IWAO
916ca91527 ignore *.so (pulseaudio modules) 2017-05-26 11:04:38 +09:00
Koichiro IWAO
682c39d842 pulse: respect XRDP_SOCKET_PATH environment variable 2017-05-26 11:04:38 +09:00
Koichiro IWAO
eb51f917da sesman: pass xrdp socket path to user session
via environment variable.
2017-05-26 11:04:38 +09:00
Koichiro IWAO
d72f7a12f7 common: separate sockets macros into basename and fullpath
since sometimes socket directory is obtained from environment variable.
2017-05-26 11:04:38 +09:00
Koichiro IWAO
2b18141f7a sesman: LOGNAME should be set to username
which is used to store login name. The login name shall be the string
that would be returned by the getlogin() function [1]. Some applications
only refers LOGNAME environment variable and don't fallback to other
variables such as USER.

Fixes #725.  Reported by @seidler2547.

[1] The Single UNIX Specification, Issue 7
2017-05-12 11:41:19 +09:00
97 changed files with 2466 additions and 994 deletions

View File

@ -4,7 +4,7 @@ FreeBSD_task:
SSL: libressl
matrix:
freebsd_instance:
image_family: freebsd-12-2
image_family: freebsd-13-2
prepare_script:
- pkg install -y $SSL git autoconf automake libtool pkgconf opus jpeg-turbo fdk-aac pixman libX11 libXfixes libXrandr nasm fusefs-libs check imlib2
- git submodule update --init --recursive

View File

@ -63,19 +63,19 @@ jobs:
- CC: gcc
feature_set: max
arch: i386
os: ubuntu-18.04
os: ubuntu-20.04
name_extra: for 32-bit arch (legacy OS)
- CC: g++
feature_set: max
arch: i386
os: ubuntu-18.04
os: ubuntu-20.04
name_extra: for 32-bit arch (legacy OS)
- CC: clang
feature_set: max
arch: i386
os: ubuntu-18.04
os: ubuntu-20.04
name_extra: for 32-bit arch (legacy OS)
name: ${{ matrix.feature_set }} features with ${{ matrix.CC }} ${{ matrix.name_extra }}
@ -83,20 +83,20 @@ jobs:
env:
CC: ${{ matrix.CC }}
# HACK (2020-11-16): github actions dosen't support YAML anchors/aliases to
# HACK (2020-11-16): github actions doesn'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
# the job config. These environment variables are then referenced as regular
# environment variables via the naming convention in the "define env" step to
# define the stardard environment variable used in the rest of the steps.
# define the standard 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
--disable-pixman"
CONF_FLAGS_amd64_max: "--enable-ipv6 --enable-jpeg --enable-fuse --enable-mp3lame
--enable-fdkaac --enable-opus --enable-rfxcodec --enable-painter
--enable-pixman --with-imlib2"
CONF_FLAGS_i386_max: "--enable-ipv6 --enable-jpeg --enable-fuse --enable-mp3lame
--enable-fdkaac --enable-opus --enable-rfxcodec --enable-painter
CONF_FLAGS_i386_max: "--enable-ipv6 --enable-jpeg --enable-mp3lame
--enable-opus --enable-rfxcodec --enable-painter
--disable-pixman --with-imlib2 --host=i686-linux"
PKG_CONFIG_PATH_i386: "/usr/lib/i386-linux-gnu/pkgconfig"
@ -112,7 +112,7 @@ jobs:
echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH_${{ matrix.arch }}" >> $GITHUB_ENV
echo "CFLAGS=$CFLAGS_${{ matrix.arch }}" >> $GITHUB_ENV
echo "LDFLAGS=$LDFLAGS_${{ matrix.arch }}" >> $GITHUB_ENV
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- run: sudo scripts/install_xrdp_build_dependencies_with_apt.sh ${{ matrix.feature_set }} ${{ matrix.arch }} --allow-downgrades --allow-remove-essential --allow-change-held-packages
- run: ./bootstrap
- run: ./configure $CONF_FLAGS
@ -127,23 +127,25 @@ jobs:
CC: gcc
# This is required to use a version of cppcheck other than that
# supplied with the operating system
CPPCHECK_VER: 2.7
CPPCHECK_VER: "2.13.0"
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
# Set steps.os.outputs.image to the specific OS (e.g. 'ubuntu20')
- name: Get operating system name and version.
id: os
run: echo "image=$ImageOS" >>$GITHUB_OUTPUT
shell: bash
- uses: actions/checkout@v4
- name: Cache cppcheck
uses: actions/cache@v2
uses: actions/cache@v4
env:
cache-name: cache-cppcheck
with:
path: ~/cppcheck.local
key: ${{ runner.os }}-${{ env.OS_VERSION }}-build-${{ env.cache-name }}-${{ env.CPPCHECK_VER }}
- run: sudo scripts/install_cppcheck_dependencies_with_apt.sh
key: ${{ steps.os.outputs.image }}-build-${{ env.cache-name }}-${{ env.CPPCHECK_VER }}
- run: sudo scripts/install_cppcheck_dependencies_with_apt.sh $CPPCHECK_VER
- run: ./bootstrap
- run: ./configure
- run: scripts/install_cppcheck.sh $CPPCHECK_REPO $CPPCHECK_VER
- run: scripts/run_cppcheck.sh -v $CPPCHECK_VER
@ -157,18 +159,19 @@ jobs:
ASTYLE_VER: 3.1
ASTYLE_REPO: https://svn.code.sf.net/p/astyle/code/tags
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
# Set steps.os.outputs.image to the specific OS (e.g. 'ubuntu20')
- name: Get operating system name and version.
id: os
run: echo "image=$ImageOS" >>$GITHUB_OUTPUT
shell: bash
- uses: actions/checkout@v4
- name: Cache astyle
uses: actions/cache@v2
uses: actions/cache@v4
env:
cache-name: cache-astyle
with:
path: ~/astyle.local
key: ${{ runner.os }}-${{ env.OS_VERSION }}-build-${{ env.cache-name }}-${{ env.ASTYLE_VER }}
key: ${{ steps.os.outputs.image }}-build-${{ env.cache-name }}-${{ env.ASTYLE_VER }}
- run: sudo scripts/install_astyle_dependencies_with_apt.sh
- run: scripts/install_astyle.sh $ASTYLE_REPO $ASTYLE_VER
- name: Format code with astyle

2
.gitignore vendored
View File

@ -52,3 +52,5 @@ tools/devel/tcp_proxy/tcp_proxy
xrdp/xrdp
xrdp/xrdp.ini
xrdp_configure_options.h
xrdpapi/xrdp-xrdpapi-simple
.vscode/*

253
NEWS.md
View File

@ -1,3 +1,254 @@
# Release notes for xrdp v0.9.25.1 (2024/03/13)
This release fixes a bug that occurred in v0.9.25 where scrolling did not work in the Xvnc backend.
Thanks to @bsmojver reporting the issue and testing!
## General announcements
_This is the last v0.9.x version which is released regularly. v0.9.x will be maintained for a while but less actively. New releases will happen only when severe security vulnerabilities or critical bugs are found._
We have created a fund on [Open Collective](https://opencollective.com/xrdp-project). Support us if you like xrdp! Direct donations to each developer via GitHub Sponsors are also welcomed.
## Bug fixes
* Mouse wheel scrolling in Xvnc session no longer works in 0.9.25 (#2993 #2994)
-----------------------
# Release notes for xrdp v0.9.25 (2024/03/11)
* Running xrdp and xrdp-sesman on separate hosts is still supported by this release, but is now deprecated. This is not secure. A future v1.0 release will replace the TCP socket used between these processes with a Unix Domain Socket, and then cross-host running will not be possible.
## General announcements
_This is the last v0.9.x version which is released regularly. v0.9.x will be maintained for a while but less actively. New releases will happen only when severe security vulnerabilities or critical bugs are found._
We have created a fund on [Open Collective](https://opencollective.com/xrdp-project). Support us if you like xrdp! Direct donations to each developer via GitHub Sponsors are also welcomed.
## Security fixes
No new security fixes in this release.
## Bug fixes
* Backport touchpad inertial scrolling (#2364 #2424 #2948).
## New features
* If the client announces support for the Image RemoteFX codec it is logged (back-port of #2946)
## Internal changes
* FreeBSD CI version bumped to 13.2 from 12.4 (#2897)
* Some test timeouts have been increased for slow CI machines (#2903)
## Known issues
* On-the-fly resolution change requires the Microsoft Store version of Remote Desktop client but sometimes crashes on connect (#1869)
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
-----------------------
# Release notes for xrdp v0.9.24 (2023/12/30)
* Running xrdp and xrdp-sesman on separate hosts is still supported by this release, but is now deprecated. This is not secure. A future v1.0 release will replace the TCP socket used between these processes with a Unix Domain Socket, and then cross-host running will not be possible.
## General announcements
We have created a fund on [Open Collective](https://opencollective.com/xrdp-project). Support us if you like xrdp!
Direct donations to each developer via GitHub Sponsors are also welcomed.
## Security fixes
No new security fixes in this release.
## Bug fixes
* Checking group membership should now work better on systems using directory services (#2806 #2817)
* Pasting more than 32K characters of text to the clipboard now succeeds (#1839 #2824)
* An incompatibility with FreeRDP 2.11.2 in the drive redirector has been fixed (#2834 #2839)
## New features
* Side buttons on some mice are now supported by NeutrinoRDP (#2860). Thanks to new contributor @naruhito for this patch.
## Internal changes
* cppcheck version used for CI bumped to 2.13.0 (#2830/#2887). Note that this greatly increases cppcheck scan times.
## Known issues
* On-the-fly resolution change requires the Microsoft Store version of Remote Desktop client but sometimes crashes on connect (#1869)
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
-----------------------
# Release notes for xrdp v0.9.23.1 (2023/09/27)
This is a security fix release for CVE-2023-42822. This update is recommended for all xrdp users.
## Security fixes
* [CVE-2023-42822: Unchecked access to font glyph info](https://www.cve.org/CVERecord?id=CVE-2023-42822)
## Bug fixes
No bug fixes other than the above security fix in this release.
## New features
No new features in this release.
## Internal changes
* cppcheck install script no longer installs z3 for cppcheck >= 2.8 (#2782)
-----------------------
# Release notes for xrdp v0.9.23 (2023/08/31)
## General announcements
* Running xrdp and xrdp-sesman on separate hosts is still supported by this release, but is now deprecated. This is not secure. A future v1.0 release will replace the TCP socket used between these processes with a Unix Domain Socket, and then cross-host running will not be possible.
## Security fixes
* [CVE-2023-40184: Improper handling of session establishment errors allows bypassing OS-level session restrictions](https://www.cve.org/CVERecord?id=CVE-2023-40184) (Reported by [@gafusss](https://github.com/gafusss))
## Bug fixes
* Environment variables set by PAM modules are no longer restricted to around 250 characters (#2712)
* X11 clipboard clients now no longer hang when requesting a clipboard format which isn't available (#2767)
## New features
No new features in this release.
## Internal changes
* Introduce release tarball generation script (#2703)
* cppcheck version used for CI bumped to 2.11 (#2738)
## Known issues
* On-the-fly resolution change requires the Microsoft Store version of Remote Desktop client but sometimes crashes on connect (#1869)
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
-----------------------
# Release notes for xrdp v0.9.22.1 (2023/05/23)
This release is just a re-packing of source code tarball since v0.9.22 tarball includes invalid source code (#2687).
See [v0.9.22 release note](https://github.com/neutrinolabs/xrdp/releases/tag/v0.9.22) for functional changes since v0.9.22.1 is what v0.9.22 should be.
Thanks to [@morgancoxuk](https://github.com/morgancoxuk) and [@bsmojver](https://github.com/bsmojver) for reporting and testing!
## References
* https://github.com/neutrinolabs/xrdp/issues/2687
* https://bugzilla.redhat.com/show_bug.cgi?id=2208248
* https://bugzilla.redhat.com/show_bug.cgi?id=2208015
-----------------------
# Release notes for xrdp v0.9.22 (2023/05/07)
## General announcements
* Running xrdp and xrdp-sesman on separate hosts is still supported by this release, but is now deprecated. This is not secure. A future v1.0 release will replace the TCP socket used between these processes with a Unix Domain Socket, and then cross-host running will not be possible.
## Security fixes
No security fixes in this release.
## New features
* Empty passwords are no longer automatically passed through to sesman for authentication (#2509)
* Don't try to listen on the scard socket if it isn't there (#2507)
* The directory where PAM configuration files are installed can now be set with --with-pamconfdir (#2552 #2557 #2566)
* Sesman can now be configured to ignore alternate shells passed from the client (#2634)
* Allow longer UserWindowManager strings (#2653)
## Bug fixes
* Minor documentation fixes (#2508 #2582)
* Memory management fixes to list module (#2548 #2577)
* Fix some noise when MP3/AAC are in use and some logging improvements (#2519 #2537 #2554)
* Fix potential NULL dereferences in chansrv (#2574)
* An erroneous free in the smartcard handling code has been removed (#2611)
* An unnecessary 'check.h' include was removed which prevented compilation on Arch systems (#2650)
## Internal changes
* cppcheck version used for CI bumped to 2.10 (#2521)
* g_malloc, g_free, g_memset, and g_memcpy are now macros. These should not be used in new code (#2612)
* FreeBSD CI now runs on FreeBSD 12.4 (#2622)
## Changes for packagers or developers
* openSUSE [Bug 1208121](https://bugzilla.opensuse.org/show_bug.cgi?id=1208121) has been addressed in upstream
## Known issues
* On-the-fly resolution change requires the Microsoft Store version of Remote Desktop client but sometimes crashes on connect (#1869)
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
-----------------------
# Release notes for xrdp v0.9.21.1 (2022/12/13)
This release only includes following fix for packagers. Packagers try to build xrdp on distributions _other than_ Arch Linux, Debian, SUSE, Red Hat(ish), FreeBSD and macOS may be required to use this release.
## Changes for packagers or developers
* Add missing xrdp-sesman.system to distributed tarball (#2466 #2468)
-----------------------
# Release notes for xrdp v0.9.21 (2022/12/10)
## General announcements
* Running xrdp and xrdp-sesman on separate hosts is still supported by this release, but is now deprecated. This is not secure. A future v1.0 release will replace the TCP socket used between these processes with a Unix Domain Socket, and then cross-host running will not be possible.
## Security fixes
This update is recommended for all xrdp users and provides following important security fixes:
* [CVE-2022-23468](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23468)
* [CVE-2022-23477](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23477)
* [CVE-2022-23478](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23478)
* [CVE-2022-23479](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23479)
* [CVE-2022-23480](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23480)
* [CVE-2022-23481](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23481)
* [CVE-2022-23483](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23483)
* [CVE-2022-23482](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23482)
* [CVE-2022-23484](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23484)
* [CVE-2022-23493](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23493)
These security issues are reported by [Team BT5 (BoB 11th)](https://github.com/Team-BT5). We appreciate their great help with making and reviewing patches.
## New features
* openSuSE Tumbleweed move to /usr/lib/pam.d is now supported in the installation scripts (#2413)
* VNC backend session now supports extra mouse buttons 6, 7 and 8 (#2426)
## Bug fixes
* Passwords are no longer left on the heap in sesman (#1599 #2439)
* Set permissions on pcsc socket dir to owner only (#2454 #2460)
## Internal changes
* CI updates to cope with github upgrades (#2395)
## Changes for packagers or developers
Nothing this time.
## Known issues
* On-the-fly resolution change requires the Microsoft Store version of Remote Desktop client but sometimes crashes on connect (#1869)
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
-----------------------
# Release notes for xrdp v0.9.20 (2022/09/15)
## General announcements
* Running xrdp and xrdp-sesman on separate hosts is still supported by this release, but is now deprecated. This is not secure. A future v1.0 release will replace the TCP socket used between these processes with a Unix Domain Socket, and then cross-host running will not be possible.
## New features
* Mitigation for too fast vertical scroll has been implemented. This is actually not a new feature of xrdp so see also [xorgxrdp v0.9.19 release note](https://github.com/neutrinolabs/xorgxrdp/releases/tag/v0.9.19).
## Bug fixes
* Windows RDS compatibility has been improved, so some old clients (e.g. Wyse Sx0) can now be used again with xrdp in non-TLS mode (#2273)
* Update xrdpapi simple example to work with new logging (#2276)
* sesman: fix spacing in log (#2282)
* Fix MSTSC crashes when resolution is changed by maximizing on a different monitor (#2292 #1928)
* Mark count with unused attribute (#2353)
* Simple maintenance improvements (#2354)
## Internal changes
* FreeBSD version for CI bumped to 12-3 (#2226)
* cppcheck version used for CI bumped to 2.9 (#2351)
## Changes for packagers or developers
Nothing this time.
## Known issues
* On-the-fly resolution change requires the Microsoft Store version of Remote Desktop client but sometimes crashes on connect (#1869)
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
-----------------------
# Release notes for xrdp v0.9.19 (2022/03/17)
## General announcements
@ -247,7 +498,7 @@ These changes are likely to impact operating system package builders and those b
* Minor manpage fixes #1611
## Other changes
* CI error fixes
* CI error fixes
* Introduce cppcheck
## Known issues

View File

@ -5,11 +5,11 @@
Please DO NOT report any security issues to public GitHub issue.
If you find a security vulnerability please kindly inform us about the problem immediately
If you find a security vulnerability please kindly inform us about the problem immediately
so that we can fix the security problem to protect a lot of users around the world as soon
as possible.
Our email address for security report is below. This is a private mailing list and not open
Our email address for security report is below. This is a private mailing list and not open
for public viewing.
* [xrdp-core@googlegroups.com](mailto:xrdp-core@googlegroups.com)

View File

@ -20,6 +20,7 @@
#define ARCH_H
#include <stdlib.h>
#include <string.h>
#if defined(HAVE_STDINT_H)
#include <stdint.h>

View File

@ -32,7 +32,7 @@
* Values for invalid and padding characters, used in the charmap
* for converting base64 to binary
*
* Thse value are specially chosen to make it easy to detect padding or
* These values are specially chosen to make it easy to detect padding or
* invalid characters by or-ing together the values looked up in
* a base64 quantum */
#define E_INVALID 0x40

View File

@ -22,23 +22,53 @@
#include <config_ac.h>
#endif
#include <stdlib.h>
#include "arch.h"
#include "os_calls.h"
#include "string_calls.h"
#include "list.h"
#include "log.h"
enum
{
DEFAULT_LIST_SIZE = 10,
DEFAULT_GROW_BY_SIZE = 10
};
/*****************************************************************************/
struct list *
list_create_sized(unsigned int size)
{
struct list *self;
if (size < DEFAULT_LIST_SIZE)
{
size = DEFAULT_LIST_SIZE;
}
self = (struct list *)calloc(sizeof(struct list), 1);
if (self != NULL)
{
self->items = (tbus *)malloc(sizeof(tbus) * size);
if (self->items == NULL)
{
free(self);
self = NULL;
}
else
{
self->grow_by = DEFAULT_GROW_BY_SIZE;
self->alloc_size = size;
}
}
return self;
}
/*****************************************************************************/
struct list *
list_create(void)
{
struct list *self;
self = (struct list *)g_malloc(sizeof(struct list), 1);
self->grow_by = 10;
self->alloc_size = 10;
self->items = (tbus *)g_malloc(sizeof(tbus) * 10, 1);
return self;
return list_create_sized(DEFAULT_LIST_SIZE);
}
/*****************************************************************************/
@ -56,34 +86,46 @@ list_delete(struct list *self)
{
for (i = 0; i < self->count; i++)
{
g_free((void *)self->items[i]);
free((void *)self->items[i]);
self->items[i] = 0;
}
}
g_free(self->items);
g_free(self);
free(self->items);
free(self);
}
/*****************************************************************************/
void
static int
grow_list(struct list *self)
{
int rv = 1;
unsigned int new_alloc_size = self->alloc_size + self->grow_by;
tbus *p = (tbus *)realloc(self->items, sizeof(tbus) * new_alloc_size);
if (p == NULL)
{
rv = 0;
}
else
{
self->alloc_size = new_alloc_size;
self->items = p;
}
return rv;
}
/*****************************************************************************/
int
list_add_item(struct list *self, tbus item)
{
tbus *p;
int i;
if (self->count >= self->alloc_size)
if (self->count == self->alloc_size && !grow_list(self))
{
i = self->alloc_size;
self->alloc_size += self->grow_by;
p = (tbus *)g_malloc(sizeof(tbus) * self->alloc_size, 1);
g_memcpy(p, self->items, sizeof(tbus) * i);
g_free(self->items);
self->items = p;
return 0;
}
self->items[self->count] = item;
self->count++;
return 1;
}
/*****************************************************************************/
@ -108,16 +150,15 @@ list_clear(struct list *self)
{
for (i = 0; i < self->count; i++)
{
g_free((void *)self->items[i]);
free((void *)self->items[i]);
self->items[i] = 0;
}
}
g_free(self->items);
self->count = 0;
self->grow_by = 10;
self->alloc_size = 10;
self->items = (tbus *)g_malloc(sizeof(tbus) * 10, 1);
self->grow_by = DEFAULT_GROW_BY_SIZE;
self->alloc_size = DEFAULT_LIST_SIZE;
self->items = (tbus *)realloc(self->items, sizeof(tbus) * self->alloc_size);
}
/*****************************************************************************/
@ -147,7 +188,7 @@ list_remove_item(struct list *self, int index)
{
if (self->auto_free)
{
g_free((void *)self->items[index]);
free((void *)self->items[index]);
self->items[index] = 0;
}
@ -161,57 +202,83 @@ list_remove_item(struct list *self, int index)
}
/*****************************************************************************/
void
int
list_insert_item(struct list *self, int index, tbus item)
{
tbus *p;
int i;
if (index == self->count)
if (index > self->count)
{
list_add_item(self, item);
return;
index = self->count;
}
else if (index < 0)
{
index = 0;
}
if (index >= 0 && index < self->count)
if (self->count == self->alloc_size && !grow_list(self))
{
self->count++;
if (self->count > self->alloc_size)
{
i = self->alloc_size;
self->alloc_size += self->grow_by;
p = (tbus *)g_malloc(sizeof(tbus) * self->alloc_size, 1);
g_memcpy(p, self->items, sizeof(tbus) * i);
g_free(self->items);
self->items = p;
}
for (i = (self->count - 2); i >= index; i--)
{
self->items[i + 1] = self->items[i];
}
self->items[index] = item;
return 0;
}
// Move all the items above this location up one
for (i = self->count ; i > index ; --i)
{
self->items[i] = self->items[i - 1];
}
self->count++;
self->items[index] = item;
return 1;
}
/*****************************************************************************/
/* append one list to another using strdup for each item in the list */
/* begins copy at start_index, a zero based index on the source list */
void
int
list_append_list_strdup(struct list *self, struct list *dest, int start_index)
{
int index;
tbus item;
char *dup;
int rv = 1;
int entry_dest_count = dest->count;
for (index = start_index; index < self->count; index++)
{
item = list_get_item(self, index);
dup = g_strdup((char *)item);
list_add_item(dest, (tbus)dup);
const char *item = (const char *)list_get_item(self, index);
char *dup;
if (item == NULL)
{
// This shouldn't really happen, but if it does we'll
// copy the item anyway.
dup = NULL;
}
else
{
dup = g_strdup(item);
if (dup == NULL)
{
rv = 0;
break;
}
}
if (!list_add_item(dest, (tbus)dup))
{
rv = 0;
break;
}
}
if (rv == 0)
{
// Remove the additional items we added
while (dest->count > entry_dest_count)
{
list_remove_item(dest, dest->count - 1);
}
}
return rv;
}
/*****************************************************************************/

View File

@ -35,9 +35,27 @@ struct list
struct list *
list_create(void);
/**
* Creates a list with at least the specified number of items
* reserved
* @param size Number of items to reserve
* @return list, or NULL if no memory
*/
struct list *
list_create_sized(unsigned int size);
void
list_delete(struct list *self);
void
/**
* Adds an item to a list
* @param self The list
* @param item The item to add
* @result 0 if a memory allocation failure occurred. In this
* case the item is not added
*
* Memory allocation failures will not occur if the list is
* sized appropriately when created.
*/
int
list_add_item(struct list *self, tintptr item);
tintptr
list_get_item(const struct list *self, int index);
@ -47,9 +65,32 @@ int
list_index_of(struct list *self, tintptr item);
void
list_remove_item(struct list *self, int index);
void
/**
* Inserts an item into a list
* @param self The list
* @param index The location to insert the item before
* @param item The item to add
* @result 0 if a memory allocation failure occurred. In this
* case the item is not added
*
* Memory allocation failures will not occur if the list is
* sized appropriately when created.
*/
int
list_insert_item(struct list *self, int index, tintptr item);
void
/**
* Adds strings to a list from another list
* @param self The source list
* @param dest Destination list
* @param start_index Index to start on the source list (zero based)
*
* @result 0 if a memory allocation failure occurred. In this
* case the destination list is unaltered.
*
* Strings from the source list are copied with strdup()
* The dest list should have auto_free set, or memory leaks will occur
*/
int
list_append_list_strdup(struct list *self, struct list *dest, int start_index);
void
list_dump_items(struct list *self);

View File

@ -81,7 +81,7 @@ enum logReturns
* @brief Logging macro for messages that are for an XRDP developer to
* understand and debug XRDP code.
*
* Note: all log levels are relavant to help a developer understand XRDP at
* Note: all log levels are relevant to help a developer understand XRDP at
* different levels of granularity.
*
* Note: the logging function calls are removed when USE_DEVEL_LOGGING is
@ -107,7 +107,7 @@ enum logReturns
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args)
/**
* @brief Logging macro for messages that are for a systeam administrator to
* @brief Logging macro for messages that are for a system administrator to
* configure and run XRDP on their machine.
*
* Note: the logging function calls contain additional code location info when
@ -297,8 +297,8 @@ internal_log_is_enabled_for_level(const enum logLevels log_level,
const enum logLevels override_log_level);
/**
* @param function_name, the function name (typicaly the __func__ macro)
* @param file_name, the file name (typicaly the __FILE__ macro)
* @param function_name, the function name (typically the __func__ macro)
* @param file_name, the file name (typically the __FILE__ macro)
* @param[out] log_level_return, the log level to use instead of the destination log level
* @return true if the logger location overrides the destination log levels
*/
@ -402,9 +402,9 @@ log_hexdump(const enum logLevels log_level,
*
* Please prefer to use the LOG and LOG_DEVEL macros instead of this function directly.
*
* @param function_name, the function name (typicaly the __func__ macro)
* @param file_name, the file name (typicaly the __FILE__ macro)
* @param line_number, the line number in the file (typicaly the __LINE__ macro)
* @param function_name, the function name (typically the __func__ macro)
* @param file_name, the file name (typically the __FILE__ macro)
* @param line_number, the line number in the file (typically the __LINE__ macro)
* @param lvl, the loglevel
* @param msg, the logtext.
* @param ...

View File

@ -119,5 +119,10 @@ enum IRP_MN
IRP_MN_NOTIFY_CHANGE_DIRECTORY = 0x00000002
};
/*
* General Capability Set (2.2.2.7.1)
*/
/* extendedPDU fields */
#define RDPDR_USER_LOGGEDON_PDU 0x00000004
#endif /* MS_RDPEFS_H */

View File

@ -24,7 +24,7 @@
/* LicensingMessage (MS-RDPELE 2.2.2) */
/* TODO: to be renamed */
#define LICENCE_TAG_DEMAND 0x01 /* LICNSE_REQUEST */
#define LICENCE_TAG_DEMAND 0x01 /* LICENSE_REQUEST */
#define LICENCE_TAG_AUTHREQ 0x02 /* PLATFORM_CHALLENGE */
#define LICENCE_TAG_ISSUE 0x03 /* NEW_LICENSE */
#define LICENCE_TAG_REISSUE 0x04 /* UPGRADE_LICENSE */

View File

@ -171,38 +171,6 @@ g_deinit(void)
g_rm_temp_dir();
}
/*****************************************************************************/
/* allocate memory, returns a pointer to it, size bytes are allocated,
if zero is non zero, each byte will be set to zero */
void *
g_malloc(int size, int zero)
{
char *rv;
rv = (char *)malloc(size);
if (zero)
{
if (rv != 0)
{
memset(rv, 0, size);
}
}
return rv;
}
/*****************************************************************************/
/* free the memory pointed to by ptr, ptr can be zero */
void
g_free(void *ptr)
{
if (ptr != 0)
{
free(ptr);
}
}
/*****************************************************************************/
/* output text to stdout, try to use g_write / g_writeln instead to avoid
linux / windows EOL problems */
@ -312,20 +280,6 @@ g_hexdump(const char *p, int len)
}
}
/*****************************************************************************/
void
g_memset(void *ptr, int val, int size)
{
memset(ptr, val, size);
}
/*****************************************************************************/
void
g_memcpy(void *d_ptr, const void *s_ptr, int size)
{
memcpy(d_ptr, s_ptr, size);
}
/*****************************************************************************/
int
g_getchar(void)
@ -427,6 +381,7 @@ g_tcp_socket(void)
{
switch (errno)
{
case EPROTONOSUPPORT: /* if IPv6 is supported, but don't have an IPv6 address */
case EAFNOSUPPORT: /* if IPv6 not supported, retry IPv4 */
LOG(LOG_LEVEL_INFO, "IPv6 not supported, falling back to IPv4");
rv = (int)socket(AF_INET, SOCK_STREAM, 0);
@ -2695,7 +2650,7 @@ g_execvp(const char *p1, char *args[])
g_strnjoin(args_str, ARGS_STR_LEN, " ", (const char **) args, args_len);
LOG(LOG_LEVEL_DEBUG,
"Calling exec (excutable: %s, arguments: %s)",
"Calling exec (executable: %s, arguments: %s)",
p1, args_str);
g_rm_temp_dir();
@ -2703,7 +2658,7 @@ g_execvp(const char *p1, char *args[])
/* should not get here */
LOG(LOG_LEVEL_ERROR,
"Error calling exec (excutable: %s, arguments: %s) "
"Error calling exec (executable: %s, arguments: %s) "
"returned errno: %d, description: %s",
p1, args_str, g_get_errno(), g_get_strerror());
@ -2727,7 +2682,7 @@ g_execlp3(const char *a1, const char *a2, const char *a3)
g_strnjoin(args_str, ARGS_STR_LEN, " ", args, 2);
LOG(LOG_LEVEL_DEBUG,
"Calling exec (excutable: %s, arguments: %s)",
"Calling exec (executable: %s, arguments: %s)",
a1, args_str);
g_rm_temp_dir();
@ -2735,7 +2690,7 @@ g_execlp3(const char *a1, const char *a2, const char *a3)
/* should not get here */
LOG(LOG_LEVEL_ERROR,
"Error calling exec (excutable: %s, arguments: %s) "
"Error calling exec (executable: %s, arguments: %s) "
"returned errno: %d, description: %s",
a1, args_str, g_get_errno(), g_get_strerror());
@ -3187,42 +3142,95 @@ g_getgroup_info(const char *groupname, int *gid)
}
/*****************************************************************************/
/* returns error */
/* if zero is returned, then ok is set */
/* does not work in win32 */
#ifdef HAVE_GETGROUPLIST
int
g_check_user_in_group(const char *username, int gid, int *ok)
{
int rv = 1;
struct passwd *pwd_1 = getpwnam(username);
if (pwd_1 != NULL)
{
// Get number of groups for user
//
// Some implementations of getgrouplist() (i.e. muslc) don't
// allow ngroups to be <1 on entry
int ngroups = 1;
GETGROUPS_T dummy;
getgrouplist(username, pwd_1->pw_gid, &dummy, &ngroups);
if (ngroups > 0) // Should always be true
{
GETGROUPS_T *grouplist;
grouplist = (GETGROUPS_T *)malloc(ngroups * sizeof(grouplist[0]));
if (grouplist != NULL)
{
// Now get the actual groups. The number of groups returned
// by this call is not necessarily the same as the number
// returned by the first call.
int allocgroups = ngroups;
getgrouplist(username, pwd_1->pw_gid, grouplist, &ngroups);
ngroups = MIN(ngroups, allocgroups);
rv = 0;
*ok = 0;
int i;
for (i = 0 ; i < ngroups; ++i)
{
if (grouplist[i] == (GETGROUPS_T)gid)
{
*ok = 1;
break;
}
}
free(grouplist);
}
}
}
return rv;
}
/*****************************************************************************/
#else // HAVE_GETGROUPLIST
int
g_check_user_in_group(const char *username, int gid, int *ok)
{
#if defined(_WIN32)
return 1;
#else
struct group *groups;
int i;
groups = getgrgid(gid);
if (groups == 0)
struct passwd *pwd_1 = getpwnam(username);
struct group *groups = getgrgid(gid);
if (pwd_1 == NULL || groups == NULL)
{
return 1;
}
*ok = 0;
i = 0;
while (0 != groups->gr_mem[i])
if (pwd_1->pw_gid == gid)
{
if (0 == g_strcmp(groups->gr_mem[i], username))
{
*ok = 1;
break;
}
*ok = 1;
}
else
{
*ok = 0;
i = 0;
i++;
while (0 != groups->gr_mem[i])
{
if (0 == g_strcmp(groups->gr_mem[i], username))
{
*ok = 1;
break;
}
i++;
}
}
return 0;
#endif
}
#endif // HAVE_GETGROUPLIST
/*****************************************************************************/
/* returns the time since the Epoch (00:00:00 UTC, January 1, 1970),

View File

@ -50,8 +50,6 @@ int g_rm_temp_dir(void);
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_printf(const char *format, ...) printflike(1, 2);
void g_sprintf(char *dest, const char *format, ...) \
printflike(2, 3);
@ -60,8 +58,6 @@ 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);
int g_getchar(void);
int g_tcp_set_no_delay(int sck);
int g_tcp_set_keepalive(int sck);
@ -177,6 +173,15 @@ 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);
/**
* Checks whether a user is in the specified group
* @param username Name of user
* @param gid GID of group
* @param[out] ok Whether user is in group
* @return Non-zero if a system error occurred. In this instance OK is not set
*
* Primary group of username is also checked
*/
int g_check_user_in_group(const char *username, int gid, int *ok);
int g_time1(void);
int g_time2(void);
@ -198,4 +203,10 @@ int g_tcp6_bind_address(int sck, const char *port, const char *address);
#define g_new0(struct_type, n_structs) \
(struct_type *) calloc((n_structs), sizeof(struct_type))
/* remove these when no longer used */
#define g_malloc(_size, _zero) (_zero ? calloc(1, _size) : malloc(_size))
#define g_free free
#define g_memset memset
#define g_memcpy memcpy
#endif

View File

@ -1652,7 +1652,7 @@ quick_sort_rects (
*
* Side Effects:
* The passed-in ``region'' may be modified.
* overlap set to TRUE if any retangles overlapped,
* overlap set to TRUE if any rectangles overlapped,
* else FALSE;
*
* Strategy:

View File

@ -337,7 +337,7 @@ ssl_sha1_clear(void *sha1_info)
#else
if (sha1_info != NULL)
{
EVP_DigestInit_ex(sha1_info, g_md_sha1, NULL);
EVP_DigestInit_ex((EVP_MD_CTX *)sha1_info, g_md_sha1, NULL);
}
#endif
}
@ -417,7 +417,7 @@ ssl_md5_clear(void *md5_info)
#else
if (md5_info != NULL)
{
EVP_DigestInit_ex(md5_info, g_md_md5, NULL);
EVP_DigestInit_ex((EVP_MD_CTX *)md5_info, g_md_md5, NULL);
}
#endif
}

View File

@ -27,7 +27,7 @@
* Map a character to a string value
*
* This structure is used by g_format_info_string() to specify the
* string which chould be output for %'ch', where ch is a character
* string which could be output for %'ch', where ch is a character
*/
struct info_string_tag
{
@ -117,7 +117,7 @@ g_text2bool(const char *s);
* @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).
* @return A pointer to the beginning of the joined string (ie. returns dest).
*/
char *
g_strnjoin(char *dest, int dest_len, const char *joiner, const char *src[], int src_len);

View File

@ -297,8 +297,8 @@ trans_check_wait_objs(struct trans *self)
tbus in_sck = (tbus) 0;
struct trans *in_trans = (struct trans *) NULL;
int read_bytes = 0;
int to_read = 0;
int read_so_far = 0;
unsigned int to_read = 0;
unsigned int read_so_far = 0;
int rv = 0;
enum xrdp_source cur_source;
@ -369,13 +369,24 @@ trans_check_wait_objs(struct trans *self)
}
else if (self->trans_can_recv(self, self->sck, 0))
{
/* CVE-2022-23479 - check a malicious caller hasn't managed
* to set the header_size to an unreasonable value */
if (self->header_size > (unsigned int)self->in_s->size)
{
LOG(LOG_LEVEL_ERROR,
"trans_check_wait_objs: Reading %u bytes beyond buffer",
self->header_size - (unsigned int)self->in_s->size);
self->status = TRANS_STATUS_DOWN;
return 1;
}
cur_source = XRDP_SOURCE_NONE;
if (self->si != 0)
{
cur_source = self->si->cur_source;
self->si->cur_source = self->my_source;
}
read_so_far = (int) (self->in_s->end - self->in_s->data);
read_so_far = self->in_s->end - self->in_s->data;
to_read = self->header_size - read_so_far;
if (to_read > 0)
@ -415,7 +426,7 @@ trans_check_wait_objs(struct trans *self)
}
}
read_so_far = (int) (self->in_s->end - self->in_s->data);
read_so_far = self->in_s->end - self->in_s->data;
if (read_so_far == self->header_size)
{

View File

@ -69,7 +69,7 @@ enum xrdp_source
* While input is being read from a 'struct trans' and processed, the
* cur_source member is set to the my_source member from the transport.
* During this processing, trans_write_copy() may be called to send output
* on another struct trans. If this happens, and the ouput needs to be
* on another struct trans. If this happens, and the output needs to be
* buffered, trans_write_copy() can add the number of bytes generated by
* the input trans to the source field for the cur_source. This allows us to
* see how much output has been buffered for each input source.
@ -98,7 +98,7 @@ struct trans
ttrans_data_in trans_data_in;
ttrans_conn_in trans_conn_in;
void *callback_data;
int header_size;
unsigned int header_size;
struct stream *in_s;
struct stream *out_s;
char *listen_filename;

View File

@ -29,7 +29,7 @@
*
* xrdp constants
*
* Constants defined in publically available Microsoft documents are not
* Constants defined in publicly available Microsoft documents are not
* stored here, but are stored in the include files ms-*.h, where the name
* of the file is the name of the document defining the constant.
*
@ -232,6 +232,12 @@
#define BUTTON_STATE_UP 0
#define BUTTON_STATE_DOWN 1
/* touch gestures */
#define TOUCH_TWO_FINGERS_DOWN 0
#define TOUCH_TWO_FINGERS_UP 1
#define TOUCH_TWO_FINGERS_LEFT 2
#define TOUCH_TWO_FINGERS_RIGHT 3
/* messages */
#define WM_PAINT 3
#define WM_KEYDOWN 15
@ -255,6 +261,10 @@
#define WM_BUTTON8DOWN 116
#define WM_BUTTON9UP 117
#define WM_BUTTON9DOWN 118
#define WM_TOUCH_VSCROLL 140
#define WM_TOUCH_HSCROLL 141
#define WM_INVALIDATE 200
#define CB_ITEMCHANGE 300

View File

@ -1,7 +1,8 @@
# Process this file with autoconf to produce a configure script
AC_PREREQ(2.65)
AC_INIT([xrdp], [0.9.19], [xrdp-devel@googlegroups.com])
AC_INIT([xrdp], [0.9.25.1], [xrdp-devel@googlegroups.com])
AC_DEFINE([VERSION_YEAR], 2024, [Copyright year])
AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in)
AM_INIT_AUTOMAKE([1.7.2 foreign])
AC_CONFIG_MACRO_DIR([m4])
@ -189,6 +190,12 @@ AM_COND_IF([DEVEL_DEBUG],
[AX_APPEND_COMPILE_FLAGS([-g -O0])],
[AX_APPEND_COMPILE_FLAGS([-O2])])
# Define HAVE_XXXXX macros for some system functions
AC_CHECK_FUNCS([getgrouplist])
# The type used by getgrouplist() is the same type used by getgroups()
AC_TYPE_GETGROUPS
# Don't fail without working nasm if rfxcodec is not enabled
if test "x$enable_rfxcodec" != xyes; then
with_simd=no
@ -464,6 +471,12 @@ if test "x$enable_strict_locations" != "xyes"; then
localstatedir="/var";
fi
AC_ARG_WITH([pamconfdir],
[AS_HELP_STRING([--with-pamconfdir=DIR],
[Use directory for pam.d config (default: /etc/pam.d)])],
[], [with_pamconfdir="$sysconfdir/pam.d"])
AC_SUBST([pamconfdir], [$with_pamconfdir])
PKG_INSTALLDIR
AC_CHECK_HEADERS([sys/prctl.h])
@ -542,6 +555,7 @@ echo " exec_prefix $exec_prefix"
echo " libdir $libdir"
echo " bindir $bindir"
echo " sysconfdir $sysconfdir"
echo " pamconfdir $pamconfdir"
echo ""
echo " unit tests performable $perform_unit_tests"
echo ""

View File

@ -283,6 +283,10 @@ To keep compatibility, the following aliases are also available.
If set to \fB1\fR, \fBtrue\fR or \fByes\fR, require group membership even
if the group specified in \fBTerminalServerUsers\fR doesn't exist.
.TP
\fBAllowAlternateShell\fR=\fI[true|false]\fR
If set to \fB0\fR, \fBfalse\fR or \fBno\fR, prevent usage of alternate shells by users.
.SH "X11 SERVER"
Following parameters can be used in the \fB[X11rdp]\fR, \fB[Xvnc]\fR and
\fB[Xorg]\fR sections.
@ -324,8 +328,8 @@ drive. To fix this, consult the docs for your chosen desktop.
\fBFileUmask\fR=\fImode\fR
Additional umask to apply to files in the \fBFuseMountName\fR directory.
The default value of 077 prevents other users on the system from reading
files on your redirected drives. This may not be approprate for all
environents, and so you can change this value to allow other users to
files on your redirected drives. This may not be appropriate for all
environments, and so you can change this value to allow other users to
access your remote files if required.
.TP

View File

@ -72,14 +72,18 @@ msg(char *msg1, ...)
static int
show_last_error(void)
{
LPVOID lpMsgBuf;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&lpMsgBuf, 0, NULL);
msg("GetLastError - %s", lpMsgBuf);
LocalFree(lpMsgBuf);
LPVOID lpMsgBuf = NULL;
DWORD len;
len = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&lpMsgBuf, 0, NULL);
if (len > 0)
{
msg("GetLastError - %s", lpMsgBuf);
LocalFree(lpMsgBuf);
}
return 0;
}

View File

@ -1,7 +1,6 @@
#!/bin/sh
command -v setxkbmap
if test $? -ne 0
if ! command -v setxkbmap >/dev/null
then
echo "error, setxkbmap not found"
exit 1

View File

@ -90,11 +90,11 @@ case "$1" in
value=$?
[ $value -gt 0 ] && exitval=$value
fi
# Make pidfile readables for all users (for status to work)
# Make pidfile readable for all users (for status to work)
[ -e $PIDDIR/xrdp-sesman.pid ] && chmod 0644 $PIDDIR/xrdp-sesman.pid
[ -e $PIDDIR/$NAME.pid ] && chmod 0644 $PIDDIR/$NAME.pid
# Note: Unfortunately, xrdp currently takes too long to create
# the pidffile unless properly patched
# the pidfile unless properly patched
log_end_msg $exitval
;;
stop)

View File

@ -1,11 +1,12 @@
PAM_FILES = \
xrdp-sesman.arch \
xrdp-sesman.debian \
xrdp-sesman.redhat \
xrdp-sesman.suse \
xrdp-sesman.freebsd \
xrdp-sesman.macos \
xrdp-sesman.unix \
xrdp-sesman.arch
xrdp-sesman.redhat \
xrdp-sesman.suse \
xrdp-sesman.system \
xrdp-sesman.unix
EXTRA_DIST = $(PAM_FILES) mkpamrules
@ -25,7 +26,7 @@ endif
endif
endif
pamddir = $(sysconfdir)/pam.d
pamddir = $(pamconfdir)
pamd_DATA = \
$(PAMFILE)

View File

@ -8,7 +8,11 @@ outfile="$3"
service="xrdp-sesman"
pamdir="/etc/pam.d"
pamdir_suse="/usr/etc/pam.d"
pamdir_suse="/usr/lib/pam.d"
if [ ! -d $pamdir_suse ]; then
# Older SUSE distros uses /usr/etc/pam.d
pamdir_suse="/usr/etc/pam.d"
fi
# Modules needed by xrdp-sesman.unix, if we get to that
unix_modules_needed="pam_unix.so pam_env.so pam_nologin.so"
@ -22,8 +26,8 @@ find_pam_module_dir()
# Looks for the pam security module directory
set -- $pam_module_dir_searchpath
for d in "$@"; do
if [ -s $d/pam_unix.so ]; then
echo $d
if [ -s "$d/pam_unix.so" ]; then
echo "$d"
break
fi
done
@ -34,7 +38,7 @@ can_apply_unix_config()
result=0
module_dir="$1"
for m in $unix_modules_needed; do
if [ ! -s $module_dir/$m ]; then
if [ ! -s "$module_dir/$m" ]; then
echo " ** $m not found" >&2
result=1
fi

@ -1 +1 @@
Subproject commit d8f126abc48a1b949a0be27b334099161c06f0fc
Subproject commit c537401ac2fd5fa4671701f67367413feb51edff

View File

@ -67,6 +67,9 @@ struct xrdp_mcs
struct stream *client_mcs_data;
struct stream *server_mcs_data;
struct list *channel_list;
/* This boolean is set to indicate we're expecting channel join
* requests as part of the connect sequence */
int expecting_channel_join_requests;
};
/* fastpath */

View File

@ -591,6 +591,11 @@ xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len)
g_memcpy(self->client_info.h264_prop, s->p, i1);
self->client_info.h264_prop_len = i1;
}
else if (g_memcmp(codec_guid, XR_CODEC_GUID_IMAGE_REMOTEFX, 16) == 0)
{
LOG(LOG_LEVEL_INFO, "xrdp_caps_process_codecs: Image RemoteFX, codec id %d, properties len %d",
codec_id, codec_properties_length);
}
else
{
LOG(LOG_LEVEL_WARNING, "xrdp_caps_process_codecs: unknown codec id %d", codec_id);
@ -667,13 +672,27 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
int len;
char *p;
if (!s_check_rem_and_log(s, 10,
"Parsing [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU"
" - header"))
{
return 1;
}
in_uint8s(s, 4); /* rdp_shareid */
in_uint8s(s, 2); /* userid */
in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */
in_uint16_le(s, cap_len);
if (!s_check_rem_and_log(s, source_len + 2 + 2,
"Parsing [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU"
" - header2"))
{
return 1;
}
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), "

View File

@ -27,6 +27,11 @@
#include "ms-rdpbcgr.h"
#include "log.h"
/* Forward references */
static int
handle_non_tls_client_channel_join_requests(struct xrdp_mcs *self,
struct stream *s, int *appid);
/*****************************************************************************/
struct xrdp_mcs *
xrdp_mcs_create(struct xrdp_sec *owner, struct trans *trans,
@ -109,7 +114,7 @@ xrdp_mcs_send_cjcf(struct xrdp_mcs *self, int userid, int chanid)
out_uint16_be(s, chanid); /* channelId (OPTIONAL) */
s_mark_end(s);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sening [ITU-T T.125] ChannelJoinConfirm "
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [ITU-T T.125] ChannelJoinConfirm "
"result SUCCESS, initiator %d, requested %d, "
"channelId %d", userid, chanid, chanid);
if (xrdp_iso_send(self->iso_layer, s) != 0)
@ -123,6 +128,34 @@ xrdp_mcs_send_cjcf(struct xrdp_mcs *self, int userid, int chanid)
return 0;
}
/*****************************************************************************/
/* Reads the header of a DomainMCSPDU and gets the appid
*
* @return 0 for success */
static int
get_domain_mcs_pdu_header(struct xrdp_mcs *self, struct stream *s, int *appid)
{
int opcode;
if (xrdp_iso_recv(self->iso_layer, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_mcs_recv: xrdp_iso_recv failed");
return 1;
}
if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T T.125] DomainMCSPDU"))
{
return 1;
}
/* The DomainMCSPDU choice index is a 6-bit int with the 2 least
significant bits of the byte as padding */
in_uint8(s, opcode);
*appid = opcode >> 2; /* 2-bit padding */
LOG_DEVEL(LOG_LEVEL_TRACE,
"Received [ITU-T T.125] DomainMCSPDU choice index %d", *appid);
return 0;
}
/*****************************************************************************/
/*
* Processes an [ITU-T T.125] DomainMCSPDU message.
@ -136,70 +169,32 @@ int
xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
{
int appid;
int opcode;
int len;
int userid;
int chanid;
while (1)
if (get_domain_mcs_pdu_header(self, s, &appid) != 0)
{
if (xrdp_iso_recv(self->iso_layer, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_mcs_recv: xrdp_iso_recv failed");
return 1;
}
if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T T.125] DomainMCSPDU"))
{
return 1;
}
/* The DomainMCSPDU choice index is a 6-bit int with the 2 least
significant bits of the byte as padding */
in_uint8(s, opcode);
appid = opcode >> 2; /* 2-bit padding */
LOG_DEVEL(LOG_LEVEL_TRACE,
"Received [ITU-T T.125] DomainMCSPDU choice index %d", appid);
if (appid == MCS_DPUM) /* Disconnect Provider Ultimatum */
{
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] DisconnectProviderUltimatum");
LOG(LOG_LEVEL_DEBUG, "Recieved disconnection request");
return 1;
}
/* MCS_CJRQ: Channel Join ReQuest
this is channels getting added from the client */
if (appid == MCS_CJRQ)
{
if (!s_check_rem_and_log(s, 4, "Parsing [ITU-T T.125] ChannelJoinRequest"))
{
return 1;
}
in_uint16_be(s, userid);
in_uint16_be(s, chanid);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] ChannelJoinRequest "
"initiator 0x%4.4x, channelId 0x%4.4x", userid, chanid);
if (xrdp_mcs_send_cjcf(self, userid, chanid) != 0)
{
LOG(LOG_LEVEL_WARNING, "[ITU-T T.125] Channel join sequence: failed");
}
s = libxrdp_force_read(self->iso_layer->trans);
if (s == 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_mcs_recv: libxrdp_force_read failed");
return 1;
}
continue;
}
break;
return 1;
}
if (self->expecting_channel_join_requests)
{
if (handle_non_tls_client_channel_join_requests(self, s, &appid) != 0)
{
return 1;
}
LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] completed");
self->expecting_channel_join_requests = 0;
}
if (appid == MCS_DPUM) /* Disconnect Provider Ultimatum */
{
LOG_DEVEL(LOG_LEVEL_TRACE,
"Received [ITU-T T.125] DisconnectProviderUltimatum");
LOG(LOG_LEVEL_DEBUG, "Received disconnection request");
return 1;
}
if (appid != MCS_SDRQ)
{
LOG(LOG_LEVEL_ERROR, "Received [ITU-T T.125] DomainMCSPDU "
@ -714,10 +709,11 @@ xrdp_mcs_send_aucf(struct xrdp_mcs *self)
*
* returns error */
static int
xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
xrdp_mcs_recv_cjrq(struct xrdp_mcs *self, int *channel_id)
{
int opcode;
struct stream *s;
int initiator;
s = libxrdp_force_read(self->iso_layer->trans);
if (s == 0)
@ -753,8 +749,8 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
return 1;
}
in_uint8s(s, 4); /* initiator (2 bytes)
channelId (2 bytes) */
in_uint16_be(s, initiator);
in_uint16_be(s, *channel_id);
/*
* [MS-RDPBCGR] 2.2.1.8 says that the mcsAUrq field is 5 bytes (which have
@ -772,8 +768,9 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
}
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [ITU-T T.125] ChannelJoinRequest "
"initiator (ignored), channelId (ignored), "
"initiator %d, channelId %d, "
"nonStandard (%s)",
initiator, *channel_id,
(opcode & 2) ? "present" : "not present");
if (!s_check_end_and_log(s, "MCS protocol error [ITU-T T.125] ChannelJoinRequest"))
@ -974,7 +971,7 @@ xrdp_mcs_out_gcc_data(struct xrdp_sec *self)
SEC_TAG_SRV_INFO,
self->mcs_layer->iso_layer->rdpNegData ? 12 : 8);
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding struct [MS-RDPBCGR] TS_UD_SC_CORE "
"<Requiered fields> version 0x%8.8x", 0x00080004);
"<Required fields> version 0x%8.8x", 0x00080004);
if (self->mcs_layer->iso_layer->rdpNegData)
{
/* RequestedProtocol */
@ -1174,6 +1171,127 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self)
return 0;
}
/*****************************************************************************/
/* Handle all client channel join requests for a non-TLS connection
*
* @param self MCS structure
* @param s Input stream
* @param[in,out] appid Type of the MCS PDU whose header has just been read.
* @return 0 for success
*
* For non-TLS connections, the channel join MCS PDUs are followed by
* another MCS PDU. This not the case for TLS connections.
*
* Called when an MCS PDU header has been read, but the PDU has not
* been processed.
*
* If the PDU is a channel join request, it is processed, and the next
* PDU header is read. When we've exhausted all the channel join requests,
* the type of the next PDU is passed back to the caller for the caller
* to process.
*
* In order to cater for older clients which may not conform exactly to
* the specification, we simply take all the join requests which come in,
* and respond to them.
*
* See :-
* - https://github.com/neutrinolabs/xrdp/issues/2166
* - [MS-RDPBCGR] 3.2.5.3.8 and 3.2.5.3.8
*/
static int
handle_non_tls_client_channel_join_requests(struct xrdp_mcs *self,
struct stream *s, int *appid)
{
int rv = 0;
while (*appid == MCS_CJRQ)
{
int userid;
int chanid;
if (!s_check_rem_and_log(s, 4, "Parsing [ITU-T T.125] "
"ChannelJoinRequest"))
{
rv = 1;
break;
}
in_uint16_be(s, userid);
in_uint16_be(s, chanid);
LOG_DEVEL(LOG_LEVEL_TRACE,
"Received [ITU-T T.125] ChannelJoinRequest "
"initiator 0x%4.4x, channelId 0x%4.4x", userid, chanid);
if (xrdp_mcs_send_cjcf(self, userid, chanid) != 0)
{
LOG(LOG_LEVEL_WARNING,
"[ITU-T T.125] Channel join sequence: failed");
}
/* Get the next PDU header */
s = libxrdp_force_read(self->iso_layer->trans);
if (s == 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_mcs_recv: libxrdp_force_read failed");
rv = 1;
break;
}
if (get_domain_mcs_pdu_header(self, s, appid) != 0)
{
rv = 1;
break;
}
}
return rv;
}
/*****************************************************************************/
/* Handle all client channel join requests for a TLS connection
*
* @param self MCS structure
* @return 0 for success
*
* When were are about to negotiate a TLS connection, it is important that
* we agree on the exact number of client join request / client join confirm
* PDUs, so that we get the TLS 'client hello' message exactly when
* expected.
*
* See [MS-RDPBCGR] 3.2.5.3.8 and 3.2.5.3.8
*/
static int
handle_tls_client_channel_join_requests(struct xrdp_mcs *self)
{
int index;
int rv = 0;
static const char *tag = "[MCS Connection Sequence (TLS)]";
/*
* Expect a channel join request PDU for each of the static virtual
* channels, plus the user channel (self->chanid) and the I/O channel
* (MCS_GLOBAL_CHANNEL) */
for (index = 0; index < self->channel_list->count + 2; index++)
{
int channel_id;
LOG(LOG_LEVEL_DEBUG, "%s receive channel join request", tag);
if (xrdp_mcs_recv_cjrq(self, &channel_id) != 0)
{
LOG(LOG_LEVEL_ERROR, "%s receive channel join request failed", tag);
rv = 1;
break;
}
LOG(LOG_LEVEL_DEBUG, "%s send channel join confirm", tag);
if (xrdp_mcs_send_cjcf(self, self->userid, channel_id) != 0)
{
LOG(LOG_LEVEL_ERROR, "%s send channel join confirm failed", tag);
rv = 1;
break;
}
}
return rv;
}
/*****************************************************************************/
/* Process and send the MCS messages for the RDP Connection Sequence
* [MS-RDPBCGR] 1.3.1.1
@ -1183,8 +1301,6 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self)
int
xrdp_mcs_incoming(struct xrdp_mcs *self)
{
int index;
LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] receive connection request");
if (xrdp_mcs_recv_connect_initial(self) != 0)
{
@ -1199,17 +1315,17 @@ xrdp_mcs_incoming(struct xrdp_mcs *self)
return 1;
}
LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] construct connection reponse");
LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] construct connection response");
if (xrdp_mcs_out_gcc_data(self->sec_layer) != 0)
{
LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] construct connection reponse failed");
LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] construct connection response failed");
return 1;
}
LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] send connection reponse");
LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] send connection response");
if (xrdp_mcs_send_connect_response(self) != 0)
{
LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] send connection reponse failed");
LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] send connection response failed");
return 1;
}
@ -1234,25 +1350,25 @@ xrdp_mcs_incoming(struct xrdp_mcs *self)
return 1;
}
for (index = 0; index < self->channel_list->count + 2; index++)
if (self->iso_layer->selectedProtocol > PROTOCOL_RDP)
{
LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] receive channel join request");
if (xrdp_mcs_recv_cjrq(self) != 0)
/* TLS connection. Client and server have to agree on MCS channel
* join messages, and these have to be processed before the TLS
* client hello */
if (handle_tls_client_channel_join_requests(self) != 0)
{
LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] receive channel join request failed");
return 1;
}
LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] send channel join confirm");
if (xrdp_mcs_send_cjcf(self, self->userid,
self->userid + MCS_USERCHANNEL_BASE + index) != 0)
{
LOG(LOG_LEVEL_ERROR, "[MCS Connection Sequence] send channel join confirm failed");
return 1;
}
LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence (TLS)] completed");
}
else
{
/* Non-TLS connection - channel joins handled in MCS PDU
* processing loop */
self->expecting_channel_join_requests = 1;
}
LOG(LOG_LEVEL_DEBUG, "[MCS Connection Sequence] completed");
return 0;
}

View File

@ -953,6 +953,17 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
}
in_uint16_le(s, len_password);
/*
* Ignore autologin requests if the password is empty. System managers
* who really want to allow empty passwords can do this with a
* special session type */
if (len_password == 0 && self->rdp_layer->client_info.rdp_autologin)
{
LOG(LOG_LEVEL_DEBUG,
"Client supplied password is empty, disabling autologin");
self->rdp_layer->client_info.rdp_autologin = 0;
}
if (len_password >= INFO_CLIENT_MAX_CB_LEN)
{
LOG(LOG_LEVEL_ERROR,
@ -1014,7 +1025,7 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
&& len_password == 0
&& (sep = g_strchr(self->rdp_layer->client_info.username, '\x1f')) != NULL)
{
LOG(LOG_LEVEL_DEBUG, "Client supplied a Logon token. Overwritting password with logon token.");
LOG(LOG_LEVEL_DEBUG, "Client supplied a Logon token. Overwriting password with logon token.");
g_strncpy(self->rdp_layer->client_info.password, sep + 1,
sizeof(self->rdp_layer->client_info.password) - 1);
self->rdp_layer->client_info.username[sep - self->rdp_layer->client_info.username] = '\0';
@ -1038,7 +1049,7 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
if (self->rdp_layer->client_info.domain_user_separator[0] != '\0'
&& self->rdp_layer->client_info.domain[0] != '\0')
{
LOG(LOG_LEVEL_DEBUG, "Client supplied domain with user name. Overwritting user name with user name parsed from domain.");
LOG(LOG_LEVEL_DEBUG, "Client supplied domain with user name. Overwriting user name with user name parsed from domain.");
int size = sizeof(self->rdp_layer->client_info.username);
g_strncat(self->rdp_layer->client_info.username, self->rdp_layer->client_info.domain_user_separator, size - 1 - g_strlen(self->rdp_layer->client_info.domain_user_separator));
g_strncat(self->rdp_layer->client_info.username, self->rdp_layer->client_info.domain, size - 1 - g_strlen(self->rdp_layer->client_info.domain));
@ -1081,7 +1092,7 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
{
return 1;
}
/* TS_EXTENDED_INFO_PACKET requiered fields */
/* TS_EXTENDED_INFO_PACKET required fields */
in_uint8s(s, 2); /* clientAddressFamily */
in_uint16_le(s, len_ip);
if (unicode_utf16_in(s, len_ip - 2, tmpdata, sizeof(tmpdata) - 1) != 0)
@ -1100,7 +1111,7 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s)
return 1;
}
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_EXTENDED_INFO_PACKET "
"<Requiered Fields> clientAddressFamily (ignored), "
"<Required Fields> clientAddressFamily (ignored), "
"cbClientAddress (ignored), clientAddress (ignored), "
"cbClientDir (ignored), clientDir (ignored)");
@ -1946,6 +1957,18 @@ xrdp_sec_send_fastpath(struct xrdp_sec *self, struct stream *s)
static int
xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s)
{
#define CS_CORE_MIN_LENGTH \
(\
4 + /* Version */ \
2 + 2 + /* desktopWidth + desktopHeight */ \
2 + 2 + /* colorDepth + SASSequence */ \
4 + /* keyboardLayout */ \
4 + 32 + /* clientBuild + clientName */ \
4 + 4 + 4 + /* keyboardType + keyboardSubType + keyboardFunctionKey */ \
64 + /* imeFileName */ \
0)
int version;
int colorDepth;
int postBeta2ColorDepth;
int highColorDepth;
@ -1953,8 +1976,15 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s)
int earlyCapabilityFlags;
char clientName[INFO_CLIENT_NAME_BYTES / 2] = { '\0' };
/* TS_UD_CS_CORE requiered fields */
in_uint8s(s, 4); /* version */
UNUSED_VAR(version);
/* TS_UD_CS_CORE required fields */
if (!s_check_rem_and_log(s, CS_CORE_MIN_LENGTH,
"Parsing [MS-RDPBCGR] TS_UD_CS_CORE"))
{
return 1;
}
in_uint32_le(s, version);
in_uint16_le(s, self->rdp_layer->client_info.width);
in_uint16_le(s, self->rdp_layer->client_info.height);
in_uint16_le(s, colorDepth);
@ -1977,12 +2007,13 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s)
in_uint8s(s, 4); /* keyboardFunctionKey */
in_uint8s(s, 64); /* imeFileName */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE "
"<Requiered fields> version (ignored), desktopWidth %d, "
"desktopHeight %d, colorDepth %s, SASSequence (ingored), "
"<Required fields> version %08x, desktopWidth %d, "
"desktopHeight %d, colorDepth %s, SASSequence (ignored), "
"keyboardLayout (ignored), clientBuild (ignored), "
"clientName %s, keyboardType (ignored), "
"keyboardSubType (ignored), keyboardFunctionKey (ignored), "
"imeFileName (ignroed)",
"imeFileName (ignored)",
version,
self->rdp_layer->client_info.width,
self->rdp_layer->client_info.height,
(colorDepth == 0xca00 ? "RNS_UD_COLOR_4BPP" :
@ -1990,6 +2021,10 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s)
clientName);
/* TS_UD_CS_CORE optional fields */
if (!s_check_rem(s, 2))
{
return 0;
}
in_uint16_le(s, postBeta2ColorDepth);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE "
"<Optional Field> postBeta2ColorDepth %s",
@ -2134,6 +2169,7 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s)
"<Optional Field> desktopOrientation (ignored)");
return 0;
#undef CS_CORE_MIN_LENGTH
}
/*****************************************************************************/
@ -2269,6 +2305,7 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
int index;
struct xrdp_client_info *client_info;
struct mcs_channel_item *channel_item;
int next_mcs_channel_id;
client_info = &(self->rdp_layer->client_info);
/* this is an option set in xrdp.ini */
@ -2290,6 +2327,13 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
"max 31, received %d", num_channels);
return 1;
}
/* GOTCHA: When adding a channel the MCS channel ID is set to
* MCS_GLOBAL_CHANNEL + (index + 1). This is assumed by
* xrdp_channel_process(), when mapping an incoming PDU into an
* entry in this array */
next_mcs_channel_id = MCS_GLOBAL_CHANNEL + 1;
for (index = 0; index < num_channels; index++)
{
channel_item = g_new0(struct mcs_channel_item, 1);
@ -2306,7 +2350,7 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] "
"TS_UD_CS_NET.CHANNEL_DEF %d, name %s, options 0x%8.8x",
index, channel_item->name, channel_item->flags);
channel_item->chanid = MCS_GLOBAL_CHANNEL + (index + 1);
channel_item->chanid = next_mcs_channel_id++;
list_add_item(self->mcs_layer->channel_list,
(intptr_t) channel_item);
LOG(LOG_LEVEL_DEBUG,
@ -2324,6 +2368,13 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec *self, struct stream *s)
g_free(channel_item);
}
}
/* Set the user channel as well */
self->mcs_layer->chanid = next_mcs_channel_id++;
self->mcs_layer->userid = self->mcs_layer->chanid - MCS_USERCHANNEL_BASE;
LOG_DEVEL(LOG_LEVEL_DEBUG, "MCS user is %d, channel id is %d",
self->mcs_layer->userid, self->mcs_layer->chanid);
return 0;
}
@ -2675,12 +2726,12 @@ xrdp_sec_in_mcs_data(struct xrdp_sec *self)
in_uint32_le(s, client_info->keyboard_type); /* [MS-RDPBCGR] TS_UD_CS_CORE keyboardType */
in_uint32_le(s, client_info->keyboard_subtype); /* [MS-RDPBCGR] TS_UD_CS_CORE keyboardSubType */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_UD_CS_CORE "
"<Requiered fields> version (ignored), desktopWidth (ignored), "
"desktopHeight (ignored), colorDepth (ignored), SASSequence (ingored), "
"<Required fields> version (ignored), desktopWidth (ignored), "
"desktopHeight (ignored), colorDepth (ignored), SASSequence (ignored), "
"keyboardLayout 0x%8.8x, clientBuild %d, "
"clientName %s, keyboardType 0x%8.8x, "
"keyboardSubType 0x%8.8x, keyboardFunctionKey (ignored), "
"imeFileName (ignroed)",
"imeFileName (ignored)",
client_info->keylayout,
client_info->build,
client_info->hostname,

View File

@ -244,7 +244,7 @@ lxrdp_connect(struct mod *mod)
break;
case INSUFFICIENTPRIVILEGESERROR:
g_snprintf(buf, 128, "Insufficent privileges on target server");
g_snprintf(buf, 128, "Insufficient privileges on target server");
break;
default:
@ -425,6 +425,38 @@ lxrdp_event(struct mod *mod, int msg, long param1, long param2,
case 110:
break;
case 115: /* extended mouse button8 up */
LOG_DEVEL(LOG_LEVEL_DEBUG, "extended mouse button8 up %ld %ld", param1, param2);
x = param1;
y = param2;
flags = PTR_XFLAGS_BUTTON1;
mod->inst->input->ExtendedMouseEvent(mod->inst->input, flags, x, y);
break;
case 116: /* extended mouse button8 down */
LOG_DEVEL(LOG_LEVEL_DEBUG, "extended mouse button8 down %ld %ld", param1, param2);
x = param1;
y = param2;
flags = PTR_XFLAGS_BUTTON1 | PTR_XFLAGS_DOWN;
mod->inst->input->ExtendedMouseEvent(mod->inst->input, flags, x, y);
break;
case 117: /* extended mouse button9 up */
LOG_DEVEL(LOG_LEVEL_DEBUG, "extended mouse button9 up %ld %ld", param1, param2);
x = param1;
y = param2;
flags = PTR_XFLAGS_BUTTON2;
mod->inst->input->ExtendedMouseEvent(mod->inst->input, flags, x, y);
break;
case 118: /* extended mouse button9 down */
LOG_DEVEL(LOG_LEVEL_DEBUG, "extended mouse button9 down %ld %ld", param1, param2);
x = param1;
y = param2;
flags = PTR_XFLAGS_BUTTON2 | PTR_XFLAGS_DOWN;
mod->inst->input->ExtendedMouseEvent(mod->inst->input, flags, x, y);
break;
case 200:
LOG_DEVEL(LOG_LEVEL_DEBUG, "Invalidate request sent from client");
x = (param1 >> 16) & 0xffff;

View File

@ -34,12 +34,12 @@ call_make()
status=1
log=`mktemp /tmp/astyle-log.XXXXXXXXXX`
if [ -n "$log" ]; then
make "$@" >$log 2>&1
make "$@" >"$log" 2>&1
status=$?
if [ $status -ne 0 ]; then
cat $log >&2
cat "$log" >&2
fi
rm $log
rm "$log"
fi
# Re-enable `set -e` if active before
@ -80,27 +80,27 @@ fi
# Put everything in this directory
FILESDIR=$INSTALL_ROOT/$ASTYLE_VER
svn checkout ${REPO_URL}/${ASTYLE_VER}/AStyle $workdir
svn checkout ${REPO_URL}/${ASTYLE_VER}/AStyle "$workdir"
cd $workdir
cd "$workdir"
make_args="DESTDIR=$FILESDIR"
echo "Creating Makefiles..."
cmake .
echo "Making astyle..."
call_make $make_args
echo "Installing astyle..."
mkdir -p $FILESDIR
mkdir -p "$FILESDIR"
call_make install $make_args
# make install DESTDIR=~/astyle.local/3.1
)
status=$?
if [ $status -eq 0 ]; then
rm -rf $workdir
rm -rf "$workdir"
else
"** Script failed. Work dir is $workdir" >&2
fi

View File

@ -2,6 +2,6 @@
set -eufx
PACKAGES="subversion cmake"
apt-get update
apt-get -yq --no-install-suggests --no-install-recommends install $PACKAGES

View File

@ -34,12 +34,12 @@ call_make()
status=1
log=`mktemp /tmp/cppcheck-log.XXXXXXXXXX`
if [ -n "$log" ]; then
make "$@" >$log 2>&1
make "$@" >"$log" 2>&1
status=$?
if [ $status -ne 0 ]; then
cat $log >&2
cat "$log" >&2
fi
rm $log
rm "$log"
fi
# Re-enable `set -e` if active before
@ -119,16 +119,24 @@ fi
# See https://stackoverflow.com/questions/
# 791959/download-a-specific-tag-with-git
git clone -b $CPPCHECK_VER --depth 1 $REPO_URL $workdir
git clone -b "$CPPCHECK_VER" --depth 1 "$REPO_URL" "$workdir"
cd $workdir
cd "$workdir"
make_args="MATCHCOMPILER=yes FILESDIR=$FILESDIR PREFIX=$FILESDIR"
case "$CPPCHECK_VER" in
1.*)
# CFGDIR is needed for cppcheck before 1.86
make_args="FILESDIR=$FILESDIR PREFIX=$FILESDIR CFGDIR=$FILESDIR"
make_args="$make_args CFGDIR=$FILESDIR"
;;
*) make_args="FILESDIR=$FILESDIR PREFIX=$FILESDIR USE_Z3=yes"
2.8 | 2.9 | 2.1*)
# Cppcheck 2.8 removed the dependency on z3
# Cppcheck 2.8 added optional support for utilizing Boost
make_args="$make_args CPPFLAGS=-DHAVE_BOOST"
;;
2.*)
make_args="$make_args 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.
@ -138,20 +146,29 @@ fi
if [ ! -f /usr/include/z3_version.h ]; then
create_z3_version_h
fi
;;
esac
# Use all available CPUs
if [ -f /proc/cpuinfo ]; then
cpus=`grep ^processor /proc/cpuinfo | wc -l`
if [ -n "$cpus" ]; then
make_args="$make_args -j $cpus"
fi
fi
echo "Making cppcheck..."
# CFGDIR is needed for cppcheck before 1.86
call_make $make_args
echo "Installing cppcheck..."
mkdir -p $FILESDIR
mkdir -p "$FILESDIR"
call_make install $make_args
)
status=$?
if [ $status -eq 0 ]; then
rm -rf $workdir
rm -rf "$workdir"
else
"** Script failed. Work dir is $workdir" >&2
fi

View File

@ -1,7 +1,35 @@
#!/bin/sh
set -eufx
PACKAGES="libz3-dev z3"
# these are the packages necessary to run ./configure so config_ac.h is generated
PACKAGES="libpam0g-dev libxfixes-dev libxrandr-dev nasm"
usage()
{
echo "** Usage: $0 <version-tag>"
echo " e.g. $0 1.90"
} >&2
if [ $# -ne 1 ]; then
usage
exit 1
fi
CPPCHECK_VER="$1"
apt-get update
case "$CPPCHECK_VER" in
1.*)
# no dependencies
;;
2.8 | 2.9 | 2.1*)
# Cppcheck 2.8 removed the dependency on z3
# Cppcheck 2.8 added optional support for utilizing Boost
PACKAGES="$PACKAGES libboost-container-dev"
;;
2.*)
PACKAGES="$PACKAGES libz3-dev z3"
;;
esac
apt-get -yq --no-install-suggests --no-install-recommends install $PACKAGES

View File

@ -70,7 +70,7 @@ in
libx11-dev \
libxrandr-dev \
libxfixes-dev"
case "$FEATURE_SET"
in
min)
@ -94,6 +94,11 @@ in
esac
;;
i386)
# This list is not as complete as the amd64 list. It currently
# supports 32-bit CI building only, rather than being a generic
# build support tool.
# - Ubuntu 18.04 -> 20.04
# Removed fdk-aac-dev:i386 and libfuse-dev:i386
PACKAGES="$PACKAGES \
g++-multilib \
gcc-multilib \
@ -102,7 +107,6 @@ in
libjpeg-dev:i386 \
libimlib2-dev:i386 \
libmp3lame-dev:i386 \
libfdk-aac-dev:i386 \
libopus-dev:i386 \
libpam0g-dev:i386 \
libssl-dev:i386 \
@ -110,9 +114,8 @@ in
libxext-dev:i386 \
libxfixes-dev:i386 \
libxrandr-dev:i386 \
libxrender-dev:i386 \
libfuse-dev:i386"
libxrender-dev:i386"
dpkg --add-architecture i386
dpkg --print-architecture
dpkg --print-foreign-architectures

65
scripts/make_release_tarball.sh Executable file
View File

@ -0,0 +1,65 @@
#!/bin/sh
#
# Script to generate release tarball
#
# This script will generate release tarball. If the repository HEAD is not
# tagged, the script will be aborted. Target GitHub repository, branch can be
# customized by GH_* envirnment variable.
#
# Usage:
# Just execute the script. This script is intended to be run by maintainers
# so build dependencies are not taken care of.
#
# $ ./scripts/make_release_tarball.sh
# (snip)
# ===============================================
# Release tarball has been generated at:
# /tmp/tmp.q8kme7m7/xrdp-0.9.22.1.tar.gz
#
# CHECKSUM:
# 3ca220d6941ca6dab6a8bd1b50fcffffcf386ce01fbbc350099fdc83684380e0 xrdp-0.9.22.1.tar.gz
#
# Copy tarball to /home/meta/github/metalefty/xrdp? [y/N] y
#
# If the script is executed with BATCH=yes, the full path of the release
# tarball will be printed on the last line. Clip it using tail command.
#
# $ BATCH=yes ./scripts/make_release_tarball.sh | tail -n1
set -e
: ${GH_ACCOUNT:=neutrinolabs}
: ${GH_PROJECT:=xrdp}
: ${GH_BRANCH:=v0.9}
: ${BATCH:=""}
WRKDIR=$(mktemp -d)
# clean checkout
git clone --recursive --branch "${GH_BRANCH}" "https://github.com/${GH_ACCOUNT}/${GH_PROJECT}.git" "${WRKDIR}"
cd "${WRKDIR}"
git diff --no-ext-diff --quiet --exit-code # check if there's no changes on working tree
RELVER=$(git describe --tags --exact-match HEAD) # check if working HEAD refs a release tag
./bootstrap
./configure
make distcheck
echo
echo ===============================================
echo Release tarball has been generated at:
echo ${WRKDIR}/xrdp-${RELVER#v}.tar.gz
echo
echo CHECKSUM:
sha256sum xrdp-${RELVER#v}.tar.gz
echo
if [ -z "${BATCH}" ]; then
echo -n "Copy tarball to ${OLDPWD}? [y/N] "
read -t 60 copy_tarball
case "${copy_tarball}" in
[Yy]*) cp -i xrdp-${RELVER#v}.tar.gz "${OLDPWD}"; exit ;;
esac
else
echo ${WRKDIR}/xrdp-${RELVER#v}.tar.gz
fi

View File

@ -69,6 +69,6 @@ ASTYLE_FLAGS="--options=astyle_config.as ./\*.c ./\*.h"
# Display the astyle version and command for debugging
"$ASTYLE" --version && {
echo Command: $ASTYLE $ASTYLE_FLAGS
echo "Command: $ASTYLE $ASTYLE_FLAGS"
"$ASTYLE" $ASTYLE_FLAGS
}

View File

@ -43,16 +43,24 @@ fi
# Supply default flags passed to cppcheck if necessary
if [ -z "$CPPCHECK_FLAGS" ]; then
CPPCHECK_FLAGS="--quiet --force --std=c11 --std=c++11 --inline-suppr \
--enable=warning --error-exitcode=1"
--enable=warning --error-exitcode=1 \
--suppress=shiftTooManyBits:libxrdp/xrdp_mppc_enc.c \
-I . -I common"
fi
CPPCHECK_FLAGS="$CPPCHECK_FLAGS -D__cppcheck__"
# Any options/directories specified?
if [ $# -eq 0 ]; then
set -- -j 2 .
if [ -f /proc/cpuinfo ]; then
cpus=$(grep '^processor' /proc/cpuinfo | wc -l)
else
cpus=2
fi
set -- -j $cpus .
fi
# Display the cppcheck version and command for debugging
"$CPPCHECK" --version && {
echo Command: $CPPCHECK $CPPCHECK_FLAGS "$@"
echo "Command: $CPPCHECK $CPPCHECK_FLAGS" "$@"
"$CPPCHECK" $CPPCHECK_FLAGS "$@"
}

View File

@ -8,6 +8,7 @@ AM_CPPFLAGS = \
-DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
-DXRDP_PAMCONF_PATH=\"${pamconfdir}\" \
-I$(top_srcdir)/common \
-I$(top_srcdir)/sesman/libscp

View File

@ -35,7 +35,6 @@
int
access_login_allowed(const char *user)
{
int gid;
int ok;
if ((0 == g_strncmp(user, "root", 5)) && (0 == g_cfg->sec.allow_root))
@ -51,18 +50,6 @@ access_login_allowed(const char *user)
return 1;
}
if (0 != g_getuser_info(user, &gid, 0, 0, 0, 0))
{
LOG(LOG_LEVEL_ERROR, "Cannot read user info! - login denied");
return 0;
}
if (g_cfg->sec.ts_users == gid)
{
LOG(LOG_LEVEL_DEBUG, "ts_users is user's primary group");
return 1;
}
if (0 != g_check_user_in_group(user, g_cfg->sec.ts_users, &ok))
{
LOG(LOG_LEVEL_ERROR, "Cannot read group info! - login denied");
@ -83,7 +70,6 @@ access_login_allowed(const char *user)
int
access_login_mng_allowed(const char *user)
{
int gid;
int ok;
if ((0 == g_strncmp(user, "root", 5)) && (0 == g_cfg->sec.allow_root))
@ -100,18 +86,6 @@ access_login_mng_allowed(const char *user)
return 1;
}
if (0 != g_getuser_info(user, &gid, 0, 0, 0, 0))
{
LOG(LOG_LEVEL_ERROR, "[MNG] Cannot read user info! - login denied");
return 0;
}
if (g_cfg->sec.ts_admins == gid)
{
LOG(LOG_LEVEL_INFO, "[MNG] ts_users is user's primary group");
return 1;
}
if (0 != g_check_user_in_group(user, g_cfg->sec.ts_admins, &ok))
{
LOG(LOG_LEVEL_ERROR, "[MNG] Cannot read group info! - login denied");

View File

@ -88,6 +88,27 @@ static struct xr_wave_format_ex **g_client_formats = NULL;
static int g_current_format = 0; /* index in g_client_formats */
/*****************************************************************************/
/*
* This can be called from sound.c because it includes audin.h.
*/
const char *
audin_wave_format_tag_to_str(int tag)
{
return
(tag == WAVE_FORMAT_PCM) ? "WAVE_FORMAT_PCM" :
(tag == WAVE_FORMAT_ADPCM) ? "WAVE_FORMAT_ADPCM" :
(tag == WAVE_FORMAT_ALAW) ? "WAVE_FORMAT_ALAW" :
(tag == WAVE_FORMAT_MULAW) ? "WAVE_FORMAT_MULAW" :
(tag == WAVE_FORMAT_MULAW) ? "WAVE_FORMAT_MULAW" :
(tag == WAVE_FORMAT_MPEGLAYER3) ? "WAVE_FORMAT_MPEGLAYER3" :
(tag == WAVE_FORMAT_OPUS) ? "WAVE_FORMAT_OPUS" :
(tag == WAVE_FORMAT_AAC) ? "WAVE_FORMAT_AAC" :
"UNKNOWN";
}
/*****************************************************************************/
static int
cleanup_client_formats(void)
@ -181,15 +202,16 @@ audin_send_open(int chan_id)
int error;
int bytes;
struct stream *s;
struct xr_wave_format_ex *wf;
struct xr_wave_format_ex *wf = g_client_formats[g_current_format];
LOG_DEVEL(LOG_LEVEL_INFO, "audin_send_open:");
make_stream(s);
init_stream(s, 8192);
/* wf->cbSize was checked when the format was received */
init_stream(s, wf->cbSize + 64);
out_uint8(s, MSG_SNDIN_OPEN);
out_uint32_le(s, 2048); /* FramesPerPacket */
out_uint32_le(s, g_current_format); /* initialFormat */
wf = g_client_formats[g_current_format];
out_uint16_le(s, wf->wFormatTag);
out_uint16_le(s, wf->nChannels);
out_uint32_le(s, wf->nSamplesPerSec);
@ -260,9 +282,17 @@ audin_process_formats(int chan_id, struct stream *s)
in_uint16_le(s, wf->nBlockAlign);
in_uint16_le(s, wf->wBitsPerSample);
in_uint16_le(s, wf->cbSize);
LOG_DEVEL(LOG_LEVEL_INFO, "audin_process_formats: recved format wFormatTag 0x%4.4x "
"nChannels %d nSamplesPerSec %d",
wf->wFormatTag, wf->nChannels, wf->nSamplesPerSec);
LOG(LOG_LEVEL_INFO, "audin_process_formats:");
LOG(LOG_LEVEL_INFO, " wFormatNo %d", index);
LOG(LOG_LEVEL_INFO, " wFormatTag %s", audin_wave_format_tag_to_str(wf->wFormatTag));
LOG(LOG_LEVEL_INFO, " nChannels %d", wf->nChannels);
LOG(LOG_LEVEL_INFO, " nSamplesPerSec %d", wf->nSamplesPerSec);
LOG(LOG_LEVEL_INFO, " nAvgBytesPerSec %d", wf->nAvgBytesPerSec);
LOG(LOG_LEVEL_INFO, " nBlockAlign %d", wf->nBlockAlign);
LOG(LOG_LEVEL_INFO, " wBitsPerSample %d", wf->wBitsPerSample);
LOG(LOG_LEVEL_INFO, " cbSize %d", wf->cbSize);
if (wf->cbSize > 0)
{
if (!s_check_rem(s, wf->cbSize))

View File

@ -22,6 +22,8 @@
#ifndef _AUDIN_H_
#define _AUDIN_H_
const char *
audin_wave_format_tag_to_str(int tag);
int
audin_init(void);
int

View File

@ -197,7 +197,7 @@ check_timeout(void)
struct timeout_obj *temp_tobj;
int count;
tui32 now;
UNUSED_VAR(count);
LOG_DEVEL(LOG_LEVEL_DEBUG, "check_timeout:");
count = 0;
tobj = g_timeout_head;
@ -317,6 +317,10 @@ send_rail_drawing_orders(char *data, int size)
int error;
s = trans_get_out_s(g_con_trans, 8192);
if (s == NULL)
{
return 1;
}
out_uint32_le(s, 0); /* version */
out_uint32_le(s, 8 + 8 + size); /* size */
out_uint32_le(s, 10); /* msg id */

View File

@ -662,7 +662,7 @@ xfs_readdir(struct xfs_fs *xfs, struct xfs_dir_handle *handle, off_t *off)
XFS_INODE_ALL *dxino = NULL;
XFS_INODE_ALL *xino = NULL;
/* Check the direcory is still valid */
/* Check the directory is still valid */
if (handle->inum < xfs->inode_count &&
((dxino = xfs->inode_table[handle->inum]) != NULL) &&
(dxino->pub.mode & S_IFDIR) != 0 &&

View File

@ -179,6 +179,7 @@ x-special/gnome-copied-files
#include "xcommon.h"
#include "chansrv_fuse.h"
#include "ms-rdpeclip.h"
#include "xrdp_constants.h"
static char g_bmp_image_header[] =
{
@ -245,10 +246,22 @@ static int g_cliprdr_flags = CB_USE_LONG_FORMAT_NAMES |
static int g_formatIds[16];
static int g_num_formatIds = 0;
static int g_file_format_id = -1;
/* Format ID assigned to "FileGroupDescriptorW" by the client */
static int g_file_group_descriptor_format_id = -1;
static char g_last_atom_name[256] = "";
/*
* Values for the named formats we send to the client in
* a Format List PDU
*/
enum
{
CB_FORMAT_FILE_GROUP_DESCRIPTOR = 0xc0bc
};
/*****************************************************************************/
static char *
get_atom_text(Atom atom)
@ -646,7 +659,7 @@ clipboard_send_format_announce(int xrdp_clip_type)
case XRDP_CB_FILE:
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_send_format_announce: XRDP_CB_FILE");
/* canned response for "file" */
out_uint32_le(s, 0x0000c0bc);
out_uint32_le(s, CB_FORMAT_FILE_GROUP_DESCRIPTOR);
clipboard_out_unicode(s, "FileGroupDescriptorW", 21);
out_uint32_le(s, 0x0000c0ba);
clipboard_out_unicode(s, "FileContents", 13);
@ -690,7 +703,7 @@ clipboard_send_format_announce(int xrdp_clip_type)
case XRDP_CB_FILE:
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_send_format_announce: XRDP_CB_FILE");
/* canned response for "file" */
out_uint32_le(s, 0x0000c0bc);
out_uint32_le(s, CB_FORMAT_FILE_GROUP_DESCRIPTOR);
out_uint8p(s, windows_native_format, sizeof(windows_native_format));
out_uint32_le(s, 0x0000c0ba);
out_uint8p(s, windows_native_format, sizeof(windows_native_format));
@ -1028,11 +1041,11 @@ clipboard_process_format_announce(struct stream *s, int clip_msg_status,
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_format_announce: max formats");
}
/* format id for file copy copy seems to keep changing */
/* seen 0x0000c0c8, 0x0000c0ed */
/* format id for file copy copy is dynamic and announced by the
* client */
if (g_strcmp(desc, "FileGroupDescriptorW") == 0)
{
g_file_format_id = formatId;
g_file_group_descriptor_format_id = formatId;
}
}
@ -1100,48 +1113,48 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
in_uint32_le(s, requestedFormatId);
switch (requestedFormatId)
{
case CB_FORMAT_FILE: /* 0xC0BC */
case CB_FORMAT_FILE_GROUP_DESCRIPTOR:
if ((g_clip_s2c.xrdp_clip_type == XRDP_CB_FILE) && g_clip_s2c.converted)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CB_FORMAT_FILE");
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CB_FORMAT_FILE_GROUP_DESCRIPTOR");
clipboard_send_data_response(XRDP_CB_FILE, g_clip_s2c.data,
g_clip_s2c.total_bytes);
}
else
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CB_FORMAT_FILE, "
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CB_FORMAT_FILE_GROUP_DESCRIPTOR, "
"calling XConvertSelection to g_utf8_atom");
g_clip_s2c.xrdp_clip_type = XRDP_CB_FILE;
XConvertSelection(g_display, g_clipboard_atom, g_clip_s2c.type,
g_clip_property_atom, g_wnd, CurrentTime);
}
break;
case CB_FORMAT_DIB: /* 0x0008 */
case CF_DIB:
if ((g_clip_s2c.xrdp_clip_type == XRDP_CB_BITMAP) && g_clip_s2c.converted)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CB_FORMAT_DIB");
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CF_DIB");
clipboard_send_data_response(XRDP_CB_BITMAP, g_clip_s2c.data,
g_clip_s2c.total_bytes);
}
else
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CB_FORMAT_DIB, "
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CF_DIB, "
"calling XConvertSelection to g_image_bmp_atom");
g_clip_s2c.xrdp_clip_type = XRDP_CB_BITMAP;
XConvertSelection(g_display, g_clipboard_atom, g_image_bmp_atom,
g_clip_property_atom, g_wnd, CurrentTime);
}
break;
case CB_FORMAT_UNICODETEXT: /* 0x000D */
case CF_UNICODETEXT:
if ((g_clip_s2c.xrdp_clip_type == XRDP_CB_TEXT) && g_clip_s2c.converted)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CB_FORMAT_UNICODETEXT");
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CF_UNICODETEXT");
clipboard_send_data_response(XRDP_CB_TEXT, g_clip_s2c.data,
g_clip_s2c.total_bytes);
}
else
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CB_FORMAT_UNICODETEXT, "
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_request: CF_UNICODETEXT, "
"calling XConvertSelection to g_utf8_atom");
g_clip_s2c.xrdp_clip_type = XRDP_CB_TEXT;
XConvertSelection(g_display, g_clipboard_atom, g_utf8_atom,
@ -1157,12 +1170,15 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
return 0;
}
/*****************************************************************************/
/* client to server */
/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate whether
processing of the CB_FORMAT_DATA_REQUEST was successful; if processing
was successful, CB_FORMAT_DATA_RESPONSE includes contents of requested
clipboard data. */
/**************************************************************************//**
* Process a CB_FORMAT_DATA_RESPONSE for an X client requesting an image
*
* @param s Stream containing CLIPRDR_FILELIST ([MS-RDPECLIP])
* @param clip_msg_status msgFlags from Clipboard PDU Header
* @param clip_msg_len dataLen from Clipboard PDU Header
*
* @return Status
*/
static int
clipboard_process_data_response_for_image(struct stream *s,
int clip_msg_status,
@ -1289,6 +1305,90 @@ clipboard_process_data_response_for_file(struct stream *s,
return rv;
}
/**************************************************************************//**
* Process a CB_FORMAT_DATA_RESPONSE for an X client requesting text
*
* @param s Stream containing CLIPRDR_FILELIST ([MS-RDPECLIP])
* @param clip_msg_status msgFlags from Clipboard PDU Header
* @param clip_msg_len dataLen from Clipboard PDU Header
*
* @return Status
*/
static int
clipboard_process_data_response_for_text(struct stream *s,
int clip_msg_status,
int clip_msg_len)
{
XSelectionRequestEvent *lxev = &g_saved_selection_req_event;
twchar *wtext;
twchar wchr;
int len;
int index;
int byte_count;
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_response_for_text: ");
len = (int)(s->end - s->p);
if (len < 1)
{
len = 0;
}
byte_count = ((len / 2) + 1) * sizeof(twchar);
wtext = (twchar *) g_malloc(byte_count, 0);
if (wtext == 0)
{
LOG(LOG_LEVEL_ERROR, "Can't allocate %d bytes for text clip response",
byte_count);
clipboard_refuse_selection(lxev);
}
else
{
index = 0;
while (s_check_rem(s, 2))
{
in_uint16_le(s, wchr);
wtext[index] = wchr;
if (wchr == 0)
{
break;
}
index++;
}
wtext[index] = 0;
g_free(g_clip_c2s.data);
g_clip_c2s.data = 0;
g_clip_c2s.total_bytes = 0;
len = g_wcstombs(0, wtext, 0);
if (len < 0)
{
LOG(LOG_LEVEL_ERROR,
"Received malformed Unicode paste text from client");
clipboard_refuse_selection(lxev);
}
else
{
byte_count = len + 16;
g_clip_c2s.data = (char *) g_malloc(byte_count, 0);
if (g_clip_c2s.data == 0)
{
LOG(LOG_LEVEL_ERROR,
"Can't allocate %d bytes for text clip response",
byte_count);
clipboard_refuse_selection(lxev);
}
else
{
g_wcstombs(g_clip_c2s.data, wtext, len + 1);
g_clip_c2s.total_bytes = g_strlen(g_clip_c2s.data);
g_clip_c2s.read_bytes_done = g_clip_c2s.total_bytes;
clipboard_provide_selection_c2s(lxev, lxev->target);
}
}
g_free(wtext);
}
return 0;
}
/*****************************************************************************/
/* client to server */
/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate whether
@ -1300,75 +1400,46 @@ static int
clipboard_process_data_response(struct stream *s, int clip_msg_status,
int clip_msg_len)
{
XSelectionRequestEvent *lxev;
twchar *wtext;
twchar wchr;
int len;
int index;
int rv = 0;
XSelectionRequestEvent *lxev = &g_saved_selection_req_event;
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_response:");
lxev = &g_saved_selection_req_event;
g_clip_c2s.in_request = 0;
if (g_clip_c2s.xrdp_clip_type == XRDP_CB_BITMAP)
if ((clip_msg_status & CB_RESPONSE_FAIL) != 0)
{
/* Requested data was not returned from the client. Most likely
* the client has lost the selection between announcing it and
* responding to our request */
clipboard_refuse_selection(lxev);
}
else if ((clip_msg_status & CB_RESPONSE_OK) == 0)
{
/* One of CB_RESPONSE_FAIL or CB_RESPONSE_OK MUST be set in
* a CLIPRDR_FORMAT_DATA_RESPONSE msg */
LOG(LOG_LEVEL_ERROR, "CLIPRDR_FORMAT_DATA_RESPONSE is badly formed");
clipboard_refuse_selection(lxev);
}
else if (g_clip_c2s.xrdp_clip_type == XRDP_CB_BITMAP)
{
clipboard_process_data_response_for_image(s, clip_msg_status,
clip_msg_len);
return 0;
}
if (g_clip_c2s.xrdp_clip_type == XRDP_CB_FILE)
else if (g_clip_c2s.xrdp_clip_type == XRDP_CB_FILE)
{
clipboard_process_data_response_for_file(s, clip_msg_status,
clip_msg_len);
return 0;
}
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_response: "
"CLIPRDR_DATA_RESPONSE");
len = (int)(s->end - s->p);
if (len < 1)
else
{
return 0;
clipboard_process_data_response_for_text(s, clip_msg_status,
clip_msg_len);
}
wtext = (twchar *) g_malloc(((len / 2) + 1) * sizeof(twchar), 0);
if (wtext == 0)
{
return 0;
}
index = 0;
while (s_check_rem(s, 2))
{
in_uint16_le(s, wchr);
wtext[index] = wchr;
if (wchr == 0)
{
break;
}
index++;
}
wtext[index] = 0;
g_free(g_clip_c2s.data);
g_clip_c2s.data = 0;
g_clip_c2s.total_bytes = 0;
len = g_wcstombs(0, wtext, 0);
if (len >= 0)
{
g_clip_c2s.data = (char *) g_malloc(len + 16, 0);
if (g_clip_c2s.data == 0)
{
g_free(wtext);
return 0;
}
g_wcstombs(g_clip_c2s.data, wtext, len + 1);
}
if (g_clip_c2s.data != 0)
{
g_clip_c2s.total_bytes = g_strlen(g_clip_c2s.data);
g_clip_c2s.read_bytes_done = g_clip_c2s.total_bytes;
clipboard_provide_selection_c2s(lxev, lxev->target);
}
g_free(wtext);
return 0;
return rv;
}
/*****************************************************************************/
static int
clipboard_process_clip_caps(struct stream *s, int clip_msg_status,
@ -1417,161 +1488,6 @@ clipboard_process_clip_caps(struct stream *s, int clip_msg_status,
return 0;
}
/*****************************************************************************/
static int
ss_part(char *data, int data_bytes)
{
int index;
char *text;
LOG_DEVEL(LOG_LEVEL_DEBUG, "ss_part: data_bytes %d read_bytes_done %d "
"incr_bytes_done %d", data_bytes,
g_clip_c2s.read_bytes_done,
g_clip_c2s.incr_bytes_done);
/* copy to buffer */
if (g_clip_c2s.type == g_utf8_atom)
{
/* todo unicode */
text = (char *)g_malloc(data_bytes, 0);
index = 0;
data_bytes /= 2;
while (index < data_bytes)
{
text[index] = data[index * 2];
index++;
}
text[index] = 0;
g_memcpy(g_clip_c2s.data + g_clip_c2s.read_bytes_done, text, data_bytes);
g_clip_c2s.read_bytes_done += data_bytes;
g_free(text);
}
else
{
g_memcpy(g_clip_c2s.data + g_clip_c2s.read_bytes_done, data, data_bytes);
g_clip_c2s.read_bytes_done += data_bytes;
}
if (g_clip_c2s.incr_in_progress)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "ss_part: incr_in_progress set");
return 0;
}
if (g_clip_c2s.read_bytes_done <= g_clip_c2s.incr_bytes_done)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "ss_part: read_bytes_done < incr_bytes_done");
return 0;
}
data = g_clip_c2s.data + g_clip_c2s.incr_bytes_done;
data_bytes = g_clip_c2s.read_bytes_done - g_clip_c2s.incr_bytes_done;
if (data_bytes > g_incr_max_req_size)
{
data_bytes = g_incr_max_req_size;
}
g_clip_c2s.incr_bytes_done += data_bytes;
XChangeProperty(g_display, g_clip_c2s.window,
g_clip_c2s.property, g_clip_c2s.type, 8,
PropModeReplace, (tui8 *)data, data_bytes);
g_clip_c2s.incr_in_progress = 1;
return 0;
}
/*****************************************************************************/
static int
ss_end(void)
{
char *data;
int data_bytes;
LOG_DEVEL(LOG_LEVEL_DEBUG, "ss_end:");
g_clip_c2s.doing_response_ss = 0;
g_clip_c2s.in_request = 0;
if (g_clip_c2s.incr_in_progress)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "ss_end: incr_in_progress set");
return 0;
}
if (g_clip_c2s.read_bytes_done <= g_clip_c2s.incr_bytes_done)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "ss_end: read_bytes_done < incr_bytes_done");
return 0;
}
data = g_clip_c2s.data + g_clip_c2s.incr_bytes_done;
data_bytes = g_clip_c2s.read_bytes_done - g_clip_c2s.incr_bytes_done;
if (data_bytes > g_incr_max_req_size)
{
data_bytes = g_incr_max_req_size;
}
g_clip_c2s.incr_bytes_done += data_bytes;
XChangeProperty(g_display, g_clip_c2s.window,
g_clip_c2s.property, g_clip_c2s.type, 8,
PropModeReplace, (tui8 *)data, data_bytes);
g_clip_c2s.incr_in_progress = 1;
return 0;
}
/*****************************************************************************/
static int
ss_start(char *data, int data_bytes, int total_bytes)
{
XEvent xev;
XSelectionRequestEvent *req;
long val1[2];
int incr_bytes;
LOG_DEVEL(LOG_LEVEL_DEBUG, "ss_start: data_bytes %d total_bytes %d",
data_bytes, total_bytes);
req = &g_saved_selection_req_event;
incr_bytes = total_bytes;
if (req->target == g_image_bmp_atom)
{
incr_bytes += 14;
}
else if (req->target == g_utf8_atom)
{
incr_bytes /= 2;
}
val1[0] = incr_bytes; /* a guess */
val1[1] = 0;
g_clip_c2s.doing_response_ss = 1;
g_clip_c2s.incr_bytes_done = 0;
g_clip_c2s.read_bytes_done = 0;
g_clip_c2s.type = req->target;
g_clip_c2s.property = req->property;
g_clip_c2s.window = req->requestor;
g_free(g_clip_c2s.data);
g_clip_c2s.data = (char *)g_malloc(incr_bytes + 64, 0);
g_clip_c2s.total_bytes = incr_bytes;
XChangeProperty(g_display, req->requestor, req->property,
g_incr_atom, 32, PropModeReplace, (tui8 *)val1, 1);
/* we need events from that other window */
XSelectInput(g_display, req->requestor, PropertyChangeMask);
g_memset(&xev, 0, sizeof(xev));
xev.xselection.type = SelectionNotify;
xev.xselection.send_event = True;
xev.xselection.display = req->display;
xev.xselection.requestor = req->requestor;
xev.xselection.selection = req->selection;
xev.xselection.target = req->target;
xev.xselection.property = req->property;
xev.xselection.time = req->time;
XSendEvent(g_display, req->requestor, False, NoEventMask, &xev);
if (req->target == g_image_bmp_atom)
{
g_memcpy(g_clip_c2s.data, g_bmp_image_header, 14);
g_clip_c2s.read_bytes_done = 14;
}
g_clip_c2s.incr_in_progress = 1;
ss_part(data, data_bytes);
return 0;
}
/*****************************************************************************/
int
clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length,
@ -1582,7 +1498,6 @@ clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length,
int clip_msg_status;
int rv;
struct stream *ls;
char *holdp;
if (!g_clip_up)
{
@ -1598,37 +1513,6 @@ clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length,
chan_id, chan_flags, length, total_length,
g_clip_c2s.in_request, g_ins->size);
if (g_clip_c2s.doing_response_ss)
{
ss_part(s->p, length);
if ((chan_flags & 3) == 2)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_data_in: calling ss_end");
ss_end();
}
return 0;
}
if (g_clip_c2s.in_request)
{
if (total_length > 32 * 1024)
{
if ((chan_flags & 3) == 1)
{
holdp = s->p;
in_uint16_le(s, clip_msg_id);
in_uint16_le(s, clip_msg_status);
in_uint32_le(s, clip_msg_len);
if (clip_msg_id == CB_FORMAT_DATA_RESPONSE)
{
ss_start(s->p, length - 8, total_length - 8);
return 0;
}
s->p = holdp;
}
}
}
if ((chan_flags & 3) == 3)
{
ls = s;
@ -2295,21 +2179,30 @@ clipboard_event_selection_request(XEvent *xevent)
atom_buf[1] = g_timestamp_atom;
atom_buf[2] = g_multiple_atom;
atom_count = 3;
if ((g_cfg->restrict_inbound_clipboard & CLIP_RESTRICT_TEXT) == 0)
/* Only announce text if the client is advertising text, or
* a file list */
if (clipboard_find_format_id(CF_UNICODETEXT) >= 0 ||
clipboard_find_format_id(CF_OEMTEXT) >= 0 ||
clipboard_find_format_id(CF_TEXT) >= 0 ||
clipboard_find_format_id(g_file_group_descriptor_format_id) >= 0)
{
atom_buf[atom_count] = XA_STRING;
atom_count++;
atom_buf[atom_count] = g_utf8_atom;
atom_count++;
if ((g_cfg->restrict_inbound_clipboard & CLIP_RESTRICT_TEXT) == 0)
{
atom_buf[atom_count] = XA_STRING;
atom_count++;
atom_buf[atom_count] = g_utf8_atom;
atom_count++;
}
}
if (clipboard_find_format_id(CB_FORMAT_DIB) >= 0 &&
if (clipboard_find_format_id(CF_DIB) >= 0 &&
(g_cfg->restrict_inbound_clipboard & CLIP_RESTRICT_IMAGE) == 0)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, " reporting image/bmp");
atom_buf[atom_count] = g_image_bmp_atom;
atom_count++;
}
if (clipboard_find_format_id(g_file_format_id) >= 0 &&
if (clipboard_find_format_id(g_file_group_descriptor_format_id) >= 0 &&
(g_cfg->restrict_inbound_clipboard & CLIP_RESTRICT_FILE) == 0)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, " reporting text/uri-list");
@ -2353,7 +2246,7 @@ clipboard_event_selection_request(XEvent *xevent)
}
else if ((lxev->target == XA_STRING) || (lxev->target == g_utf8_atom))
{
if (clipboard_find_format_id(g_file_format_id) >= 0)
if (clipboard_find_format_id(g_file_group_descriptor_format_id) >= 0)
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_event_selection_request: "
"text requested when files available");
@ -2371,7 +2264,7 @@ clipboard_event_selection_request(XEvent *xevent)
sizeof(g_saved_selection_req_event));
g_clip_c2s.type = lxev->target;
g_clip_c2s.xrdp_clip_type = XRDP_CB_FILE;
clipboard_send_data_request(g_file_format_id);
clipboard_send_data_request(g_file_group_descriptor_format_id);
}
}
@ -2387,11 +2280,14 @@ clipboard_event_selection_request(XEvent *xevent)
}
else
{
/* The client may have advertised CF_TEXT or CF_OEMTEXT,
* but the Windows clipboard will convert these formats
* to Unicode if asked */
g_memcpy(&g_saved_selection_req_event, lxev,
sizeof(g_saved_selection_req_event));
g_clip_c2s.type = lxev->target;
g_clip_c2s.xrdp_clip_type = XRDP_CB_TEXT;
clipboard_send_data_request(CB_FORMAT_UNICODETEXT);
clipboard_send_data_request(CF_UNICODETEXT);
}
}
@ -2430,7 +2326,7 @@ clipboard_event_selection_request(XEvent *xevent)
sizeof(g_saved_selection_req_event));
g_clip_c2s.type = g_image_bmp_atom;
g_clip_c2s.xrdp_clip_type = XRDP_CB_BITMAP;
clipboard_send_data_request(CB_FORMAT_DIB);
clipboard_send_data_request(CF_DIB);
}
return 0;
@ -2467,7 +2363,7 @@ clipboard_event_selection_request(XEvent *xevent)
sizeof(g_saved_selection_req_event));
g_clip_c2s.type = g_file_atom1;
g_clip_c2s.xrdp_clip_type = XRDP_CB_FILE;
clipboard_send_data_request(g_file_format_id);
clipboard_send_data_request(g_file_group_descriptor_format_id);
return 0;
}
@ -2505,7 +2401,7 @@ clipboard_event_selection_request(XEvent *xevent)
sizeof(g_saved_selection_req_event));
g_clip_c2s.type = g_file_atom2;
g_clip_c2s.xrdp_clip_type = XRDP_CB_FILE;
clipboard_send_data_request(g_file_format_id);
clipboard_send_data_request(g_file_group_descriptor_format_id);
return 0;
}
}
@ -2676,14 +2572,12 @@ clipboard_event_property_notify(XEvent *xevent)
format_in_bytes = FORMAT_TO_BYTES(actual_format_return);
new_data_len = nitems_returned * format_in_bytes;
cptr = (char *) g_malloc(g_clip_s2c.total_bytes + new_data_len, 0);
g_memcpy(cptr, g_clip_s2c.data, g_clip_s2c.total_bytes);
g_free(g_clip_s2c.data);
if (cptr == NULL)
{
/* cannot add any more data */
g_free(g_clip_s2c.data);
g_clip_s2c.data = 0;
/* cannot add any more data */
if (data != 0)
{
XFree(data);
@ -2692,14 +2586,15 @@ clipboard_event_property_notify(XEvent *xevent)
XDeleteProperty(g_display, g_wnd, g_clip_s2c.property);
return 0;
}
g_memcpy(cptr, g_clip_s2c.data, g_clip_s2c.total_bytes);
g_free(g_clip_s2c.data);
LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_event_property_notify: new_data_len %d", new_data_len);
g_clip_s2c.data = cptr;
g_memcpy(g_clip_s2c.data + g_clip_s2c.total_bytes, data, new_data_len);
g_clip_s2c.total_bytes += new_data_len;
if (data)
{
g_memcpy(g_clip_s2c.data + g_clip_s2c.total_bytes, data, new_data_len);
g_clip_s2c.total_bytes += new_data_len;
XFree(data);
}

View File

@ -22,19 +22,6 @@
#include "arch.h"
#include "parse.h"
/*
* TODO : Replace these with the definitions in xrdp_constants.h
* where possible */
#define CB_FORMAT_RAW 0x0000
#define CB_FORMAT_TEXT 0x0001
#define CB_FORMAT_DIB 0x0008
#define CB_FORMAT_UNICODETEXT 0x000D
#define CB_FORMAT_HTML 0xD010
#define CB_FORMAT_PNG 0xD011
#define CB_FORMAT_JPEG 0xD012
#define CB_FORMAT_GIF 0xD013
#define CB_FORMAT_FILE 0xC0BC
/* these are the supported general types */
#define XRDP_CB_TEXT 1
#define XRDP_CB_BITMAP 2
@ -65,8 +52,6 @@ struct clip_c2s /* client to server, pasting from mstsc to linux app */
int xrdp_clip_type; /* XRDP_CB_TEXT, XRDP_CB_BITMAP, XRDP_CB_FILE, ... */
int converted;
int in_request; /* a data request has been sent to client */
int doing_response_ss; /* doing response short circuit */
Time clip_time;
};
struct clip_file_desc /* CLIPRDR_FILEDESCRIPTOR */

View File

@ -503,7 +503,7 @@ clipboard_send_file_data(int streamId, int lindex,
g_file_close(fd);
/* Log who transferred which file via clipboard for the purpose of audit */
LOG(LOG_LEVEL_INFO, "S2C: Transfered a file: filename=%s, uid=%d", full_fn, g_getuid());
LOG(LOG_LEVEL_INFO, "S2C: Transferred a file: filename=%s, uid=%d", full_fn, g_getuid());
return rv;
}

View File

@ -98,12 +98,20 @@ enum COMPLETION_TYPE
/* globals */
extern int g_rdpdr_chan_id; /* in chansrv.c */
int g_is_printer_redir_supported = 0;
int g_is_port_redir_supported = 0;
int g_is_drive_redir_supported = 0;
int g_is_smartcard_redir_supported = 0;
int g_drive_redir_version = 1;
char g_full_name_for_filesystem[1024];
/* Capabilities from GENERAL_CAPS_SET in Client Core Capability Response */
struct client_caps
{
tui32 extended_pdu;
int printer_redir_supported;
int port_redir_supported;
int drive_redir_supported;
int smartcard_redir_supported;
unsigned int drive_redir_version;
};
static struct client_caps g_ccap;
tui32 g_completion_id = 1;
tui32 g_clientID; /* unique client ID - announced by client */
@ -131,10 +139,10 @@ static void devredir_send_server_core_cap_req(void);
static void devredir_send_server_clientID_confirm(void);
static void devredir_send_server_user_logged_on(void);
static void devredir_proc_client_core_cap_resp(struct stream *s);
static void devredir_proc_client_devlist_announce_req(struct stream *s);
static void devredir_proc_client_devlist_remove_req(struct stream *s);
static void devredir_proc_device_iocompletion(struct stream *s);
static int devredir_proc_client_core_cap_resp(struct stream *s);
static int devredir_proc_client_devlist_announce_req(struct stream *s);
static int devredir_proc_client_devlist_remove_req(struct stream *s);
static int devredir_proc_device_iocompletion(struct stream *s);
static void devredir_proc_query_dir_response(IRP *irp,
struct stream *s_in,
tui32 DeviceId,
@ -211,9 +219,9 @@ const char *completion_type_to_str(enum COMPLETION_TYPE cid)
/*****************************************************************************/
/*
* Convert Windows permssions to Linux permissions.
* Convert Windows permissions to Linux permissions.
*
* We can't curently support group or other permissions as separate from the
* We can't currently support group or other permissions as separate from the
* owner (not that there's much point). We'll assume our caller will provide
* a umask if appropriate
*/
@ -323,6 +331,11 @@ devredir_data_in(struct stream *s, int chan_id, int chan_flags, int length,
}
/* read header from incoming data */
if (!s_check_rem_and_log(ls, 4, "Parsing [MS-RDPEFS] RDPDR_HEADER"))
{
rv = -1;
goto done;
}
xstream_rd_u16_le(ls, comp_type);
xstream_rd_u16_le(ls, pktID);
@ -340,57 +353,76 @@ devredir_data_in(struct stream *s, int chan_id, int chan_flags, int length,
switch (pktID)
{
case PAKID_CORE_CLIENTID_CONFIRM:
xstream_seek(ls, 2); /* major version, we ignore it */
xstream_rd_u16_le(ls, minor_ver);
xstream_rd_u32_le(ls, g_clientID);
g_client_rdp_version = minor_ver;
switch (minor_ver)
if (!s_check_rem_and_log(ls, 6, "Parsing [MS-RDPEFS] DR_CORE_CLIENT_ANNOUNCE_RSP"))
{
case RDP_CLIENT_50:
break;
case RDP_CLIENT_51:
break;
case RDP_CLIENT_52:
break;
case RDP_CLIENT_60_61:
break;
rv = -1;
}
else
{
xstream_seek(ls, 2); /* major version, we ignore it */
xstream_rd_u16_le(ls, minor_ver);
xstream_rd_u32_le(ls, g_clientID);
g_client_rdp_version = minor_ver;
switch (minor_ver)
{
case RDP_CLIENT_50:
break;
case RDP_CLIENT_51:
break;
case RDP_CLIENT_52:
break;
case RDP_CLIENT_60_61:
break;
}
}
// LK_TODO devredir_send_server_clientID_confirm();
break;
case PAKID_CORE_CLIENT_NAME:
/* client is telling us its computer name; do we even care? */
/* let client know login was successful */
devredir_send_server_user_logged_on();
usleep(1000 * 100);
/* let client know our capabilities */
devredir_send_server_core_cap_req();
/* See 3.3.5.1.6 for sequencing rules */
if (g_client_rdp_version >= RDP_CLIENT_51)
{
/* let client know our capabilities */
devredir_send_server_core_cap_req();
}
/* send confirm clientID */
devredir_send_server_clientID_confirm();
break;
case PAKID_CORE_CLIENT_CAPABILITY:
devredir_proc_client_core_cap_resp(ls);
rv = devredir_proc_client_core_cap_resp(ls);
if (rv == 0)
{
if ((g_ccap.extended_pdu & RDPDR_USER_LOGGEDON_PDU) != 0)
{
/* Tell client to announce remaining devices */
devredir_send_server_user_logged_on();
}
else if (g_client_rdp_version >= RDP_CLIENT_51)
{
/* See 3.3.5.1.7 */
devredir_send_server_clientID_confirm();
}
}
break;
case PAKID_CORE_DEVICELIST_ANNOUNCE:
devredir_proc_client_devlist_announce_req(ls);
rv = devredir_proc_client_devlist_announce_req(ls);
break;
case PAKID_CORE_DEVICELIST_REMOVE:
devredir_proc_client_devlist_remove_req(ls);
rv = devredir_proc_client_devlist_remove_req(ls);
break;
case PAKID_CORE_DEVICE_IOCOMPLETION:
devredir_proc_device_iocompletion(ls);
rv = devredir_proc_device_iocompletion(ls);
break;
default:
@ -413,7 +445,7 @@ done:
int
devredir_get_wait_objs(tbus *objs, int *count, int *timeout)
{
if (g_is_smartcard_redir_supported)
if (g_ccap.smartcard_redir_supported)
{
return scard_get_wait_objs(objs, count, timeout);
}
@ -424,7 +456,7 @@ devredir_get_wait_objs(tbus *objs, int *count, int *timeout)
int
devredir_check_wait_objs(void)
{
if (g_is_smartcard_redir_supported)
if (g_ccap.smartcard_redir_supported)
{
return scard_check_wait_objs();
}
@ -723,67 +755,138 @@ devredir_send_drive_dir_request(IRP *irp, tui32 device_id,
** process data received from client **
******************************************************************************/
/**
* Process a GENERAL_CAPS_SET packet from the client
* @param s Stream. CAPABILITY_HEADER is already read
* @param cap_len Amount of data left in stream for the packet
* @return 0 for success, -1 otherwise
*
* Caller is responsible for skipping unused data from this
* capability in the input stream.
*/
static int
process_client_general_caps_set(struct stream *s, unsigned int cap_len,
struct client_caps *ccap)
{
int rv = -1;
// Data we don't check at the start of the packet
#define PACKET_SKIP_LENGTH ( \
4 + /* osType */ \
4 + /* osVersion */ \
2 + /* protocolMajorVersion */ \
2 + /* protocolMinorVersion */ \
4 + /* ioCode1 */ \
4) /* ioCode2 */
if (cap_len < (PACKET_SKIP_LENGTH + 4))
{
LOG(LOG_LEVEL_ERROR,
"[MS-RDPEFS] GENERAL_CAPS_SET: Short packet (%u bytes) encountered",
cap_len);
}
else
{
xstream_seek(s, PACKET_SKIP_LENGTH);
xstream_rd_u32_le(s, ccap->extended_pdu);
rv = 0;
}
return rv;
#undef PACKET_SKIP_LENGTH
}
/**
* @brief process client's response to our core_capability_req() msg
*
* @param s stream containing client's response
* @return 0 for success, -1 otherwise
*****************************************************************************/
static void
static int
devredir_proc_client_core_cap_resp(struct stream *s)
{
#define CAPABILITY_HEADER_LEN 8
int i;
tui16 num_caps;
tui16 cap_type;
tui16 cap_len;
tui32 cap_version;
char *holdp;
// Reset to defaults
memset(&g_ccap, 0, sizeof(g_ccap));
g_ccap.drive_redir_version = 1;
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEFS] DR_CORE_CAPABLITY_RSP"))
{
return -1;
}
xstream_rd_u16_le(s, num_caps);
xstream_seek(s, 2); /* padding */
for (i = 0; i < num_caps; i++)
{
holdp = s->p;
if (!s_check_rem_and_log(s, CAPABILITY_HEADER_LEN,
"Parsing [MS-RDPEFS] CAPABILITY_HEADER"))
{
return -1;
}
xstream_rd_u16_le(s, cap_type);
xstream_rd_u16_le(s, cap_len);
xstream_rd_u32_le(s, cap_version);
/* Convert the length to a remaining length. Underflow is possible,
* but this is an unsigned type so that's OK */
cap_len -= CAPABILITY_HEADER_LEN;
if (!s_check_rem_and_log(s, cap_len,
"Parsing [MS-RDPEFS] CAPABILITY_HEADER data"))
{
return -1;
}
// Save our stream position. iso_hdr is otherwise
// unused in this stream
s_push_layer(s, iso_hdr, 0);
switch (cap_type)
{
case CAP_GENERAL_TYPE:
LOG_DEVEL(LOG_LEVEL_DEBUG, "got CAP_GENERAL_TYPE");
if (process_client_general_caps_set(s, cap_len, &g_ccap) < 0)
{
return -1;
}
break;
case CAP_PRINTER_TYPE:
LOG_DEVEL(LOG_LEVEL_DEBUG, "got CAP_PRINTER_TYPE");
g_is_printer_redir_supported = 1;
g_ccap.printer_redir_supported = 1;
break;
case CAP_PORT_TYPE:
LOG_DEVEL(LOG_LEVEL_DEBUG, "got CAP_PORT_TYPE");
g_is_port_redir_supported = 1;
g_ccap.port_redir_supported = 1;
break;
case CAP_DRIVE_TYPE:
LOG_DEVEL(LOG_LEVEL_DEBUG, "got CAP_DRIVE_TYPE");
g_is_drive_redir_supported = 1;
g_ccap.drive_redir_supported = 1;
if (cap_version == 2)
{
g_drive_redir_version = 2;
g_ccap.drive_redir_version = 2;
}
break;
case CAP_SMARTCARD_TYPE:
LOG_DEVEL(LOG_LEVEL_DEBUG, "got CAP_SMARTCARD_TYPE");
g_is_smartcard_redir_supported = 1;
scard_init();
g_ccap.smartcard_redir_supported = (scard_init() == 0);
break;
}
s->p = holdp + cap_len;
s_pop_layer(s, iso_hdr); // Move back to start of capability data
xstream_seek(s, cap_len);
}
return 0;
#undef CAPABILITY_HEADER_LEN
}
static void
static int
devredir_proc_client_devlist_announce_req(struct stream *s)
{
unsigned int i;
@ -795,12 +898,22 @@ devredir_proc_client_devlist_announce_req(struct stream *s)
enum NTSTATUS response_status;
/* get number of devices being announced */
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEFS] DR_CORE_DEVICELIST_ANNOUNCE_REQ"))
{
return -1;
}
xstream_rd_u32_le(s, device_count);
LOG_DEVEL(LOG_LEVEL_DEBUG, "num of devices announced: %d", device_count);
for (i = 0; i < device_count; i++)
{
if (!s_check_rem_and_log(s, 4 + 4 + 8 + 4,
"Parsing [MS-RDPEFS] DEVICE_ANNOUNCE"))
{
return -1;
}
xstream_rd_u32_le(s, device_type);
xstream_rd_u32_le(s, g_device_id);
/* get preferred DOS name
@ -816,25 +929,28 @@ devredir_proc_client_devlist_announce_req(struct stream *s)
/* Read the device data length from the stream */
xstream_rd_u32_le(s, device_data_len);
if (device_data_len > 0 &&
!s_check_rem_and_log(s, device_data_len,
"Parsing [MS-RDPEFS] DEVICE_ANNOUNCE devdata"))
{
return -1;
}
switch (device_type)
{
case RDPDR_DTYP_FILESYSTEM:
/* get device data len */
if (device_data_len)
{
xstream_rd_string(g_full_name_for_filesystem, s,
device_data_len);
}
/* At present we don't use the full name - see
* [MS-RDPEFS] 2.2.3.1 for details of the contents */
xstream_skip_u8(s, device_data_len);
LOG(LOG_LEVEL_INFO, "Detected remote drive '%s'",
preferred_dos_name);
LOG_DEVEL(LOG_LEVEL_DEBUG,
"device_type=FILE_SYSTEM device_id=0x%x dosname=%s "
"device_data_len=%d full_name=%s", g_device_id,
"device_data_len=%d", g_device_id,
preferred_dos_name,
device_data_len, g_full_name_for_filesystem);
device_data_len);
response_status = STATUS_SUCCESS;
@ -881,9 +997,11 @@ devredir_proc_client_devlist_announce_req(struct stream *s)
devredir_send_server_device_announce_resp(g_device_id,
response_status);
}
return 0;
}
static void
static int
devredir_proc_client_devlist_remove_req(struct stream *s)
{
unsigned int i;
@ -891,7 +1009,16 @@ devredir_proc_client_devlist_remove_req(struct stream *s)
tui32 device_id;
/* get number of devices being announced */
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEFS] DR_DEVICELIST_REMOVE"))
{
return -1;
}
xstream_rd_u32_le(s, device_count);
if (!s_check_rem_and_log(s, 4 * device_count,
"Parsing [MS-RDPEFS] DR_DEVICELIST_REMOVE list"))
{
return -1;
}
LOG_DEVEL(LOG_LEVEL_DEBUG, "num of devices removed: %d", device_count);
{
@ -901,9 +1028,10 @@ devredir_proc_client_devlist_remove_req(struct stream *s)
xfuse_delete_share(device_id);
}
}
return 0;
}
static void
static int
devredir_proc_device_iocompletion(struct stream *s)
{
IRP *irp = NULL;
@ -914,6 +1042,10 @@ devredir_proc_device_iocompletion(struct stream *s)
tui32 Length;
enum COMPLETION_TYPE comp_type;
if (!s_check_rem_and_log(s, 12, "Parsing [MS-RDPEFS] DR_DEVICE_IOCOMPLETION"))
{
return -1;
}
xstream_rd_u32_le(s, DeviceId);
xstream_rd_u32_le(s, CompletionId);
xstream_rd_u32_le(s, IoStatus32);
@ -959,6 +1091,10 @@ devredir_proc_device_iocompletion(struct stream *s)
}
else
{
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEFS] DR_CREATE_RSP"))
{
return -1;
}
xstream_rd_u32_le(s, irp->FileId);
devredir_send_drive_dir_request(irp, DeviceId,
1, irp->pathname);
@ -966,6 +1102,10 @@ devredir_proc_device_iocompletion(struct stream *s)
break;
case CID_CREATE_REQ:
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEFS] DR_CREATE_RSP"))
{
return -1;
}
xstream_rd_u32_le(s, irp->FileId);
xfuse_devredir_cb_create_file(
@ -978,6 +1118,10 @@ devredir_proc_device_iocompletion(struct stream *s)
break;
case CID_OPEN_REQ:
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEFS] DR_CREATE_RSP"))
{
return -1;
}
xstream_rd_u32_le(s, irp->FileId);
xfuse_devredir_cb_open_file((struct state_open *) irp->fuse_info,
@ -989,7 +1133,15 @@ devredir_proc_device_iocompletion(struct stream *s)
break;
case CID_READ:
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEFS] DR_READ_RSP"))
{
return -1;
}
xstream_rd_u32_le(s, Length);
if (!s_check_rem_and_log(s, Length, "Parsing [MS-RDPEFS] DR_READ_RSP"))
{
return -1;
}
xfuse_devredir_cb_read_file((struct state_read *) irp->fuse_info,
IoStatus,
s->p, Length);
@ -997,6 +1149,10 @@ devredir_proc_device_iocompletion(struct stream *s)
break;
case CID_WRITE:
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEFS] DR_WRITE_RSP"))
{
return -1;
}
xstream_rd_u32_le(s, Length);
xfuse_devredir_cb_write_file((struct state_write *) irp->fuse_info,
IoStatus,
@ -1019,6 +1175,10 @@ devredir_proc_device_iocompletion(struct stream *s)
break;
case CID_RMDIR_OR_FILE:
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEFS] DR_CREATE_RSP"))
{
return -1;
}
xstream_rd_u32_le(s, irp->FileId);
devredir_proc_cid_rmdir_or_file(irp, IoStatus);
break;
@ -1028,6 +1188,10 @@ devredir_proc_device_iocompletion(struct stream *s)
break;
case CID_RENAME_FILE:
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEFS] DR_CREATE_RSP"))
{
return -1;
}
xstream_rd_u32_le(s, irp->FileId);
devredir_proc_cid_rename_file(irp, IoStatus);
break;
@ -1051,6 +1215,7 @@ devredir_proc_device_iocompletion(struct stream *s)
break;
}
}
return 0;
}
static void

View File

@ -106,7 +106,7 @@ struct irp
};
IRP *devredir_irp_new(void);
/* As above, but allocates sufficent space for the specified
/* As above, but allocates sufficient space for the specified
* pathname, and copies it in to the pathname field */
IRP *devredir_irp_with_pathname_new(const char *pathname);
/* As above, but specifies a pathname length with pathname

0
sesman/chansrv/pcsc/wrapper/Makefile Executable file → Normal file
View File

0
sesman/chansrv/pcsc/wrapper/winscard-func-names.txt Executable file → Normal file
View File

0
sesman/chansrv/pcsc/wrapper/winscard-funcs.h Executable file → Normal file
View File

0
sesman/chansrv/pcsc/wrapper/winscard.c Executable file → Normal file
View File

0
sesman/chansrv/pcsc/wrapper/winscard.def Executable file → Normal file
View File

View File

@ -799,7 +799,7 @@ scard_send_get_attrib(void *user_data, char *card, int card_bytes,
******************************************************************************/
/**
* Crate a new stream and insert specified IOCTL
* Create a new stream and insert specified IOCTL
*
* @param irp information about the I/O
* @param ioctl the IOCTL code

View File

@ -342,7 +342,7 @@ context_add_card(struct pcsc_uds_client *uds_client,
if (pcscCard == 0)
{
LOG(LOG_LEVEL_ERROR,
"context_add_card: failed to allocate memmory for pcsc_card");
"context_add_card: failed to allocate memory for pcsc_card");
return 0;
}
g_autoinc++;
@ -355,7 +355,7 @@ context_add_card(struct pcsc_uds_client *uds_client,
if (acontext->cards == 0)
{
LOG(LOG_LEVEL_ERROR, "context_add_card: failed to allocate "
"memmory for uds_client->contexts->cards");
"memory for uds_client->contexts->cards");
return 0;
}
}
@ -498,6 +498,10 @@ scard_function_establish_context_return(void *user_data,
"app_context %d", app_context);
}
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, app_context);
out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */
@ -564,6 +568,10 @@ scard_function_release_context_return(void *user_data,
}
con = uds_client->con;
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */
s_mark_end(out_s);
@ -623,7 +631,6 @@ scard_process_list_readers(struct trans *con, struct stream *in_s)
{
LOG(LOG_LEVEL_ERROR, "scard_process_list_readers: "
"get_pcsc_context_by_app_context failed");
g_free(groups);
return 1;
}
pcscListReaders = g_new0(struct pcsc_list_readers, 1);
@ -723,6 +730,10 @@ scard_function_list_readers_return(void *user_data,
}
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, llen);
out_uint32_le(out_s, readers);
@ -826,6 +837,10 @@ scard_function_connect_return(void *user_data,
}
}
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, hCard);
out_uint32_le(out_s, dwActiveProtocol);
@ -894,6 +909,10 @@ scard_function_disconnect_return(void *user_data,
}
con = uds_client->con;
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */
s_mark_end(out_s);
@ -960,6 +979,10 @@ scard_function_begin_transaction_return(void *user_data,
}
con = uds_client->con;
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */
s_mark_end(out_s);
@ -1030,6 +1053,10 @@ scard_function_end_transaction_return(void *user_data,
con = uds_client->con;
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */
s_mark_end(out_s);
@ -1179,6 +1206,10 @@ scard_function_transmit_return(void *user_data,
}
LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_transmit_return: cbRecvLength %d", cbRecvLength);
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, recv_ior.dwProtocol);
out_uint32_le(out_s, recv_ior.cbPciLength);
@ -1274,6 +1305,10 @@ scard_function_control_return(void *user_data,
}
LOG_DEVEL(LOG_LEVEL_DEBUG, "scard_function_control_return: cbRecvLength %d", cbRecvLength);
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, cbRecvLength);
out_uint8a(out_s, recvBuf, cbRecvLength);
@ -1447,6 +1482,10 @@ scard_function_status_return(void *user_data,
"dwProtocol %d dwState %d name %s",
dwAtrLen, dwReaderLen, dwProtocol, dwState, lreader_name);
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
dwReaderLen = g_strlen(lreader_name);
out_uint32_le(out_s, dwReaderLen);
@ -1560,6 +1599,10 @@ scard_function_get_status_change_return(void *user_data,
con = uds_client->con;
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
if (status != 0)
{
@ -1650,6 +1693,10 @@ scard_function_cancel_return(void *user_data,
}
con = uds_client->con;
out_s = trans_get_out_s(con, 8192);
if (out_s == NULL)
{
return 1;
}
s_push_layer(out_s, iso_hdr, 8);
out_uint32_le(out_s, status); /* SCARD_S_SUCCESS status */
s_mark_end(out_s);
@ -1853,6 +1900,8 @@ scard_pcsc_init(void)
if (g_lis == 0)
{
g_lis = trans_create(2, 8192, 8192);
// TODO: See #2501. Use needs a way to move PCSCLITE_CSOCK_NAME
// to a location not under $HOME.
home = g_getenv("HOME");
disp = g_display_num;
g_snprintf(g_pcsclite_ipc_dir, 255, "%s/.pcsc%d", home, disp);
@ -1874,7 +1923,9 @@ scard_pcsc_init(void)
}
}
}
g_chmod_hex(g_pcsclite_ipc_dir, 0x1777);
/* Only the current user should be able to access the remote
* smartcard */
g_chmod_hex(g_pcsclite_ipc_dir, 0x700);
g_snprintf(g_pcsclite_ipc_file, 255, "%s/pcscd.comm", g_pcsclite_ipc_dir);
g_lis->trans_conn_in = my_pcsc_trans_conn_in;
error = trans_listen(g_lis, g_pcsclite_ipc_file);

View File

@ -369,14 +369,15 @@ sound_process_output_format(int aindex, int wFormatTag, int nChannels,
int nBlockAlign, int wBitsPerSample,
int cbSize, char *data)
{
LOG_DEVEL(LOG_LEVEL_INFO, "sound_process_output_format:");
LOG_DEVEL(LOG_LEVEL_INFO, " wFormatTag %d", wFormatTag);
LOG_DEVEL(LOG_LEVEL_INFO, " nChannels %d", nChannels);
LOG_DEVEL(LOG_LEVEL_INFO, " nSamplesPerSec %d", nSamplesPerSec);
LOG_DEVEL(LOG_LEVEL_INFO, " nAvgBytesPerSec %d", nAvgBytesPerSec);
LOG_DEVEL(LOG_LEVEL_INFO, " nBlockAlign %d", nBlockAlign);
LOG_DEVEL(LOG_LEVEL_INFO, " wBitsPerSample %d", wBitsPerSample);
LOG_DEVEL(LOG_LEVEL_INFO, " cbSize %d", cbSize);
LOG(LOG_LEVEL_INFO, "sound_process_output_format:");
LOG(LOG_LEVEL_INFO, " wFormatNo %d", aindex);
LOG(LOG_LEVEL_INFO, " wFormatTag %s", audin_wave_format_tag_to_str(wFormatTag));
LOG(LOG_LEVEL_INFO, " nChannels %d", nChannels);
LOG(LOG_LEVEL_INFO, " nSamplesPerSec %d", nSamplesPerSec);
LOG(LOG_LEVEL_INFO, " nAvgBytesPerSec %d", nAvgBytesPerSec);
LOG(LOG_LEVEL_INFO, " nBlockAlign %d", nBlockAlign);
LOG(LOG_LEVEL_INFO, " wBitsPerSample %d", wBitsPerSample);
LOG(LOG_LEVEL_INFO, " cbSize %d", cbSize);
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "", data, cbSize);
@ -898,6 +899,8 @@ sound_send_wave_data_chunk(char *data, int data_bytes)
format_index = g_current_client_format_index;
data_bytes = sound_wave_compress(data, data_bytes, &format_index);
LOG(LOG_LEVEL_TRACE, "sound_send_wave_data_chunk: wFormatNo %d", format_index);
/* part one of 2 PDU wave info */
LOG_DEVEL(LOG_LEVEL_DEBUG, "sound_send_wave_data_chunk: sending %d bytes", data_bytes);
@ -1057,7 +1060,7 @@ sound_process_wave_confirm(struct stream *s, int size)
in_uint8(s, cConfirmedBlockNo);
time_diff = time - g_sent_time[cConfirmedBlockNo & 0xff];
LOG(LOG_LEVEL_DEBUG, "sound_process_wave_confirm: wTimeStamp %d, "
LOG(LOG_LEVEL_TRACE, "sound_process_wave_confirm: wTimeStamp %d, "
"cConfirmedBlockNo %d time diff %d",
wTimeStamp, cConfirmedBlockNo, time_diff);
@ -1089,12 +1092,43 @@ sound_process_wave_confirm(struct stream *s, int size)
static int
process_pcm_message(int id, int size, struct stream *s)
{
static int sending_silence = 0;
static int silence_start_time = 0;
switch (id)
{
case 0:
if ((g_client_does_fdk_aac || g_client_does_mp3lame) && sending_silence)
{
if ((g_time3() - silence_start_time) < 1000)
{
/* do not send data within 1000mS after SNDC_CLOSE is sent. to avoid stutter */
return 0;
}
sending_silence = 0;
}
return sound_send_wave_data(s->p, size);
break;
case 1:
if ((g_client_does_fdk_aac || g_client_does_mp3lame) && sending_silence == 0)
{
/* workaround for mstsc.exe. send silence data before send close */
int send_silence_times = g_client_does_fdk_aac ? 4 : 2; /* This value comes by trial and error */
char *buf = (char *) g_malloc(g_bbuf_size, 0);
if (buf != NULL)
{
int i;
silence_start_time = g_time3();
sending_silence = 1;
for (i = 0; i < send_silence_times; i++)
{
g_memset(buf, 0, g_bbuf_size);
sound_send_wave_data_chunk(buf, g_bbuf_size);
}
free(buf);
g_time_diff = 0;
}
}
return sound_send_close();
break;
default:

View File

@ -61,7 +61,7 @@ config_read_globals(int file, struct config_sesman *cf, struct list *param_n,
cf->listen_address[0] = '\0';
cf->listen_port[0] = '\0';
cf->enable_user_wm = 0;
cf->user_wm[0] = '\0';
cf->user_wm = g_strdup("");
cf->default_wm = 0;
cf->auth_file_path = 0;
cf->reconnect_sh = 0;
@ -78,7 +78,8 @@ config_read_globals(int file, struct config_sesman *cf, struct list *param_n,
}
else if (0 == g_strcasecmp(buf, SESMAN_CFG_USERWM))
{
g_strncpy(cf->user_wm, (char *)list_get_item(param_v, i), 31);
g_free(cf->user_wm);
cf->user_wm = g_strdup((char *)list_get_item(param_v, i));
}
else if (0 == g_strcasecmp(buf, SESMAN_CFG_ENABLE_USERWM))
{
@ -212,6 +213,7 @@ config_read_security(int file, struct config_security *sc,
sc->ts_admins_enable = 0;
sc->restrict_outbound_clipboard = 0;
sc->restrict_inbound_clipboard = 0;
sc->allow_alternate_shell = 1;
file_read_section(file, SESMAN_CFG_SECURITY, param_n, param_v);
@ -279,6 +281,11 @@ config_read_security(int file, struct config_security *sc,
unrecognised);
}
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ALLOW_ALTERNATE_SHELL))
{
sc->allow_alternate_shell =
g_text2bool((char *)list_get_item(param_v, i));
}
}
@ -602,6 +609,7 @@ config_dump(struct config_sesman *config)
g_writeln(" AllowRootLogin: %d", sc->allow_root);
g_writeln(" MaxLoginRetry: %d", sc->login_retry);
g_writeln(" AlwaysGroupCheck: %d", sc->ts_always_group_check);
g_writeln(" AllowAlternateShell: %d", sc->allow_alternate_shell);
if (sc->restrict_outbound_clipboard == CLIP_RESTRICT_NONE)
{
g_writeln(" RestrictOutboundClipboard: %s", "none");
@ -714,6 +722,7 @@ config_free(struct config_sesman *cs)
{
g_free(cs->sesman_ini);
g_free(cs->default_wm);
g_free(cs->user_wm);
g_free(cs->reconnect_sh);
g_free(cs->auth_file_path);
list_delete(cs->rdp_params);

View File

@ -62,6 +62,7 @@
#define SESMAN_CFG_SEC_ALWAYSGROUPCHECK "AlwaysGroupCheck"
#define SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD "RestrictOutboundClipboard"
#define SESMAN_CFG_SEC_RESTRICT_INBOUND_CLIPBOARD "RestrictInboundClipboard"
#define SESMAN_CFG_SEC_ALLOW_ALTERNATE_SHELL "AllowAlternateShell"
#define SESMAN_CFG_SESSIONS "Sessions"
#define SESMAN_CFG_SESS_MAX "MaxSessions"
@ -141,6 +142,15 @@ struct config_security
* @brief if the clipboard should be enforced restricted. If true only allow server -> client, not vice versa.
*/
int restrict_inbound_clipboard;
/**
* @var allow_alternate_shell
* @brief allow an user-supplied alternate shell.
* @details 'YES' for all programs allowed, 'NO' for disabling of alternate
* shells.
* If not specified, 'YES' is assumed.
*/
int allow_alternate_shell;
};
/**
@ -223,9 +233,9 @@ struct config_sesman
char *default_wm;
/**
* @var user_wm
* @brief Default window manager
* @brief Default window manager.
*/
char user_wm[32];
char *user_wm;
/**
* @var reconnect_sh
* @brief Script executed when reconnected

View File

@ -427,6 +427,21 @@ scp_session_set_guid(struct SCP_SESSION *s, const struct guid *guid)
return 0;
}
/*******************************************************************/
static void
clear_and_free_string(char *p)
{
if (p != NULL)
{
char *cp;
for (cp = p ; *cp != '\0'; ++cp)
{
*cp = '\0';
}
g_free(p);
}
}
/*******************************************************************/
void
scp_session_destroy(struct SCP_SESSION *s)
@ -434,7 +449,7 @@ scp_session_destroy(struct SCP_SESSION *s)
if (s != NULL)
{
g_free(s->username);
g_free(s->password);
clear_and_free_string(s->password);
g_free(s->hostname);
g_free(s->domain);
g_free(s->program);

View File

@ -225,7 +225,7 @@ scp_v0c_reply_available(struct trans *trans)
if (trans != NULL && trans->status == TRANS_STATUS_UP)
{
/* Have we read enough data from the stream? */
if ((trans->in_s->end - trans->in_s->data) < trans->header_size)
if ((unsigned int)(trans->in_s->end - trans->in_s->data) < trans->header_size)
{
result = 0;
}

View File

@ -567,8 +567,9 @@ print_version(void)
{
g_writeln("xrdp-sesman %s", PACKAGE_VERSION);
g_writeln(" The xrdp session manager");
g_writeln(" Copyright (C) 2004-2020 Jay Sorg, "
"Neutrino Labs, and all contributors.");
g_writeln(" Copyright (C) 2004-%d Jay Sorg, "
"Neutrino Labs, and all contributors.",
VERSION_YEAR);
g_writeln(" See https://github.com/neutrinolabs/xrdp for more information.");
g_writeln("%s", "");
@ -588,7 +589,7 @@ print_help(void)
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_printf(" --dump-config display config on stdout on startup\n");
g_deinit();
}
@ -704,21 +705,13 @@ main(int argc, char **argv)
g_exit(1);
}
/* reading config */
if ((g_cfg = config_read(startup_params.sesman_ini)) == NULL)
/* starting logging subsystem */
if (!g_file_exist(startup_params.sesman_ini))
{
g_printf("error reading config %s: %s\nquitting.\n",
startup_params.sesman_ini, g_get_strerror());
g_printf("Config file %s does not exist\n", startup_params.sesman_ini);
g_deinit();
g_exit(1);
}
if (startup_params.dump_config)
{
config_dump(g_cfg);
}
/* starting logging subsystem */
log_error = log_start(
startup_params.sesman_ini, "xrdp-sesman",
(startup_params.dump_config) ? LOG_START_DUMP_CONFIG : 0);
@ -735,15 +728,29 @@ main(int argc, char **argv)
getLogFile(text, 255));
break;
default:
g_writeln("error");
// Assume sufficient messages have already been generated
break;
}
config_free(g_cfg);
g_deinit();
g_exit(1);
}
/* reading config */
if ((g_cfg = config_read(startup_params.sesman_ini)) == NULL)
{
LOG(LOG_LEVEL_ALWAYS, "error reading config %s: %s",
startup_params.sesman_ini, g_get_strerror());
log_end();
g_deinit();
g_exit(1);
}
if (startup_params.dump_config)
{
config_dump(g_cfg);
}
LOG(LOG_LEVEL_TRACE, "config loaded in %s at %s:%d", __func__, __FILE__, __LINE__);
LOG(LOG_LEVEL_TRACE, " sesman_ini = %s", g_cfg->sesman_ini);
LOG(LOG_LEVEL_TRACE, " listen_address = %s", g_cfg->listen_address);

View File

@ -37,6 +37,8 @@ RestrictOutboundClipboard=none
; false: an alias of none
; yes: an alias of all
RestrictInboundClipboard=none
; Set to 'no' to prevent users from logging in with alternate shells
#AllowAlternateShell=true
[Sessions]
;; X11DisplayOffset - x11 display number offset
@ -100,7 +102,7 @@ EnableSyslog=true
[Xorg]
; Specify the path of non-suid Xorg executable. It might differ depending
; on your distribution and version. Find out the appropreate path for your
; on your distribution and version. Find out the appropriate path for your
; environment. The typical path is known as follows:
;
; Fedora 26 or later : param=/usr/libexec/Xorg
@ -109,9 +111,10 @@ EnableSyslog=true
; Arch Linux : param=/usr/lib/Xorg
; CentOS 7 : param=/usr/bin/Xorg or param=Xorg
; CentOS 8 : param=/usr/libexec/Xorg
; FreeBSD (from 2022Q4) : param=/usr/local/libexec/Xorg
;
param=Xorg
; Leave the rest paramaters as-is unless you understand what will happen.
; Leave the rest parameters as-is unless you understand what will happen.
param=-config
param=xrdp/xorg.conf
param=-noreset
@ -135,7 +138,7 @@ param=96
#FuseMountName=/run/user/%u/thinclient_drives
#FuseMountName=/media/thinclient_drives/%U/thinclient_drives
FuseMountName=thinclient_drives
; this value allows only the user to acess their own mapped drives.
; this value allows only the user to access their own mapped drives.
; Make this more permissive (e.g. 022) if required.
FileUmask=077
; Can be used to disable FUSE functionality - see sesman.ini(5)
@ -146,8 +149,8 @@ FileUmask=077
#UseNautilus3FlistFormat=true
[ChansrvLogging]
; Note: one log file is created per display and the LogFile config value
; is ignored. The channel server log file names follow the naming convention:
; Note: one log file is created per display and the LogFile config value
; is ignored. The channel server log file names follow the naming convention:
; xrdp-chansrv.${DISPLAY}.log
;
; Note: Log levels can be any of: core, error, warning, info, debug, or trace

View File

@ -445,7 +445,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
struct list *xserver_params = (struct list *)NULL;
struct tm stime;
time_t ltime;
char authfile[256]; /* The filename for storing xauth informations */
char authfile[256]; /* The filename for storing xauth information */
int chansrv_pid;
int display_pid;
int window_manager_pid;
@ -526,7 +526,12 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
g_delete_wait_obj(g_sigchld_event);
g_delete_wait_obj(g_term_event);
auth_start_session(data, display);
if (auth_start_session(data, display) != 0)
{
// Errors are logged by the auth module, as they are
// specific to that module
g_exit(1);
}
sesman_close_all();
g_sprintf(geometry, "%dx%d", s->width, s->height);
g_sprintf(depth, "%d", s->bpp);
@ -574,7 +579,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
g_exit(0);
/*
* intermediate sesman should exit here after WM exits.
* do not execure the following codes.
* do not execute the following codes.
*/
}
#endif
@ -596,30 +601,47 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
if (x_server_running(display))
{
auth_set_env(data);
if (s->directory != 0)
if (s->directory != 0 && s->directory[0] != 0)
{
if (s->directory[0] != 0)
if (g_cfg->sec.allow_alternate_shell)
{
g_set_current_dir(s->directory);
}
else
{
LOG(LOG_LEVEL_WARNING,
"Directory change to %s requested, but not "
"allowed by AllowAlternateShell config value.",
s->directory);
}
}
if (s->program != 0 && s->program[0] != 0)
{
if (g_strchr(s->program, ' ') != 0 || g_strchr(s->program, '\t') != 0)
if (g_cfg->sec.allow_alternate_shell)
{
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);
if (g_strchr(s->program, ' ') != 0 || g_strchr(s->program, '\t') != 0)
{
LOG(LOG_LEVEL_INFO,
"Starting user requested window manager on "
"display %d with embedded 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_INFO,
"Starting user requested window manager on "
"display %d: %s", display, s->program);
g_execlp3(s->program, s->program, 0);
LOG(LOG_LEVEL_WARNING,
"Shell %s requested by user, but not allowed by "
"AllowAlternateShell config value.",
s->program);
}
}
else
@ -636,7 +658,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
{
LOG(LOG_LEVEL_INFO,
"Starting window manager on display %d"
"from user home directory: %s", display, text);
" from user home directory: %s", display, text);
g_execlp3(text, g_cfg->user_wm, 0);
}
else
@ -668,7 +690,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
"There is no X server active on display %d", display);
}
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting to start "
LOG(LOG_LEVEL_ERROR, "A fatal error has occurred attempting to start "
"the window manager on display %d, aborting connection",
display);
g_exit(0);
@ -727,7 +749,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
"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 "
LOG(LOG_LEVEL_ERROR, "A fatal error has occurred attempting to start "
"the X server on display %d, aborting connection",
display);
g_exit(1);
@ -842,7 +864,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
else
{
LOG(LOG_LEVEL_ERROR, "Unknown session type: %d", type);
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
LOG(LOG_LEVEL_ERROR, "A fatal error has occurred attempting "
"to start the X server on display %d, aborting connection",
display);
g_exit(1);
@ -856,7 +878,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
/* should not get here */
LOG(LOG_LEVEL_ERROR,
"Error starting X server on display %d", display);
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
LOG(LOG_LEVEL_ERROR, "A fatal error has occurred attempting "
"to start the X server on display %d, aborting connection",
display);

View File

@ -10,7 +10,7 @@
# Execution sequence for interactive login shell - pseudocode
#
# IF /etc/profile is readable THEN
# execute ~/.bash_profile
# execute /etc/profile
# END IF
# IF ~/.bash_profile is readable THEN
# execute ~/.bash_profile
@ -42,7 +42,7 @@ pre_start()
return 0
}
# When loging out from the interactive shell, the execution sequence is:
# When logging out from the interactive shell, the execution sequence is:
#
# IF ~/.bash_logout exists THEN
# execute ~/.bash_logout

View File

@ -4,6 +4,7 @@ AM_CPPFLAGS = \
-DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
-DXRDP_PAMCONF_PATH=\"${pamconfdir}\" \
-I$(top_srcdir)/common \
-I$(top_srcdir)/sesman/libscp \
-I$(top_srcdir)/sesman

View File

@ -42,6 +42,11 @@
#include "libscp_connection.h"
// cppcheck doesn't always set this macro to something in double-quotes
#if defined(__cppcheck__)
#undef PACKAGE_VERSION
#endif
#if !defined(PACKAGE_VERSION)
#define PACKAGE_VERSION "???"
#endif
@ -391,7 +396,7 @@ parse_program_args(int argc, char *argv[], struct session_params *sp,
if (argc <= optind)
{
LOG(LOG_LEVEL_ERROR, "No user name speciified");
LOG(LOG_LEVEL_ERROR, "No user name specified");
params_ok = 0;
}
else if ((argc - optind) > 1)

View File

@ -36,21 +36,17 @@
#include <stdio.h>
#include <security/pam_appl.h>
/* Defines the maximum size of a username or password. With pam there is no real limit */
#define MAX_BUF 8192
/* Allows the conversation function to find the username and password */
struct t_user_pass
{
char user[MAX_BUF];
char pass[MAX_BUF];
const char *user;
const char *pass;
};
struct t_auth_info
{
struct t_user_pass user_pass;
int session_opened;
int did_setcred;
struct pam_conv pamc;
pam_handle_t *ph;
};
@ -148,7 +144,18 @@ verify_pam_conv(int num_msg, const struct pam_message **msg,
{
case PAM_PROMPT_ECHO_OFF: /* password */
user_pass = (struct t_user_pass *) appdata_ptr;
reply[i].resp = g_strdup(user_pass->pass);
/* Check this function isn't being called
* later than we expected */
if (user_pass == NULL)
{
LOG(LOG_LEVEL_ERROR,
"verify_pam_conv: Password unavailable");
reply[i].resp = g_strdup("????");
}
else
{
reply[i].resp = g_strdup(user_pass->pass);
}
break;
case PAM_ERROR_MSG:
@ -197,7 +204,15 @@ get_service_name(char *service_name)
service_name[0] = 0;
if (g_file_exist("/etc/pam.d/xrdp-sesman") ||
g_file_exist(XRDP_SYSCONF_PATH "/pam.d/xrdp-sesman"))
#ifdef __LINUX_PAM__
/* /usr/lib/pam.d is hardcoded into Linux-PAM */
g_file_exist("/usr/lib/pam.d/xrdp-sesman") ||
#endif
#ifdef OPENPAM_VERSION
/* /usr/local/etc/pam.d is hardcoded into OpenPAM */
g_file_exist("/usr/local/etc/pam.d/xrdp-sesman") ||
#endif
g_file_exist(XRDP_PAMCONF_PATH "/xrdp-sesman"))
{
g_strncpy(service_name, "xrdp-sesman", 255);
}
@ -217,14 +232,19 @@ auth_userpass(const char *user, const char *pass, int *errorcode)
int error;
struct t_auth_info *auth_info;
char service_name[256];
struct t_user_pass user_pass = {user, pass};
struct pam_conv pamc = {verify_pam_conv, (void *) &user_pass};
auth_info = g_new0(struct t_auth_info, 1);
if (auth_info == NULL)
{
LOG(LOG_LEVEL_ERROR, "auth_userpass: No memory");
error = PAM_BUF_ERR;
return 0;
}
get_service_name(service_name);
auth_info = g_new0(struct t_auth_info, 1);
g_strncpy(auth_info->user_pass.user, user, MAX_BUF - 1);
g_strncpy(auth_info->user_pass.pass, pass, MAX_BUF - 1);
auth_info->pamc.conv = &verify_pam_conv;
auth_info->pamc.appdata_ptr = &(auth_info->user_pass);
error = pam_start(service_name, user, &(auth_info->pamc), &(auth_info->ph));
error = pam_start(service_name, user, &pamc, &(auth_info->ph));
if (error != PAM_SUCCESS)
{
@ -281,13 +301,23 @@ auth_userpass(const char *user, const char *pass, int *errorcode)
return 0;
}
/* Set the appdata_ptr passed to the conversation function to
* NULL, as the existing value is going out of scope */
pamc.appdata_ptr = NULL;
error = pam_set_item(auth_info->ph, PAM_CONV, &pamc);
if (error != PAM_SUCCESS)
{
LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_CONV) failed: %s",
pam_strerror(auth_info->ph, error));
}
return (long)auth_info;
}
/******************************************************************************/
/* returns error */
int
auth_start_session(long in_val, int in_display)
static int
auth_start_session_private(long in_val, int in_display)
{
struct t_auth_info *auth_info;
int error;
@ -327,6 +357,26 @@ auth_start_session(long in_val, int in_display)
return 0;
}
/******************************************************************************/
/**
* Main routine to start a session
*
* Calls the private routine and logs an additional error if the private
* routine fails
*/
int
auth_start_session(long in_val, int in_display)
{
int result = auth_start_session_private(in_val, in_display);
if (result != 0)
{
LOG(LOG_LEVEL_ERROR,
"Can't start PAM session. See PAM logging for more info");
}
return result;
}
/******************************************************************************/
/* returns error */
int
@ -389,9 +439,6 @@ auth_set_env(long in_val)
struct t_auth_info *auth_info;
char **pam_envlist;
char **pam_env;
char item[256];
char value[256];
int eq_pos;
auth_info = (struct t_auth_info *)in_val;
@ -404,16 +451,16 @@ auth_set_env(long in_val)
{
for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env)
{
eq_pos = g_pos(*pam_env, "=");
char *str = *pam_env;
int eq_pos = g_pos(str, "=");
if (eq_pos >= 0 && eq_pos < 250)
if (eq_pos > 0)
{
g_strncpy(item, *pam_env, eq_pos);
g_strncpy(value, (*pam_env) + eq_pos + 1, 255);
g_setenv(item, value, 1);
str[eq_pos] = '\0';
g_setenv(str, str + eq_pos + 1, 1);
}
g_free(*pam_env);
g_free(str);
}
g_free(pam_envlist);

View File

@ -42,7 +42,7 @@ int
auth_userpass(const char *user, const char *pass, int *errorcode)
{
pam_handle_t *pamh;
pam_userpass_t userpass;
pam_userpass_t userpass = NULL;
struct pam_conv conv = {pam_userpass_conv, &userpass};
const void *template1;
int status;

View File

@ -14,6 +14,7 @@ check_PROGRAMS = test_common
test_common_SOURCES = \
test_common.h \
test_common_main.c \
test_list_calls.c \
test_string_calls.c \
test_os_calls.c \
test_ssl_calls.c \

View File

@ -7,6 +7,7 @@
char *
bin_to_hex(const char *input, int length);
Suite *make_suite_test_list(void);
Suite *make_suite_test_string(void);
Suite *make_suite_test_os_calls(void);
Suite *make_suite_test_ssl_calls(void);

View File

@ -45,11 +45,11 @@ int main (void)
int number_failed;
SRunner *sr;
sr = srunner_create (make_suite_test_string());
sr = srunner_create (make_suite_test_list());
srunner_add_suite(sr, make_suite_test_string());
srunner_add_suite(sr, make_suite_test_os_calls());
srunner_add_suite(sr, make_suite_test_ssl_calls());
srunner_add_suite(sr, make_suite_test_base64());
// srunner_add_suite(sr, make_list_suite());
srunner_set_tap(sr, "-");
/*

View File

@ -0,0 +1,137 @@
#if defined(HAVE_CONFIG_H)
#include "config_ac.h"
#endif
#include "list.h"
#include "test_common.h"
#include "os_calls.h"
#include "string_calls.h"
#define TEST_LIST_SIZE 1000
START_TEST(test_list__simple)
{
struct list *lst = list_create();
int i;
int val;
for (i = 0 ; i < TEST_LIST_SIZE ; ++i)
{
list_add_item(lst, i);
}
ck_assert_int_eq(lst->count, TEST_LIST_SIZE);
for (i = 0 ; i < TEST_LIST_SIZE ; ++i)
{
ck_assert_int_eq(lst->items[i], i);
// Also check get method
val = list_get_item(lst, i);
ck_assert_int_eq(val, i);
}
i = list_index_of(lst, 50);
ck_assert_int_eq(i, 50);
list_remove_item(lst, 10);
ck_assert_int_eq(lst->count, TEST_LIST_SIZE - 1);
val = list_get_item(lst, 10);
ck_assert_int_eq(val, 11);
list_insert_item(lst, 10, 10);
ck_assert_int_eq(lst->count, TEST_LIST_SIZE);
val = list_get_item(lst, 10);
ck_assert_int_eq(val, 10);
list_insert_item(lst, 0, 99);
ck_assert_int_eq(lst->count, TEST_LIST_SIZE + 1);
val = list_get_item(lst, 10);
ck_assert_int_eq(val, 9);
list_clear(lst);
ck_assert_int_eq(lst->count, 0);
list_delete(lst);
}
END_TEST
// This needs to be run through valgrind to truly check all memory is
// being de-allocated
START_TEST(test_list__simple_auto_free)
{
struct list *lst = list_create();
lst->auto_free = 1;
int i;
for (i = 0 ; i < TEST_LIST_SIZE ; ++i)
{
char strval[64];
g_snprintf(strval, sizeof(strval), "%d", i);
list_add_item(lst, (tintptr)g_strdup(strval));
}
list_remove_item(lst, 0);
list_remove_item(lst, 0);
list_remove_item(lst, 0);
list_remove_item(lst, 0);
list_remove_item(lst, 0);
ck_assert_int_eq(lst->count, TEST_LIST_SIZE - 5);
list_delete(lst);
}
END_TEST
START_TEST(test_list__simple_append_list)
{
int i;
struct list *src = list_create();
struct list *dst = list_create();
src->auto_free = 0;
dst->auto_free = 1;
list_add_item(src, (tintptr)"6");
list_add_item(src, (tintptr)"7");
list_add_item(src, (tintptr)"8");
list_add_item(src, (tintptr)"9");
list_add_item(src, (tintptr)"10");
list_add_item(src, (tintptr)"11");
list_add_item(dst, (tintptr)g_strdup("0"));
list_add_item(dst, (tintptr)g_strdup("1"));
list_add_item(dst, (tintptr)g_strdup("2"));
list_add_item(dst, (tintptr)g_strdup("3"));
list_add_item(dst, (tintptr)g_strdup("4"));
list_add_item(dst, (tintptr)g_strdup("5"));
list_append_list_strdup(src, dst, 0);
ck_assert_int_eq(dst->count, 12);
for (i = 0 ; i < dst->count; ++i)
{
int val = g_atoi((const char *)list_get_item(dst, i));
ck_assert_int_eq(val, i);
}
list_delete(src);
list_clear(dst); // Exercises auto_free code paths in list.c
list_delete(dst);
}
END_TEST
/******************************************************************************/
Suite *
make_suite_test_list(void)
{
Suite *s;
TCase *tc_simple;
s = suite_create("List");
tc_simple = tcase_create("simple");
suite_add_tcase(s, tc_simple);
tcase_add_test(tc_simple, test_list__simple);
tcase_add_test(tc_simple, test_list__simple_auto_free);
tcase_add_test(tc_simple, test_list__simple_append_list);
return s;
}

View File

@ -9,6 +9,11 @@
#include "test_common.h"
/* Time to allow RSA-based test suites to run on older, slower platforms
*
* These platforms are most often seen on build farms (e.g. Debian CI) */
#define RSA_BASED_TEST_SUITE_TIMEOUT 60
START_TEST(test_rc4_enc_ok)
{
const char *key = "16_byte_key-----";
@ -369,23 +374,39 @@ Suite *
make_suite_test_ssl_calls(void)
{
Suite *s;
TCase *tc_ssl_calls;
TCase *tc;
s = suite_create("SSL-Calls");
tc_ssl_calls = tcase_create("ssl_calls");
suite_add_tcase(s, tc_ssl_calls);
tcase_add_test(tc_ssl_calls, test_rc4_enc_ok);
tcase_add_test(tc_ssl_calls, test_rc4_enc_tv0_ok);
tcase_add_test(tc_ssl_calls, test_rc4_enc_tv1_ok);
tcase_add_test(tc_ssl_calls, test_rc4_enc_tv2_ok);
tcase_add_test(tc_ssl_calls, test_rc4_enc_tv3_ok);
tcase_add_test(tc_ssl_calls, test_rc4_enc_tv4_ok);
tcase_add_test(tc_ssl_calls, test_sha1_hash_ok);
tcase_add_test(tc_ssl_calls, test_md5_hash_ok);
tcase_add_test(tc_ssl_calls, test_des3_enc_ok);
tcase_add_test(tc_ssl_calls, test_hmac_sha1_dgst_ok);
tcase_add_test(tc_ssl_calls, test_gen_key_xrdp1);
tc = tcase_create("ssl_calls_rc4");
suite_add_tcase(s, tc);
tcase_add_test(tc, test_rc4_enc_ok);
tcase_add_test(tc, test_rc4_enc_tv0_ok);
tcase_add_test(tc, test_rc4_enc_tv1_ok);
tcase_add_test(tc, test_rc4_enc_tv2_ok);
tcase_add_test(tc, test_rc4_enc_tv3_ok);
tcase_add_test(tc, test_rc4_enc_tv4_ok);
tc = tcase_create("ssl_calls_sha1");
suite_add_tcase(s, tc);
tcase_add_test(tc, test_sha1_hash_ok);
tc = tcase_create("ssl_calls_md5");
suite_add_tcase(s, tc);
tcase_add_test(tc, test_md5_hash_ok);
tc = tcase_create("ssl_calls_des3");
suite_add_tcase(s, tc);
tcase_add_test(tc, test_des3_enc_ok);
tc = tcase_create("ssl_calls_hmac_sha1");
suite_add_tcase(s, tc);
tcase_add_test(tc, test_hmac_sha1_dgst_ok);
tc = tcase_create("ssl_calls_rsa_key");
suite_add_tcase(s, tc);
tcase_set_timeout(tc, RSA_BASED_TEST_SUITE_TIMEOUT);
tcase_add_test(tc, test_gen_key_xrdp1);
return s;
}

View File

@ -3,7 +3,6 @@
#endif
#include <stdlib.h>
#include <check.h>
#include "test_libxrdp.h"
int main (void)

View File

@ -45,6 +45,9 @@ static int WHITE = COLOR24RGB(255, 255, 255);
* be considered close enough to each other */
#define MAX_SIMILAR_COLOR_DISTANCE 3
/* Time to allow some large bitmap test suites to run on slower platforms */
#define LARGE_BM_TEST_SUITE_TIMEOUT 10
void setup(void)
{
}
@ -301,37 +304,48 @@ Suite *
make_suite_test_bitmap_load(void)
{
Suite *s;
TCase *tc_bitmap_load;
#ifdef USE_IMLIB2
TCase *tc_other_load;
#endif
TCase *tc;
s = suite_create("BitmapLoad");
tc_bitmap_load = tcase_create("xrdp_bitmap_load");
tcase_add_checked_fixture(tc_bitmap_load, setup, teardown);
tcase_add_test(tc_bitmap_load, test_bitmap_load__with_invalid_image__fail);
tcase_add_test(tc_bitmap_load, test_bitmap_load__4_bit__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__8_bit__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__24_bit__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__max_width_zoom__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__max_height_zoom__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__min_zoom__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__max_width_scale__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__max_height_scale__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__min_scale__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__not_4_pixels_wide_4_bit__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__not_4_pixels_wide_8_bit__ok);
tcase_add_test(tc_bitmap_load, test_bitmap_load__not_4_pixels_wide_24_bit__ok);
tc = tcase_create("xrdp_bitmap_load_basic");
suite_add_tcase(s, tc);
tcase_add_checked_fixture(tc, setup, teardown);
tcase_add_test(tc, test_bitmap_load__with_invalid_image__fail);
tcase_add_test(tc, test_bitmap_load__4_bit__ok);
tcase_add_test(tc, test_bitmap_load__8_bit__ok);
tcase_add_test(tc, test_bitmap_load__24_bit__ok);
tc = tcase_create("xrdp_bitmap_load_zoom");
suite_add_tcase(s, tc);
tcase_add_checked_fixture(tc, setup, teardown);
tcase_set_timeout(tc, LARGE_BM_TEST_SUITE_TIMEOUT);
tcase_add_test(tc, test_bitmap_load__max_width_zoom__ok);
tcase_add_test(tc, test_bitmap_load__max_height_zoom__ok);
tcase_add_test(tc, test_bitmap_load__min_zoom__ok);
tc = tcase_create("xrdp_bitmap_load_scale");
suite_add_tcase(s, tc);
tcase_add_checked_fixture(tc, setup, teardown);
tcase_set_timeout(tc, LARGE_BM_TEST_SUITE_TIMEOUT);
tcase_add_test(tc, test_bitmap_load__max_width_scale__ok);
tcase_add_test(tc, test_bitmap_load__max_height_scale__ok);
tcase_add_test(tc, test_bitmap_load__min_scale__ok);
tc = tcase_create("xrdp_bitmap_load_not_mod_4");
suite_add_tcase(s, tc);
tcase_add_checked_fixture(tc, setup, teardown);
tcase_add_test(tc, test_bitmap_load__not_4_pixels_wide_4_bit__ok);
tcase_add_test(tc, test_bitmap_load__not_4_pixels_wide_8_bit__ok);
tcase_add_test(tc, test_bitmap_load__not_4_pixels_wide_24_bit__ok);
suite_add_tcase(s, tc_bitmap_load);
#ifdef USE_IMLIB2
tc_other_load = tcase_create("xrdp_other_load");
tcase_add_checked_fixture(tc_other_load, setup, teardown);
tcase_add_test(tc_other_load, test_png_load__blend_ok);
tcase_add_test(tc_other_load, test_jpg_load__ok);
suite_add_tcase(s, tc_other_load);
tc = tcase_create("xrdp_other_load");
suite_add_tcase(s, tc);
tcase_add_checked_fixture(tc, setup, teardown);
tcase_add_test(tc, test_png_load__blend_ok);
tcase_add_test(tc, test_jpg_load__ok);
#endif
return s;

View File

@ -425,7 +425,7 @@ resize_client(struct vnc *v, int update_in_progress, int width, int height)
*
* This has some limitations. We have no way to move multiple screens about
* on a connected client, and so we are not able to change the client unless
* we're changing to a single screeen layout.
* we're changing to a single screen layout.
*/
static int
resize_client_from_layout(struct vnc *v,
@ -547,42 +547,65 @@ lib_mod_event(struct vnc *v, int msg, long param1, long param2,
}
}
}
else if (msg >= 100 && msg <= 110) /* mouse events */
/* mouse events
*
* VNC supports up to 8 mouse buttons because mouse buttons are
* represented by 7 bits bitmask
*/
else if (msg >= WM_MOUSEMOVE && msg <= WM_BUTTON8DOWN) /* 100 to 116 */
{
switch (msg)
{
case 100:
break; /* WM_MOUSEMOVE */
case 101:
case WM_MOUSEMOVE:
break;
case WM_LBUTTONUP:
v->mod_mouse_state &= ~1;
break; /* WM_LBUTTONUP */
case 102:
break;
case WM_LBUTTONDOWN:
v->mod_mouse_state |= 1;
break; /* WM_LBUTTONDOWN */
case 103:
break;
case WM_RBUTTONUP:
v->mod_mouse_state &= ~4;
break; /* WM_RBUTTONUP */
case 104:
break;
case WM_RBUTTONDOWN:
v->mod_mouse_state |= 4;
break; /* WM_RBUTTONDOWN */
case 105:
break;
case WM_BUTTON3UP:
v->mod_mouse_state &= ~2;
break;
case 106:
case WM_BUTTON3DOWN:
v->mod_mouse_state |= 2;
break;
case 107:
case WM_BUTTON4UP:
v->mod_mouse_state &= ~8;
break;
case 108:
case WM_BUTTON4DOWN:
v->mod_mouse_state |= 8;
break;
case 109:
case WM_BUTTON5UP:
v->mod_mouse_state &= ~16;
break;
case 110:
case WM_BUTTON5DOWN:
v->mod_mouse_state |= 16;
break;
case WM_BUTTON6UP:
v->mod_mouse_state &= ~32;
break;
case WM_BUTTON6DOWN:
v->mod_mouse_state |= 32;
break;
case WM_BUTTON7UP:
v->mod_mouse_state &= ~64;
break;
case WM_BUTTON7DOWN:
v->mod_mouse_state |= 64;
break;
case WM_BUTTON8UP:
v->mod_mouse_state &= ~128;
break;
case WM_BUTTON8DOWN:
v->mod_mouse_state |= 128;
break;
}
init_stream(s, 8192);

View File

@ -32,7 +32,7 @@ class Decoder : public QObject
signals:
public slots:
public slots: // cppcheck-suppress unknownMacro
void onGeometryChanged(QRect *geometry);
};

View File

@ -19,7 +19,7 @@ class DlgAbout : public QDialog
private:
Ui::DlgAbout *ui;
private slots:
private slots: // cppcheck-suppress unknownMacro
void onOk();
};

View File

@ -42,7 +42,7 @@ class PlayAudio : public QObject
void setVcrOp(int op);
public slots:
public slots: // cppcheck-suppress unknownMacro
void play();
private:

View File

@ -46,7 +46,7 @@ class PlayVideo : public QObject
//void setVcrOp(int op);
//void onMediaRestarted();
public slots:
public slots: // cppcheck-suppress unknownMacro
void play();
//signals:

View File

@ -55,8 +55,9 @@ print_version(void)
{
g_writeln("xrdp %s", PACKAGE_VERSION);
g_writeln(" A Remote Desktop Protocol Server.");
g_writeln(" Copyright (C) 2004-2020 Jay Sorg, "
"Neutrino Labs, and all contributors.");
g_writeln(" Copyright (C) 2004-%d Jay Sorg, "
"Neutrino Labs, and all contributors.",
VERSION_YEAR);
g_writeln(" See https://github.com/neutrinolabs/xrdp for more information.");
g_writeln("%s", "");
@ -144,7 +145,7 @@ g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1,
/*****************************************************************************/
/* Signal handler for SIGINT and SIGTERM
* Note: only signal safe code (eg. setting wait event) should be executed in
* this funciton. For more details see `man signal-safety`
* this function. For more details see `man signal-safety`
*/
static void
xrdp_shutdown(int sig)
@ -158,7 +159,7 @@ xrdp_shutdown(int sig)
/*****************************************************************************/
/* Signal handler for SIGCHLD
* Note: only signal safe code (eg. setting wait event) should be executed in
* this funciton. For more details see `man signal-safety`
* this function. For more details see `man signal-safety`
*/
static void
xrdp_child(int sig)
@ -171,7 +172,7 @@ xrdp_child(int sig)
/*****************************************************************************/
/* No-op signal handler.
* Note: only signal safe code (eg. setting wait event) should be executed in
* this funciton. For more details see `man signal-safety`
* this function. For more details see `man signal-safety`
*/
static void
xrdp_sig_no_op(int sig)

View File

@ -119,6 +119,8 @@ xrdp_wm_get_vis_region(struct xrdp_wm *self, struct xrdp_bitmap *bitmap,
int
xrdp_wm_mouse_move(struct xrdp_wm *self, int x, int y);
int
xrdp_wm_mouse_touch(struct xrdp_wm *self, int gesture, int param);
int
xrdp_wm_mouse_click(struct xrdp_wm *self, int x, int y, int but, int down);
int
xrdp_wm_key(struct xrdp_wm *self, int device_flags, int scan_code);
@ -345,6 +347,15 @@ xrdp_font_delete(struct xrdp_font *self);
int
xrdp_font_item_compare(struct xrdp_font_char *font1,
struct xrdp_font_char *font2);
/**
* Gets a checked xrdp_font_char from a font
* @param f Font
* @param c32 Unicode codepoint
*/
#define XRDP_FONT_GET_CHAR(f, c32) \
(((unsigned int)(c32) >= ' ') && ((unsigned int)(c32) < (f)->char_count) \
? ((f)->chars + (unsigned int)(c32)) \
: (f)->default_char)
/* funcs.c */
int

View File

@ -205,7 +205,6 @@ drdynvc=true
cliprdr=true
rail=true
xrdpvr=true
tcutils=true
; for debugging xrdp, in section xrdp1, change port=-1 to this:
#port=/tmp/.xrdp/xrdp_display_10

View File

@ -607,7 +607,7 @@ xrdp_bitmap_load_bmp(struct xrdp_bitmap *self, const char *filename,
}
/* Validate the bit count for the file, read any palette, and
* dtermine the row size and row processing function */
* determine the row size and row processing function */
switch (header.bit_count)
{
case 24:
@ -749,7 +749,7 @@ log_imlib2_error(enum logLevels level, const char *filename,
msg = " No memory";
break;
case IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS:
msg = "No file decriptors";
msg = "No file descriptors";
break;
case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE:
msg = "No disk space";

View File

@ -65,6 +65,12 @@ static char w_char[] =
};
#endif
// Unicode definitions
#define UNICODE_WHITE_SQUARE 0x25a1
// First character allocated in the 'struct xrdp_font.chars' array
#define FIRST_CHAR ' '
/*****************************************************************************/
struct xrdp_font *
xrdp_font_create(struct xrdp_wm *wm)
@ -74,7 +80,7 @@ xrdp_font_create(struct xrdp_wm *wm)
int fd;
int b;
int i;
int index;
unsigned int char_count;
int datasize;
int file_size;
struct xrdp_font_char *f;
@ -100,17 +106,39 @@ xrdp_font_create(struct xrdp_wm *wm)
}
self = (struct xrdp_font *)g_malloc(sizeof(struct xrdp_font), 1);
if (self == NULL)
{
LOG(LOG_LEVEL_ERROR, "xrdp_font_create: "
"Can't allocate memory for font");
return self;
}
self->wm = wm;
make_stream(s);
init_stream(s, file_size + 1024);
fd = g_file_open(file_path);
if (fd != -1)
if (fd < 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_font_create: Can't open %s - %s", file_path,
g_get_strerror());
g_free(self);
self = NULL;
}
else
{
b = g_file_read(fd, s->data, file_size + 1024);
g_file_close(fd);
if (b > 0)
// Got at least a header?
if (b < (4 + 32 + 2 + 2 + 8))
{
LOG(LOG_LEVEL_ERROR,
"xrdp_font_create: Font %s is truncated", file_path);
g_free(self);
self = NULL;
}
else
{
s->end = s->data + b;
in_uint8s(s, 4);
@ -118,11 +146,27 @@ xrdp_font_create(struct xrdp_wm *wm)
in_uint16_le(s, self->size);
in_uint16_le(s, self->style);
in_uint8s(s, 8);
index = 32;
char_count = FIRST_CHAR;
while (s_check_rem(s, 16))
while (!s_check_end(s))
{
f = self->font_items + index;
if (!s_check_rem(s, 16))
{
LOG(LOG_LEVEL_WARNING,
"xrdp_font_create: "
"Can't parse header for character U+%X", char_count);
break;
}
if (char_count >= MAX_FONT_CHARS)
{
LOG(LOG_LEVEL_WARNING,
"xrdp_font_create: "
"Ignoring characters >= U+%x", MAX_FONT_CHARS);
break;
}
f = self->chars + char_count;
in_sint16_le(s, i);
f->width = i;
in_sint16_le(s, i);
@ -139,23 +183,56 @@ xrdp_font_create(struct xrdp_wm *wm)
if (datasize < 0 || datasize > 512)
{
/* shouldn't happen */
LOG(LOG_LEVEL_ERROR, "error in xrdp_font_create, datasize wrong "
"width %d, height %d, datasize %d, index %d",
f->width, f->height, datasize, index);
LOG(LOG_LEVEL_ERROR,
"xrdp_font_create: "
"datasize for U+%x wrong "
"width %d, height %d, datasize %d",
char_count, f->width, f->height, datasize);
break;
}
if (s_check_rem(s, datasize))
if (!s_check_rem(s, datasize))
{
f->data = (char *)g_malloc(datasize, 0);
in_uint8a(s, f->data, datasize);
LOG(LOG_LEVEL_ERROR,
"xrdp_font_create: "
"Not enough data for character U+%X", char_count);
break;
}
if ((f->data = (char *)g_malloc(datasize, 0)) == NULL)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_font_create: "
"Allocation error for character U+%X", char_count);
break;
}
in_uint8a(s, f->data, datasize);
++char_count;
}
self->char_count = char_count;
if (char_count <= FIRST_CHAR)
{
/* We read no characters from the font */
xrdp_font_delete(self);
self = NULL;
}
else
{
// Find a default glyph
if (char_count > UNICODE_WHITE_SQUARE)
{
self->default_char = &self->chars[UNICODE_WHITE_SQUARE];
}
else if (char_count > '?')
{
self->default_char = &self->chars['?'];
}
else
{
LOG(LOG_LEVEL_ERROR, "error in xrdp_font_create");
self->default_char = &self->chars[FIRST_CHAR];
}
index++;
}
}
}
@ -178,16 +255,16 @@ xrdp_font_create(struct xrdp_wm *wm)
void
xrdp_font_delete(struct xrdp_font *self)
{
int i;
unsigned int i;
if (self == 0)
{
return;
}
for (i = 0; i < NUM_FONTS; i++)
for (i = FIRST_CHAR; i < self->char_count; i++)
{
g_free(self->font_items[i].data);
g_free(self->chars[i].data);
}
g_free(self);

View File

@ -722,13 +722,13 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
if (globals->ls_title[0] == 0)
{
g_gethostname(buf1, 256);
g_sprintf(buf, "Login to %s", buf1);
g_snprintf(buf, sizeof(buf), "Login to %s", buf1);
set_string(&self->login_window->caption1, buf);
}
else
{
/*self->login_window->caption1 = globals->ls_title[0];*/
g_sprintf(buf, "%s", globals->ls_title);
g_snprintf(buf, sizeof(buf), "%s", globals->ls_title);
set_string(&self->login_window->caption1, buf);
}
@ -737,7 +737,7 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
/* Load the background image. */
/* If no file is specified no default image will be loaded. */
/* We only load the image if bpp > 8, and if the user hasn't
* disabled wallpaer in the performance settings */
* disabled wallpaper in the performance settings */
if (globals->ls_background_image[0] != 0)
{
if (self->screen->bpp <= 8)
@ -1312,8 +1312,6 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
LOG(LOG_LEVEL_DEBUG, "tcp_keepalive: %d", globals->tcp_keepalive);
LOG(LOG_LEVEL_DEBUG, "tcp_send_buffer_bytes: %d", globals->tcp_send_buffer_bytes);
LOG(LOG_LEVEL_DEBUG, "tcp_recv_buffer_bytes: %d", globals->tcp_recv_buffer_bytes);
LOG(LOG_LEVEL_DEBUG, "new_cursors: %d", globals->new_cursors);
LOG(LOG_LEVEL_DEBUG, "allow_multimon: %d", globals->allow_multimon);
LOG(LOG_LEVEL_DEBUG, "grey: %d", globals->grey);
LOG(LOG_LEVEL_DEBUG, "black: %d", globals->black);

View File

@ -55,7 +55,6 @@ xrdp_mm_chansrv_connect(struct xrdp_mm *self, const char *ip, const char *port);
static void
xrdp_mm_connect_sm(struct xrdp_mm *self);
/*****************************************************************************/
struct xrdp_mm *
xrdp_mm_create(struct xrdp_wm *owner)
@ -676,22 +675,31 @@ xrdp_mm_trans_send_channel_setup(struct xrdp_mm *self, struct trans *trans)
static int
xrdp_mm_trans_process_channel_data(struct xrdp_mm *self, struct stream *s)
{
int size;
int total_size;
unsigned int size;
unsigned int total_size;
int chan_id;
int chan_flags;
int rv;
int rv = 0;
in_uint16_le(s, chan_id);
in_uint16_le(s, chan_flags);
in_uint16_le(s, size);
in_uint32_le(s, total_size);
rv = 0;
if (rv == 0)
if (!s_check_rem_and_log(s, 10, "Reading channel data header"))
{
rv = libxrdp_send_to_channel(self->wm->session, chan_id, s->p, size, total_size,
chan_flags);
rv = 1;
}
else
{
in_uint16_le(s, chan_id);
in_uint16_le(s, chan_flags);
in_uint16_le(s, size);
in_uint32_le(s, total_size);
if (!s_check_rem_and_log(s, size, "Reading channel data data"))
{
rv = 1;
}
else
{
rv = libxrdp_send_to_channel(self->wm->session, chan_id,
s->p, size, total_size, chan_flags);
}
}
return rv;
@ -929,6 +937,12 @@ xrdp_mm_process_rail_update_window_text(struct xrdp_mm *self, struct stream *s)
g_memset(&rwso, 0, sizeof(rwso));
in_uint32_le(s, size); /* title size */
if (size < 0 || !s_check_rem(s, size))
{
LOG(LOG_LEVEL_ERROR, "%s : invalid window text size %d",
__func__, size);
return 1;
}
rwso.title_info = g_new(char, size + 1);
in_uint8a(s, rwso.title_info, size);
rwso.title_info[size] = 0;
@ -1107,27 +1121,47 @@ dynamic_monitor_data(intptr_t id, int chan_id, char *data, int bytes)
}
session_width = rect.right - rect.left;
session_height = rect.bottom - rect.top;
if ((session_width > 0) && (session_height > 0))
{
// TODO: Unify this logic with server_reset
libxrdp_reset(wm->session, session_width, session_height, wm->screen->bpp);
/* reset cache */
xrdp_cache_reset(wm->cache, wm->client_info);
/* resize the main window */
xrdp_bitmap_resize(wm->screen, session_width, session_height);
/* load some stuff */
xrdp_wm_load_static_colors_plus(wm, 0);
xrdp_wm_load_static_pointers(wm);
/* redraw */
xrdp_bitmap_invalidate(wm->screen, 0);
struct xrdp_mod *v = wm->mm->mod;
if (v != 0)
{
v->mod_server_version_message(v);
v->mod_server_monitor_resize(v, session_width, session_height);
v->mod_server_monitor_full_invalidate(v, session_width, session_height);
}
if (session_width <= 0 && session_height <= 0)
{
return 0;
}
if (session_width == wm->client_info->width
&& session_height == wm->client_info->height)
{
return 0;
}
// TODO: Unify this logic with server_reset
libxrdp_reset(wm->session, session_width, session_height, wm->screen->bpp);
/* reset cache */
xrdp_cache_reset(wm->cache, wm->client_info);
/* resize the main window */
xrdp_bitmap_resize(wm->screen, session_width, session_height);
/* load some stuff */
xrdp_wm_load_static_colors_plus(wm, 0);
xrdp_wm_load_static_pointers(wm);
/* redraw */
xrdp_bitmap_invalidate(wm->screen, 0);
struct xrdp_mod *v = wm->mm->mod;
if (v == 0)
{
return 0;
}
v->mod_server_version_message(v);
v->mod_server_monitor_resize(v, session_width, session_height);
v->mod_server_monitor_full_invalidate(v, session_width, session_height);
// Need to recreate the encoder for connections that use it.
if (wm->mm->encoder != NULL)
{
xrdp_encoder_delete(wm->mm->encoder);
wm->mm->encoder = NULL;
}
if (wm->mm->encoder == NULL)
{
wm->mm->encoder = xrdp_encoder_create(wm->mm);
}
return 0;
}
@ -1340,7 +1374,7 @@ xrdp_mm_trans_process_drdynvc_channel_open(struct xrdp_mm *self,
int error;
int chan_id;
int chansrv_chan_id;
char *name;
char name[1024 + 1];
struct xrdp_drdynvc_procs procs;
if (!s_check_rem(s, 2))
@ -1348,33 +1382,32 @@ xrdp_mm_trans_process_drdynvc_channel_open(struct xrdp_mm *self,
return 1;
}
in_uint32_le(s, name_bytes);
if ((name_bytes < 1) || (name_bytes > 1024))
{
return 1;
}
name = g_new(char, name_bytes + 1);
if (name == NULL)
if ((name_bytes < 1) || (name_bytes > (int)(sizeof(name) - 1)))
{
return 1;
}
if (!s_check_rem(s, name_bytes))
{
g_free(name);
return 1;
}
in_uint8a(s, name, name_bytes);
name[name_bytes] = 0;
if (!s_check_rem(s, 8))
{
g_free(name);
return 1;
}
in_uint32_le(s, flags);
in_uint32_le(s, chansrv_chan_id);
if (chansrv_chan_id < 0 || chansrv_chan_id > 255)
{
LOG(LOG_LEVEL_ERROR, "Attempting to open invalid chansrv channel %d",
chansrv_chan_id);
return 1;
}
if (flags == 0)
{
/* open static channel, not supported */
g_free(name);
return 1;
}
else
@ -1390,13 +1423,11 @@ xrdp_mm_trans_process_drdynvc_channel_open(struct xrdp_mm *self,
&chan_id);
if (error != 0)
{
g_free(name);
return 1;
}
self->xr2cr_cid_map[chan_id] = chansrv_chan_id;
self->cs2xr_cid_map[chansrv_chan_id] = chan_id;
}
g_free(name);
return 0;
}
@ -1415,6 +1446,12 @@ xrdp_mm_trans_process_drdynvc_channel_close(struct xrdp_mm *self,
return 1;
}
in_uint32_le(s, chansrv_chan_id);
if (chansrv_chan_id < 0 || chansrv_chan_id > 255)
{
LOG(LOG_LEVEL_ERROR, "Attempting to close invalid chansrv channel %d",
chansrv_chan_id);
return 1;
}
chan_id = self->cs2xr_cid_map[chansrv_chan_id];
/* close dynamic channel */
error = libxrdp_drdynvc_close(self->wm->session, chan_id);

View File

@ -455,7 +455,7 @@ xrdp_painter_text_width(struct xrdp_painter *self, const char *text)
for (index = 0; index < len; index++)
{
font_item = self->font->font_items + wstr[index];
font_item = XRDP_FONT_GET_CHAR(self->font, wstr[index]);
rv = rv + font_item->incby;
}
@ -493,7 +493,7 @@ xrdp_painter_text_height(struct xrdp_painter *self, const char *text)
for (index = 0; index < len; index++)
{
font_item = self->font->font_items + wstr[index];
font_item = XRDP_FONT_GET_CHAR(self->font, wstr[index]);
rv = MAX(rv, font_item->height);
}
@ -870,7 +870,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
total_height = 0;
for (index = 0; index < len; index++)
{
font_item = font->font_items + wstr[index];
font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
k = font_item->incby;
total_width += k;
total_height = MAX(total_height, font_item->height);
@ -904,7 +904,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
draw_rect.bottom - draw_rect.top);
for (index = 0; index < len; index++)
{
font_item = font->font_items + wstr[index];
font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
g_memset(&pat, 0, sizeof(pat));
pat.format = PT_FORMAT_c1;
pat.width = font_item->width;
@ -946,7 +946,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
for (index = 0; index < len; index++)
{
font_item = font->font_items + wstr[index];
font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
i = xrdp_cache_add_char(self->wm->cache, font_item);
f = HIWORD(i);
c = LOWORD(i);

View File

@ -172,7 +172,7 @@ xrdp_process_data_in(struct trans *self)
}
len = (int) (s->end - s->data);
if (pro->server_trans->header_size > len)
if (pro->server_trans->header_size > (unsigned int)len)
{
/* not enough data read yet */
break;
@ -192,7 +192,7 @@ xrdp_process_data_in(struct trans *self)
pro->server_trans->extra_flags = 3;
len = (int) (s->end - s->data);
if (pro->server_trans->header_size > len)
if (pro->server_trans->header_size > (unsigned int)len)
{
/* not enough data read yet */
break;

View File

@ -32,6 +32,13 @@
#define MAX_NR_CHANNELS 16
#define MAX_CHANNEL_NAME 16
/* Code values used in 'xrdp_mm->code=' settings */
#define XVNC_SESSION_CODE 0
#define XORG_SESSION_CODE 20
/* To check whether touch events has been implemented on session type 'mm' */
#define XRDP_MM_IMPLEMENTS_TOUCH(mm) ((mm)->code != XVNC_SESSION_CODE)
struct source_info;
/* lib */
@ -574,7 +581,7 @@ struct xrdp_bitmap
int crc16;
};
#define NUM_FONTS 0x4e00
#define MAX_FONT_CHARS 0x4e00
#define DEFAULT_FONT_NAME "sans-10.fv1"
#define DEFAULT_ELEMENT_TOP 35
@ -594,7 +601,11 @@ struct xrdp_bitmap
struct xrdp_font
{
struct xrdp_wm *wm;
struct xrdp_font_char font_items[NUM_FONTS];
// Font characters, accessed by Unicode codepoint. The first 32
// entries are unused.
struct xrdp_font_char chars[MAX_FONT_CHARS];
unsigned int char_count; // # elements in above array
struct xrdp_font_char *default_char; // Pointer into above array
char name[32];
int size;
int style;
@ -677,8 +688,8 @@ struct xrdp_cfg_globals
/* transform to apply to logo */
int ls_logo_width; /* logo width (optional) */
int ls_logo_height; /* logo height (optional) */
int ls_logo_x_pos; /* logo x co-ordinate */
int ls_logo_y_pos; /* logo y co-ordinate */
int ls_logo_x_pos; /* logo x coordinate */
int ls_logo_y_pos; /* logo y coordinate */
int ls_label_x_pos; /* x pos of labels */
int ls_label_width; /* width of labels */
int ls_input_x_pos; /* x pos of text and combo boxes */

View File

@ -29,8 +29,6 @@
#include "log.h"
#include "string_calls.h"
/*****************************************************************************/
struct xrdp_wm *
xrdp_wm_create(struct xrdp_process *owner,
@ -1224,6 +1222,29 @@ xrdp_wm_clear_popup(struct xrdp_wm *self)
return 0;
}
/*****************************************************************************/
int
xrdp_wm_mouse_touch(struct xrdp_wm *self, int gesture, int param)
{
LOG(LOG_LEVEL_DEBUG, "mouse touch event gesture %d param %d", gesture, param);
switch (gesture)
{
case TOUCH_TWO_FINGERS_UP:
case TOUCH_TWO_FINGERS_DOWN:
self->mm->mod->mod_event(self->mm->mod, WM_TOUCH_VSCROLL,
self->mouse_x, self->mouse_y, param, 0);
break;
case TOUCH_TWO_FINGERS_RIGHT:
case TOUCH_TWO_FINGERS_LEFT:
self->mm->mod->mod_event(self->mm->mod, WM_TOUCH_HSCROLL,
self->mouse_x, self->mouse_y, param, 0);
break;
}
return 0;
}
/*****************************************************************************/
int
xrdp_wm_mouse_click(struct xrdp_wm *self, int x, int y, int but, int down)
@ -1769,13 +1790,41 @@ xrdp_wm_process_input_mouse(struct xrdp_wm *self, int device_flags,
/* vertical mouse wheel */
if (device_flags & PTRFLAGS_WHEEL)
{
int delta = 0;
if (device_flags & PTRFLAGS_WHEEL_NEGATIVE)
{
xrdp_wm_mouse_click(self, 0, 0, 5, 0);
/**
* [MS-RDPBCGR] 2.2.8.1.1.3.1.1.3 Mouse Event (TS_POINTER_EVENT)
* In negative scrolling, rotation distance is negative and the delta
* is represented by the lowest byte.
* Examples:
* device_flags = 0x020a, positive vertical scrolling, distance 10
* device_flags = 0x03f6, negative vertical scrolling, distance -10
*
* The negative number is represented by complement.
*/
delta = (device_flags & WheelRotationMask) | ~WheelRotationMask;
if (delta != 0 && XRDP_MM_IMPLEMENTS_TOUCH(self->mm))
{
// Use nature scrolling, up direction is negative.
xrdp_wm_mouse_touch(self, TOUCH_TWO_FINGERS_UP, delta);
}
else
{
xrdp_wm_mouse_click(self, 0, 0, 5, 0);
}
}
else
{
xrdp_wm_mouse_click(self, 0, 0, 4, 0);
delta = device_flags & WheelRotationMask;
if (delta != 0 && XRDP_MM_IMPLEMENTS_TOUCH(self->mm))
{
xrdp_wm_mouse_touch(self, TOUCH_TWO_FINGERS_DOWN, delta);
}
else
{
xrdp_wm_mouse_click(self, 0, 0, 4, 0);
}
}
}
@ -1787,13 +1836,41 @@ xrdp_wm_process_input_mouse(struct xrdp_wm *self, int device_flags,
*/
if (device_flags & PTRFLAGS_HWHEEL)
{
int delta = 0;
if (device_flags & PTRFLAGS_WHEEL_NEGATIVE)
{
xrdp_wm_mouse_click(self, 0, 0, 6, 0);
/**
* [MS-RDPBCGR] 2.2.8.1.1.3.1.1.3 Mouse Event (TS_POINTER_EVENT)
* In negative scrolling, rotation distance is negative and the delta
* is represented by the lowest byte.
* Examples:
* device_flags = 0x040a, positive horizontal scrolling, distance 10
* device_flags = 0x05f6, negative horizontal scrolling, distance -10
*
* The negative number is represented by complement.
*/
delta = (device_flags & WheelRotationMask) | ~WheelRotationMask;
if (delta != 0 && XRDP_MM_IMPLEMENTS_TOUCH(self->mm))
{
// Use nature scrolling, right direction is negative.
xrdp_wm_mouse_touch(self, TOUCH_TWO_FINGERS_RIGHT, delta);
}
else
{
xrdp_wm_mouse_click(self, 0, 0, 6, 0);
}
}
else
{
xrdp_wm_mouse_click(self, 0, 0, 7, 0);
delta = device_flags & WheelRotationMask;
if (delta != 0 && XRDP_MM_IMPLEMENTS_TOUCH(self->mm))
{
xrdp_wm_mouse_touch(self, TOUCH_TWO_FINGERS_LEFT, delta);
}
else
{
xrdp_wm_mouse_click(self, 0, 0, 7, 0);
}
}
}

View File

@ -13,3 +13,17 @@ module_LTLIBRARIES = \
libxrdpapi_la_SOURCES = \
xrdpapi.c \
xrdpapi.h
libxrdpapi_la_LIBADD = \
$(top_builddir)/common/libcommon.la
# Build the 'simple' example program, so it's added to the CI
noinst_PROGRAMS = xrdp-xrdpapi-simple
xrdp_xrdpapi_simple_SOURCES = \
simple.c
# If you change this, update the standalone build instructions in simple.c
xrdp_xrdpapi_simple_LDADD = \
libxrdpapi.la \
$(top_builddir)/common/libcommon.la

View File

@ -22,7 +22,8 @@
/*
* build instructions:
* gcc simple.c -o simple -L./.libs -lxrdpapi
* gcc simple.c -o simple -I.. -I../common -L./.libs -L../common/.libs \
* -DHAVE_CONFIG_H -lxrdpapi -lcommon
*/
#if defined(HAVE_CONFIG_H)
@ -34,6 +35,8 @@
#endif
#include "xrdpapi.h"
#include "log.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@ -47,25 +50,35 @@ int run_tsmf_test(void);
int
main(int argc, char **argv)
{
if (argc < 2)
int result;
struct log_config *lc;
if ((lc = log_config_init_for_console(LOG_LEVEL_DEBUG, NULL)) != NULL)
{
printf("usage: simple <echo|tsmf>\n");
return 1;
log_start_from_param(lc);
}
if (strcasecmp(argv[1], "echo") == 0)
if (argc > 1 && strcasecmp(argv[1], "echo") == 0)
{
return run_echo_test();
result = run_echo_test();
}
else if (strcasecmp(argv[1], "tsmf") == 0)
else if (argc > 1 && strcasecmp(argv[1], "tsmf") == 0)
{
return run_tsmf_test();
result = run_tsmf_test();
}
else
{
printf("usage: simple <echo|tsmf>\n");
return 1;
result = 1;
}
if (lc != NULL)
{
log_config_free(lc);
log_end();
}
return result;
}
/**
@ -89,18 +102,18 @@ run_echo_test(void)
int rv;
int count;
int pkt_count;
int i;
int bytes_written;
int bytes_read;
unsigned int i;
unsigned int bytes_written;
unsigned int bytes_read;
unsigned char c;
unsigned char *rd_ptr;
unsigned char *wr_ptr;
char *rd_ptr;
char *wr_ptr;
/* fill out_buf[] with incremental values */
for (i = 0, c = 0; i < 8192; i++, c++)
{
out_buf[i] = c;
out_buf[i] = (char)c;
}
/* open a virtual channel named ECHO */