Compare commits
227 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d78ee852c | ||
|
|
8948b95528 | ||
|
|
d7b7a3c231 | ||
|
|
41c79932c8 | ||
|
|
999dc3f968 | ||
|
|
b913f0d4de | ||
|
|
82bf205ef5 | ||
|
|
14c21566dc | ||
|
|
18cb6ef0f1 | ||
|
|
a74747f162 | ||
|
|
318eba1c4b | ||
|
|
aa05ddcf89 | ||
|
|
8f970ca670 | ||
|
|
2de41e0e00 | ||
|
|
ba2202ef91 | ||
|
|
84a747c42d | ||
|
|
a56f088f4b | ||
|
|
4114133bdb | ||
|
|
34819ac504 | ||
|
|
3ebbcdcb47 | ||
|
|
ccee5af1f4 | ||
|
|
64d36e078a | ||
|
|
2314ebe11d | ||
|
|
b32a53bf94 | ||
|
|
85c863dba6 | ||
|
|
0f6b6e5aae | ||
|
|
5d15e44e96 | ||
|
|
e775881c1b | ||
|
|
0f3ca051cb | ||
|
|
111ee54453 | ||
|
|
ca049dcf24 | ||
|
|
b610b41165 | ||
|
|
6500949a18 | ||
|
|
b782340456 | ||
|
|
2c0749d2cb | ||
|
|
90c7e72656 | ||
|
|
66c668c44b | ||
|
|
37f206d2c8 | ||
|
|
4e713c884f | ||
|
|
f6fa3fc5ba | ||
|
|
7603c5791b | ||
|
|
e6bc4db423 | ||
|
|
8323e80668 | ||
|
|
1658d71ee3 | ||
|
|
1b49f82e39 | ||
|
|
82dbfa338a | ||
|
|
2b9b84fb81 | ||
|
|
fd25fc546a | ||
|
|
58c9c1f06a | ||
|
|
4db9323413 | ||
|
|
8f311633e9 | ||
|
|
4c3dd94dde | ||
|
|
6c068fbb95 | ||
|
|
7b08610742 | ||
|
|
8c5b7cdff3 | ||
|
|
322d11b431 | ||
|
|
469a89cf53 | ||
|
|
722fe7d74f | ||
|
|
15f730524e | ||
|
|
680bba8a02 | ||
|
|
011009681e | ||
|
|
946f86f611 | ||
|
|
7e514bf339 | ||
|
|
27ea401e43 | ||
|
|
3d2b3b89f4 | ||
|
|
f1fa6bbc19 | ||
|
|
6954ab0972 | ||
|
|
7efcd9280c | ||
|
|
b3dba2bad4 | ||
|
|
b26ca93176 | ||
|
|
d2a55d9203 | ||
|
|
2f214c8452 | ||
|
|
71594b5114 | ||
|
|
1b3be3e641 | ||
|
|
6c9f7f8434 | ||
|
|
a58c895d1b | ||
|
|
929d072622 | ||
|
|
4bc8701631 | ||
|
|
d9580dee01 | ||
|
|
d4ea314ac2 | ||
|
|
d7c3809ce8 | ||
|
|
a046aeea3f | ||
|
|
bd43e80ef4 | ||
|
|
d0cd397fee | ||
|
|
0525e4fbf4 | ||
|
|
bd63675a75 | ||
|
|
35bc862775 | ||
|
|
f4e909c071 | ||
|
|
df32336c76 | ||
|
|
8810d46ff1 | ||
|
|
affc40b8f0 | ||
|
|
689950d953 | ||
|
|
a564bbbe5d | ||
|
|
44efa5db5b | ||
|
|
00d9b29fcc | ||
|
|
3080439fa9 | ||
|
|
2350267f49 | ||
|
|
cde22e3b4d | ||
|
|
b765304a43 | ||
|
|
58921a972e | ||
|
|
46b4ee2e95 | ||
|
|
2e5dd686dc | ||
|
|
7198f58d6f | ||
|
|
152c31ca89 | ||
|
|
1faca4c1f7 | ||
|
|
2d66b2f8d4 | ||
|
|
f31fee3052 | ||
|
|
1e1eeec140 | ||
|
|
cae8215f3f | ||
|
|
ba4c9b9893 | ||
|
|
a80e66e2d2 | ||
|
|
6aac2e942d | ||
|
|
d459047924 | ||
|
|
9eedaf9fa2 | ||
|
|
28a39a5d9f | ||
|
|
6308e23e1f | ||
|
|
75556d2a69 | ||
|
|
19da7a92eb | ||
|
|
83a4d55b14 | ||
|
|
a4e83996db | ||
|
|
07605c7d65 | ||
|
|
faa7021a0b | ||
|
|
814d56317c | ||
|
|
fbf374c8b0 | ||
|
|
36c54d9776 | ||
|
|
2f1196bdc4 | ||
|
|
b442abe467 | ||
|
|
de1352183a | ||
|
|
6a64039773 | ||
|
|
7c7cc2523a | ||
|
|
a1484cd0a1 | ||
|
|
a8bb8959c3 | ||
|
|
8484767250 | ||
|
|
0418502eb3 | ||
|
|
09e1a0561e | ||
|
|
7c71a4f560 | ||
|
|
413678ef3d | ||
|
|
e0578b5621 | ||
|
|
030db5524b | ||
|
|
4256d84676 | ||
|
|
6e0c496564 | ||
|
|
70e14f760e | ||
|
|
ba2b9fc606 | ||
|
|
60864014b7 | ||
|
|
191ed3e3fa | ||
|
|
c2c6efb1d3 | ||
|
|
35cca701c7 | ||
|
|
bb9766c79f | ||
|
|
c77e974080 | ||
|
|
7ad7b05261 | ||
|
|
6cb54a1c26 | ||
|
|
d49f269af8 | ||
|
|
43cf272b11 | ||
|
|
da521b27f9 | ||
|
|
4a8e5d3493 | ||
|
|
56a7c3efdd | ||
|
|
5bf82ed54c | ||
|
|
ffaf8c2cc4 | ||
|
|
af6f777697 | ||
|
|
2776ffc280 | ||
|
|
d94a7388c8 | ||
|
|
e101d6baf6 | ||
|
|
75fab21415 | ||
|
|
4770a7c923 | ||
|
|
6acf8398dd | ||
|
|
1a3a9bb479 | ||
|
|
63f16d229a | ||
|
|
2857c39d0a | ||
|
|
d64be8a1cd | ||
|
|
44e9982119 | ||
|
|
676c3ed00e | ||
|
|
8dfc28409d | ||
|
|
9b34a96f98 | ||
|
|
29d03d8710 | ||
|
|
3161d223b1 | ||
|
|
c5e0e4962c | ||
|
|
3e44629184 | ||
|
|
326f4660ce | ||
|
|
a07da5b38d | ||
|
|
4a6f0030f1 | ||
|
|
4a87550028 | ||
|
|
d602020f96 | ||
|
|
87cbab2148 | ||
|
|
ce24eaa641 | ||
|
|
fc510d5ff6 | ||
|
|
e5a0d40839 | ||
|
|
aa00974a6c | ||
|
|
8290e59a01 | ||
|
|
7e6194504e | ||
|
|
b160f84062 | ||
|
|
e19b877d7b | ||
|
|
057f5955c3 | ||
|
|
cb1d034fde | ||
|
|
220783fb92 | ||
|
|
d868b05273 | ||
|
|
fc3d2838a5 | ||
|
|
8faaa57cd7 | ||
|
|
a9d4130d20 | ||
|
|
9c508cda0f | ||
|
|
5c74b1a856 | ||
|
|
cfd653c6e5 | ||
|
|
ba2f727c9a | ||
|
|
0a068311b1 | ||
|
|
6294649d13 | ||
|
|
8e6af639e8 | ||
|
|
f2bd1af772 | ||
|
|
0b17739da0 | ||
|
|
21ff90a89b | ||
|
|
e70d783524 | ||
|
|
9e8fbf2d5a | ||
|
|
164e45b6d1 | ||
|
|
a0edfad3df | ||
|
|
43eb262643 | ||
|
|
32ff7f8956 | ||
|
|
5c622f51a4 | ||
|
|
776519af61 | ||
|
|
94e82d08cd | ||
|
|
adb381a61c | ||
|
|
c222335be9 | ||
|
|
28a1e42f98 | ||
|
|
f24aa9b8c5 | ||
|
|
66e3cf5b45 | ||
|
|
916ca91527 | ||
|
|
682c39d842 | ||
|
|
eb51f917da | ||
|
|
d72f7a12f7 | ||
|
|
2b18141f7a |
@ -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
|
||||
|
||||
53
.github/workflows/build.yml
vendored
53
.github/workflows/build.yml
vendored
@ -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
2
.gitignore
vendored
@ -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
253
NEWS.md
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#define ARCH_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(HAVE_STDINT_H)
|
||||
#include <stdint.h>
|
||||
|
||||
@ -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
|
||||
|
||||
181
common/list.c
181
common/list.c
@ -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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@ -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);
|
||||
|
||||
14
common/log.h
14
common/log.h
@ -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 ...
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
16
configure.ac
16
configure.ac
@ -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 ""
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
@ -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 */
|
||||
|
||||
@ -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), "
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -2,6 +2,6 @@
|
||||
set -eufx
|
||||
|
||||
PACKAGES="subversion cmake"
|
||||
|
||||
|
||||
apt-get update
|
||||
apt-get -yq --no-install-suggests --no-install-recommends install $PACKAGES
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
65
scripts/make_release_tarball.sh
Executable 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
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 "$@"
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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 &&
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
0
sesman/chansrv/pcsc/wrapper/Makefile
Executable file → Normal file
0
sesman/chansrv/pcsc/wrapper/winscard-func-names.txt
Executable file → Normal file
0
sesman/chansrv/pcsc/wrapper/winscard-func-names.txt
Executable file → Normal file
0
sesman/chansrv/pcsc/wrapper/winscard-funcs.h
Executable file → Normal file
0
sesman/chansrv/pcsc/wrapper/winscard-funcs.h
Executable file → Normal file
0
sesman/chansrv/pcsc/wrapper/winscard.c
Executable file → Normal file
0
sesman/chansrv/pcsc/wrapper/winscard.c
Executable file → Normal file
0
sesman/chansrv/pcsc/wrapper/winscard.def
Executable file → Normal file
0
sesman/chansrv/pcsc/wrapper/winscard.def
Executable file → Normal 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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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, "-");
|
||||
/*
|
||||
|
||||
137
tests/common/test_list_calls.c
Normal file
137
tests/common/test_list_calls.c
Normal 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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <check.h>
|
||||
#include "test_libxrdp.h"
|
||||
|
||||
int main (void)
|
||||
|
||||
@ -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;
|
||||
|
||||
59
vnc/vnc.c
59
vnc/vnc.c
@ -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);
|
||||
|
||||
@ -32,7 +32,7 @@ class Decoder : public QObject
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
public slots: // cppcheck-suppress unknownMacro
|
||||
void onGeometryChanged(QRect *geometry);
|
||||
};
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ class DlgAbout : public QDialog
|
||||
private:
|
||||
Ui::DlgAbout *ui;
|
||||
|
||||
private slots:
|
||||
private slots: // cppcheck-suppress unknownMacro
|
||||
void onOk();
|
||||
};
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ class PlayAudio : public QObject
|
||||
|
||||
void setVcrOp(int op);
|
||||
|
||||
public slots:
|
||||
public slots: // cppcheck-suppress unknownMacro
|
||||
void play();
|
||||
|
||||
private:
|
||||
|
||||
@ -46,7 +46,7 @@ class PlayVideo : public QObject
|
||||
//void setVcrOp(int op);
|
||||
//void onMediaRestarted();
|
||||
|
||||
public slots:
|
||||
public slots: // cppcheck-suppress unknownMacro
|
||||
void play();
|
||||
|
||||
//signals:
|
||||
|
||||
11
xrdp/xrdp.c
11
xrdp/xrdp.c
@ -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)
|
||||
|
||||
11
xrdp/xrdp.h
11
xrdp/xrdp.h
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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";
|
||||
|
||||
113
xrdp/xrdp_font.c
113
xrdp/xrdp_font.c
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
127
xrdp/xrdp_mm.c
127
xrdp/xrdp_mm.c
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user