Bug#1018240: Xtightvnc(1): support arbitrary stdio in -inetd, not just socket-based

2022-09-05 Thread Sven Geuer
Control: tags -1 = wontfix

Hello Ivan,

On Sat, 2022-08-27 at 17:20 +, Ivan Shmakov wrote:
> Package: tightvncserver
> Version: 1:1.3.10-5+b1
> Severity: wishlist
> Control: found -1 1:1.3.10-3
> 
> [...]


you are requesting a new feature in TightVNC which I would forward to
upstream. However upstream stopped supporting TightVNC 1.3 many years
ago with the result that it is fairly outdated nowadays. The integrated
X server for instance is still XFree86 based.

I suggest you try TigerVNC (package tigervnc-standalone-server or
tigervnc-scraping-server) instead, it relies on X.Org. If the feature
you are after is not already supported there I propose to reach out to
upstream and log a ticket under
https://github.com/TigerVNC/tigervnc/issues.

Best,
Sven



Bug#1018240: Xtightvnc(1): support arbitrary stdio in -inetd, not just socket-based

2022-08-27 Thread Ivan Shmakov
Package: tightvncserver
Version: 1:1.3.10-5+b1
Severity: wishlist
Control: found -1 1:1.3.10-3

[Please do not Cc: me, for I’m “on the list,” so to say, and
I try to reserve my inbox for private communication only.
I’d have set up Mail-Followup-To:, but there doesn’t seem to
be a way to make it point to the report being filed.]

Xtightvnc(1) concludes with:

Probably, the best way to secure Xvnc server is to allow only
loopback connections from the server machine (the -localhost option)
and to use SSH tunneling for remote access to the Xvnc server.

However, it’s arguably even more secure to either use a Unix
socket accessible by only the intended user(s) (note that
OpenSSH supports Unix to Unix, TCP to Unix, and Unix to TCP
socket forwarding; see the -L option in ssh(1)); or a pair
of pipes, such as rsync(1) uses (by essentially invoking
$ ssh -- REMOTE rsync --server to access the remote.)

Moreover, certain lightweight SSH2 servers, such as
tinysshd(8), omit support for forwarding altogether, which
doesn’t inconvenience tools such as rsync(1) in the least,
but which makes the advice above impossible to follow.

Unfortunately, the obvious candidate for such usage, the
-inetd option, doesn’t quite support it.  The cause is
twofold.  On the one hand, Xtightvnc -inetd still assumes
that the communication is done via a TCP socket, uses
setsockopt(2) on the file descriptor, and exits when that
fails.  On the other, contrary to the documentation,

  -inetd
  Xvnc is launched by inetd.  This option causes Xvnc to redirect
  network input/output to stdin/stdout.

the current implementation uses not stdin and stdout, but rather
‘stdin’ only, for both input and output.  Which isn’t a problem
when the server is started from inetd(8) proper, as in that case
both stdin and stdout point to the same socket; but /is/ a
problem in the proposed usage, where stdin and stdout are two
separate pipes (incoming and outgoing, respectively.)

Xvnc/programs/Xserver/hw/vnc/init.c
361-   close stderr.  OsInit() will redirect stderr logging to an
362-   appropriate log file or /dev/null if that doesn't work. */
363-
364:dup2(0,3);
365-inetdSock = 3;
366-close(2);
367-

Xvnc/programs/Xserver/hw/vnc/sockets.c
101-
102:if (setsockopt(inetdSock, IPPROTO_TCP, TCP_NODELAY,
103-   (char *), sizeof(one)) < 0) {
104:rfbLogPerror("setsockopt");
105-exit(1);
106-}
107-

(So far as I can tell only a single use of setsockopt(2)
in the file is relevant to the problem being described.)

As such, my suggestions would be as follows.

 1. The setsockopt(2) failure in rfbInitSockets () is
downgraded to a warning (from a fatal error.)  This
alone should be sufficient for running Xtightvnc(1)
on a Unix socket via inetd(8), which is already more
secure than a localhost-bound TCP port.

 2. In place of inetdSock, the code should use separate
inetdIn and inetdOut file descriptors, so that it’s
possible to use a pair of pipes in place of a socket.

It’s also possible to work around the problem at hand by
using socat(1) and strace(1) as follows.

#!/bin/sh
### tightvnc-ssh-pipe.sh
## Example Xtightvnc tunneling via SSH pipes.

## Connect with:
##   $ xvncviewer localhost::12345 

LOCAL_PORT=12345
REMOTE=remote.example.net

## .
exec socat TCP4-LISTEN:"$LOCAL_PORT",bind=localhost \
EXEC:"ssh -t -- ${REMOTE} \
  set -C -e -u -- ; stty raw -echo ; exec 3<> /dev/tty ; \
  strace -o /tmp/debug.\"$(date +%s.%N)\" -ft -s95 \
  -e trace=dup2 -e trace=setsockopt \
  -e inject=setsockopt\\:retval=0\\:when=4 \
  -e inject=dup2\\:retval=3\\:when=1 \
  -- Xtightvnc \\:99 -auth \"\$HOME\"/.Xauthority \
 -geometry 1280x$((1024 - 2 * 24)) -depth 24 \
 -dontdisconnect -nevershared -inetd",pty

### tightvnc-ssh-pipe.sh ends here

Here, ssh -t, together with the socat(1) ,pty option, forces
pseudo-tty allocation on the remote side; exec 3<> /dev/tty
redirects file descriptor 3 (which is the number inetdSock
is set to) to the pty thus allocated; -e inject=dup2:retval=3
:when=1 turns the dup2(2) call in init.c into a no-op; and
-e inject=setsockopt:retval=0:when=4 does the same to the
setsockopt(2) call in sockets.c.

Also, while we’re at it, note that Xtightvnc above ignores the
:99 option and binds to /tmp/.X11-unix/X1, as if :1 were given.

It should be noted that the use of pipes, or actually -inetd
/ inetd.conf(5) ‘nowait’, means that the failure of the
underlying connection invariably leads to the termination
of the associated