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 *)&one, 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 X session.  (While with the VNC server
        possessing a listening socket, which is the default case,
        and also would’ve been one were Xtightvnc(1) to support ‘wait’
        inetd.conf(5) option, it’s possible to reconnect.)  IME in
        LAN environments, it’s an acceptable tradeoff.

        Ideally, this should be complemented by a -command option in
        xvncviewer(1), to access the remote server by starting the
        command given in place of opening a TCP connection directly
        (not unlike ssh_config(5) ProxyCommand option.)  But that
        deserves a separate report IMO. 

-- 
FSF associate member #7257  http://am-1.org/~ivan/

Reply via email to