commit
6c559b965e
@ -0,0 +1 @@
|
|||||||
|
SOURCES/tigervnc-1.12.0.tar.gz
|
@ -0,0 +1 @@
|
|||||||
|
44db63993d8ad04f730b0b48e8aca32933bff15a SOURCES/tigervnc-1.12.0.tar.gz
|
@ -0,0 +1,24 @@
|
|||||||
|
From 2489f2f38eb32d9dd03718a36cbdbdf13d2f8b9b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Adam Jackson <ajax@redhat.com>
|
||||||
|
Date: Thu, 12 Nov 2015 11:10:11 -0500
|
||||||
|
Subject: [PATCH] rpath hack
|
||||||
|
|
||||||
|
Normally, rpath is undesirable. But for the X server we _know_ we need
|
||||||
|
Mesa's libGL, which will always be in %{_libdir}, and not any third-party
|
||||||
|
libGL that may be configured using ld.so.conf.
|
||||||
|
|
||||||
|
---
|
||||||
|
configure.ac | 1 +
|
||||||
|
1 files changed, 1 insertions(+), 0 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index fa15a2d..a5af1e0 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -1261,6 +1261,7 @@ AM_CONDITIONAL(GLX, test "x$GLX" = xyes)
|
||||||
|
|
||||||
|
AM_CONDITIONAL(HASHTABLE, test "x$HASHTABLE" = xyes)
|
||||||
|
|
||||||
|
+GLX_SYS_LIBS="$GLX_SYS_LIBS -Wl,-rpath=\$(libdir)"
|
||||||
|
AC_SUBST([GLX_DEFINES])
|
||||||
|
AC_SUBST([GLX_SYS_LIBS])
|
@ -0,0 +1,19 @@
|
|||||||
|
# This file contains configuration of libvnc.so module
|
||||||
|
#
|
||||||
|
# To get libvnc.so module working, do this:
|
||||||
|
# 1. run "vncpasswd" from tigervnc-server package as root user
|
||||||
|
# 2. uncomment configuration lines below
|
||||||
|
#
|
||||||
|
# Please note you can specify any option which Xvnc accepts.
|
||||||
|
# Refer to `Xvnc -help` output for detailed list of options.
|
||||||
|
|
||||||
|
#Section "Module"
|
||||||
|
# Load "vnc"
|
||||||
|
#EndSection
|
||||||
|
|
||||||
|
#Section "Screen"
|
||||||
|
# Identifier "Screen0"
|
||||||
|
# DefaultDepth 16
|
||||||
|
# Option "SecurityTypes" "VncAuth"
|
||||||
|
# Option "PasswordFile" "/root/.vnc/passwd"
|
||||||
|
#EndSection
|
@ -0,0 +1,199 @@
|
|||||||
|
From ccbd491fa48f1c43daeb1a6c5ee91a1a8fa3db88 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Grulich <jgrulich@redhat.com>
|
||||||
|
Date: Tue, 9 Aug 2022 14:31:07 +0200
|
||||||
|
Subject: [PATCH] x0vncserver: add new keysym in case we don't find a matching
|
||||||
|
keycode
|
||||||
|
|
||||||
|
We might often fail to find a matching X11 keycode when the client has
|
||||||
|
a different keyboard layout and end up with no key event. To avoid a
|
||||||
|
failure we add it as a new keysym/keycode pair so the next time a keysym
|
||||||
|
from the client that is unknown to the server is send, we will find a
|
||||||
|
match and proceed with key event. This is same behavior used in Xvnc or
|
||||||
|
x11vnc, although Xvnc has more advanced mapping from keysym to keycode.
|
||||||
|
---
|
||||||
|
unix/x0vncserver/XDesktop.cxx | 121 +++++++++++++++++++++++++++++++++-
|
||||||
|
unix/x0vncserver/XDesktop.h | 4 ++
|
||||||
|
2 files changed, 122 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
|
||||||
|
index f2046e43e..933998f05 100644
|
||||||
|
--- a/unix/x0vncserver/XDesktop.cxx
|
||||||
|
+++ b/unix/x0vncserver/XDesktop.cxx
|
||||||
|
@@ -31,6 +31,7 @@
|
||||||
|
#include <x0vncserver/XDesktop.h>
|
||||||
|
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
+#include <X11/Xutil.h>
|
||||||
|
#ifdef HAVE_XTEST
|
||||||
|
#include <X11/extensions/XTest.h>
|
||||||
|
#endif
|
||||||
|
@@ -50,6 +51,7 @@ void vncSetGlueContext(Display *dpy, void *res);
|
||||||
|
#include <x0vncserver/Geometry.h>
|
||||||
|
#include <x0vncserver/XPixelBuffer.h>
|
||||||
|
|
||||||
|
+using namespace std;
|
||||||
|
using namespace rfb;
|
||||||
|
|
||||||
|
extern const unsigned short code_map_qnum_to_xorgevdev[];
|
||||||
|
@@ -264,6 +266,9 @@ void XDesktop::start(VNCServer* vs) {
|
||||||
|
void XDesktop::stop() {
|
||||||
|
running = false;
|
||||||
|
|
||||||
|
+ // Delete added keycodes
|
||||||
|
+ deleteAddedKeysyms(dpy);
|
||||||
|
+
|
||||||
|
#ifdef HAVE_XDAMAGE
|
||||||
|
if (haveDamage)
|
||||||
|
XDamageDestroy(dpy, damage);
|
||||||
|
@@ -383,6 +388,118 @@ KeyCode XDesktop::XkbKeysymToKeycode(Display* dpy, KeySym keysym) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+KeyCode XDesktop::addKeysym(Display* dpy, KeySym keysym)
|
||||||
|
+{
|
||||||
|
+ int types[1];
|
||||||
|
+ unsigned int key;
|
||||||
|
+ XkbDescPtr xkb;
|
||||||
|
+ XkbMapChangesRec changes;
|
||||||
|
+ KeySym *syms;
|
||||||
|
+ KeySym upper, lower;
|
||||||
|
+
|
||||||
|
+ xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
|
||||||
|
+
|
||||||
|
+ if (!xkb)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ for (key = xkb->max_key_code; key >= xkb->min_key_code; key--) {
|
||||||
|
+ if (XkbKeyNumGroups(xkb, key) == 0)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (key < xkb->min_key_code)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ memset(&changes, 0, sizeof(changes));
|
||||||
|
+
|
||||||
|
+ XConvertCase(keysym, &lower, &upper);
|
||||||
|
+
|
||||||
|
+ if (upper == lower)
|
||||||
|
+ types[XkbGroup1Index] = XkbOneLevelIndex;
|
||||||
|
+ else
|
||||||
|
+ types[XkbGroup1Index] = XkbAlphabeticIndex;
|
||||||
|
+
|
||||||
|
+ XkbChangeTypesOfKey(xkb, key, 1, XkbGroup1Mask, types, &changes);
|
||||||
|
+
|
||||||
|
+ syms = XkbKeySymsPtr(xkb,key);
|
||||||
|
+ if (upper == lower)
|
||||||
|
+ syms[0] = keysym;
|
||||||
|
+ else {
|
||||||
|
+ syms[0] = lower;
|
||||||
|
+ syms[1] = upper;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ changes.changed |= XkbKeySymsMask;
|
||||||
|
+ changes.first_key_sym = key;
|
||||||
|
+ changes.num_key_syms = 1;
|
||||||
|
+
|
||||||
|
+ if (XkbChangeMap(dpy, xkb, &changes)) {
|
||||||
|
+ vlog.info("Added unknown keysym %s to keycode %d", XKeysymToString(keysym), key);
|
||||||
|
+ addedKeysyms[keysym] = key;
|
||||||
|
+ return key;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void XDesktop::deleteAddedKeysyms(Display* dpy) {
|
||||||
|
+ XkbDescPtr xkb;
|
||||||
|
+ xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
|
||||||
|
+
|
||||||
|
+ if (!xkb)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ XkbMapChangesRec changes;
|
||||||
|
+ memset(&changes, 0, sizeof(changes));
|
||||||
|
+
|
||||||
|
+ KeyCode lowestKeyCode = xkb->max_key_code;
|
||||||
|
+ KeyCode highestKeyCode = xkb->min_key_code;
|
||||||
|
+ std::map<KeySym, KeyCode>::iterator it;
|
||||||
|
+ for (it = addedKeysyms.begin(); it != addedKeysyms.end(); it++) {
|
||||||
|
+ if (XkbKeyNumGroups(xkb, it->second) != 0) {
|
||||||
|
+ // Check if we are removing keysym we added ourself
|
||||||
|
+ if (XkbKeysymToKeycode(dpy, it->first) != it->second)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ XkbChangeTypesOfKey(xkb, it->second, 0, XkbGroup1Mask, NULL, &changes);
|
||||||
|
+
|
||||||
|
+ if (it->second < lowestKeyCode)
|
||||||
|
+ lowestKeyCode = it->second;
|
||||||
|
+
|
||||||
|
+ if (it->second > highestKeyCode)
|
||||||
|
+ highestKeyCode = it->second;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ changes.changed |= XkbKeySymsMask;
|
||||||
|
+ changes.first_key_sym = lowestKeyCode;
|
||||||
|
+ changes.num_key_syms = highestKeyCode - lowestKeyCode + 1;
|
||||||
|
+ XkbChangeMap(dpy, xkb, &changes);
|
||||||
|
+
|
||||||
|
+ addedKeysyms.clear();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+KeyCode XDesktop::keysymToKeycode(Display* dpy, KeySym keysym) {
|
||||||
|
+ int keycode = 0;
|
||||||
|
+
|
||||||
|
+ // XKeysymToKeycode() doesn't respect state, so we have to use
|
||||||
|
+ // something slightly more complex
|
||||||
|
+ keycode = XkbKeysymToKeycode(dpy, keysym);
|
||||||
|
+
|
||||||
|
+ if (keycode != 0)
|
||||||
|
+ return keycode;
|
||||||
|
+
|
||||||
|
+ // TODO: try to further guess keycode with all possible mods as Xvnc does
|
||||||
|
+
|
||||||
|
+ keycode = addKeysym(dpy, keysym);
|
||||||
|
+
|
||||||
|
+ if (keycode == 0)
|
||||||
|
+ vlog.error("Failure adding new keysym 0x%lx", keysym);
|
||||||
|
+
|
||||||
|
+ return keycode;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
void XDesktop::keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down) {
|
||||||
|
#ifdef HAVE_XTEST
|
||||||
|
int keycode = 0;
|
||||||
|
@@ -398,9 +515,7 @@ void XDesktop::keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down) {
|
||||||
|
if (pressedKeys.find(keysym) != pressedKeys.end())
|
||||||
|
keycode = pressedKeys[keysym];
|
||||||
|
else {
|
||||||
|
- // XKeysymToKeycode() doesn't respect state, so we have to use
|
||||||
|
- // something slightly more complex
|
||||||
|
- keycode = XkbKeysymToKeycode(dpy, keysym);
|
||||||
|
+ keycode = keysymToKeycode(dpy, keysym);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/unix/x0vncserver/XDesktop.h b/unix/x0vncserver/XDesktop.h
|
||||||
|
index 840d43316..6ebcd9f8a 100644
|
||||||
|
--- a/unix/x0vncserver/XDesktop.h
|
||||||
|
+++ b/unix/x0vncserver/XDesktop.h
|
||||||
|
@@ -55,6 +55,9 @@ class XDesktop : public rfb::SDesktop,
|
||||||
|
const char* userName);
|
||||||
|
virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
|
||||||
|
KeyCode XkbKeysymToKeycode(Display* dpy, KeySym keysym);
|
||||||
|
+ KeyCode addKeysym(Display* dpy, KeySym keysym);
|
||||||
|
+ void deleteAddedKeysyms(Display* dpy);
|
||||||
|
+ KeyCode keysymToKeycode(Display* dpy, KeySym keysym);
|
||||||
|
virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down);
|
||||||
|
virtual void clientCutText(const char* str);
|
||||||
|
virtual unsigned int setScreenLayout(int fb_width, int fb_height,
|
||||||
|
@@ -78,6 +81,7 @@ class XDesktop : public rfb::SDesktop,
|
||||||
|
bool haveXtest;
|
||||||
|
bool haveDamage;
|
||||||
|
int maxButtons;
|
||||||
|
+ std::map<KeySym, KeyCode> addedKeysyms;
|
||||||
|
std::map<KeySym, KeyCode> pressedKeys;
|
||||||
|
bool running;
|
||||||
|
#ifdef HAVE_XDAMAGE
|
@ -0,0 +1,117 @@
|
|||||||
|
From f783d5c8b567199178b6690f347e060a69d2aa36 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Grulich <jgrulich@redhat.com>
|
||||||
|
Date: Thu, 11 Aug 2022 13:15:29 +0200
|
||||||
|
Subject: [PATCH] x0vncserver: update/display cursor only on correct screen in
|
||||||
|
zaphod mode
|
||||||
|
|
||||||
|
We have to check whether we update cursor position/shape only in case
|
||||||
|
the cursor is on our display, otherwise in zaphod mode, ie. when having
|
||||||
|
two instances of x0vncserver on screens :0.0 and :0.1 we would be having
|
||||||
|
the cursor duplicated and actually not funcional (aka ghost cursor) as
|
||||||
|
it would be actually not present. We also additionally watch EnterNotify
|
||||||
|
and LeaveNotify events in order to show/hide cursor accordingly.
|
||||||
|
|
||||||
|
Change made with help from Olivier Fourdan <ofourdan@redhat.com>
|
||||||
|
---
|
||||||
|
unix/x0vncserver/XDesktop.cxx | 60 +++++++++++++++++++++++++++++++----
|
||||||
|
1 file changed, 53 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
|
||||||
|
index f2046e43e..f07fd78bf 100644
|
||||||
|
--- a/unix/x0vncserver/XDesktop.cxx
|
||||||
|
+++ b/unix/x0vncserver/XDesktop.cxx
|
||||||
|
@@ -192,7 +192,8 @@ XDesktop::XDesktop(Display* dpy_, Geometry *geometry_)
|
||||||
|
RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask);
|
||||||
|
/* Override TXWindow::init input mask */
|
||||||
|
XSelectInput(dpy, DefaultRootWindow(dpy),
|
||||||
|
- PropertyChangeMask | StructureNotifyMask | ExposureMask);
|
||||||
|
+ PropertyChangeMask | StructureNotifyMask |
|
||||||
|
+ ExposureMask | EnterWindowMask | LeaveWindowMask);
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
vlog.info("RANDR extension not present");
|
||||||
|
@@ -217,11 +218,13 @@ void XDesktop::poll() {
|
||||||
|
Window root, child;
|
||||||
|
int x, y, wx, wy;
|
||||||
|
unsigned int mask;
|
||||||
|
- XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
|
||||||
|
- &x, &y, &wx, &wy, &mask);
|
||||||
|
- x -= geometry->offsetLeft();
|
||||||
|
- y -= geometry->offsetTop();
|
||||||
|
- server->setCursorPos(rfb::Point(x, y), false);
|
||||||
|
+
|
||||||
|
+ if (XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
|
||||||
|
+ &x, &y, &wx, &wy, &mask)) {
|
||||||
|
+ x -= geometry->offsetLeft();
|
||||||
|
+ y -= geometry->offsetTop();
|
||||||
|
+ server->setCursorPos(rfb::Point(x, y), false);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -253,7 +256,14 @@ void XDesktop::start(VNCServer* vs) {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_XFIXES
|
||||||
|
- setCursor();
|
||||||
|
+ Window root, child;
|
||||||
|
+ int x, y, wx, wy;
|
||||||
|
+ unsigned int mask;
|
||||||
|
+ // Check whether the cursor is initially on our screen
|
||||||
|
+ if (XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
|
||||||
|
+ &x, &y, &wx, &wy, &mask))
|
||||||
|
+ setCursor();
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
|
||||||
|
server->setLEDState(ledState);
|
||||||
|
@@ -701,6 +711,15 @@ bool XDesktop::handleGlobalEvent(XEvent* ev) {
|
||||||
|
if (cev->subtype != XFixesDisplayCursorNotify)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
+ Window root, child;
|
||||||
|
+ int x, y, wx, wy;
|
||||||
|
+ unsigned int mask;
|
||||||
|
+
|
||||||
|
+ // Check whether the cursor is initially on our screen
|
||||||
|
+ if (!XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
|
||||||
|
+ &x, &y, &wx, &wy, &mask))
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
return setCursor();
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_XRANDR
|
||||||
|
@@ -753,6 +772,33 @@ bool XDesktop::handleGlobalEvent(XEvent* ev) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
+#ifdef HAVE_XFIXES
|
||||||
|
+ } else if (ev->type == EnterNotify) {
|
||||||
|
+ XCrossingEvent* cev;
|
||||||
|
+
|
||||||
|
+ if (!running)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ cev = (XCrossingEvent*)ev;
|
||||||
|
+
|
||||||
|
+ if (cev->window != cev->root)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ return setCursor();
|
||||||
|
+ } else if (ev->type == LeaveNotify) {
|
||||||
|
+ XCrossingEvent* cev;
|
||||||
|
+
|
||||||
|
+ if (!running)
|
||||||
|
+ return true;
|
||||||
|
+
|
||||||
|
+ cev = (XCrossingEvent*)ev;
|
||||||
|
+
|
||||||
|
+ if (cev->window == cev->root)
|
||||||
|
+ return false;
|
||||||
|
+
|
||||||
|
+ server->setCursor(0, 0, Point(), NULL);
|
||||||
|
+ return true;
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
@ -0,0 +1,34 @@
|
|||||||
|
From 2daf4126882f82b6e392dfbae87205dbdc559c3d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre Ossman <ossman@cendio.se>
|
||||||
|
Date: Thu, 23 Dec 2021 15:58:00 +0100
|
||||||
|
Subject: [PATCH] Fix typo in mirror monitor detection
|
||||||
|
|
||||||
|
Bug introduced in fb561eb but still somehow passed manual testing.
|
||||||
|
Resulted in some stray reads off the end of the stack, which were
|
||||||
|
hopefully harmless.
|
||||||
|
---
|
||||||
|
vncviewer/MonitorIndicesParameter.cxx | 8 ++++----
|
||||||
|
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/vncviewer/MonitorIndicesParameter.cxx b/vncviewer/MonitorIndicesParameter.cxx
|
||||||
|
index 5130831cb..4ac74dd1a 100644
|
||||||
|
--- a/vncviewer/MonitorIndicesParameter.cxx
|
||||||
|
+++ b/vncviewer/MonitorIndicesParameter.cxx
|
||||||
|
@@ -211,13 +211,13 @@ std::vector<MonitorIndicesParameter::Monitor> MonitorIndicesParameter::fetchMoni
|
||||||
|
// Only keep a single entry for mirrored screens
|
||||||
|
match = false;
|
||||||
|
for (int j = 0; j < ((int) monitors.size()); j++) {
|
||||||
|
- if (monitors[i].x != monitor.x)
|
||||||
|
+ if (monitors[j].x != monitor.x)
|
||||||
|
continue;
|
||||||
|
- if (monitors[i].y != monitor.y)
|
||||||
|
+ if (monitors[j].y != monitor.y)
|
||||||
|
continue;
|
||||||
|
- if (monitors[i].w != monitor.w)
|
||||||
|
+ if (monitors[j].w != monitor.w)
|
||||||
|
continue;
|
||||||
|
- if (monitors[i].h != monitor.h)
|
||||||
|
+ if (monitors[j].h != monitor.h)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
match = true;
|
@ -0,0 +1,25 @@
|
|||||||
|
From faf81b4b238e24fe29eb53f885a25367e212dd7b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Zdenek Pytela <zpytela@redhat.com>
|
||||||
|
Date: Mon, 7 Feb 2022 10:45:41 +0100
|
||||||
|
Subject: [PATCH] SELinux: use /root/.vnc in file context specification
|
||||||
|
|
||||||
|
Instead of HOME_ROOT/.vnc, /root/.vnc should be used
|
||||||
|
for user root's home to specify default file context
|
||||||
|
as HOME_ROOT actually means base for home dirs (usually /home).
|
||||||
|
---
|
||||||
|
unix/vncserver/selinux/vncsession.fc | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/unix/vncserver/selinux/vncsession.fc b/unix/vncserver/selinux/vncsession.fc
|
||||||
|
index 6aaf4b1f4..bc81f8f25 100644
|
||||||
|
--- a/unix/vncserver/selinux/vncsession.fc
|
||||||
|
+++ b/unix/vncserver/selinux/vncsession.fc
|
||||||
|
@@ -18,7 +18,7 @@
|
||||||
|
#
|
||||||
|
|
||||||
|
HOME_DIR/\.vnc(/.*)? gen_context(system_u:object_r:vnc_home_t,s0)
|
||||||
|
-HOME_ROOT/\.vnc(/.*)? gen_context(system_u:object_r:vnc_home_t,s0)
|
||||||
|
+/root/\.vnc(/.*)? gen_context(system_u:object_r:vnc_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)
|
@ -0,0 +1,28 @@
|
|||||||
|
From 774c6bcf33b5c9b94c1ff12895775e77c555decc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre Ossman <ossman@cendio.se>
|
||||||
|
Date: Thu, 9 Feb 2023 11:30:37 +0100
|
||||||
|
Subject: [PATCH] Sanity check when cleaning up keymap changes
|
||||||
|
|
||||||
|
Make sure we don't send a bogus request to the X server in the (common)
|
||||||
|
case that we don't actually have anything to restore.
|
||||||
|
|
||||||
|
(cherry picked from commit 1e3484f2017f038dd5149cd50741feaf39a680e4)
|
||||||
|
---
|
||||||
|
unix/x0vncserver/XDesktop.cxx | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
|
||||||
|
index d5c6b2db9..f9c810968 100644
|
||||||
|
--- a/unix/x0vncserver/XDesktop.cxx
|
||||||
|
+++ b/unix/x0vncserver/XDesktop.cxx
|
||||||
|
@@ -481,6 +481,10 @@ void XDesktop::deleteAddedKeysyms(Display* dpy) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Did we actually find something to remove?
|
||||||
|
+ if (highestKeyCode < lowestKeyCode)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
changes.changed |= XkbKeySymsMask;
|
||||||
|
changes.first_key_sym = lowestKeyCode;
|
||||||
|
changes.num_key_syms = highestKeyCode - lowestKeyCode + 1;
|
@ -0,0 +1,31 @@
|
|||||||
|
From 717d787de8f913070446444e37d552b51f05515e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Zdenek Pytela <zpytela@redhat.com>
|
||||||
|
Date: Mon, 16 Jan 2023 12:35:40 +0100
|
||||||
|
Subject: [PATCH] SELinux: Allow vncsession create ~/.vnc directory
|
||||||
|
|
||||||
|
Addresses the following AVC denial:
|
||||||
|
|
||||||
|
type=PROCTITLE msg=audit(01/12/2023 02:58:12.648:696) : proctitle=/usr/sbin/vncsession fedora :1
|
||||||
|
type=PATH msg=audit(01/12/2023 02:58:12.648:696) : item=1 name=/home/fedora/.vnc nametype=CREATE cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
|
||||||
|
type=PATH msg=audit(01/12/2023 02:58:12.648:696) : item=0 name=/home/fedora/ inode=262145 dev=fc:02 mode=dir,700 ouid=fedora ogid=fedora rdev=00:00 obj=unconfined_u:object_r:user_home_dir_t:s0 nametype=PARENT cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
|
||||||
|
type=CWD msg=audit(01/12/2023 02:58:12.648:696) : cwd=/home/fedora
|
||||||
|
type=SYSCALL msg=audit(01/12/2023 02:58:12.648:696) : arch=x86_64 syscall=mkdir success=no exit=EACCES(Permission denied) a0=0x7fff47d52540 a1=0755 a2=0x0 a3=0x0 items=2 ppid=2869 pid=2880 auid=fedora uid=fedora gid=fedora euid=fedora suid=fedora fsuid=fedora egid=fedora sgid=fedora fsgid=fedora tty=(none) ses=8 comm=vncsession exe=/usr/sbin/vncsession subj=system_u:system_r:vnc_session_t:s0 key=(null)
|
||||||
|
type=AVC msg=audit(01/12/2023 02:58:12.648:696) : avc: denied { create } for pid=2880 comm=vncsession name=.vnc scontext=system_u:system_r:vnc_session_t:s0 tcontext=system_u:object_r:vnc_home_t:s0 tclass=dir permissive=0
|
||||||
|
|
||||||
|
Resolves: rhbz#2143704
|
||||||
|
---
|
||||||
|
unix/vncserver/selinux/vncsession.te | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/unix/vncserver/selinux/vncsession.te b/unix/vncserver/selinux/vncsession.te
|
||||||
|
index fb966c14b..680be8ea1 100644
|
||||||
|
--- a/unix/vncserver/selinux/vncsession.te
|
||||||
|
+++ b/unix/vncserver/selinux/vncsession.te
|
||||||
|
@@ -37,6 +37,7 @@ allow vnc_session_t self:fifo_file rw_fifo_file_perms;
|
||||||
|
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)
|
||||||
|
|
||||||
|
+create_dirs_pattern(vnc_session_t, vnc_home_t, vnc_home_t)
|
||||||
|
manage_files_pattern(vnc_session_t, vnc_home_t, vnc_home_t)
|
||||||
|
manage_fifo_files_pattern(vnc_session_t, vnc_home_t, vnc_home_t)
|
||||||
|
manage_sock_files_pattern(vnc_session_t, vnc_home_t, vnc_home_t)
|
@ -0,0 +1,81 @@
|
|||||||
|
From d2d52704624ce841f4a392fccd82079d87ff13b6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Grulich <jgrulich@redhat.com>
|
||||||
|
Date: Thu, 11 Nov 2021 13:52:41 +0100
|
||||||
|
Subject: [PATCH] SELinux: restore SELinux context in case of different
|
||||||
|
policies
|
||||||
|
|
||||||
|
---
|
||||||
|
CMakeLists.txt | 13 +++++++++++++
|
||||||
|
unix/vncserver/CMakeLists.txt | 2 +-
|
||||||
|
unix/vncserver/vncsession.c | 16 ++++++++++++++++
|
||||||
|
3 files changed, 30 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index 50247c7da..1708eb3d8 100644
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -268,6 +268,19 @@ if(UNIX AND NOT APPLE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
+# Check for SELinux library
|
||||||
|
+if(UNIX AND NOT APPLE)
|
||||||
|
+ check_include_files(selinux/selinux.h HAVE_SELINUX_H)
|
||||||
|
+ if(HAVE_SELINUX_H)
|
||||||
|
+ set(CMAKE_REQUIRED_LIBRARIES -lselinux)
|
||||||
|
+ set(CMAKE_REQUIRED_LIBRARIES)
|
||||||
|
+ set(SELINUX_LIBS selinux)
|
||||||
|
+ add_definitions("-DHAVE_SELINUX")
|
||||||
|
+ else()
|
||||||
|
+ message(WARNING "Could not find SELinux development files")
|
||||||
|
+ endif()
|
||||||
|
+endif()
|
||||||
|
+
|
||||||
|
# Generate config.h and make sure the source finds it
|
||||||
|
configure_file(config.h.in config.h)
|
||||||
|
add_definitions(-DHAVE_CONFIG_H)
|
||||||
|
diff --git a/unix/vncserver/CMakeLists.txt b/unix/vncserver/CMakeLists.txt
|
||||||
|
index f65ccc7db..ae69dc098 100644
|
||||||
|
--- a/unix/vncserver/CMakeLists.txt
|
||||||
|
+++ b/unix/vncserver/CMakeLists.txt
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
add_executable(vncsession vncsession.c)
|
||||||
|
-target_link_libraries(vncsession ${PAM_LIBS})
|
||||||
|
+target_link_libraries(vncsession ${PAM_LIBS} ${SELINUX_LIBS})
|
||||||
|
|
||||||
|
configure_file(vncserver@.service.in vncserver@.service @ONLY)
|
||||||
|
configure_file(vncsession-start.in vncsession-start @ONLY)
|
||||||
|
diff --git a/unix/vncserver/vncsession.c b/unix/vncserver/vncsession.c
|
||||||
|
index 3573e5e9b..f6d2fd59e 100644
|
||||||
|
--- a/unix/vncserver/vncsession.c
|
||||||
|
+++ b/unix/vncserver/vncsession.c
|
||||||
|
@@ -37,6 +37,11 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
+#ifdef HAVE_SELINUX
|
||||||
|
+#include <selinux/selinux.h>
|
||||||
|
+#include <selinux/restorecon.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
|
// PAM service name
|
||||||
|
@@ -360,6 +365,17 @@ redir_stdio(const char *homedir, const char *display)
|
||||||
|
syslog(LOG_CRIT, "Failure creating \"%s\": %s", logfile, strerror(errno));
|
||||||
|
_exit(EX_OSERR);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#ifdef HAVE_SELINUX
|
||||||
|
+ int result;
|
||||||
|
+ if (selinux_file_context_verify(logfile, 0) == 0) {
|
||||||
|
+ result = selinux_restorecon(logfile, SELINUX_RESTORECON_RECURSE);
|
||||||
|
+
|
||||||
|
+ if (result < 0) {
|
||||||
|
+ syslog(LOG_WARNING, "Failure restoring SELinux context for \"%s\": %s", logfile, strerror(errno));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
hostlen = sysconf(_SC_HOST_NAME_MAX);
|
@ -0,0 +1,12 @@
|
|||||||
|
diff --git a/unix/vncserver/vncserver-config-defaults b/unix/vncserver/vncserver-config-defaults
|
||||||
|
index 0c217bf..2889347 100644
|
||||||
|
--- a/unix/vncserver/vncserver-config-defaults
|
||||||
|
+++ b/unix/vncserver/vncserver-config-defaults
|
||||||
|
@@ -13,3 +13,7 @@
|
||||||
|
# geometry=2000x1200
|
||||||
|
# localhost
|
||||||
|
# alwaysshared
|
||||||
|
+
|
||||||
|
+# Default to GNOME session
|
||||||
|
+# Note: change this only when you know what are you doing
|
||||||
|
+session=gnome
|
@ -0,0 +1,113 @@
|
|||||||
|
From 1919a8ab86c99b47ba86dc697abcdf3343b0aafa Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Grulich <jgrulich@redhat.com>
|
||||||
|
Date: Tue, 1 Feb 2022 14:31:05 +0100
|
||||||
|
Subject: Add vncsession-restore script to restore SELinux context
|
||||||
|
|
||||||
|
The vncsession-restore script is used in the ExecStartPre option
|
||||||
|
for systemd service file in order to properly start the session
|
||||||
|
in case the policy is updated (e.g. after Tigervnc update).
|
||||||
|
|
||||||
|
diff --git a/unix/vncserver/CMakeLists.txt b/unix/vncserver/CMakeLists.txt
|
||||||
|
index ae69dc09..04eb6fc4 100644
|
||||||
|
--- a/unix/vncserver/CMakeLists.txt
|
||||||
|
+++ b/unix/vncserver/CMakeLists.txt
|
||||||
|
@@ -2,6 +2,7 @@ add_executable(vncsession vncsession.c)
|
||||||
|
target_link_libraries(vncsession ${PAM_LIBS} ${SELINUX_LIBS})
|
||||||
|
|
||||||
|
configure_file(vncserver@.service.in vncserver@.service @ONLY)
|
||||||
|
+configure_file(vncsession-restore.in vncsession-restore @ONLY)
|
||||||
|
configure_file(vncsession-start.in vncsession-start @ONLY)
|
||||||
|
configure_file(vncserver.in vncserver @ONLY)
|
||||||
|
configure_file(vncsession.man.in vncsession.man @ONLY)
|
||||||
|
@@ -20,4 +21,5 @@ install(FILES HOWTO.md DESTINATION ${CMAKE_INSTALL_FULL_DOCDIR})
|
||||||
|
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})
|
||||||
|
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vncsession-restore DESTINATION ${CMAKE_INSTALL_FULL_LIBEXECDIR})
|
||||||
|
endif()
|
||||||
|
diff --git a/unix/vncserver/vncserver@.service.in b/unix/vncserver/vncserver@.service.in
|
||||||
|
index 39f81b73..a83e05a3 100644
|
||||||
|
--- a/unix/vncserver/vncserver@.service.in
|
||||||
|
+++ b/unix/vncserver/vncserver@.service.in
|
||||||
|
@@ -35,6 +35,7 @@ After=syslog.target network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
+ExecStartPre=+@CMAKE_INSTALL_FULL_LIBEXECDIR@/vncsession-restore %i
|
||||||
|
ExecStart=@CMAKE_INSTALL_FULL_LIBEXECDIR@/vncsession-start %i
|
||||||
|
PIDFile=/run/vncsession-%i.pid
|
||||||
|
SELinuxContext=system_u:system_r:vnc_session_t:s0
|
||||||
|
diff --git a/unix/vncserver/vncsession-restore.in b/unix/vncserver/vncsession-restore.in
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..d3abc57d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/unix/vncserver/vncsession-restore.in
|
||||||
|
@@ -0,0 +1,68 @@
|
||||||
|
+#!/bin/bash
|
||||||
|
+#
|
||||||
|
+# Copyright 2022 Jan Grulich <jgrulich@redhat.com>
|
||||||
|
+#
|
||||||
|
+# 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- | sed 's/ *$//g'`
|
||||||
|
+
|
||||||
|
+if [ -z "${USER}" ]; then
|
||||||
|
+ echo "No user configured for display ${DISPLAY}" >&2
|
||||||
|
+ exit 1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+USER_HOMEDIR=`getent passwd ${USER} | cut -f6 -d:`
|
||||||
|
+
|
||||||
|
+if [ -z "${USER_HOMEDIR}" ]; then
|
||||||
|
+ echo "Failed to get home directory for ${USER}" >&2
|
||||||
|
+ exit 1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ ! -d "${USER_HOMEDIR}/.vnc" ]; then
|
||||||
|
+ exit 0
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+MATCHPATHCON=`which matchpathcon`
|
||||||
|
+
|
||||||
|
+if [ $? -eq 0 ]; then
|
||||||
|
+ ${MATCHPATHCON} -V "${USER_HOMEDIR}/.vnc" &>/dev/null
|
||||||
|
+ if [ $? -eq 0 ]; then
|
||||||
|
+ exit 0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+RESTORECON=`which restorecon`
|
||||||
|
+
|
||||||
|
+if [ $? -eq 0 ]; then
|
||||||
|
+ exec "${RESTORECON}" -R "${USER_HOMEDIR}/.vnc" >&2
|
||||||
|
+ return $?
|
||||||
|
+fi
|
@ -0,0 +1,91 @@
|
|||||||
|
diff -up xserver/configure.ac.xserver116-rebased xserver/configure.ac
|
||||||
|
--- xserver/configure.ac.xserver116-rebased 2016-09-29 13:14:45.595441590 +0200
|
||||||
|
+++ xserver/configure.ac 2016-09-29 13:14:45.631442006 +0200
|
||||||
|
@@ -74,6 +74,7 @@ dnl forcing an entire recompile.x
|
||||||
|
AC_CONFIG_HEADERS(include/version-config.h)
|
||||||
|
|
||||||
|
AM_PROG_AS
|
||||||
|
+AC_PROG_CXX
|
||||||
|
AC_PROG_LN_S
|
||||||
|
LT_PREREQ([2.2])
|
||||||
|
LT_INIT([disable-static win32-dll])
|
||||||
|
@@ -1863,6 +1864,10 @@ if test "x$XVFB" = xyes; then
|
||||||
|
AC_SUBST([XVFB_SYS_LIBS])
|
||||||
|
fi
|
||||||
|
|
||||||
|
+dnl Xvnc DDX
|
||||||
|
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"])
|
||||||
|
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||||
|
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||||
|
|
||||||
|
dnl Xnest DDX
|
||||||
|
|
||||||
|
@@ -1898,6 +1903,8 @@ if test "x$XORG" = xauto; then
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT([$XORG])
|
||||||
|
|
||||||
|
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||||
|
+
|
||||||
|
if test "x$XORG" = xyes; then
|
||||||
|
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||||
|
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||||
|
@@ -2116,7 +2123,6 @@ if test "x$XORG" = xyes; then
|
||||||
|
AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
|
||||||
|
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||||
|
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||||
|
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||||
|
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||||
|
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||||
|
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||||
|
@@ -2691,6 +2697,7 @@ hw/dmx/Makefile
|
||||||
|
hw/dmx/man/Makefile
|
||||||
|
hw/vfb/Makefile
|
||||||
|
hw/vfb/man/Makefile
|
||||||
|
+hw/vnc/Makefile
|
||||||
|
hw/xnest/Makefile
|
||||||
|
hw/xnest/man/Makefile
|
||||||
|
hw/xwin/Makefile
|
||||||
|
diff -up xserver/hw/Makefile.am.xserver116-rebased xserver/hw/Makefile.am
|
||||||
|
--- xserver/hw/Makefile.am.xserver116-rebased 2016-09-29 13:14:45.601441659 +0200
|
||||||
|
+++ xserver/hw/Makefile.am 2016-09-29 13:14:45.631442006 +0200
|
||||||
|
@@ -38,7 +38,8 @@ SUBDIRS = \
|
||||||
|
$(DMX_SUBDIRS) \
|
||||||
|
$(KDRIVE_SUBDIRS) \
|
||||||
|
$(XQUARTZ_SUBDIRS) \
|
||||||
|
- $(XWAYLAND_SUBDIRS)
|
||||||
|
+ $(XWAYLAND_SUBDIRS) \
|
||||||
|
+ vnc
|
||||||
|
|
||||||
|
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
|
||||||
|
|
||||||
|
diff --git xserver/mi/miinitext.c xserver/mi/miinitext.c
|
||||||
|
index 5596e21..003fc3c 100644
|
||||||
|
--- xserver/mi/miinitext.c
|
||||||
|
+++ xserver/mi/miinitext.c
|
||||||
|
@@ -107,8 +107,15 @@ SOFTWARE.
|
||||||
|
#include "os.h"
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
+#ifdef TIGERVNC
|
||||||
|
+extern void vncExtensionInit(INITARGS);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* List of built-in (statically linked) extensions */
|
||||||
|
static const ExtensionModule staticExtensions[] = {
|
||||||
|
+#ifdef TIGERVNC
|
||||||
|
+ {vncExtensionInit, "VNC-EXTENSION", NULL},
|
||||||
|
+#endif
|
||||||
|
{GEExtensionInit, "Generic Event Extension", &noGEExtension},
|
||||||
|
{ShapeExtensionInit, "SHAPE", NULL},
|
||||||
|
#ifdef MITSHM
|
||||||
|
--- xserver/include/os.h~ 2016-10-03 09:07:29.000000000 +0200
|
||||||
|
+++ xserver/include/os.h 2016-10-03 14:13:00.013654506 +0200
|
||||||
|
@@ -621,7 +621,7 @@
|
||||||
|
extern _X_EXPORT void
|
||||||
|
LogClose(enum ExitCode error);
|
||||||
|
extern _X_EXPORT Bool
|
||||||
|
-LogSetParameter(LogParameter param, int value);
|
||||||
|
+LogSetParameter(enum _LogParameter param, int value);
|
||||||
|
extern _X_EXPORT void
|
||||||
|
LogVWrite(int verb, const char *f, va_list args)
|
||||||
|
_X_ATTRIBUTE_PRINTF(2, 0);
|
@ -0,0 +1,897 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
# First make sure we're operating in a sane environment.
|
||||||
|
$exedir = "";
|
||||||
|
$slashndx = rindex($0, "/");
|
||||||
|
if($slashndx>=0) {
|
||||||
|
$exedir = substr($0, 0, $slashndx+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&SanityCheck();
|
||||||
|
|
||||||
|
&NotifyAboutDeprecation();
|
||||||
|
|
||||||
|
#
|
||||||
|
# Global variables. You may want to configure some of these for
|
||||||
|
# your site
|
||||||
|
#
|
||||||
|
|
||||||
|
$geometry = "1024x768";
|
||||||
|
#$depth = 16;
|
||||||
|
|
||||||
|
$vncUserDir = "$ENV{HOME}/.vnc";
|
||||||
|
$vncUserConfig = "$vncUserDir/config";
|
||||||
|
|
||||||
|
$vncSystemConfigDir = "/etc/tigervnc";
|
||||||
|
$vncSystemConfigDefaultsFile = "$vncSystemConfigDir/vncserver-config-defaults";
|
||||||
|
$vncSystemConfigMandatoryFile = "$vncSystemConfigDir/vncserver-config-mandatory";
|
||||||
|
|
||||||
|
$skipxstartup = 0;
|
||||||
|
$xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority";
|
||||||
|
|
||||||
|
$xstartupFile = $vncUserDir . "/xstartup";
|
||||||
|
$defaultXStartup
|
||||||
|
= ("#!/bin/sh\n\n".
|
||||||
|
"unset SESSION_MANAGER\n".
|
||||||
|
"unset DBUS_SESSION_BUS_ADDRESS\n".
|
||||||
|
"/etc/X11/xinit/xinitrc\n".
|
||||||
|
"# Assume either Gnome will be started by default when installed\n".
|
||||||
|
"# We want to kill the session automatically in this case when user logs out. In case you modify\n".
|
||||||
|
"# /etc/X11/xinit/Xclients or ~/.Xclients yourself to achieve a different result, then you should\n".
|
||||||
|
"# be responsible to modify below code to avoid that your session will be automatically killed\n".
|
||||||
|
"if [ -e /usr/bin/gnome-session ]; then\n".
|
||||||
|
" vncserver -kill \$DISPLAY\n".
|
||||||
|
"fi\n");
|
||||||
|
|
||||||
|
$defaultConfig
|
||||||
|
= ("## Supported server options to pass to vncserver upon invocation can be listed\n".
|
||||||
|
"## in this file. See the following manpages for more: vncserver(1) Xvnc(1).\n".
|
||||||
|
"## Several common ones are shown below. Uncomment and modify to your liking.\n".
|
||||||
|
"##\n".
|
||||||
|
"# securitytypes=vncauth,tlsvnc\n".
|
||||||
|
"# desktop=sandbox\n".
|
||||||
|
"# geometry=2000x1200\n".
|
||||||
|
"# localhost\n".
|
||||||
|
"# alwaysshared\n");
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check command line options
|
||||||
|
|
||||||
|
&ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1,
|
||||||
|
"-help",0,"-h",0,"--help",0,"-fp",1,"-list",0,"-fg",0,"-autokill",0,"-noxstartup",0,"-xstartup",1);
|
||||||
|
|
||||||
|
&Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'});
|
||||||
|
|
||||||
|
&Kill() if ($opt{'-kill'});
|
||||||
|
|
||||||
|
&List() if ($opt{'-list'});
|
||||||
|
|
||||||
|
# Uncomment this line if you want default geometry, depth and pixelformat
|
||||||
|
# to match the current X display:
|
||||||
|
# &GetXDisplayDefaults();
|
||||||
|
|
||||||
|
if ($opt{'-geometry'}) {
|
||||||
|
$geometry = $opt{'-geometry'};
|
||||||
|
}
|
||||||
|
if ($opt{'-depth'}) {
|
||||||
|
$depth = $opt{'-depth'};
|
||||||
|
$pixelformat = "";
|
||||||
|
}
|
||||||
|
if ($opt{'-pixelformat'}) {
|
||||||
|
$pixelformat = $opt{'-pixelformat'};
|
||||||
|
}
|
||||||
|
if ($opt{'-noxstartup'}) {
|
||||||
|
$skipxstartup = 1;
|
||||||
|
}
|
||||||
|
if ($opt{'-xstartup'}) {
|
||||||
|
$xstartupFile = $opt{'-xstartup'};
|
||||||
|
}
|
||||||
|
if ($opt{'-fp'}) {
|
||||||
|
$fontPath = $opt{'-fp'};
|
||||||
|
$fpArgSpecified = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&CheckGeometryAndDepth();
|
||||||
|
|
||||||
|
# Create the user's vnc directory if necessary.
|
||||||
|
if (!(-e $vncUserDir)) {
|
||||||
|
if (!mkdir($vncUserDir,0755)) {
|
||||||
|
die "$prog: Could not create $vncUserDir.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find display number.
|
||||||
|
if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) {
|
||||||
|
$displayNumber = $1;
|
||||||
|
shift(@ARGV);
|
||||||
|
if (!&CheckDisplayNumber($displayNumber)) {
|
||||||
|
warn "A VNC server is already running as :$displayNumber\n";
|
||||||
|
$displayNumber = &GetDisplayNumber();
|
||||||
|
}
|
||||||
|
} elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/) && ($ARGV[0] !~ /^\+/)) {
|
||||||
|
&Usage();
|
||||||
|
} else {
|
||||||
|
$displayNumber = &GetDisplayNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
$vncPort = 5900 + $displayNumber;
|
||||||
|
|
||||||
|
if ($opt{'-name'}) {
|
||||||
|
$desktopName = $opt{'-name'};
|
||||||
|
} else {
|
||||||
|
$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} = "edString($desktopName);
|
||||||
|
$default_opts{auth} = "edString($xauthorityFile);
|
||||||
|
$default_opts{geometry} = $geometry if ($geometry);
|
||||||
|
$default_opts{depth} = $depth if ($depth);
|
||||||
|
$default_opts{pixelformat} = $pixelformat if ($pixelformat);
|
||||||
|
$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, prompt the user to
|
||||||
|
# create a VNC password if they don't already have one.
|
||||||
|
#
|
||||||
|
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ...and finally we check CLI args, which in the case of the topic at
|
||||||
|
# hand (VNC auth or not), override anything found in configuration files
|
||||||
|
# (even so-called "mandatory" settings).
|
||||||
|
for ($i = 0; $i < @ARGV; ++$i) {
|
||||||
|
# -SecurityTypes can be followed by a space or "="
|
||||||
|
my @splitargs = split('=', $ARGV[$i]);
|
||||||
|
if (@splitargs <= 1 && $i < @ARGV - 1) {
|
||||||
|
push(@splitargs, $ARGV[$i + 1]);
|
||||||
|
}
|
||||||
|
if (lc(@splitargs[0]) eq "-securitytypes") {
|
||||||
|
if (@splitargs > 1) {
|
||||||
|
$securityTypeArgSpecified = 1;
|
||||||
|
}
|
||||||
|
foreach $arg2 (split(',', @splitargs[1])) {
|
||||||
|
if (grep {$_ eq lc($arg2)} @vncAuthStrings) {
|
||||||
|
$vncAuthEnabled = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((lc(@splitargs[0]) eq "-password")
|
||||||
|
|| (lc(@splitargs[0]) eq "-passwordfile"
|
||||||
|
|| (lc(@splitargs[0]) eq "-rfbauth"))) {
|
||||||
|
$passwordArgSpecified = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$desktopLog = "$vncUserDir/$host:$displayNumber.log";
|
||||||
|
unlink($desktopLog);
|
||||||
|
|
||||||
|
# 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);
|
||||||
|
|
||||||
|
# Now start the X VNC Server
|
||||||
|
|
||||||
|
# We build up our Xvnc command with options
|
||||||
|
$cmd = $exedir."Xvnc :$displayNumber";
|
||||||
|
|
||||||
|
foreach my $k (sort keys %config) {
|
||||||
|
$cmd .= " -$k $config{$k}";
|
||||||
|
delete $default_opts{$k}; # file options take precedence
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $k (sort keys %default_opts) {
|
||||||
|
$cmd .= " -$k $default_opts{$k}";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add color database stuff here, e.g.:
|
||||||
|
# $cmd .= " -co /usr/lib/X11/rgb";
|
||||||
|
|
||||||
|
foreach $arg (@ARGV) {
|
||||||
|
$cmd .= " " . "edString($arg);
|
||||||
|
}
|
||||||
|
$cmd .= " >> " . "edString($desktopLog) . " 2>&1";
|
||||||
|
|
||||||
|
# Run $cmd and record the process ID.
|
||||||
|
$pidFile = "$vncUserDir/$host:$displayNumber.pid";
|
||||||
|
system("$cmd & echo \$! >$pidFile");
|
||||||
|
|
||||||
|
# Give Xvnc a chance to start up
|
||||||
|
|
||||||
|
sleep(3);
|
||||||
|
if ($fontPath ne $defFontPath) {
|
||||||
|
unless (kill 0, `cat $pidFile`) {
|
||||||
|
if ($fpArgSpecified) {
|
||||||
|
warn "\nWARNING: The first attempt to start Xvnc failed, probably because the font\n";
|
||||||
|
warn "path you specified using the -fp argument is incorrect. Attempting to\n";
|
||||||
|
warn "determine an appropriate font path for this system and restart Xvnc using\n";
|
||||||
|
warn "that font path ...\n";
|
||||||
|
} else {
|
||||||
|
warn "\nWARNING: The first attempt to start Xvnc failed, possibly because the font\n";
|
||||||
|
warn "catalog is not properly configured. Attempting to determine an appropriate\n";
|
||||||
|
warn "font path for this system and restart Xvnc using that font path ...\n";
|
||||||
|
}
|
||||||
|
$cmd =~ s@-fp [^ ]+@@;
|
||||||
|
$cmd .= " -fp $defFontPath" if ($defFontPath);
|
||||||
|
system("$cmd & echo \$! >$pidFile");
|
||||||
|
sleep(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unless (kill 0, `cat $pidFile`) {
|
||||||
|
warn "Could not start Xvnc.\n\n";
|
||||||
|
unlink $pidFile;
|
||||||
|
open(LOG, "<$desktopLog");
|
||||||
|
while (<LOG>) { print; }
|
||||||
|
close(LOG);
|
||||||
|
die "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n";
|
||||||
|
|
||||||
|
# Create the user's xstartup script if necessary.
|
||||||
|
if (! $skipxstartup) {
|
||||||
|
if (!(-e "$xstartupFile")) {
|
||||||
|
warn "Creating default startup script $xstartupFile\n";
|
||||||
|
open(XSTARTUP, ">$xstartupFile");
|
||||||
|
print XSTARTUP $defaultXStartup;
|
||||||
|
close(XSTARTUP);
|
||||||
|
chmod 0755, "$xstartupFile";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create the user's config file if necessary.
|
||||||
|
if (!(-e "$vncUserDir/config")) {
|
||||||
|
warn "Creating default config $vncUserDir/config\n";
|
||||||
|
open(VNCUSERCONFIG, ">$vncUserDir/config");
|
||||||
|
print VNCUSERCONFIG $defaultConfig;
|
||||||
|
close(VNCUSERCONFIG);
|
||||||
|
chmod 0644, "$vncUserDir/config";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run the X startup script.
|
||||||
|
if (! $skipxstartup) {
|
||||||
|
warn "Starting applications specified in $xstartupFile\n";
|
||||||
|
}
|
||||||
|
warn "Log file is $desktopLog\n\n";
|
||||||
|
|
||||||
|
# If the unix domain socket exists then use that (DISPLAY=:n) otherwise use
|
||||||
|
# TCP (DISPLAY=host:n)
|
||||||
|
|
||||||
|
if (-e "/tmp/.X11-unix/X$displayNumber" ||
|
||||||
|
-e "/usr/spool/sockets/X11/$displayNumber")
|
||||||
|
{
|
||||||
|
$ENV{DISPLAY}= ":$displayNumber";
|
||||||
|
} else {
|
||||||
|
$ENV{DISPLAY}= "$host:$displayNumber";
|
||||||
|
}
|
||||||
|
$ENV{VNCDESKTOP}= $desktopName;
|
||||||
|
|
||||||
|
if ($opt{'-fg'}) {
|
||||||
|
if (! $skipxstartup) {
|
||||||
|
system("$xstartupFile >> " . "edString($desktopLog) . " 2>&1");
|
||||||
|
}
|
||||||
|
if (kill 0, `cat $pidFile`) {
|
||||||
|
$opt{'-kill'} = ':'.$displayNumber;
|
||||||
|
&Kill();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($opt{'-autokill'}) {
|
||||||
|
if (! $skipxstartup) {
|
||||||
|
system("($xstartupFile; $0 -kill :$displayNumber) >> "
|
||||||
|
. "edString($desktopLog) . " 2>&1 &");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (! $skipxstartup) {
|
||||||
|
system("$xstartupFile >> " . "edString($desktopLog)
|
||||||
|
. " 2>&1 &");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit;
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# 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 ($k eq "session") {
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# CheckGeometryAndDepth simply makes sure that the geometry and depth values
|
||||||
|
# are sensible.
|
||||||
|
#
|
||||||
|
|
||||||
|
sub CheckGeometryAndDepth
|
||||||
|
{
|
||||||
|
if ($geometry =~ /^(\d+)x(\d+)$/) {
|
||||||
|
$width = $1; $height = $2;
|
||||||
|
|
||||||
|
if (($width<1) || ($height<1)) {
|
||||||
|
die "$prog: geometry $geometry is invalid\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$geometry = "${width}x$height";
|
||||||
|
} else {
|
||||||
|
die "$prog: geometry $geometry is invalid\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($depth && (($depth < 8) || ($depth > 32))) {
|
||||||
|
die "Depth must be between 8 and 32\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel
|
||||||
|
# format of the current X display being used. If successful, it sets the
|
||||||
|
# options as appropriate so that the X VNC server will use the same settings
|
||||||
|
# (minus an allowance for window manager decorations on the geometry). Using
|
||||||
|
# the same depth and pixel format means that the VNC server won't have to
|
||||||
|
# translate pixels when the desktop is being viewed on this X display (for
|
||||||
|
# TrueColor displays anyway).
|
||||||
|
#
|
||||||
|
|
||||||
|
sub GetXDisplayDefaults
|
||||||
|
{
|
||||||
|
local (@lines, @matchlines, $width, $height, $defaultVisualId, $i,
|
||||||
|
$red, $green, $blue);
|
||||||
|
|
||||||
|
$wmDecorationWidth = 4; # a guess at typical size for window manager
|
||||||
|
$wmDecorationHeight = 24; # decoration size
|
||||||
|
|
||||||
|
return if (!defined($ENV{DISPLAY}));
|
||||||
|
|
||||||
|
@lines = `xdpyinfo 2>/dev/null`;
|
||||||
|
|
||||||
|
return if ($? != 0);
|
||||||
|
|
||||||
|
@matchlines = grep(/dimensions/, @lines);
|
||||||
|
if (@matchlines) {
|
||||||
|
($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/);
|
||||||
|
|
||||||
|
$width -= $wmDecorationWidth;
|
||||||
|
$height -= $wmDecorationHeight;
|
||||||
|
|
||||||
|
$geometry = "${width}x$height";
|
||||||
|
}
|
||||||
|
|
||||||
|
@matchlines = grep(/default visual id/, @lines);
|
||||||
|
if (@matchlines) {
|
||||||
|
($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/);
|
||||||
|
|
||||||
|
for ($i = 0; $i < @lines; $i++) {
|
||||||
|
if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) {
|
||||||
|
if (($lines[$i+1] !~ /TrueColor/) ||
|
||||||
|
($lines[$i+2] !~ /depth/) ||
|
||||||
|
($lines[$i+4] !~ /red, green, blue masks/))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if ($i >= @lines);
|
||||||
|
|
||||||
|
($depth) = ($lines[$i+2] =~ /depth:\s+(\d+)/);
|
||||||
|
($red,$green,$blue)
|
||||||
|
= ($lines[$i+4]
|
||||||
|
=~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/);
|
||||||
|
|
||||||
|
$red = hex($red);
|
||||||
|
$green = hex($green);
|
||||||
|
$blue = hex($blue);
|
||||||
|
|
||||||
|
if ($red > $blue) {
|
||||||
|
$red = int(log($red) / log(2)) - int(log($green) / log(2));
|
||||||
|
$green = int(log($green) / log(2)) - int(log($blue) / log(2));
|
||||||
|
$blue = int(log($blue) / log(2)) + 1;
|
||||||
|
$pixelformat = "rgb$red$green$blue";
|
||||||
|
} else {
|
||||||
|
$blue = int(log($blue) / log(2)) - int(log($green) / log(2));
|
||||||
|
$green = int(log($green) / log(2)) - int(log($red) / log(2));
|
||||||
|
$red = int(log($red) / log(2)) + 1;
|
||||||
|
$pixelformat = "bgr$blue$green$red";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# quotedString returns a string which yields the original string when parsed
|
||||||
|
# by a shell.
|
||||||
|
#
|
||||||
|
|
||||||
|
sub quotedString
|
||||||
|
{
|
||||||
|
local ($in) = @_;
|
||||||
|
|
||||||
|
$in =~ s/\'/\'\"\'\"\'/g;
|
||||||
|
|
||||||
|
return "'$in'";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# removeSlashes turns slashes into underscores for use as a file name.
|
||||||
|
#
|
||||||
|
|
||||||
|
sub removeSlashes
|
||||||
|
{
|
||||||
|
local ($in) = @_;
|
||||||
|
|
||||||
|
$in =~ s|/|_|g;
|
||||||
|
|
||||||
|
return "$in";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Usage
|
||||||
|
#
|
||||||
|
|
||||||
|
sub Usage
|
||||||
|
{
|
||||||
|
die("\nusage: $prog [:<number>] [-name <desktop-name>] [-depth <depth>]\n".
|
||||||
|
" [-geometry <width>x<height>]\n".
|
||||||
|
" [-pixelformat rgbNNN|bgrNNN]\n".
|
||||||
|
" [-fp <font-path>]\n".
|
||||||
|
" [-cc <visual>]\n".
|
||||||
|
" [-fg]\n".
|
||||||
|
" [-autokill]\n".
|
||||||
|
" [-noxstartup]\n".
|
||||||
|
" [-xstartup <file>]\n".
|
||||||
|
" <Xvnc-options>...\n\n".
|
||||||
|
" $prog -kill <X-display>\n\n".
|
||||||
|
" $prog -list\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# List
|
||||||
|
#
|
||||||
|
|
||||||
|
sub List
|
||||||
|
{
|
||||||
|
opendir(dir, $vncUserDir);
|
||||||
|
my @filelist = readdir(dir);
|
||||||
|
closedir(dir);
|
||||||
|
print "\nTigerVNC server sessions:\n\n";
|
||||||
|
print "X DISPLAY #\tPROCESS ID\n";
|
||||||
|
foreach my $file (@filelist) {
|
||||||
|
if ($file =~ /$host:(\d+)$\.pid/) {
|
||||||
|
chop($tmp_pid = `cat $vncUserDir/$file`);
|
||||||
|
if (kill 0, $tmp_pid) {
|
||||||
|
print ":".$1."\t\t".`cat $vncUserDir/$file`;
|
||||||
|
} else {
|
||||||
|
unlink ($vncUserDir . "/" . $file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Kill
|
||||||
|
#
|
||||||
|
|
||||||
|
sub Kill
|
||||||
|
{
|
||||||
|
$opt{'-kill'} =~ s/(:\d+)\.\d+$/$1/; # e.g. turn :1.0 into :1
|
||||||
|
|
||||||
|
if ($opt{'-kill'} =~ /^:\d+$/) {
|
||||||
|
$pidFile = "$vncUserDir/$host$opt{'-kill'}.pid";
|
||||||
|
} else {
|
||||||
|
if ($opt{'-kill'} !~ /^$host:/) {
|
||||||
|
die "\nCan't tell if $opt{'-kill'} is on $host\n".
|
||||||
|
"Use -kill :<number> instead\n\n";
|
||||||
|
}
|
||||||
|
$pidFile = "$vncUserDir/$opt{'-kill'}.pid";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! -r $pidFile) {
|
||||||
|
die "\nCan't find file $pidFile\n".
|
||||||
|
"You'll have to kill the Xvnc process manually\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$SIG{'HUP'} = 'IGNORE';
|
||||||
|
chop($pid = `cat $pidFile`);
|
||||||
|
warn "Killing Xvnc process ID $pid\n";
|
||||||
|
|
||||||
|
if (kill 0, $pid) {
|
||||||
|
system("kill $pid");
|
||||||
|
sleep(1);
|
||||||
|
if (kill 0, $pid) {
|
||||||
|
print "Xvnc seems to be deadlocked. Kill the process manually and then re-run\n";
|
||||||
|
print " ".$0." -kill ".$opt{'-kill'}."\n";
|
||||||
|
print "to clean up the socket files.\n";
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
warn "Xvnc process ID $pid already killed\n";
|
||||||
|
$opt{'-kill'} =~ s/://;
|
||||||
|
|
||||||
|
if (-e "/tmp/.X11-unix/X$opt{'-kill'}") {
|
||||||
|
print "Xvnc did not appear to shut down cleanly.";
|
||||||
|
print " Removing /tmp/.X11-unix/X$opt{'-kill'}\n";
|
||||||
|
unlink "/tmp/.X11-unix/X$opt{'-kill'}";
|
||||||
|
}
|
||||||
|
if (-e "/tmp/.X$opt{'-kill'}-lock") {
|
||||||
|
print "Xvnc did not appear to shut down cleanly.";
|
||||||
|
print " Removing /tmp/.X$opt{'-kill'}-lock\n";
|
||||||
|
unlink "/tmp/.X$opt{'-kill'}-lock";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink $pidFile;
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# ParseOptions takes a list of possible options and a boolean indicating
|
||||||
|
# whether the option has a value following, and sets up an associative array
|
||||||
|
# %opt of the values of the options given on the command line. It removes all
|
||||||
|
# the arguments it uses from @ARGV and returns them in @optArgs.
|
||||||
|
#
|
||||||
|
|
||||||
|
sub ParseOptions
|
||||||
|
{
|
||||||
|
local (@optval) = @_;
|
||||||
|
local ($opt, @opts, %valFollows, @newargs);
|
||||||
|
|
||||||
|
while (@optval) {
|
||||||
|
$opt = shift(@optval);
|
||||||
|
push(@opts,$opt);
|
||||||
|
$valFollows{$opt} = shift(@optval);
|
||||||
|
}
|
||||||
|
|
||||||
|
@optArgs = ();
|
||||||
|
%opt = ();
|
||||||
|
|
||||||
|
arg: while (defined($arg = shift(@ARGV))) {
|
||||||
|
foreach $opt (@opts) {
|
||||||
|
if ($arg eq $opt) {
|
||||||
|
push(@optArgs, $arg);
|
||||||
|
if ($valFollows{$opt}) {
|
||||||
|
if (@ARGV == 0) {
|
||||||
|
&Usage();
|
||||||
|
}
|
||||||
|
$opt{$opt} = shift(@ARGV);
|
||||||
|
push(@optArgs, $opt{$opt});
|
||||||
|
} else {
|
||||||
|
$opt{$opt} = 1;
|
||||||
|
}
|
||||||
|
next arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
push(@newargs,$arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ARGV = @newargs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# 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") {
|
||||||
|
for (split(/:/,$ENV{PATH})) {
|
||||||
|
if (-x "$_/$cmd") {
|
||||||
|
next cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
die "$prog: couldn't find \"$cmd\" on your PATH.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if($exedir eq "") {
|
||||||
|
cmd2:
|
||||||
|
foreach $cmd ("Xvnc","vncpasswd") {
|
||||||
|
for (split(/:/,$ENV{PATH})) {
|
||||||
|
if (-x "$_/$cmd") {
|
||||||
|
next cmd2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
die "$prog: couldn't find \"$cmd\" on your PATH.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cmd3:
|
||||||
|
foreach $cmd ($exedir."Xvnc",$exedir."vncpasswd") {
|
||||||
|
for (split(/:/,$ENV{PATH})) {
|
||||||
|
if (-x "$cmd") {
|
||||||
|
next cmd3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
die "$prog: couldn't find \"$cmd\".\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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub NotifyAboutDeprecation
|
||||||
|
{
|
||||||
|
warn "\nWARNING: vncserver has been replaced by a systemd unit and is now considered deprecated and removed in upstream.\n";
|
||||||
|
warn "Please read /usr/share/doc/tigervnc/HOWTO.md for more information.\n";
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
From 947bd1b3f4a23565bf10879ec41ba06ebe1e1c76 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Olivier Fourdan <ofourdan@redhat.com>
|
||||||
|
Date: Mon, 13 Mar 2023 11:08:47 +0100
|
||||||
|
Subject: [PATCH xserver] composite: Fix use-after-free of the COW
|
||||||
|
|
||||||
|
ZDI-CAN-19866/CVE-2023-1393
|
||||||
|
|
||||||
|
If a client explicitly destroys the compositor overlay window (aka COW),
|
||||||
|
we would leave a dangling pointer to that window in the CompScreen
|
||||||
|
structure, which will trigger a use-after-free later.
|
||||||
|
|
||||||
|
Make sure to clear the CompScreen pointer to the COW when the latter gets
|
||||||
|
destroyed explicitly by the client.
|
||||||
|
|
||||||
|
This vulnerability was discovered by:
|
||||||
|
Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
|
||||||
|
|
||||||
|
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
|
||||||
|
Reviewed-by: Adam Jackson <ajax@redhat.com>
|
||||||
|
---
|
||||||
|
composite/compwindow.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/composite/compwindow.c b/composite/compwindow.c
|
||||||
|
index 4e2494b86..b30da589e 100644
|
||||||
|
--- a/composite/compwindow.c
|
||||||
|
+++ b/composite/compwindow.c
|
||||||
|
@@ -620,6 +620,11 @@ compDestroyWindow(WindowPtr pWin)
|
||||||
|
ret = (*pScreen->DestroyWindow) (pWin);
|
||||||
|
cs->DestroyWindow = pScreen->DestroyWindow;
|
||||||
|
pScreen->DestroyWindow = compDestroyWindow;
|
||||||
|
+
|
||||||
|
+ /* Did we just destroy the overlay window? */
|
||||||
|
+ if (pWin == cs->pOverlayWin)
|
||||||
|
+ cs->pOverlayWin = NULL;
|
||||||
|
+
|
||||||
|
/* compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.40.0
|
||||||
|
|
@ -0,0 +1,38 @@
|
|||||||
|
# The vncserver service unit file
|
||||||
|
#
|
||||||
|
# Quick HowTo:
|
||||||
|
# 1. Copy this file to /etc/systemd/system/xvnc@.service
|
||||||
|
# 2. Copy xvnc.socket to /etc/systemd/system/xvnc.socket
|
||||||
|
# 3. Run `systemctl daemon-reload`
|
||||||
|
# 4. Run `systemctl enable xvnc.socket`
|
||||||
|
#
|
||||||
|
# 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=XVNC Per-Connection Daemon
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=-/usr/bin/Xvnc -inetd -query localhost -geometry 1024x768 -depth 24 -once -SecurityTypes=None -Log *:syslog:30
|
||||||
|
User=nobody
|
||||||
|
StandardInput=socket
|
||||||
|
StandardError=syslog
|
@ -0,0 +1,9 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=XVNC Server
|
||||||
|
|
||||||
|
[Socket]
|
||||||
|
ListenStream=5900
|
||||||
|
Accept=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue