Browse Source

Start sessions via PAM

This sets up a more correct session as there are key tasks that
need to be performed by PAM. E.g. systemd will allocate cgroups
and start base services.

In order to easily handle this as a system service the mapping of
displays is now done via a configuration file.
tags/v1.10.90
Pierre Ossman 5 years ago
parent
commit
1af1cfdf87

+ 2
- 0
CMakeLists.txt View File

@@ -29,7 +29,9 @@ set(RCVERSION 1,10,80,0)
# Installation paths
set(SYSCONF_DIR "${CMAKE_INSTALL_PREFIX}/etc")
set(BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin")
set(SBIN_DIR "${CMAKE_INSTALL_PREFIX}/sbin")
set(DATA_DIR "${CMAKE_INSTALL_PREFIX}/share")
set(LIBEXEC_DIR "${CMAKE_INSTALL_PREFIX}/libexec")
set(MAN_DIR "${DATA_DIR}/man")
set(LOCALE_DIR "${DATA_DIR}/locale")
set(DOC_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/${CMAKE_PROJECT_NAME}-${VERSION}")

+ 1
- 0
config.h.in View File

@@ -5,6 +5,7 @@
#cmakedefine HAVE_ACTIVE_DESKTOP_L
#cmakedefine ENABLE_NLS 1

#cmakedefine LIBEXEC_DIR "@LIBEXEC_DIR@"
#cmakedefine DATA_DIR "@DATA_DIR@"
#cmakedefine LOCALE_DIR "@LOCALE_DIR@"


+ 11
- 4
contrib/packages/deb/ubuntu-bionic/debian/rules View File

@@ -58,6 +58,7 @@ config-stamp: xorg-source-stamp
-DBUILD_STATIC=off \
-DCMAKE_INSTALL_PREFIX:PATH=/usr \
-DSYSCONF_DIR:PATH=/etc \
-DLIBEXEC_DIR:PATH=/usr/lib/$(DEB_HOST_MULTIARCH) \
-DUNIT_DIR:PATH=/lib/systemd/system
(cd unix/xserver; \
export PIXMANINCDIR=/usr/include/pixman-1; \
@@ -172,20 +173,24 @@ install: build
$(CURDIR)/debian/tigervncserver/usr/bin/tigervncconfig
mv $(CURDIR)/debian/tigervncserver/usr/bin/vncpasswd \
$(CURDIR)/debian/tigervncserver/usr/bin/tigervncpasswd
mv $(CURDIR)/debian/tigervncserver/usr/bin/vncserver \
$(CURDIR)/debian/tigervncserver/usr/bin/tigervncserver
mv $(CURDIR)/debian/tigervncserver/usr/bin/x0vncserver \
$(CURDIR)/debian/tigervncserver/usr/bin/x0tigervncserver
mv $(CURDIR)/debian/tigervncserver/usr/sbin/vncsession \
$(CURDIR)/debian/tigervncserver/usr/sbin/tigervncsession
mv $(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/vncserver \
$(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/tigervncserver
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncconfig.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncconfig.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncpasswd.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncpasswd.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncserver.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncserver.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0vncserver.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0tigervncserver.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xvnc.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xtigervnc.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncsession.8 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncsession.8
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncserver.8 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncserver.8
# delete development files
rm -f $(CURDIR)/debian/tigervncserver/usr/lib/xorg/modules/extensions/libvnc.la
# move viewer files to viewer package, rename on the fly
@@ -216,6 +221,8 @@ install: build
$(CURDIR)/debian/tigervncserver/usr/share/doc/tigervncserver/
rm -rf $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervnc-*/
# dh_movefiles
sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \
debian/tigervncserver.postinst.in > debian/tigervncserver.postinst

# Build architecture-independent files here.
# Pass -i to all debhelper commands in this target to reduce clutter.

+ 0
- 32
contrib/packages/deb/ubuntu-bionic/debian/tigervncserver.postinst View File

@@ -1,32 +0,0 @@
#!/bin/sh

set -e

if [ "$1" = "configure" ]; then
MAN=/usr/share/man/man1
BIN=/usr/bin
update-alternatives --install \
$BIN/vncserver vncserver $BIN/tigervncserver 64 \
--slave \
$MAN/vncserver.1.gz vncserver.1.gz $MAN/tigervncserver.1.gz
update-alternatives --install \
$BIN/Xvnc Xvnc $BIN/Xtigervnc 74 \
--slave \
$MAN/Xvnc.1.gz Xvnc.1.gz $MAN/Xtigervnc.1.gz
update-alternatives --install \
$BIN/x0vncserver x0vncserver $BIN/x0tigervncserver 74 \
--slave \
$MAN/x0vncserver.1.gz x0vncserver.1.gz $MAN/x0tigervncserver.1.gz
update-alternatives --install \
$BIN/vncpasswd vncpasswd $BIN/tigervncpasswd 74 \
--slave \
$MAN/vncpasswd.1.gz vncpasswd.1.gz $MAN/tigervncpasswd.1.gz
update-alternatives --install \
$BIN/vncconfig vncconfig $BIN/tigervncconfig 64 \
--slave \
$MAN/vncconfig.1.gz vncconfig.1.gz $MAN/tigervncconfig.1.gz
fi

#DEBHELPER#

exit 0

+ 38
- 0
contrib/packages/deb/ubuntu-bionic/debian/tigervncserver.postinst.in View File

@@ -0,0 +1,38 @@
#!/bin/sh

set -e

if [ "$1" = "configure" ]; then
MAN=/usr/share/man
BIN=/usr/bin
SBIN=/usr/sbin
LIB=/usr/lib/@DEB_HOST_MULTIARCH@
update-alternatives --install \
$SBIN/vncsession vncsession $SBIN/tigervncsession 64 \
--slave \
$LIB/vncserver vncserver $LIB/tigervncserver \
--slave \
$MAN/man8/vncsession.8.gz vncsession.8.gz $MAN/man8/tigervncsession.8.gz \
--slave \
$MAN/man8/vncserver.8.gz vncserver.8.gz $MAN/man8/tigervncserver.8.gz
update-alternatives --install \
$BIN/Xvnc Xvnc $BIN/Xtigervnc 74 \
--slave \
$MAN/man1/Xvnc.1.gz Xvnc.1.gz $MAN/man1/Xtigervnc.1.gz
update-alternatives --install \
$BIN/x0vncserver x0vncserver $BIN/x0tigervncserver 74 \
--slave \
$MAN/man1/x0vncserver.1.gz x0vncserver.1.gz $MAN/man1/x0tigervncserver.1.gz
update-alternatives --install \
$BIN/vncpasswd vncpasswd $BIN/tigervncpasswd 74 \
--slave \
$MAN/man1/vncpasswd.1.gz vncpasswd.1.gz $MAN/man1/tigervncpasswd.1.gz
update-alternatives --install \
$BIN/vncconfig vncconfig $BIN/tigervncconfig 64 \
--slave \
$MAN/man1/vncconfig.1.gz vncconfig.1.gz $MAN/man1/tigervncconfig.1.gz
fi

#DEBHELPER#

exit 0

+ 2
- 1
contrib/packages/deb/ubuntu-bionic/debian/tigervncserver.prerm View File

@@ -4,8 +4,9 @@ set -e

if [ "$1" = "remove" ] ; then
BIN=/usr/bin
SBIN=/usr/sbin
update-alternatives --remove \
vncserver $BIN/tigervncserver
vncsession $SBIN/tigervncsession
update-alternatives --remove \
Xvnc $BIN/Xtigervnc
update-alternatives --remove \

+ 11
- 4
contrib/packages/deb/ubuntu-xenial/debian/rules View File

@@ -59,6 +59,7 @@ config-stamp: xorg-source-stamp
-DBUILD_STATIC=off \
-DCMAKE_INSTALL_PREFIX:PATH=/usr \
-DSYSCONF_DIR:PATH=/etc \
-DLIBEXEC_DIR:PATH=/usr/lib/$(DEB_HOST_MULTIARCH) \
-DUNIT_DIR:PATH=/lib/systemd/system
(cd unix/xserver; \
export PIXMANINCDIR=/usr/include/pixman-1; \
@@ -173,20 +174,24 @@ install: build
$(CURDIR)/debian/tigervncserver/usr/bin/tigervncconfig
mv $(CURDIR)/debian/tigervncserver/usr/bin/vncpasswd \
$(CURDIR)/debian/tigervncserver/usr/bin/tigervncpasswd
mv $(CURDIR)/debian/tigervncserver/usr/bin/vncserver \
$(CURDIR)/debian/tigervncserver/usr/bin/tigervncserver
mv $(CURDIR)/debian/tigervncserver/usr/bin/x0vncserver \
$(CURDIR)/debian/tigervncserver/usr/bin/x0tigervncserver
mv $(CURDIR)/debian/tigervncserver/usr/sbin/vncsession \
$(CURDIR)/debian/tigervncserver/usr/sbin/tigervncsession
mv $(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/vncserver \
$(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/tigervncserver
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncconfig.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncconfig.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncpasswd.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncpasswd.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncserver.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncserver.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0vncserver.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0tigervncserver.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xvnc.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xtigervnc.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncsession.8 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncsession.8
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncserver.8 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncserver.8
# delete development files
rm -f $(CURDIR)/debian/tigervncserver/usr/lib/xorg/modules/extensions/libvnc.la
# move viewer files to viewer package, rename on the fly
@@ -217,6 +222,8 @@ install: build
$(CURDIR)/debian/tigervncserver/usr/share/doc/tigervncserver/
rm -rf $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervnc-*/
# dh_movefiles
sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \
debian/tigervncserver.postinst.in > debian/tigervncserver.postinst

# Build architecture-independent files here.
# Pass -i to all debhelper commands in this target to reduce clutter.

+ 0
- 32
contrib/packages/deb/ubuntu-xenial/debian/tigervncserver.postinst View File

@@ -1,32 +0,0 @@
#!/bin/sh

set -e

if [ "$1" = "configure" ]; then
MAN=/usr/share/man/man1
BIN=/usr/bin
update-alternatives --install \
$BIN/vncserver vncserver $BIN/tigervncserver 64 \
--slave \
$MAN/vncserver.1.gz vncserver.1.gz $MAN/tigervncserver.1.gz
update-alternatives --install \
$BIN/Xvnc Xvnc $BIN/Xtigervnc 74 \
--slave \
$MAN/Xvnc.1.gz Xvnc.1.gz $MAN/Xtigervnc.1.gz
update-alternatives --install \
$BIN/x0vncserver x0vncserver $BIN/x0tigervncserver 74 \
--slave \
$MAN/x0vncserver.1.gz x0vncserver.1.gz $MAN/x0tigervncserver.1.gz
update-alternatives --install \
$BIN/vncpasswd vncpasswd $BIN/tigervncpasswd 74 \
--slave \
$MAN/vncpasswd.1.gz vncpasswd.1.gz $MAN/tigervncpasswd.1.gz
update-alternatives --install \
$BIN/vncconfig vncconfig $BIN/tigervncconfig 64 \
--slave \
$MAN/vncconfig.1.gz vncconfig.1.gz $MAN/tigervncconfig.1.gz
fi

#DEBHELPER#

exit 0

+ 38
- 0
contrib/packages/deb/ubuntu-xenial/debian/tigervncserver.postinst.in View File

@@ -0,0 +1,38 @@
#!/bin/sh

set -e

if [ "$1" = "configure" ]; then
MAN=/usr/share/man
BIN=/usr/bin
SBIN=/usr/sbin
LIB=/usr/lib/@DEB_HOST_MULTIARCH@
update-alternatives --install \
$SBIN/vncsession vncsession $SBIN/tigervncsession 64 \
--slave \
$LIB/vncserver vncserver $LIB/tigervncserver \
--slave \
$MAN/man8/vncsession.8.gz vncsession.8.gz $MAN/man8/tigervncsession.8.gz \
--slave \
$MAN/man8/vncserver.8.gz vncserver.8.gz $MAN/man8/tigervncserver.8.gz
update-alternatives --install \
$BIN/Xvnc Xvnc $BIN/Xtigervnc 74 \
--slave \
$MAN/man1/Xvnc.1.gz Xvnc.1.gz $MAN/man1/Xtigervnc.1.gz
update-alternatives --install \
$BIN/x0vncserver x0vncserver $BIN/x0tigervncserver 74 \
--slave \
$MAN/man1/x0vncserver.1.gz x0vncserver.1.gz $MAN/man1/x0tigervncserver.1.gz
update-alternatives --install \
$BIN/vncpasswd vncpasswd $BIN/tigervncpasswd 74 \
--slave \
$MAN/man1/vncpasswd.1.gz vncpasswd.1.gz $MAN/man1/tigervncpasswd.1.gz
update-alternatives --install \
$BIN/vncconfig vncconfig $BIN/tigervncconfig 64 \
--slave \
$MAN/man1/vncconfig.1.gz vncconfig.1.gz $MAN/man1/tigervncconfig.1.gz
fi

#DEBHELPER#

exit 0

+ 2
- 1
contrib/packages/deb/ubuntu-xenial/debian/tigervncserver.prerm View File

@@ -4,8 +4,9 @@ set -e

if [ "$1" = "remove" ] ; then
BIN=/usr/bin
SBIN=/usr/sbin
update-alternatives --remove \
vncserver $BIN/tigervncserver
vncsession $SBIN/tigervncsession
update-alternatives --remove \
Xvnc $BIN/Xtigervnc
update-alternatives --remove \

+ 0
- 9
contrib/packages/rpm/el7/SOURCES/tigervnc-shebang.patch View File

@@ -1,9 +0,0 @@
diff -up tigervnc-1.3.0/unix/vncserver.shebang tigervnc-1.3.0/unix/vncserver
--- tigervnc-1.3.0/unix/vncserver.shebang 2013-07-24 12:22:34.962158378 +0100
+++ tigervnc-1.3.0/unix/vncserver 2013-07-24 12:22:41.593188190 +0100
@@ -1,4 +1,4 @@
-#!/usr/bin/env perl
+#!/usr/bin/perl
#
# Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved.
# Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved.

+ 7
- 7
contrib/packages/rpm/el7/SPECS/tigervnc.spec View File

@@ -35,8 +35,6 @@ Obsoletes: vnc < 4.1.3-2, vnc-libs < 4.1.3-2
Provides: tightvnc = 1.5.0-0.15.20090204svn3586
Obsoletes: tightvnc < 1.5.0-0.15.20090204svn3586

Patch17: tigervnc-shebang.patch

%description
Virtual Network Computing (VNC) is a remote display system which
allows you to view a computing 'desktop' environment not only on the
@@ -129,9 +127,6 @@ done
patch -p1 -b --suffix .vnc < ../xserver120.patch
popd

# Don't use shebang in vncserver script.
%patch17 -p1 -b .shebang

%build
%ifarch sparcv9 sparc64 s390 s390x
export CFLAGS="$RPM_OPT_FLAGS -fPIC"
@@ -222,13 +217,18 @@ fi

%files server
%defattr(-,root,root,-)
%config(noreplace) %{_sysconfdir}/pam.d/tigervnc
%config(noreplace) %{_sysconfdir}/tigervnc/vncserver-config-defaults
%config(noreplace) %{_sysconfdir}/tigervnc/vncserver-config-mandatory
%config(noreplace) %{_sysconfdir}/tigervnc/vncserver.users
%{_unitdir}/vncserver@.service
%{_bindir}/x0vncserver
%{_bindir}/vncserver
%{_mandir}/man1/vncserver.1*
%{_sbindir}/vncsession
%{_libexecdir}/vncserver
%{_libexecdir}/vncsession-start
%{_mandir}/man1/x0vncserver.1*
%{_mandir}/man8/vncserver.8*
%{_mandir}/man8/vncsession.8*

%files server-minimal
%defattr(-,root,root,-)

+ 2
- 2
unix/vncconfig/vncconfig.man View File

@@ -111,8 +111,8 @@ When run as a "helper" app, make the window iconified at startup.
.SH SEE ALSO
.BR vncpasswd (1),
.BR vncviewer (1),
.BR vncserver (1),
.BR Xvnc (1)
.BR Xvnc (1),
.BR vncsession (8)
.br
https://www.tigervnc.org


+ 1
- 1
unix/vncpasswd/vncpasswd.man View File

@@ -43,9 +43,9 @@ Default location of the VNC password file.

.SH SEE ALSO
.BR vncviewer (1),
.BR vncserver (1),
.BR Xvnc (1)
.BR vncconfig (1),
.BR vncsession (8)
.br
https://www.tigervnc.org


+ 12
- 2
unix/vncserver/CMakeLists.txt View File

@@ -1,10 +1,20 @@
add_executable(vncsession vncsession.c)
target_link_libraries(vncsession ${PAM_LIBS})

configure_file(vncserver@.service.in vncserver@.service @ONLY)
configure_file(vncsession-start.in vncsession-start @ONLY)
configure_file(vncserver.in vncserver @ONLY)

install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vncserver DESTINATION ${BIN_DIR})
install(FILES vncserver.man DESTINATION ${MAN_DIR}/man1 RENAME vncserver.1)
install(TARGETS vncsession DESTINATION ${SBIN_DIR})
install(FILES tigervnc.pam DESTINATION ${SYSCONF_DIR}/pam.d RENAME tigervnc)
install(FILES vncsession.man DESTINATION ${MAN_DIR}/man8 RENAME vncsession.8)
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vncserver DESTINATION ${LIBEXEC_DIR})
install(FILES vncserver.man DESTINATION ${MAN_DIR}/man8 RENAME vncserver.8)
install(FILES vncserver-config-defaults vncserver-config-mandatory DESTINATION ${SYSCONF_DIR}/tigervnc)

install(FILES vncserver.users DESTINATION ${SYSCONF_DIR}/tigervnc)

if(INSTALL_SYSTEMD_UNITS)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/vncserver@.service DESTINATION ${UNIT_DIR})
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vncsession-start DESTINATION ${LIBEXEC_DIR})
endif()

+ 11
- 0
unix/vncserver/tigervnc.pam View File

@@ -0,0 +1,11 @@
#%PAM-1.0
# pam_selinux.so close should be the first session rule
-session required pam_selinux.so close
session required pam_loginuid.so
-session required pam_selinux.so open
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session required pam_limits.so
-session optional pam_systemd.so
session required pam_unix.so
-session optional pam_reauthorize.so prepare

+ 4
- 36
unix/vncserver/vncserver.in View File

@@ -88,8 +88,6 @@ if ((@ARGV == 1) && ($ARGV[0] =~ /^:(\d+)$/)) {
if (!&CheckDisplayNumber($displayNumber)) {
die "A VNC server is already running as :$displayNumber\n";
}
} elsif (@ARGV == 0) {
$displayNumber = &GetDisplayNumber();
} else {
&Usage();
}
@@ -127,8 +125,8 @@ LoadConfig($vncUserConfig);
LoadConfig($vncSystemConfigMandatoryFile, 1);

#
# Check whether VNC authentication is enabled, and if so, prompt the user to
# create a VNC password if they don't already have one.
# Check whether VNC authentication is enabled, and if so, check that
# a VNC password has been created.
#

$securityTypeArgSpecified = 0;
@@ -154,17 +152,10 @@ if ($config{'password'} ||
if ((!$securityTypeArgSpecified || $vncAuthEnabled) && !$passwordArgSpecified) {
($z,$z,$mode) = stat("$vncUserDir/passwd");
if (!(-e "$vncUserDir/passwd") || ($mode & 077)) {
warn "\nYou will require a password to access your desktops.\n\n";
system($exedir."vncpasswd -q $vncUserDir/passwd");
if (($? >> 8) != 0) {
exit 1;
}
die "VNC authentication enabled, but no password file created.\n";
}
}

$desktopLog = "$vncUserDir/$host:$displayNumber.log";
unlink($desktopLog);

#
# Find a desktop session to run
#
@@ -264,11 +255,6 @@ warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n";

warn "Starting desktop session $sessionname\n";

warn "Log file is $desktopLog\n\n";

open STDOUT, "> $desktopLog"
open STDERR, ">&STDOUT"

exec(@cmd);

die "Failed to start session.\n";
@@ -314,24 +300,6 @@ sub LoadConfig {
}


#
# GetDisplayNumber gets the lowest available display number. A display number
# n is taken if something is listening on the VNC server port (5900+n) or the
# X server port (6000+n).
#

sub GetDisplayNumber
{
foreach $n (1..99) {
if (&CheckDisplayNumber($n)) {
return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02
}
}

die "$prog: no free display number on $host.\n";
}


#
# Load a session desktop file
#
@@ -439,7 +407,7 @@ sub CheckDisplayNumber

sub Usage
{
die("\nusage: $prog [:<number>]\n\n");
die("\nusage: $prog <display>\n\n");
}



+ 1
- 85
unix/vncserver/vncserver.man View File

@@ -1,85 +1 @@
.TH vncserver 1 "" "TigerVNC" "Virtual Network Computing"
.SH NAME
vncserver \- start a VNC server
.SH SYNOPSIS
.B vncserver
.RI [: display# ]
.SH DESCRIPTION
.B vncserver
is used to start a VNC (Virtual Network Computing) desktop.
.B vncserver
is a Perl script which simplifies the process of starting an Xvnc server. It
runs Xvnc with appropriate options and starts a window manager on the VNC
desktop.

.B vncserver
can be run with no options at all. In this case it will choose the first
available display number (usually :1), start Xvnc with that display number,
and start the default window manager in the Xvnc session. You can also
specify the display number, in which case vncserver will attempt to start
Xvnc with that display number and exit if the display number is not
available. For example:

.RS
vncserver :13
.RE

vncserver will exit once the started session exits.

.SH FILES
Several VNC-related files are found in the directory $HOME/.vnc:
.TP
/etc/tigervnc/vncserver-config-defaults
The optional system-wide equivalent of $HOME/.vnc/config. If this file exists
and defines options to be passed to Xvnc, they will be used as defaults for
users. The user's $HOME/.vnc/config overrides settings configured in this file.
The overall configuration file load order is: this file, $HOME/.vnc/config,
and then /etc/tigervnc/vncserver-config-mandatory. None are required to exist.
.TP
/etc/tigervnc/vncserver-config-mandatory
The optional system-wide equivalent of $HOME/.vnc/config. If this file exists
and defines options to be passed to Xvnc, they will override any of the same
options defined in a user's $HOME/.vnc/config. This file offers a mechanism
to establish some basic form of system-wide policy. WARNING! There is
nothing stopping users from constructing their own vncserver-like script
that calls Xvnc directly to bypass any options defined in
/etc/tigervnc/vncserver-config-mandatory. The overall configuration file load
order is: /etc/tigervnc/vncserver-config-defaults, $HOME/.vnc/config, and then
this file. None are required to exist.
.TP
$HOME/.vnc/config
An optional server config file wherein options to be passed to Xvnc are listed
to avoid hard-coding them to the physical invocation. List options in this file
one per line. For those requiring an argument, simply separate the option from
the argument with an equal sign, for example: "geometry=2000x1200" or
"securitytypes=vncauth,tlsvnc". Options without an argument are simply listed
as a single word, for example: "localhost" or "alwaysshared".

The special option
.B session
can be used to control which session type will be started. This should match
one of the files in \fI/usr/share/xsessions\fP. E.g. if there is a file called
"gnome.desktop", then "session=gnome" would be set to use that session type.
.TP
$HOME/.vnc/passwd
The VNC password file.
.TP
$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.log
The log file for Xvnc and the session.

.SH SEE ALSO
.BR vncviewer (1),
.BR vncpasswd (1),
.BR vncconfig (1),
.BR Xvnc (1)
.br
https://www.tigervnc.org

.SH AUTHOR
Tristan Richardson, RealVNC Ltd., D. R. Commander and others.

VNC was originally developed by the RealVNC team while at Olivetti
Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were
implemented by Constantin Kaplinsky. Many other people have since
participated in development, testing and support. This manual is part
of the TigerVNC software suite.
.so man8/vncsession.8

+ 8
- 0
unix/vncserver/vncserver.users View File

@@ -0,0 +1,8 @@
# TigerVNC User assignment
#
# This file assigns users to specific VNC display numbers.
# The syntax is <display>=<username>. E.g.:
#
# :2=andrew
# :3=lisa


+ 9
- 14
unix/vncserver/vncserver@.service.in View File

@@ -1,13 +1,11 @@
# The vncserver service unit file
#
# Quick HowTo:
# 1. Copy this file to /etc/systemd/system/vncserver@.service
# 2. Switches for vncserver should be entered in ~/.vnc/config rather than
# hard-coded into this unit file. See the vncserver(1) manpage.
# 3. Replace <USER> with the desired user
# ("runuser -l <USER> -c /usr/bin/vncserver %i")
# 4. Run `systemctl daemon-reload`
# 5. Run `systemctl enable vncserver@:<display>.service`
# 1. Add a user mapping to /etc/tigervnc/vncserver.users.
# 2. Adjust the global or user configuration. See the
# vncsession(8) manpage for details. (OPTIONAL)
# 3. Run `systemctl enable vncserver@:<display>.service`
# 4. Run `systemctl start vncserver@:<display>.service`
#
# DO NOT RUN THIS SERVICE if your local area network is
# untrusted! For a secure way of using VNC, you should
@@ -24,9 +22,9 @@
# You can then point a VNC client on hostA at vncdisplay N of localhost and with
# the help of ssh, you end up seeing what hostB makes available on port 590M
#
# Use "-nolisten tcp" to prevent X connections to your VNC server via TCP.
# Use "nolisten=tcp" to prevent X connections to your VNC server via TCP.
#
# Use "-localhost" to prevent remote VNC clients connecting except when
# Use "localhost" to prevent remote VNC clients connecting except when
# doing so through a secure tunnel. See the "-via" option in the
# `man vncviewer' manual page.

@@ -37,11 +35,8 @@ After=syslog.target network.target

[Service]
Type=forking
# Clean any existing files in /tmp/.X11-unix environment
ExecStartPre=/bin/sh -c '@BIN_DIR@/vncserver -kill %i > /dev/null 2>&1 || :'
ExecStart=/usr/sbin/runuser -l <USER> -c "@BIN_DIR@/vncserver %i"
PIDFile=/home/<USER>/.vnc/%H%i.pid
ExecStop=/bin/sh -c '@BIN_DIR@/vncserver -kill %i > /dev/null 2>&1 || :'
ExecStart=/usr/libexec/vncsession-start %i
PIDFile=/var/run/vncsession-%i.pid

[Install]
WantedBy=multi-user.target

+ 43
- 0
unix/vncserver/vncsession-start.in View File

@@ -0,0 +1,43 @@
#!/bin/bash
#
# Copyright 2019 Pierre Ossman for Cendio AB
#
# This is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
# USA.
#

USERSFILE="@SYSCONF_DIR@/tigervnc/vncserver.users"

if [ $# -ne 1 ]; then
echo "Syntax:" >&2
echo " $0 <display>" >&2
exit 1
fi

if [ ! -f "${USERSFILE}" ]; then
echo "Users file ${USERSFILE} missing" >&2
exit 1
fi

DISPLAY="$1"

USER=`grep "^${DISPLAY}=" "${USERSFILE}" 2>/dev/null | head -1 | cut -d = -f 2-`

if [ -z "${USER}" ]; then
echo "No user configured for display ${DISPLAY}" >&2
exit 1
fi

exec "@SBIN_DIR@/vncsession" "${USER}" "${DISPLAY}"

+ 592
- 0
unix/vncserver/vncsession.c View File

@@ -0,0 +1,592 @@
/*
* Copyright 2018 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/

#include <config.h>

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <limits.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#include <syslog.h>
#include <security/pam_appl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>

extern char **environ;

// PAM service name
const char *SERVICE_NAME = "tigervnc";

// Main script PID
volatile static pid_t script = -1;

// Daemon completion pipe
int daemon_pipe_fd = -1;

static int
begin_daemon(void)
{
int devnull, fds[2];
pid_t pid;

/* Pipe to report startup success */
if (pipe(fds) < 0) {
perror("pipe");
return -1;
}

/* First fork */
pid = fork();
if (pid < 0) {
perror("fork");
return -1;
}

if (pid != 0) {
ssize_t len;
char buf[1];

close(fds[1]);

/* Wait for child to finish startup */
len = read(fds[0], buf, 1);
if (len != 1) {
fprintf(stderr, "Failure daemonizing\n");
_exit(EX_OSERR);
}

_exit(0);
}

close(fds[0]);
daemon_pipe_fd = fds[1];

/* Detach from terminal */
if (setsid() < 0) {
perror("setsid");
return -1;
}

/* Another fork required to fully detach */
pid = fork();
if (pid < 0) {
perror("fork");
return -1;
}

if (pid == 0)
_exit(0);

/* Send all stdio to /dev/null */
devnull = open("/dev/null", O_RDWR);
if (devnull < 0) {
fprintf(stderr, "Failed to open /dev/null: %s\n", strerror(errno));
return -1;
}
if ((dup2(devnull, 0) < 0) ||
(dup2(devnull, 1) < 0) ||
(dup2(devnull, 2) < 0)) {
perror("dup2");
return -1;
}
if (devnull > 2)
close(devnull);

/* Full control of access bits */
umask(0);

/* A safe working directory */
if (chdir("/") < 0) {
perror("chdir");
return -1;
}

return 0;
}

static void
finish_daemon(void)
{
write(daemon_pipe_fd, "+", 1);
close(daemon_pipe_fd);
daemon_pipe_fd = -1;
}

static void
sighandler(int sig)
{
if (script > 0) {
kill(script, SIGTERM);
}
}

static void
setup_signals(void)
{
struct sigaction act;

memset(&act, 0, sizeof(act));
act.sa_handler = sighandler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;

sigaction(SIGHUP, &act, NULL);
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
sigaction(SIGQUIT, &act, NULL);
sigaction(SIGPIPE, &act, NULL);
}

static int
conv(int num_msg,
const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
/* Opening a session should not require a conversation */
return PAM_CONV_ERR;
}

static pam_handle_t *
run_pam(int *pamret, const char *username, const char *display)
{
pam_handle_t *pamh;

/* Say hello to PAM */
struct pam_conv pconv;
pconv.conv = conv;
pconv.appdata_ptr = NULL;
*pamret = pam_start(SERVICE_NAME, username, &pconv, &pamh);
if (*pamret != PAM_SUCCESS) {
/* pam_strerror requires a pamh argument, but if pam_start
fails, pamh is invalid. In practice, at least the Linux
implementation of pam_strerror does not use the pamh
argument, but let's take care - avoid pam_strerror here. */
syslog(LOG_CRIT, "pam_start failed: %d", *pamret);
return NULL;
}

/* ConsoleKit and systemd (and possibly others) uses this to
determine if the session is local or not. It needs to be set to
something that can't be interpreted as localhost. We don't know
what the client's address is though, and that might change on
reconnects. We also don't want to set it to some text string as
that results in a DNS lookup with e.g. libaudit. Let's use a
fake IPv4 address from the documentation range. */
/* FIXME: This might throw an error on a IPv6-only host */
*pamret = pam_set_item(pamh, PAM_RHOST, "203.0.113.20");
if (*pamret != PAM_SUCCESS) {
syslog(LOG_CRIT, "pam_set_item(PAM_RHOST) failed: %d (%s)",
*pamret, pam_strerror(pamh, *pamret));
return pamh;
}

#ifdef PAM_XDISPLAY
/* Let PAM modules use this to tag the session as a graphical one */
*pamret = pam_set_item(pamh, PAM_XDISPLAY, display);
/* Note: PAM_XDISPLAY is only supported by modern versions of PAM */
if (*pamret != PAM_BAD_ITEM && *pamret != PAM_SUCCESS) {
syslog(LOG_CRIT, "pam_set_item(PAM_XDISPLAY) failed: %d (%s)",
*pamret, pam_strerror(pamh, *pamret));
return pamh;
}
#endif

/* Open session */
*pamret = pam_open_session(pamh, PAM_SILENT);
if (*pamret != PAM_SUCCESS) {
syslog(LOG_CRIT, "pam_open_session failed: %d (%s)",
*pamret, pam_strerror(pamh, *pamret));
return pamh;
}

return pamh;
}

static int
stop_pam(pam_handle_t * pamh, int pamret)
{
/* Close session */
if (pamret == PAM_SUCCESS) {
pamret = pam_close_session(pamh, PAM_SILENT);
if (pamret != PAM_SUCCESS) {
syslog(LOG_ERR, "pam_close_session failed: %d (%s)",
pamret, pam_strerror(pamh, pamret));
}
}

/* If PAM was OK and we are running on a SELinux system, new
processes images will be executed in the root context. */

/* Say goodbye */
pamret = pam_end(pamh, pamret);
if (pamret != PAM_SUCCESS) {
/* avoid pam_strerror - we have no pamh. */
syslog(LOG_ERR, "pam_end failed: %d", pamret);
return EX_OSERR;
}
return pamret;
}

static char **
prepare_environ(pam_handle_t * pamh)
{
char **pam_env, **child_env, **entry;
int orig_count, pam_count;

/* This function merges the normal environment with PAM's changes */

pam_env = pam_getenvlist(pamh);
if (pam_env == NULL)
return NULL;

/*
* Worst case scenario is that PAM only adds variables, so allocate
* based on that assumption.
*/
orig_count = 0;
for (entry = environ; *entry != NULL; entry++)
orig_count++;
pam_count = 0;
for (entry = pam_env; *entry != NULL; entry++)
pam_count++;

child_env = calloc(orig_count + pam_count + 1, sizeof(char *));
if (child_env == NULL)
return NULL;

memcpy(child_env, environ, sizeof(char *) * orig_count);
for (entry = child_env; *entry != NULL; entry++) {
*entry = strdup(*entry);
if (*entry == NULL) // FIXME: cleanup
return NULL;
}

for (entry = pam_env; *entry != NULL; entry++) {
size_t varlen;
char **orig_entry;

varlen = strcspn(*entry, "=") + 1;

/* Check for overwrite */
for (orig_entry = child_env; *orig_entry != NULL; orig_entry++) {
if (strncmp(*entry, *orig_entry, varlen) != 0)
continue;

free(*orig_entry);
*orig_entry = *entry;
break;
}

/* New variable? */
if (*orig_entry == NULL) {
/*
* orig_entry will be pointing at the terminating entry,
* so we can just tack it on here. The new NULL was already
* prepared by calloc().
*/
*orig_entry = *entry;
}
}

return child_env;
}

static void
switch_user(const char *username, uid_t uid, gid_t gid)
{
// We must change group stuff first, because only root can do that.
if (setgid(gid) < 0) {
perror(": setgid");
_exit(EX_OSERR);
}

// Supplementary groups.
if (initgroups(username, gid) < 0) {
perror("initgroups");
_exit(EX_OSERR);
}

// Set euid, ruid and suid
if (setuid(uid) < 0) {
perror("setuid");
_exit(EX_OSERR);
}
}

static void
redir_stdio(const char *homedir, const char *display)
{
int fd;
char hostname[HOST_NAME_MAX+1];
char logfile[PATH_MAX];

fd = open("/dev/null", O_RDONLY);
if (fd == -1) {
perror("open");
_exit(EX_OSERR);
}
if (dup2(fd, 0) == -1) {
perror("dup2");
_exit(EX_OSERR);
}
close(fd);

snprintf(logfile, sizeof(logfile), "%s/.vnc", homedir);
if (mkdir(logfile, 0755) == -1) {
if (errno != EEXIST) {
perror("mkdir");
_exit(EX_OSERR);
}
}

if (gethostname(hostname, sizeof(hostname)) == -1) {
perror("gethostname");
_exit(EX_OSERR);
}

snprintf(logfile, sizeof(logfile), "%s/.vnc/%s%s.log",
homedir, hostname, display);
fd = open(logfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd == -1) {
perror("open");
_exit(EX_OSERR);
}
if ((dup2(fd, 1) == -1) || (dup2(fd, 2) == -1)) {
perror("dup2");
_exit(EX_OSERR);
}
close(fd);
}

static void
close_fds(void)
{
DIR *dir;
struct dirent *entry;

dir = opendir("/proc/self/fd");
if (dir == NULL) {
perror("opendir");
_exit(EX_OSERR);
}

while ((entry = readdir(dir)) != NULL) {
int fd;
fd = atoi(entry->d_name);
if (fd < 3)
continue;
close(fd);
}

closedir(dir);
}

static pid_t
run_script(const char *username, const char *display, char **envp)
{
struct passwd *pwent;
pid_t pid;
const char *child_argv[3];

pwent = getpwnam(username);
if (pwent == NULL) {
syslog(LOG_CRIT, "getpwnam: %s", strerror(errno));
return -1;
}

pid = fork();
if (pid < 0) {
syslog(LOG_CRIT, "fork: %s", strerror(errno));
return pid;
}

/* two processes now */

if (pid > 0)
return pid;

/* child */

switch_user(pwent->pw_name, pwent->pw_uid, pwent->pw_gid);

close_fds();

redir_stdio(pwent->pw_dir, display);

// execvpe() is not POSIX and is missing from older glibc
// First clear out everything
while ((environ != NULL) && (*environ != NULL)) {
char *var, *eq;
var = strdup(*environ);
eq = strchr(var, '=');
if (eq)
*eq = '\0';
unsetenv(var);
free(var);
}

// Then copy over the desired environment
for (; *envp != NULL; envp++)
putenv(*envp);

// Set up some basic environment for the script
setenv("HOME", pwent->pw_dir, 1);
setenv("SHELL", pwent->pw_shell, 1);
setenv("LOGNAME", pwent->pw_name, 1);
setenv("USER", pwent->pw_name, 1);
setenv("USERNAME", pwent->pw_name, 1);

child_argv[0] = LIBEXEC_DIR "/vncserver";
child_argv[1] = display;
child_argv[2] = NULL;

execvp(child_argv[0], (char*const*)child_argv);

// execvp failed
perror("execvp");

_exit(EX_OSERR);
}

int
main(int argc, char **argv)
{
char pid_file[PATH_MAX];
FILE *f;

const char *username, *display;

if ((argc != 3) || (argv[2][0] != ':')) {
fprintf(stderr, "Syntax:\n");
fprintf(stderr, " %s <username> <display>\n", argv[0]);
return EX_USAGE;
}

username = argv[1];
display = argv[2];

if (geteuid() != 0) {
fprintf(stderr, "This program needs to be run as root!\n");
return EX_USAGE;
}

if (getpwnam(username) == NULL) {
if (errno == 0)
fprintf(stderr, "User \"%s\" does not exist\n", username);
else
fprintf(stderr, "Cannot look up user \"%s\": %s\n",
username, strerror(errno));
return EX_OSERR;
}

if (begin_daemon() == -1)
return EX_OSERR;

openlog("vncsession", LOG_PID, LOG_AUTH);

/* Indicate that this is a graphical user session. We need to do
this here before PAM as pam_systemd.so looks at these. */
if ((putenv("XDG_SESSION_CLASS=user") < 0) ||
(putenv("XDG_SESSION_TYPE=x11") < 0)) {
syslog(LOG_CRIT, "putenv: %s", strerror(errno));
return EX_OSERR;
}

/* Init PAM */
int pamret;
pam_handle_t *pamh = run_pam(&pamret, username, display);
if (!pamh) {
return EX_OSERR;
}
if (pamret != PAM_SUCCESS) {
stop_pam(pamh, pamret);
return EX_OSERR;
}

char **child_env;
child_env = prepare_environ(pamh);
if (child_env == NULL) {
syslog(LOG_CRIT, "Failure creating child process environment");
stop_pam(pamh, pamret);
return EX_OSERR;
}

setup_signals();

script = run_script(username, display, child_env);
if (script == -1) {
syslog(LOG_CRIT, "Failure starting vncserver script");
stop_pam(pamh, pamret);
return EX_OSERR;
}

snprintf(pid_file, sizeof(pid_file),
"/var/run/vncsession-%s.pid", display);
f = fopen(pid_file, "w");
if (f == NULL) {
syslog(LOG_ERR, "Failure creating pid file \"%s\": %s",
pid_file, strerror(errno));
} else {
fprintf(f, "%ld\n", (long)getpid());
fclose(f);
}

finish_daemon();

while (1) {
int status;
pid_t gotpid = waitpid(script, &status, 0);
if (gotpid < 0) {
if (errno != EINTR) {
syslog(LOG_CRIT, "waitpid: %s", strerror(errno));
exit(EXIT_FAILURE);
}
continue;
}
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0) {
syslog(LOG_WARNING,
"vncsession: vncserver exited with status=%d",
WEXITSTATUS(status));
}
break;
}
else if (WIFSIGNALED(status)) {
syslog(LOG_WARNING,
"vncsession: vncserver was terminated by signal %d",
WTERMSIG(status));
break;
}
}

unlink(pid_file);

stop_pam(pamh, pamret);

return 0;
}

+ 75
- 0
unix/vncserver/vncsession.man View File

@@ -0,0 +1,75 @@
.TH vncsession 8 "" "TigerVNC" "Virtual Network Computing"
.SH NAME
vncsession \- start a VNC server
.SH SYNOPSIS
.B vncsession
.RI < username >
.RI <: display# >
.SH DESCRIPTION
.B vncsession
is used to start a VNC (Virtual Network Computing) desktop.
.B vncsession
performs all the necessary steps to create a new user session, run Xvnc with
appropriate options and starts a window manager on the VNC desktop.

.B vncsession
is rarely called directly and is normally started by the system service
manager.

.SH FILES
Several VNC-related files are found in the directory $HOME/.vnc:
.TP
/etc/tigervnc/vncserver-config-defaults
The optional system-wide equivalent of $HOME/.vnc/config. If this file exists
and defines options to be passed to Xvnc, they will be used as defaults for
users. The user's $HOME/.vnc/config overrides settings configured in this file.
The overall configuration file load order is: this file, $HOME/.vnc/config,
and then /etc/tigervnc/vncserver-config-mandatory. None are required to exist.
.TP
/etc/tigervnc/vncserver-config-mandatory
The optional system-wide equivalent of $HOME/.vnc/config. If this file exists
and defines options to be passed to Xvnc, they will override any of the same
options defined in a user's $HOME/.vnc/config. This file offers a mechanism
to establish some basic form of system-wide policy. WARNING! There is
nothing stopping users from constructing their own vncsession-like script
that calls Xvnc directly to bypass any options defined in
/etc/tigervnc/vncserver-config-mandatory. The overall configuration file load
order is: /etc/tigervnc/vncserver-config-defaults, $HOME/.vnc/config, and then
this file. None are required to exist.
.TP
$HOME/.vnc/config
An optional server config file wherein options to be passed to Xvnc are listed
to avoid hard-coding them to the physical invocation. List options in this file
one per line. For those requiring an argument, simply separate the option from
the argument with an equal sign, for example: "geometry=2000x1200" or
"securitytypes=vncauth,tlsvnc". Options without an argument are simply listed
as a single word, for example: "localhost" or "alwaysshared".

The special option
.B session
can be used to control which session type will be started. This should match
one of the files in \fI/usr/share/xsessions\fP. E.g. if there is a file called
"gnome.desktop", then "session=gnome" would be set to use that session type.
.TP
$HOME/.vnc/passwd
The VNC password file.
.TP
$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.log
The log file for Xvnc and the session.

.SH SEE ALSO
.BR vncviewer (1),
.BR vncpasswd (1),
.BR vncconfig (1),
.BR Xvnc (1)
.br
https://www.tigervnc.org

.SH AUTHOR
Tristan Richardson, RealVNC Ltd., D. R. Commander and others.

VNC was originally developed by the RealVNC team while at Olivetti
Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were
implemented by Constantin Kaplinsky. Many other people have since
participated in development, testing and support. This manual is part
of the TigerVNC software suite.

+ 4
- 4
unix/xserver/hw/vnc/Xvnc.man View File

@@ -18,9 +18,9 @@ that the VNC server display number will be the same as the X server display
number, which means you can use eg. snoopy:2 to refer to display 2 on machine
"snoopy" in both the X world and the VNC world.

The best way of starting \fBXvnc\fP is via the \fBvncserver\fP script. This
sets up the environment appropriately and runs some X applications to get you
going. See the manual page for \fBvncserver\fP(1) for more information.
The best way of starting \fBXvnc\fP is via \fBvncsession\fP. This sets up the
environment appropriately and starts a desktop environment. See the manual
page for \fBvncsession\fP(8) for more information.

.SH OPTIONS
.B Xvnc
@@ -383,8 +383,8 @@ created automatically the next time he connects.
.SH SEE ALSO
.BR vncconfig (1),
.BR vncpasswd (1),
.BR vncserver (1),
.BR vncviewer (1),
.BR vncsession (8),
.BR Xserver (1),
.BR inetd (1)
.br

+ 1
- 1
vncviewer/vncviewer.man View File

@@ -333,7 +333,7 @@ Default certificate revocation list.
.BR Xvnc (1),
.BR vncpasswd (1),
.BR vncconfig (1),
.BR vncserver (1)
.BR vncsession (8)
.br
https://www.tigervnc.org


Loading…
Cancel
Save