2177 lines
67 KiB
Diff
2177 lines
67 KiB
Diff
|
From 8f09de712b53e54d15d2bd5367c10a61c57cda23 Mon Sep 17 00:00:00 2001
|
||
|
From: Jan Grulich <jgrulich@redhat.com>
|
||
|
Date: Wed, 6 May 2020 10:37:21 +0200
|
||
|
Subject: Foo
|
||
|
|
||
|
|
||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||
|
index 2d19b72..78eb93d 100644
|
||
|
--- a/CMakeLists.txt
|
||
|
+++ b/CMakeLists.txt
|
||
|
@@ -7,6 +7,10 @@ if(POLICY CMP0022)
|
||
|
cmake_policy(SET CMP0022 OLD)
|
||
|
endif()
|
||
|
|
||
|
+if(${CMAKE_VERSION} VERSION_LESS "3.4.0")
|
||
|
+ message(WARNING "CMake 3.4.0 or newer is required to get correct default installation paths")
|
||
|
+endif()
|
||
|
+
|
||
|
# Internal cmake modules
|
||
|
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
|
||
|
|
||
|
@@ -27,17 +31,16 @@ set(VERSION 1.10.1)
|
||
|
set(RCVERSION 1,10,1,0)
|
||
|
|
||
|
# Installation paths
|
||
|
-set(BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin")
|
||
|
-set(DATA_DIR "${CMAKE_INSTALL_PREFIX}/share")
|
||
|
-set(MAN_DIR "${DATA_DIR}/man")
|
||
|
-set(LOCALE_DIR "${DATA_DIR}/locale")
|
||
|
-set(DOC_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/${CMAKE_PROJECT_NAME}-${VERSION}")
|
||
|
-
|
||
|
-if(WIN32)
|
||
|
-set(BIN_DIR "${CMAKE_INSTALL_PREFIX}")
|
||
|
-set(DOC_DIR "${CMAKE_INSTALL_PREFIX}")
|
||
|
+include(GNUInstallDirs)
|
||
|
+set(CMAKE_INSTALL_UNITDIR "lib/systemd/system" CACHE PATH "systemd unit files (lib/systemd/system)")
|
||
|
+if(IS_ABSOLUTE "${CMAKE_INSTALL_UNITDIR}")
|
||
|
+ set(CMAKE_INSTALL_FULL_UNITDIR "${CMAKE_INSTALL_UNITDIR}")
|
||
|
+else()
|
||
|
+ set(CMAKE_INSTALL_FULL_UNITDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_UNITDIR}")
|
||
|
endif()
|
||
|
|
||
|
+option(INSTALL_SYSTEMD_UNITS "Install TigerVNC systemd units" ON)
|
||
|
+
|
||
|
if(MSVC)
|
||
|
message(FATAL_ERROR "TigerVNC cannot be built with Visual Studio. Please use MinGW")
|
||
|
endif()
|
||
|
@@ -259,8 +262,7 @@ if(ENABLE_GNUTLS)
|
||
|
endif()
|
||
|
|
||
|
# Check for PAM library
|
||
|
-option(ENABLE_PAM "Enable PAM authentication support" ON)
|
||
|
-if(ENABLE_PAM)
|
||
|
+if(UNIX AND NOT APPLE)
|
||
|
check_include_files(security/pam_appl.h HAVE_PAM_H)
|
||
|
set(CMAKE_REQUIRED_LIBRARIES -lpam)
|
||
|
check_function_exists(pam_start HAVE_PAM_START)
|
||
|
@@ -268,10 +270,9 @@ if(ENABLE_PAM)
|
||
|
if(HAVE_PAM_H AND HAVE_PAM_START)
|
||
|
set(PAM_LIBS pam)
|
||
|
else()
|
||
|
- set(ENABLE_PAM 0)
|
||
|
+ message(FATAL_ERROR "Could not find PAM development files")
|
||
|
endif()
|
||
|
endif()
|
||
|
-set(HAVE_PAM ${ENABLE_PAM})
|
||
|
|
||
|
# Generate config.h and make sure the source finds it
|
||
|
configure_file(config.h.in config.h)
|
||
|
diff --git a/cmake/BuildPackages.cmake b/cmake/BuildPackages.cmake
|
||
|
index ec96318..1f25192 100644
|
||
|
--- a/cmake/BuildPackages.cmake
|
||
|
+++ b/cmake/BuildPackages.cmake
|
||
|
@@ -86,5 +86,5 @@ endif() #UNIX
|
||
|
# Common
|
||
|
#
|
||
|
|
||
|
-install(FILES ${CMAKE_SOURCE_DIR}/LICENCE.TXT DESTINATION ${DOC_DIR})
|
||
|
-install(FILES ${CMAKE_SOURCE_DIR}/README.rst DESTINATION ${DOC_DIR})
|
||
|
+install(FILES ${CMAKE_SOURCE_DIR}/LICENCE.TXT DESTINATION ${CMAKE_INSTALL_FULL_DOCDIR})
|
||
|
+install(FILES ${CMAKE_SOURCE_DIR}/README.rst DESTINATION ${CMAKE_INSTALL_FULL_DOCDIR})
|
||
|
diff --git a/cmake/StaticBuild.cmake b/cmake/StaticBuild.cmake
|
||
|
index e539619..793b190 100644
|
||
|
--- a/cmake/StaticBuild.cmake
|
||
|
+++ b/cmake/StaticBuild.cmake
|
||
|
@@ -115,7 +115,7 @@ endif()
|
||
|
if(BUILD_STATIC_GCC)
|
||
|
# This ensures that we don't depend on libstdc++ or libgcc_s
|
||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nodefaultlibs")
|
||
|
- set(STATIC_BASE_LIBRARIES "-Wl,-Bstatic -lstdc++ -Wl,-Bdynamic")
|
||
|
+ set(STATIC_BASE_LIBRARIES "")
|
||
|
if(ENABLE_ASAN AND NOT WIN32 AND NOT APPLE)
|
||
|
set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -Wl,-Bstatic -lasan -Wl,-Bdynamic -ldl -lm -lpthread")
|
||
|
endif()
|
||
|
@@ -135,5 +135,6 @@ if(BUILD_STATIC_GCC)
|
||
|
else()
|
||
|
set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -lgcc -lgcc_eh -lc")
|
||
|
endif()
|
||
|
- set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${STATIC_BASE_LIBRARIES}")
|
||
|
+ set(CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} ${STATIC_BASE_LIBRARIES}")
|
||
|
+ set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic ${STATIC_BASE_LIBRARIES}")
|
||
|
endif()
|
||
|
diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt
|
||
|
index 8e532a2..689cdcc 100644
|
||
|
--- a/common/rfb/CMakeLists.txt
|
||
|
+++ b/common/rfb/CMakeLists.txt
|
||
|
@@ -75,7 +75,7 @@ endif(WIN32)
|
||
|
|
||
|
set(RFB_LIBRARIES ${JPEG_LIBRARIES} os rdr Xregion)
|
||
|
|
||
|
-if(HAVE_PAM)
|
||
|
+if(UNIX AND NOT APPLE)
|
||
|
set(RFB_SOURCES ${RFB_SOURCES} UnixPasswordValidator.cxx
|
||
|
UnixPasswordValidator.h pam.c pam.h)
|
||
|
set(RFB_LIBRARIES ${RFB_LIBRARIES} ${PAM_LIBS})
|
||
|
diff --git a/common/rfb/SSecurityPlain.cxx b/common/rfb/SSecurityPlain.cxx
|
||
|
index 6f72432..f577c0d 100644
|
||
|
--- a/common/rfb/SSecurityPlain.cxx
|
||
|
+++ b/common/rfb/SSecurityPlain.cxx
|
||
|
@@ -25,10 +25,10 @@
|
||
|
#include <rfb/SConnection.h>
|
||
|
#include <rfb/Exception.h>
|
||
|
#include <rdr/InStream.h>
|
||
|
-#ifdef HAVE_PAM
|
||
|
+#if !defined(WIN32) && !defined(__APPLE__)
|
||
|
#include <rfb/UnixPasswordValidator.h>
|
||
|
#endif
|
||
|
-#ifdef BUILD_WIN
|
||
|
+#ifdef WIN32
|
||
|
#include <rfb/WinPasswdValidator.h>
|
||
|
#endif
|
||
|
|
||
|
@@ -62,10 +62,10 @@ bool PasswordValidator::validUser(const char* username)
|
||
|
|
||
|
SSecurityPlain::SSecurityPlain(SConnection* sc) : SSecurity(sc)
|
||
|
{
|
||
|
-#ifdef HAVE_PAM
|
||
|
- valid = new UnixPasswordValidator();
|
||
|
-#elif BUILD_WIN
|
||
|
+#ifdef WIN32
|
||
|
valid = new WinPasswdValidator();
|
||
|
+#elif !defined(__APPLE__)
|
||
|
+ valid = new UnixPasswordValidator();
|
||
|
#else
|
||
|
valid = NULL;
|
||
|
#endif
|
||
|
diff --git a/common/rfb/UnixPasswordValidator.cxx b/common/rfb/UnixPasswordValidator.cxx
|
||
|
index d096079..ee7bc0d 100644
|
||
|
--- a/common/rfb/UnixPasswordValidator.cxx
|
||
|
+++ b/common/rfb/UnixPasswordValidator.cxx
|
||
|
@@ -25,9 +25,7 @@
|
||
|
#include <rfb/Configuration.h>
|
||
|
#include <rfb/Exception.h>
|
||
|
#include <rfb/UnixPasswordValidator.h>
|
||
|
-#ifdef HAVE_PAM
|
||
|
#include <rfb/pam.h>
|
||
|
-#endif
|
||
|
|
||
|
using namespace rfb;
|
||
|
|
||
|
@@ -43,10 +41,6 @@ bool UnixPasswordValidator::validateInternal(SConnection * sc,
|
||
|
const char *username,
|
||
|
const char *password)
|
||
|
{
|
||
|
-#ifdef HAVE_PAM
|
||
|
CharArray service(strDup(pamService.getData()));
|
||
|
return do_pam_auth(service.buf, username, password);
|
||
|
-#else
|
||
|
- throw AuthFailureException("PAM not supported");
|
||
|
-#endif
|
||
|
}
|
||
|
diff --git a/common/rfb/pam.c b/common/rfb/pam.c
|
||
|
index cb067fd..acac0f4 100644
|
||
|
--- a/common/rfb/pam.c
|
||
|
+++ b/common/rfb/pam.c
|
||
|
@@ -22,9 +22,6 @@
|
||
|
#include <config.h>
|
||
|
#endif
|
||
|
|
||
|
-#ifndef HAVE_PAM
|
||
|
-#error "This source should not be compiled when PAM is unsupported"
|
||
|
-#endif
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
diff --git a/common/rfb/pam.h b/common/rfb/pam.h
|
||
|
index 2688f21..d378d19 100644
|
||
|
--- a/common/rfb/pam.h
|
||
|
+++ b/common/rfb/pam.h
|
||
|
@@ -21,14 +21,6 @@
|
||
|
#ifndef __RFB_PAM_H__
|
||
|
#define __RFB_PAM_H__
|
||
|
|
||
|
-#ifdef HAVE_CONFIG_H
|
||
|
-#include <config.h>
|
||
|
-#endif
|
||
|
-
|
||
|
-#ifndef HAVE_PAM
|
||
|
-#error "This header should not be included when PAM is unsupported"
|
||
|
-#endif
|
||
|
-
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
diff --git a/config.h.in b/config.h.in
|
||
|
index 2d6db9c..2d7a741 100644
|
||
|
--- a/config.h.in
|
||
|
+++ b/config.h.in
|
||
|
@@ -4,10 +4,10 @@
|
||
|
#cmakedefine HAVE_ACTIVE_DESKTOP_H
|
||
|
#cmakedefine HAVE_ACTIVE_DESKTOP_L
|
||
|
#cmakedefine ENABLE_NLS 1
|
||
|
-#cmakedefine HAVE_PAM
|
||
|
|
||
|
-#cmakedefine DATA_DIR "@DATA_DIR@"
|
||
|
-#cmakedefine LOCALE_DIR "@LOCALE_DIR@"
|
||
|
+#cmakedefine CMAKE_INSTALL_FULL_LIBEXECDIR "@CMAKE_INSTALL_FULL_LIBEXECDIR@"
|
||
|
+#cmakedefine CMAKE_INSTALL_FULL_DATADIR "@CMAKE_INSTALL_FULL_DATADIR@"
|
||
|
+#cmakedefine CMAKE_INSTALL_FULL_LOCALEDIR "@CMAKE_INSTALL_FULL_LOCALEDIR@"
|
||
|
|
||
|
/* MS Visual Studio 2008 and newer doesn't know ssize_t */
|
||
|
#if defined(HAVE_GNUTLS) && defined(WIN32) && !defined(__MINGW32__)
|
||
|
diff --git a/java/CMakeLists.txt b/java/CMakeLists.txt
|
||
|
index f61e355..77ec21b 100644
|
||
|
--- a/java/CMakeLists.txt
|
||
|
+++ b/java/CMakeLists.txt
|
||
|
@@ -7,8 +7,6 @@ endif()
|
||
|
|
||
|
find_package(Java)
|
||
|
|
||
|
-set(DATA_DIR "${CMAKE_INSTALL_PREFIX}/share")
|
||
|
-
|
||
|
set(DEFAULT_JAVACFLAGS "-source 8 -target 8 -encoding UTF-8 -Xlint:all,-serial,-cast,-unchecked,-fallthrough,-dep-ann,-deprecation,-rawtypes")
|
||
|
set(JAVACFLAGS ${DEFAULT_JAVACFLAGS} CACHE STRING
|
||
|
"Java compiler flags (Default: ${DEFAULT_JAVACFLAGS})")
|
||
|
diff --git a/media/CMakeLists.txt b/media/CMakeLists.txt
|
||
|
index 256d435..088c72f 100644
|
||
|
--- a/media/CMakeLists.txt
|
||
|
+++ b/media/CMakeLists.txt
|
||
|
@@ -13,11 +13,11 @@ if(CONVERT_EXECUTABLE)
|
||
|
if(UNIX AND NOT APPLE)
|
||
|
foreach(SIZE 16 22 24 32 48)
|
||
|
install(FILES icons/tigervnc_${SIZE}.png
|
||
|
- DESTINATION ${DATA_DIR}/icons/hicolor/${SIZE}x${SIZE}/apps
|
||
|
+ DESTINATION ${CMAKE_INSTALL_FULL_DATADIR}/icons/hicolor/${SIZE}x${SIZE}/apps
|
||
|
RENAME tigervnc.png)
|
||
|
endforeach()
|
||
|
install(FILES icons/tigervnc.svg
|
||
|
- DESTINATION ${DATA_DIR}/icons/hicolor/scalable/apps)
|
||
|
+ DESTINATION ${CMAKE_INSTALL_FULL_DATADIR}/icons/hicolor/scalable/apps)
|
||
|
endif()
|
||
|
endif()
|
||
|
|
||
|
diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt
|
||
|
index 9c8ddef..2eb10e7 100644
|
||
|
--- a/po/CMakeLists.txt
|
||
|
+++ b/po/CMakeLists.txt
|
||
|
@@ -46,7 +46,7 @@ foreach(lang ${po_FILES})
|
||
|
)
|
||
|
|
||
|
install(FILES ${mo}
|
||
|
- DESTINATION "${LOCALE_DIR}/${lang}/LC_MESSAGES"
|
||
|
+ DESTINATION "${CMAKE_INSTALL_FULL_LOCALEDIR}/${lang}/LC_MESSAGES"
|
||
|
RENAME tigervnc.mo
|
||
|
)
|
||
|
|
||
|
diff --git a/unix/CMakeLists.txt b/unix/CMakeLists.txt
|
||
|
index 7a1457d..5456e00 100644
|
||
|
--- a/unix/CMakeLists.txt
|
||
|
+++ b/unix/CMakeLists.txt
|
||
|
@@ -2,7 +2,5 @@ add_subdirectory(tx)
|
||
|
add_subdirectory(common)
|
||
|
add_subdirectory(vncconfig)
|
||
|
add_subdirectory(vncpasswd)
|
||
|
+add_subdirectory(vncserver)
|
||
|
add_subdirectory(x0vncserver)
|
||
|
-
|
||
|
-install(PROGRAMS vncserver DESTINATION ${BIN_DIR})
|
||
|
-install(FILES vncserver.man DESTINATION ${MAN_DIR}/man1 RENAME vncserver.1)
|
||
|
diff --git a/unix/vncconfig/CMakeLists.txt b/unix/vncconfig/CMakeLists.txt
|
||
|
index 959681f..c3823ab 100644
|
||
|
--- a/unix/vncconfig/CMakeLists.txt
|
||
|
+++ b/unix/vncconfig/CMakeLists.txt
|
||
|
@@ -11,5 +11,5 @@ add_executable(vncconfig
|
||
|
|
||
|
target_link_libraries(vncconfig tx rfb network rdr ${X11_LIBRARIES})
|
||
|
|
||
|
-install(TARGETS vncconfig DESTINATION ${BIN_DIR})
|
||
|
-install(FILES vncconfig.man DESTINATION ${MAN_DIR}/man1 RENAME vncconfig.1)
|
||
|
+install(TARGETS vncconfig DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
|
||
|
+install(FILES vncconfig.man DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man1 RENAME vncconfig.1)
|
||
|
diff --git a/unix/vncconfig/vncconfig.man b/unix/vncconfig/vncconfig.man
|
||
|
index b685a46..ed9ddda 100644
|
||
|
--- a/unix/vncconfig/vncconfig.man
|
||
|
+++ b/unix/vncconfig/vncconfig.man
|
||
|
@@ -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
|
||
|
|
||
|
diff --git a/unix/vncpasswd/CMakeLists.txt b/unix/vncpasswd/CMakeLists.txt
|
||
|
index a04ed0b..9f716fa 100644
|
||
|
--- a/unix/vncpasswd/CMakeLists.txt
|
||
|
+++ b/unix/vncpasswd/CMakeLists.txt
|
||
|
@@ -5,5 +5,5 @@ add_executable(vncpasswd
|
||
|
|
||
|
target_link_libraries(vncpasswd tx rfb os)
|
||
|
|
||
|
-install(TARGETS vncpasswd DESTINATION ${BIN_DIR})
|
||
|
-install(FILES vncpasswd.man DESTINATION ${MAN_DIR}/man1 RENAME vncpasswd.1)
|
||
|
+install(TARGETS vncpasswd DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
|
||
|
+install(FILES vncpasswd.man DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man1 RENAME vncpasswd.1)
|
||
|
diff --git a/unix/vncpasswd/vncpasswd.man b/unix/vncpasswd/vncpasswd.man
|
||
|
index 9e68181..c70a425 100644
|
||
|
--- a/unix/vncpasswd/vncpasswd.man
|
||
|
+++ b/unix/vncpasswd/vncpasswd.man
|
||
|
@@ -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
|
||
|
|
||
|
diff --git a/unix/vncserver.man b/unix/vncserver.man
|
||
|
deleted file mode 100644
|
||
|
index 95f7960..0000000
|
||
|
--- a/unix/vncserver.man
|
||
|
+++ /dev/null
|
||
|
@@ -1,204 +0,0 @@
|
||
|
-.TH vncserver 1 "" "TigerVNC" "Virtual Network Computing"
|
||
|
-.SH NAME
|
||
|
-vncserver \- start or stop a VNC server
|
||
|
-.SH SYNOPSIS
|
||
|
-.B vncserver
|
||
|
-.RI [: display# ]
|
||
|
-.RB [ \-name
|
||
|
-.IR desktop-name ]
|
||
|
-.RB [ \-geometry
|
||
|
-.IR width x height ]
|
||
|
-.RB [ \-depth
|
||
|
-.IR depth ]
|
||
|
-.RB [ \-pixelformat
|
||
|
-.IR format ]
|
||
|
-.RB [ \-fp
|
||
|
-.IR font-path ]
|
||
|
-.RB [ \-fg ]
|
||
|
-.RB [ \-autokill ]
|
||
|
-.RB [ \-noxstartup ]
|
||
|
-.RB [ \-xstartup
|
||
|
-.IR script ]
|
||
|
-.RI [ Xvnc-options... ]
|
||
|
-.br
|
||
|
-.BI "vncserver \-kill :" display#
|
||
|
-.br
|
||
|
-.BI "vncserver \-list"
|
||
|
-.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
|
||
|
-
|
||
|
-Editing the file $HOME/.vnc/xstartup allows you to change the applications run
|
||
|
-at startup (but note that this will not affect an existing VNC session.)
|
||
|
-
|
||
|
-.SH OPTIONS
|
||
|
-You can get a list of options by passing \fB\-h\fP as an option to vncserver.
|
||
|
-In addition to the options listed below, any unrecognised options will be
|
||
|
-passed to Xvnc - see the Xvnc man page, or "Xvnc \-help", for details.
|
||
|
-
|
||
|
-.TP
|
||
|
-.B \-name \fIdesktop-name\fP
|
||
|
-Each VNC desktop has a name which may be displayed by the viewer. The desktop
|
||
|
-name defaults to "\fIhost\fP:\fIdisplay#\fP (\fIusername\fP)", but you can
|
||
|
-change it with this option. The desktop name option is passed to the xstartup
|
||
|
-script via the $VNCDESKTOP environment variable, which allows you to run a
|
||
|
-different set of applications depending on the name of the desktop.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-geometry \fIwidth\fPx\fIheight\fP
|
||
|
-Specify the size of the VNC desktop to be created. Default is 1024x768.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-depth \fIdepth\fP
|
||
|
-Specify the pixel depth (in bits) of the VNC desktop to be created. Default is
|
||
|
-24. Other possible values are 8, 15 and 16 - anything else is likely to cause
|
||
|
-strange behaviour by applications.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-pixelformat \fIformat\fP
|
||
|
-Specify pixel format for Xvnc to use (BGRnnn or RGBnnn). The default for
|
||
|
-depth 8 is BGR233 (meaning the most significant two bits represent blue, the
|
||
|
-next three green, and the least significant three represent red), the default
|
||
|
-for depth 16 is RGB565, and the default for depth 24 is RGB888.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-cc 3
|
||
|
-As an alternative to the default TrueColor visual, this allows you to run an
|
||
|
-Xvnc server with a PseudoColor visual (i.e. one which uses a color map or
|
||
|
-palette), which can be useful for running some old X applications which only
|
||
|
-work on such a display. Values other than 3 (PseudoColor) and 4 (TrueColor)
|
||
|
-for the \-cc option may result in strange behaviour, and PseudoColor desktops
|
||
|
-must have an 8-bit depth.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-kill :\fIdisplay#\fP
|
||
|
-This kills a VNC desktop previously started with vncserver. It does this by
|
||
|
-killing the Xvnc process, whose process ID is stored in the file
|
||
|
-"$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.pid". The
|
||
|
-.B \-kill
|
||
|
-option ignores anything preceding the first colon (":") in the display
|
||
|
-argument. Thus, you can invoke "vncserver \-kill $DISPLAY", for example at the
|
||
|
-end of your xstartup file after a particular application exits.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-fp \fIfont-path\fP
|
||
|
-If the vncserver script detects that the X Font Server (XFS) is running, it
|
||
|
-will attempt to start Xvnc and configure Xvnc to use XFS for font handling.
|
||
|
-Otherwise, if XFS is not running, the vncserver script will attempt to start
|
||
|
-Xvnc and allow Xvnc to use its own preferred method of font handling (which may
|
||
|
-be a hard-coded font path or, on more recent systems, a font catalog.) In
|
||
|
-any case, if Xvnc fails to start, the vncserver script will then attempt to
|
||
|
-determine an appropriate X font path for this system and start Xvnc using
|
||
|
-that font path.
|
||
|
-
|
||
|
-The
|
||
|
-.B \-fp
|
||
|
-argument allows you to override the above fallback logic and specify a font
|
||
|
-path for Xvnc to use.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-fg
|
||
|
-Runs Xvnc as a foreground process. This has two effects: (1) The VNC server
|
||
|
-can be aborted with CTRL-C, and (2) the VNC server will exit as soon as the
|
||
|
-user logs out of the window manager in the VNC session. This may be necessary
|
||
|
-when launching TigerVNC from within certain grid computing environments.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-autokill
|
||
|
-Automatically kill Xvnc whenever the xstartup script exits. In most cases,
|
||
|
-this has the effect of terminating Xvnc when the user logs out of the window
|
||
|
-manager.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-noxstartup
|
||
|
-Do not run the %HOME/.vnc/xstartup script after launching Xvnc. This
|
||
|
-option allows you to manually start a window manager in your TigerVNC session.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-xstartup \fIscript\fP
|
||
|
-Run a custom startup script, instead of %HOME/.vnc/xstartup, after launching
|
||
|
-Xvnc. This is useful to run full-screen applications.
|
||
|
-.
|
||
|
-.TP
|
||
|
-.B \-list
|
||
|
-Lists all VNC desktops started by vncserver.
|
||
|
-
|
||
|
-.SH FILES
|
||
|
-Several VNC-related files are found in the directory $HOME/.vnc:
|
||
|
-.TP
|
||
|
-$HOME/.vnc/xstartup
|
||
|
-A shell script specifying X applications to be run when a VNC desktop is
|
||
|
-started. If this file does not exist, then vncserver will create a default
|
||
|
-xstartup script which attempts to launch your chosen window manager.
|
||
|
-.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. Likewise, any CLI arguments passed
|
||
|
-to vncserver will override ANY config file setting of the same name. 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".
|
||
|
-.TP
|
||
|
-$HOME/.vnc/passwd
|
||
|
-The VNC password file.
|
||
|
-.TP
|
||
|
-$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.log
|
||
|
-The log file for Xvnc and applications started in xstartup.
|
||
|
-.TP
|
||
|
-$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.pid
|
||
|
-Identifies the Xvnc process ID, used by the
|
||
|
-.B \-kill
|
||
|
-option.
|
||
|
-
|
||
|
-.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.
|
||
|
diff --git a/unix/vncserver/CMakeLists.txt b/unix/vncserver/CMakeLists.txt
|
||
|
new file mode 100644
|
||
|
index 0000000..eeb4b7b
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/CMakeLists.txt
|
||
|
@@ -0,0 +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(TARGETS vncsession DESTINATION ${CMAKE_INSTALL_FULL_SBINDIR})
|
||
|
+install(FILES tigervnc.pam DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/pam.d RENAME tigervnc)
|
||
|
+install(FILES vncsession.man DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man8 RENAME vncsession.8)
|
||
|
+install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vncserver DESTINATION ${CMAKE_INSTALL_FULL_LIBEXECDIR})
|
||
|
+install(FILES vncserver.man DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man8 RENAME vncserver.8)
|
||
|
+install(FILES vncserver-config-defaults vncserver-config-mandatory DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/tigervnc)
|
||
|
+
|
||
|
+install(FILES vncserver.users DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/tigervnc)
|
||
|
+
|
||
|
+if(INSTALL_SYSTEMD_UNITS)
|
||
|
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/vncserver@.service DESTINATION ${CMAKE_INSTALL_FULL_UNITDIR})
|
||
|
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vncsession-start DESTINATION ${CMAKE_INSTALL_FULL_LIBEXECDIR})
|
||
|
+endif()
|
||
|
diff --git a/unix/vncserver/selinux/Makefile b/unix/vncserver/selinux/Makefile
|
||
|
new file mode 100644
|
||
|
index 0000000..904a2d5
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/selinux/Makefile
|
||
|
@@ -0,0 +1,24 @@
|
||
|
+# SELinux module for TigerVNC's vncsession
|
||
|
+#
|
||
|
+# This will install the policy module, but not load it. To apply
|
||
|
+# it you should also run:
|
||
|
+#
|
||
|
+# sudo semodule -i /usr/share/selinux/packages/vncsession.pp
|
||
|
+# sudo restorecon /usr/sbin/vncsession /usr/libexec/vncsession-start
|
||
|
+#
|
||
|
+
|
||
|
+PREFIX=/usr
|
||
|
+DATADIR=$(PREFIX)/share
|
||
|
+
|
||
|
+all: vncsession.pp
|
||
|
+
|
||
|
+%.pp: %.te
|
||
|
+ make -f $(DATADIR)/selinux/devel/Makefile $@
|
||
|
+
|
||
|
+clean:
|
||
|
+ rm -f *.pp
|
||
|
+ rm -rf tmp
|
||
|
+
|
||
|
+install: vncsession.pp
|
||
|
+ mkdir -p $(DESTDIR)$(DATADIR)/selinux/packages
|
||
|
+ install vncsession.pp $(DESTDIR)$(DATADIR)/selinux/packages/vncsession.pp
|
||
|
diff --git a/unix/vncserver/selinux/vncsession.fc b/unix/vncserver/selinux/vncsession.fc
|
||
|
new file mode 100644
|
||
|
index 0000000..121cdd2
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/selinux/vncsession.fc
|
||
|
@@ -0,0 +1,26 @@
|
||
|
+#
|
||
|
+# 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.
|
||
|
+#
|
||
|
+
|
||
|
+HOME_DIR/\.vnc(/.*)? gen_context(system_u:object_r:xdm_home_t,s0)
|
||
|
+HOME_ROOT/\.vnc(/.*)? gen_context(system_u:object_r:xdm_home_t,s0)
|
||
|
+
|
||
|
+/usr/sbin/vncsession -- gen_context(system_u:object_r:vnc_session_exec_t,s0)
|
||
|
+/usr/libexec/vncsession-start -- gen_context(system_u:object_r:vnc_session_exec_t,s0)
|
||
|
+
|
||
|
+/var/run/vncsession-:[0-9]*\.pid -- gen_context(system_u:object_r:vnc_session_var_run_t,s0)
|
||
|
diff --git a/unix/vncserver/selinux/vncsession.if b/unix/vncserver/selinux/vncsession.if
|
||
|
new file mode 100644
|
||
|
index 0000000..3eb6a30
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/selinux/vncsession.if
|
||
|
@@ -0,0 +1 @@
|
||
|
+## <summary></summary>
|
||
|
diff --git a/unix/vncserver/selinux/vncsession.te b/unix/vncserver/selinux/vncsession.te
|
||
|
new file mode 100644
|
||
|
index 0000000..941f28d
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/selinux/vncsession.te
|
||
|
@@ -0,0 +1,67 @@
|
||
|
+#
|
||
|
+# Copyright 2018-2020 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.
|
||
|
+#
|
||
|
+
|
||
|
+policy_module(vncsession, 1.0.0);
|
||
|
+
|
||
|
+gen_require(`
|
||
|
+ type unconfined_t;
|
||
|
+ type xdm_home_t;
|
||
|
+')
|
||
|
+
|
||
|
+type vnc_session_exec_t;
|
||
|
+corecmd_executable_file(vnc_session_exec_t)
|
||
|
+type vnc_session_t;
|
||
|
+init_daemon_domain(vnc_session_t, vnc_session_exec_t)
|
||
|
+auth_login_pgm_domain(vnc_session_t)
|
||
|
+
|
||
|
+type vnc_session_var_run_t;
|
||
|
+files_pid_file(vnc_session_var_run_t)
|
||
|
+allow vnc_session_t vnc_session_var_run_t:file manage_file_perms;
|
||
|
+files_pid_filetrans(vnc_session_t, vnc_session_var_run_t, file)
|
||
|
+
|
||
|
+auth_write_login_records(vnc_session_t)
|
||
|
+
|
||
|
+can_exec(vnc_session_t, vnc_session_exec_t)
|
||
|
+
|
||
|
+userdom_spec_domtrans_all_users(vnc_session_t)
|
||
|
+userdom_signal_all_users(vnc_session_t)
|
||
|
+
|
||
|
+allow vnc_session_t self:capability { kill chown dac_override dac_read_search fowner setgid setuid sys_resource };
|
||
|
+allow vnc_session_t self:process { getcap setsched setexec setrlimit };
|
||
|
+allow vnc_session_t self:fifo_file rw_fifo_file_perms;
|
||
|
+
|
||
|
+manage_files_pattern(vnc_session_t, xdm_home_t, xdm_home_t)
|
||
|
+manage_fifo_files_pattern(vnc_session_t, xdm_home_t, xdm_home_t)
|
||
|
+manage_sock_files_pattern(vnc_session_t, xdm_home_t, xdm_home_t)
|
||
|
+manage_lnk_files_pattern(vnc_session_t, xdm_home_t, xdm_home_t)
|
||
|
+
|
||
|
+userdom_user_home_dir_filetrans(unconfined_t, xdm_home_t, dir, ".vnc")
|
||
|
+userdom_user_home_dir_filetrans(vnc_session_t, xdm_home_t, dir, ".vnc")
|
||
|
+
|
||
|
+userdom_admin_home_dir_filetrans(vnc_session_t, xdm_home_t, dir, ".vnc")
|
||
|
+userdom_admin_home_dir_filetrans(unconfined_t, xdm_home_t, dir, ".vnc")
|
||
|
+
|
||
|
+miscfiles_read_localization(vnc_session_t)
|
||
|
+
|
||
|
+kernel_read_kernel_sysctls(vnc_session_t)
|
||
|
+
|
||
|
+logging_append_all_logs(vnc_session_t)
|
||
|
+
|
||
|
+mcs_process_set_categories(vnc_session_t)
|
||
|
+mcs_killall(vnc_session_t)
|
||
|
diff --git a/unix/vncserver/tigervnc.pam b/unix/vncserver/tigervnc.pam
|
||
|
new file mode 100644
|
||
|
index 0000000..0f4cb3a
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/tigervnc.pam
|
||
|
@@ -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
|
||
|
diff --git a/unix/vncserver/vncserver-config-defaults b/unix/vncserver/vncserver-config-defaults
|
||
|
new file mode 100644
|
||
|
index 0000000..0c217bf
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/vncserver-config-defaults
|
||
|
@@ -0,0 +1,15 @@
|
||
|
+## Default settings for VNC servers started by the vncserver service
|
||
|
+#
|
||
|
+# Any settings given here will override the builtin defaults, but can
|
||
|
+# also be overriden by ~/.vnc/config and vncserver-config-mandatory.
|
||
|
+#
|
||
|
+# See the following manpages for more details: vncserver(1) Xvnc(1)
|
||
|
+#
|
||
|
+# Several common settings are shown below. Uncomment and modify to your
|
||
|
+# liking.
|
||
|
+
|
||
|
+# securitytypes=vncauth,tlsvnc
|
||
|
+# desktop=sandbox
|
||
|
+# geometry=2000x1200
|
||
|
+# localhost
|
||
|
+# alwaysshared
|
||
|
diff --git a/unix/vncserver/vncserver-config-mandatory b/unix/vncserver/vncserver-config-mandatory
|
||
|
new file mode 100644
|
||
|
index 0000000..98c32f6
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/vncserver-config-mandatory
|
||
|
@@ -0,0 +1,15 @@
|
||
|
+## Mandatory settings for VNC servers started by the vncserver service
|
||
|
+#
|
||
|
+# Any settings given here will override the builtin defaults and
|
||
|
+# settings specified in ~/.vnc/config or vnc-config-defaults.
|
||
|
+#
|
||
|
+# See the following manpages for more details: vncserver(1) Xvnc(1)
|
||
|
+#
|
||
|
+# Several common settings are shown below. Uncomment and modify to your
|
||
|
+# liking.
|
||
|
+
|
||
|
+# securitytypes=vncauth,tlsvnc
|
||
|
+# desktop=sandbox
|
||
|
+# geometry=2000x1200
|
||
|
+# localhost
|
||
|
+# alwaysshared
|
||
|
diff --git a/unix/vncserver/vncserver.in b/unix/vncserver/vncserver.in
|
||
|
new file mode 100755
|
||
|
index 0000000..8e05b72
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/vncserver.in
|
||
|
@@ -0,0 +1,485 @@
|
||
|
+#!/usr/bin/perl
|
||
|
+#
|
||
|
+# Copyright (C) 2015-2019 Pierre Ossman for Cendio AB
|
||
|
+# Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved.
|
||
|
+# Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||
|
+# Copyright (C) 2002-2003 Constantin Kaplinsky. All Rights Reserved.
|
||
|
+# Copyright (C) 2002-2005 RealVNC Ltd.
|
||
|
+# Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||
|
+#
|
||
|
+# 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.
|
||
|
+#
|
||
|
+
|
||
|
+#
|
||
|
+# vncserver - wrapper script to start an X VNC server.
|
||
|
+#
|
||
|
+
|
||
|
+&SanityCheck();
|
||
|
+
|
||
|
+#
|
||
|
+# Global variables. You may want to configure some of these for
|
||
|
+# your site
|
||
|
+#
|
||
|
+
|
||
|
+$vncUserDir = "$ENV{HOME}/.vnc";
|
||
|
+$vncUserConfig = "$vncUserDir/config";
|
||
|
+
|
||
|
+$vncSystemConfigDir = "/etc/tigervnc";
|
||
|
+$vncSystemConfigDefaultsFile = "$vncSystemConfigDir/vncserver-config-defaults";
|
||
|
+$vncSystemConfigMandatoryFile = "$vncSystemConfigDir/vncserver-config-mandatory";
|
||
|
+
|
||
|
+$xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority";
|
||
|
+
|
||
|
+chop($host = `uname -n`);
|
||
|
+
|
||
|
+if (-d "/etc/X11/fontpath.d") {
|
||
|
+ $fontPath = "catalogue:/etc/X11/fontpath.d";
|
||
|
+}
|
||
|
+
|
||
|
+@fontpaths = ('/usr/share/X11/fonts', '/usr/share/fonts', '/usr/share/fonts/X11/');
|
||
|
+if (! -l "/usr/lib/X11") {push(@fontpaths, '/usr/lib/X11/fonts');}
|
||
|
+if (! -l "/usr/X11") {push(@fontpaths, '/usr/X11/lib/X11/fonts');}
|
||
|
+if (! -l "/usr/X11R6") {push(@fontpaths, '/usr/X11R6/lib/X11/fonts');}
|
||
|
+push(@fontpaths, '/usr/share/fonts/default');
|
||
|
+
|
||
|
+@fonttypes = ('misc',
|
||
|
+ '75dpi',
|
||
|
+ '100dpi',
|
||
|
+ 'Speedo',
|
||
|
+ 'Type1');
|
||
|
+
|
||
|
+foreach $_fpath (@fontpaths) {
|
||
|
+ foreach $_ftype (@fonttypes) {
|
||
|
+ if (-f "$_fpath/$_ftype/fonts.dir") {
|
||
|
+ if (! -l "$_fpath/$_ftype") {
|
||
|
+ $defFontPath .= "$_fpath/$_ftype,";
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+if ($defFontPath) {
|
||
|
+ if (substr($defFontPath, -1, 1) == ',') {
|
||
|
+ chop $defFontPath;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+if ($fontPath eq "") {
|
||
|
+ $fontPath = $defFontPath;
|
||
|
+}
|
||
|
+
|
||
|
+# Find display number.
|
||
|
+if ((@ARGV == 1) && ($ARGV[0] =~ /^:(\d+)$/)) {
|
||
|
+ $displayNumber = $1;
|
||
|
+ if (!&CheckDisplayNumber($displayNumber)) {
|
||
|
+ die "A VNC server is already running as :$displayNumber\n";
|
||
|
+ }
|
||
|
+} else {
|
||
|
+ &Usage();
|
||
|
+}
|
||
|
+
|
||
|
+$vncPort = 5900 + $displayNumber;
|
||
|
+
|
||
|
+$desktopName = "$host:$displayNumber ($ENV{USER})";
|
||
|
+
|
||
|
+my %default_opts;
|
||
|
+my %config;
|
||
|
+
|
||
|
+# We set some reasonable defaults. Config file settings
|
||
|
+# override these where present.
|
||
|
+$default_opts{desktop} = $desktopName;
|
||
|
+$default_opts{auth} = $xauthorityFile;
|
||
|
+$default_opts{rfbwait} = 30000;
|
||
|
+$default_opts{rfbauth} = "$vncUserDir/passwd";
|
||
|
+$default_opts{rfbport} = $vncPort;
|
||
|
+$default_opts{fp} = $fontPath if ($fontPath);
|
||
|
+$default_opts{pn} = "";
|
||
|
+
|
||
|
+# Load user-overrideable system defaults
|
||
|
+LoadConfig($vncSystemConfigDefaultsFile);
|
||
|
+
|
||
|
+# Then the user's settings
|
||
|
+LoadConfig($vncUserConfig);
|
||
|
+
|
||
|
+# And then override anything set above if mandatory settings exist.
|
||
|
+# WARNING: "Mandatory" is used loosely here! As the man page says,
|
||
|
+# there is nothing stopping someone from EASILY subverting the
|
||
|
+# settings in $vncSystemConfigMandatoryFile by simply passing
|
||
|
+# CLI args to vncserver, which trump config files! To properly
|
||
|
+# hard force policy in a non-subvertible way would require major
|
||
|
+# development work that touches Xvnc itself.
|
||
|
+LoadConfig($vncSystemConfigMandatoryFile, 1);
|
||
|
+
|
||
|
+#
|
||
|
+# Check whether VNC authentication is enabled, and if so, check that
|
||
|
+# a VNC password has been created.
|
||
|
+#
|
||
|
+
|
||
|
+$securityTypeArgSpecified = 0;
|
||
|
+$vncAuthEnabled = 0;
|
||
|
+$passwordArgSpecified = 0;
|
||
|
+@vncAuthStrings = ("vncauth", "tlsvnc", "x509vnc");
|
||
|
+
|
||
|
+# ...first we check our configuration files' settings
|
||
|
+if ($config{'securitytypes'}) {
|
||
|
+ $securityTypeArgSpecified = 1;
|
||
|
+ foreach $arg2 (split(',', $config{'securitytypes'})) {
|
||
|
+ if (grep {$_ eq lc($arg2)} @vncAuthStrings) {
|
||
|
+ $vncAuthEnabled = 1;
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+if ($config{'password'} ||
|
||
|
+ $config{'passwordfile'} ||
|
||
|
+ $config{'rfbauth'}) {
|
||
|
+ $passwordArgSpecified = 1;
|
||
|
+}
|
||
|
+
|
||
|
+if ((!$securityTypeArgSpecified || $vncAuthEnabled) && !$passwordArgSpecified) {
|
||
|
+ ($z,$z,$mode) = stat("$vncUserDir/passwd");
|
||
|
+ if (!(-e "$vncUserDir/passwd") || ($mode & 077)) {
|
||
|
+ die "VNC authentication enabled, but no password file created.\n";
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+#
|
||
|
+# Find a desktop session to run
|
||
|
+#
|
||
|
+
|
||
|
+my $sessionname;
|
||
|
+my %session;
|
||
|
+
|
||
|
+$sessionname = delete $config{'session'};
|
||
|
+
|
||
|
+if ($sessionname) {
|
||
|
+ %session = LoadXSession($sessionname);
|
||
|
+ if (!%session) {
|
||
|
+ warn "Could not load configured desktop session $sessionname\n";
|
||
|
+ $sessionname = undef;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+if (!$sessionname) {
|
||
|
+ foreach $file (glob("/usr/share/xsessions/*.desktop")) {
|
||
|
+ ($name) = $file =~ /^.*\/(.*)[.]desktop$/;
|
||
|
+ %session = LoadXSession($name);
|
||
|
+ if (%session) {
|
||
|
+ $sessionname = $name;
|
||
|
+ last;
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+if (!$sessionname) {
|
||
|
+ die "Could not find a desktop session to run\n";
|
||
|
+}
|
||
|
+
|
||
|
+warn "Using desktop session $sessionname\n";
|
||
|
+
|
||
|
+if (!$session{'Exec'}) {
|
||
|
+ die "No command specified for desktop session\n";
|
||
|
+}
|
||
|
+
|
||
|
+$ENV{GDMSESSION} = $sessionname;
|
||
|
+$ENV{DESKTOP_SESSION} = $sessionname;
|
||
|
+$ENV{XDG_SESSION_DESKTOP} = $sessionname;
|
||
|
+
|
||
|
+if ($session{'DesktopNames'}) {
|
||
|
+ $ENV{XDG_DESKTOP_NAMES} = $session{'DesktopNames'} =~ s/;/:/gr;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+# Make an X server cookie and set up the Xauthority file
|
||
|
+# mcookie is a part of util-linux, usually only GNU/Linux systems have it.
|
||
|
+$cookie = `mcookie`;
|
||
|
+# Fallback for non GNU/Linux OS - use /dev/urandom on systems that have it,
|
||
|
+# otherwise use perl's random number generator, seeded with the sum
|
||
|
+# of the current time, our PID and part of the encrypted form of the password.
|
||
|
+if ($cookie eq "" && open(URANDOM, '<', '/dev/urandom')) {
|
||
|
+ my $randata;
|
||
|
+ if (sysread(URANDOM, $randata, 16) == 16) {
|
||
|
+ $cookie = unpack 'h*', $randata;
|
||
|
+ }
|
||
|
+ close(URANDOM);
|
||
|
+}
|
||
|
+if ($cookie eq "") {
|
||
|
+ srand(time+$$+unpack("L",`cat $vncUserDir/passwd`));
|
||
|
+ for (1..16) {
|
||
|
+ $cookie .= sprintf("%02x", int(rand(256)) % 256);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+open(XAUTH, "|xauth -f $xauthorityFile source -");
|
||
|
+print XAUTH "add $host:$displayNumber . $cookie\n";
|
||
|
+print XAUTH "add $host/unix:$displayNumber . $cookie\n";
|
||
|
+close(XAUTH);
|
||
|
+
|
||
|
+$ENV{XAUTHORITY} = $xauthorityFile;
|
||
|
+
|
||
|
+# Now start the X VNC Server
|
||
|
+
|
||
|
+@cmd = ("xinit");
|
||
|
+
|
||
|
+push(@cmd, $Xsession, $session{'Exec'});
|
||
|
+
|
||
|
+push(@cmd, '--');
|
||
|
+
|
||
|
+
|
||
|
+# We build up our Xvnc command with options
|
||
|
+push(@cmd, "@CMAKE_INSTALL_FULL_BINDIR@/Xvnc", ":$displayNumber");
|
||
|
+
|
||
|
+foreach my $k (sort keys %config) {
|
||
|
+ push(@cmd, "-$k");
|
||
|
+ push(@cmd, $config{$k}) if $config{$k};
|
||
|
+ delete $default_opts{$k}; # file options take precedence
|
||
|
+}
|
||
|
+
|
||
|
+foreach my $k (sort keys %default_opts) {
|
||
|
+ push(@cmd, "-$k");
|
||
|
+ push(@cmd, $default_opts{$k}) if $default_opts{$k};
|
||
|
+}
|
||
|
+
|
||
|
+warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n";
|
||
|
+
|
||
|
+warn "Starting desktop session $sessionname\n";
|
||
|
+
|
||
|
+exec(@cmd);
|
||
|
+
|
||
|
+die "Failed to start session.\n";
|
||
|
+
|
||
|
+###############################################################################
|
||
|
+# Functions
|
||
|
+###############################################################################
|
||
|
+
|
||
|
+#
|
||
|
+# Populate the global %config hash with settings from a specified
|
||
|
+# vncserver configuration file if it exists
|
||
|
+#
|
||
|
+# Args: 1. file path
|
||
|
+# 2. optional boolean flag to enable warning when a previously
|
||
|
+# set configuration setting is being overridden
|
||
|
+#
|
||
|
+sub LoadConfig {
|
||
|
+ local ($configFile, $warnoverride) = @_;
|
||
|
+ local ($toggle) = undef;
|
||
|
+
|
||
|
+ if (stat($configFile)) {
|
||
|
+ if (open(IN, $configFile)) {
|
||
|
+ while (<IN>) {
|
||
|
+ next if /^#/;
|
||
|
+ if (my ($k, $v) = /^\s*(\w+)\s*=\s*(.+)$/) {
|
||
|
+ $k = lc($k); # must normalize key case
|
||
|
+ if ($warnoverride && $config{$k}) {
|
||
|
+ print("Warning: $configFile is overriding previously defined '$k' to be '$v'\n");
|
||
|
+ }
|
||
|
+ $config{$k} = $v;
|
||
|
+ } elsif ($_ =~ m/^\s*(\S+)/) {
|
||
|
+ # We can't reasonably warn on override of toggles (e.g. AlwaysShared)
|
||
|
+ # because it would get crazy to do so. We'd have to check if the
|
||
|
+ # current config file being loaded defined the logical opposite setting
|
||
|
+ # (NeverShared vs. AlwaysShared, etc etc).
|
||
|
+ $toggle = lc($1); # must normalize key case
|
||
|
+ $config{$toggle} = $k;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ close(IN);
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+#
|
||
|
+# Load a session desktop file
|
||
|
+#
|
||
|
+sub LoadXSession {
|
||
|
+ local ($name) = @_;
|
||
|
+ my $file, $found_group, %session;
|
||
|
+
|
||
|
+ $file = "/usr/share/xsessions/$name.desktop";
|
||
|
+
|
||
|
+ if (!stat($file)) {
|
||
|
+ warn "Could not find session desktop file $file";
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!open(IN, $file)) {
|
||
|
+ warn "Could not open session desktop file $file";
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ $found_group = 0;
|
||
|
+ while (my $line = <IN>) {
|
||
|
+ next if $line =~ /^#/;
|
||
|
+ next if $line =~ /^\s*$/;
|
||
|
+
|
||
|
+ if (!$found_group) {
|
||
|
+ next if $line != "[Desktop Entry]";
|
||
|
+ $found_group = 1;
|
||
|
+ next;
|
||
|
+ } else {
|
||
|
+ last if $line =~ /^\[/;
|
||
|
+ }
|
||
|
+
|
||
|
+ my ($key, $value) = $line =~ /^\s*([]A-Za-z0-9_@\-\[]+)\s*=\s*(.*)$/;
|
||
|
+ if (!$key) {
|
||
|
+ warn "Invalid session desktop file $file";
|
||
|
+ close(IN);
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ $value =~ s/\\s/ /g;
|
||
|
+ $value =~ s/\\n/\n/g;
|
||
|
+ $value =~ s/\\t/\t/g;
|
||
|
+ $value =~ s/\\r/\r/g;
|
||
|
+ $value =~ s/\\\\/\\/g;
|
||
|
+
|
||
|
+ $session{$key} = $value;
|
||
|
+ }
|
||
|
+
|
||
|
+ close(IN);
|
||
|
+
|
||
|
+ return %session;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+#
|
||
|
+# CheckDisplayNumber checks if the given display number is available. 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 CheckDisplayNumber
|
||
|
+{
|
||
|
+ local ($n) = @_;
|
||
|
+
|
||
|
+ socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
|
||
|
+ eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
|
||
|
+ if (!bind(S, pack('S n x12', $AF_INET, 6000 + $n))) {
|
||
|
+ close(S);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ close(S);
|
||
|
+
|
||
|
+ socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
|
||
|
+ eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
|
||
|
+ if (!bind(S, pack('S n x12', $AF_INET, 5900 + $n))) {
|
||
|
+ close(S);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ close(S);
|
||
|
+
|
||
|
+ if (-e "/tmp/.X$n-lock") {
|
||
|
+ warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n";
|
||
|
+ warn "Remove this file if there is no X server $host:$n\n";
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (-e "/tmp/.X11-unix/X$n") {
|
||
|
+ warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n";
|
||
|
+ warn "Remove this file if there is no X server $host:$n\n";
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (-e "/usr/spool/sockets/X11/$n") {
|
||
|
+ warn("\nWarning: $host:$n is taken because of ".
|
||
|
+ "/usr/spool/sockets/X11/$n\n");
|
||
|
+ warn "Remove this file if there is no X server $host:$n\n";
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+#
|
||
|
+# Usage
|
||
|
+#
|
||
|
+
|
||
|
+sub Usage
|
||
|
+{
|
||
|
+ die("\nusage: $prog <display>\n\n");
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+# Routine to make sure we're operating in a sane environment.
|
||
|
+sub SanityCheck
|
||
|
+{
|
||
|
+ local ($cmd);
|
||
|
+
|
||
|
+ # Get the program name
|
||
|
+ ($prog) = ($0 =~ m|([^/]+)$|);
|
||
|
+
|
||
|
+ #
|
||
|
+ # Check we have all the commands we'll need on the path.
|
||
|
+ #
|
||
|
+
|
||
|
+ cmd:
|
||
|
+ foreach $cmd ("uname","xauth","xinit") {
|
||
|
+ for (split(/:/,$ENV{PATH})) {
|
||
|
+ if (-x "$_/$cmd") {
|
||
|
+ next cmd;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ die "$prog: couldn't find \"$cmd\" on your PATH.\n";
|
||
|
+ }
|
||
|
+
|
||
|
+ foreach $cmd ("/etc/X11/xinit/Xsession", "/etc/X11/Xsession") {
|
||
|
+ if (-x "$cmd") {
|
||
|
+ $Xsession = $cmd;
|
||
|
+ last;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ if (not defined $Xsession) {
|
||
|
+ die "$prog: Couldn't find suitable Xsession.\n";
|
||
|
+ }
|
||
|
+
|
||
|
+
|
||
|
+ if (!defined($ENV{HOME})) {
|
||
|
+ die "$prog: The HOME environment variable is not set.\n";
|
||
|
+ }
|
||
|
+
|
||
|
+ #
|
||
|
+ # Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an
|
||
|
+ # eval, and if it fails we try 'require "sys/socket.ph"'. If this fails,
|
||
|
+ # we just guess at the values. If you find perl moaning here, just
|
||
|
+ # hard-code the values of AF_INET and SOCK_STREAM. You can find these out
|
||
|
+ # for your platform by looking in /usr/include/sys/socket.h and related
|
||
|
+ # files.
|
||
|
+ #
|
||
|
+
|
||
|
+ chop($os = `uname`);
|
||
|
+ chop($osrev = `uname -r`);
|
||
|
+
|
||
|
+ eval 'use Socket';
|
||
|
+ if ($@) {
|
||
|
+ eval 'require "sys/socket.ph"';
|
||
|
+ if ($@) {
|
||
|
+ if (($os eq "SunOS") && ($osrev !~ /^4/)) {
|
||
|
+ $AF_INET = 2;
|
||
|
+ $SOCK_STREAM = 2;
|
||
|
+ } else {
|
||
|
+ $AF_INET = 2;
|
||
|
+ $SOCK_STREAM = 1;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ $AF_INET = &AF_INET;
|
||
|
+ $SOCK_STREAM = &SOCK_STREAM;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ $AF_INET = &AF_INET;
|
||
|
+ $SOCK_STREAM = &SOCK_STREAM;
|
||
|
+ }
|
||
|
+}
|
||
|
diff --git a/unix/vncserver/vncserver.man b/unix/vncserver/vncserver.man
|
||
|
new file mode 100644
|
||
|
index 0000000..f1017be
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/vncserver.man
|
||
|
@@ -0,0 +1 @@
|
||
|
+.so man8/vncsession.8
|
||
|
diff --git a/unix/vncserver/vncserver.users b/unix/vncserver/vncserver.users
|
||
|
new file mode 100644
|
||
|
index 0000000..24875c8
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/vncserver.users
|
||
|
@@ -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
|
||
|
+
|
||
|
diff --git a/unix/vncserver/vncserver@.service.in b/unix/vncserver/vncserver@.service.in
|
||
|
new file mode 100644
|
||
|
index 0000000..584ecf4
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/vncserver@.service.in
|
||
|
@@ -0,0 +1,43 @@
|
||
|
+# The vncserver service unit file
|
||
|
+#
|
||
|
+# Quick HowTo:
|
||
|
+# 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
|
||
|
+# limit connections to the local host and then tunnel from
|
||
|
+# the machine you want to view VNC on (host A) to the machine
|
||
|
+# whose VNC output you want to view (host B)
|
||
|
+#
|
||
|
+# [user@hostA ~]$ ssh -v -C -L 590N:localhost:590M hostB
|
||
|
+#
|
||
|
+# this will open a connection on port 590N of your hostA to hostB's port 590M
|
||
|
+# (in fact, it ssh-connects to hostB and then connects to localhost (on hostB).
|
||
|
+# See the ssh man page for details on port forwarding)
|
||
|
+#
|
||
|
+# 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 "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.
|
||
|
+
|
||
|
+
|
||
|
+[Unit]
|
||
|
+Description=Remote desktop service (VNC)
|
||
|
+After=syslog.target network.target
|
||
|
+
|
||
|
+[Service]
|
||
|
+Type=forking
|
||
|
+ExecStart=@CMAKE_INSTALL_FULL_LIBEXECDIR@/vncsession-start %i
|
||
|
+PIDFile=/var/run/vncsession-%i.pid
|
||
|
+SELinuxContext=system_u:system_r:vnc_session_t:s0
|
||
|
+
|
||
|
+[Install]
|
||
|
+WantedBy=multi-user.target
|
||
|
diff --git a/unix/vncserver/vncsession-start.in b/unix/vncserver/vncsession-start.in
|
||
|
new file mode 100644
|
||
|
index 0000000..b20fcdd
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/vncsession-start.in
|
||
|
@@ -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="@CMAKE_INSTALL_FULL_SYSCONFDIR@/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 "@CMAKE_INSTALL_FULL_SBINDIR@/vncsession" "${USER}" "${DISPLAY}"
|
||
|
diff --git a/unix/vncserver/vncsession.c b/unix/vncserver/vncsession.c
|
||
|
new file mode 100644
|
||
|
index 0000000..21a40f6
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/vncsession.c
|
||
|
@@ -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] = CMAKE_INSTALL_FULL_LIBEXECDIR "/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;
|
||
|
+}
|
||
|
diff --git a/unix/vncserver/vncsession.man b/unix/vncserver/vncsession.man
|
||
|
new file mode 100644
|
||
|
index 0000000..2138209
|
||
|
--- /dev/null
|
||
|
+++ b/unix/vncserver/vncsession.man
|
||
|
@@ -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.
|
||
|
diff --git a/unix/x0vncserver/CMakeLists.txt b/unix/x0vncserver/CMakeLists.txt
|
||
|
index 8beade7..af82415 100644
|
||
|
--- a/unix/x0vncserver/CMakeLists.txt
|
||
|
+++ b/unix/x0vncserver/CMakeLists.txt
|
||
|
@@ -52,5 +52,5 @@ endif()
|
||
|
|
||
|
target_link_libraries(x0vncserver ${X11_LIBRARIES})
|
||
|
|
||
|
-install(TARGETS x0vncserver DESTINATION ${BIN_DIR})
|
||
|
-install(FILES x0vncserver.man DESTINATION ${MAN_DIR}/man1 RENAME x0vncserver.1)
|
||
|
+install(TARGETS x0vncserver DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
|
||
|
+install(FILES x0vncserver.man DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man1 RENAME x0vncserver.1)
|
||
|
diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man
|
||
|
index 9c8a889..9559179 100644
|
||
|
--- a/unix/xserver/hw/vnc/Xvnc.man
|
||
|
+++ b/unix/xserver/hw/vnc/Xvnc.man
|
||
|
@@ -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
|
||
|
diff --git a/vncviewer/CMakeLists.txt b/vncviewer/CMakeLists.txt
|
||
|
index 3c18646..7e25d45 100644
|
||
|
--- a/vncviewer/CMakeLists.txt
|
||
|
+++ b/vncviewer/CMakeLists.txt
|
||
|
@@ -60,9 +60,9 @@ if(APPLE)
|
||
|
target_link_libraries(vncviewer "-framework IOKit")
|
||
|
endif()
|
||
|
|
||
|
-install(TARGETS vncviewer DESTINATION ${BIN_DIR})
|
||
|
+install(TARGETS vncviewer DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
|
||
|
if(UNIX)
|
||
|
- install(FILES vncviewer.man DESTINATION ${MAN_DIR}/man1 RENAME vncviewer.1)
|
||
|
+ install(FILES vncviewer.man DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man1 RENAME vncviewer.1)
|
||
|
|
||
|
configure_file(vncviewer.desktop.in.in vncviewer.desktop.in)
|
||
|
find_program(INTLTOOL_MERGE_EXECUTABLE intltool-merge)
|
||
|
@@ -91,10 +91,10 @@ if(UNIX)
|
||
|
)
|
||
|
endif()
|
||
|
add_custom_target(desktop ALL DEPENDS vncviewer.desktop)
|
||
|
- install(FILES ${CMAKE_CURRENT_BINARY_DIR}/vncviewer.desktop DESTINATION ${DATA_DIR}/applications)
|
||
|
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/vncviewer.desktop DESTINATION ${CMAKE_INSTALL_FULL_DATADIR}/applications)
|
||
|
|
||
|
foreach(res 16 22 24 32 48)
|
||
|
- install(FILES ../media/icons/tigervnc_${res}.png DESTINATION ${DATA_DIR}/icons/hicolor/${res}x${res}/apps RENAME tigervnc.png)
|
||
|
+ install(FILES ../media/icons/tigervnc_${res}.png DESTINATION ${CMAKE_INSTALL_FULL_DATADIR}/icons/hicolor/${res}x${res}/apps RENAME tigervnc.png)
|
||
|
endforeach()
|
||
|
- install(FILES ../media/icons/tigervnc.svg DESTINATION ${DATA_DIR}/icons/hicolor/scalable/apps)
|
||
|
+ install(FILES ../media/icons/tigervnc.svg DESTINATION ${CMAKE_INSTALL_FULL_DATADIR}/icons/hicolor/scalable/apps)
|
||
|
endif()
|
||
|
diff --git a/vncviewer/vncviewer.cxx b/vncviewer/vncviewer.cxx
|
||
|
index 4a8370b..ae4cb6f 100644
|
||
|
--- a/vncviewer/vncviewer.cxx
|
||
|
+++ b/vncviewer/vncviewer.cxx
|
||
|
@@ -227,7 +227,7 @@ static void init_fltk()
|
||
|
bool exists;
|
||
|
|
||
|
sprintf(icon_path, "%s/icons/hicolor/%dx%d/apps/tigervnc.png",
|
||
|
- DATA_DIR, icon_sizes[i], icon_sizes[i]);
|
||
|
+ CMAKE_INSTALL_FULL_DATADIR, icon_sizes[i], icon_sizes[i]);
|
||
|
|
||
|
#ifndef WIN32
|
||
|
struct stat st;
|
||
|
@@ -505,7 +505,7 @@ int main(int argc, char** argv)
|
||
|
argv0 = argv[0];
|
||
|
|
||
|
setlocale(LC_ALL, "");
|
||
|
- bindtextdomain(PACKAGE_NAME, LOCALE_DIR);
|
||
|
+ bindtextdomain(PACKAGE_NAME, CMAKE_INSTALL_FULL_LOCALEDIR);
|
||
|
textdomain(PACKAGE_NAME);
|
||
|
|
||
|
rfb::SecurityClient::setDefaults();
|
||
|
diff --git a/vncviewer/vncviewer.desktop.in.in b/vncviewer/vncviewer.desktop.in.in
|
||
|
index d775dde..9d658e4 100644
|
||
|
--- a/vncviewer/vncviewer.desktop.in.in
|
||
|
+++ b/vncviewer/vncviewer.desktop.in.in
|
||
|
@@ -2,7 +2,7 @@
|
||
|
Name=TigerVNC Viewer
|
||
|
GenericName=Remote Desktop Viewer
|
||
|
Comment=Connect to VNC server and display remote desktop
|
||
|
-Exec=@BIN_DIR@/vncviewer
|
||
|
+Exec=@CMAKE_INSTALL_FULL_BINDIR@/vncviewer
|
||
|
Icon=tigervnc
|
||
|
Terminal=false
|
||
|
Type=Application
|
||
|
diff --git a/vncviewer/vncviewer.man b/vncviewer/vncviewer.man
|
||
|
index f93e096..a8d8c77 100644
|
||
|
--- a/vncviewer/vncviewer.man
|
||
|
+++ b/vncviewer/vncviewer.man
|
||
|
@@ -327,7 +327,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
|
||
|
|