import libvncserver-0.9.11-17.el8

c8 imports/c8/libvncserver-0.9.11-17.el8
CentOS Sources 4 years ago committed by MSVSphere Packaging Team
commit 586007f669

1
.gitignore vendored

@ -0,0 +1 @@
SOURCES/LibVNCServer-0.9.11.tar.gz

@ -0,0 +1 @@
d844a2c9e69465d104a8468dce515a49e4db9585 SOURCES/LibVNCServer-0.9.11.tar.gz

@ -0,0 +1,47 @@
From b793e8c51ab253c0951e43a84e9d448416462887 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 27 Nov 2019 16:58:29 +0100
Subject: [PATCH] auth: Add API to unregister built in security handlers
If I have a VNC server that first accepts password based authentication,
then switches to something not using password (e.g. a prompt on screen),
the security handler from the first would still be sent as, meaning
clients would still ask for a password without there being one.
---
libvncserver/auth.c | 7 +++++++
rfb/rfb.h | 1 +
2 files changed, 8 insertions(+)
diff --git a/libvncserver/auth.c b/libvncserver/auth.c
index 55e0b3c9..8b6fc48f 100644
--- a/libvncserver/auth.c
+++ b/libvncserver/auth.c
@@ -248,6 +248,13 @@ determinePrimarySecurityType(rfbClientPtr cl)
}
}
+void
+rfbUnregisterPrimarySecurityHandlers (void)
+{
+ rfbUnregisterSecurityHandler(&VncSecurityHandlerNone);
+ rfbUnregisterSecurityHandler(&VncSecurityHandlerVncAuth);
+}
+
void
rfbSendSecurityTypeList(rfbClientPtr cl,
enum rfbSecurityTag exclude)
diff --git a/rfb/rfb.h b/rfb/rfb.h
index 70b92242..738dbd82 100644
--- a/rfb/rfb.h
+++ b/rfb/rfb.h
@@ -887,6 +887,7 @@ extern void rfbProcessClientSecurityType(rfbClientPtr cl);
extern void rfbAuthProcessClientMessage(rfbClientPtr cl);
extern void rfbRegisterSecurityHandler(rfbSecurityHandler* handler);
extern void rfbUnregisterSecurityHandler(rfbSecurityHandler* handler);
+extern void rfbUnregisterPrimarySecurityHandlers (void);
extern void rfbRegisterChannelSecurityHandler(rfbSecurityHandler* handler);
extern void rfbUnregisterChannelSecurityHandler(rfbSecurityHandler* handler);
extern void rfbSendSecurityTypeList(rfbClientPtr cl, enum rfbSecurityTag exclude);
--
2.23.0

@ -0,0 +1,241 @@
From fb4b12407e869c3da33df65ed3a43ef87aeae1c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Mon, 11 Jun 2018 23:47:02 +0200
Subject: [PATCH 1/2] libvncserver: Add API to add custom I/O entry points
Add API to make it possible to channel RFB input and output through
another layer, for example TLS. This is done by making it possible to
override the default read/write/peek functions.
---
libvncserver/rfbserver.c | 4 ++
libvncserver/sockets.c | 79 ++++++++++++++++++++++++++++++++++++----
rfb/rfb.h | 17 +++++++++
3 files changed, 93 insertions(+), 7 deletions(-)
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index bc9cc117..0c8ee735 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -319,6 +319,10 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
cl->screen = rfbScreen;
cl->sock = sock;
+ cl->readFromSocket = rfbDefaultReadFromSocket;
+ cl->peekAtSocket = rfbDefaultPeekAtSocket;
+ cl->hasPendingOnSocket = rfbDefaultHasPendingOnSocket;
+ cl->writeToSocket = rfbDefaultWriteToSocket;
cl->viewOnly = FALSE;
/* setup pseudo scaling */
cl->scaledScreen = rfbScreen;
diff --git a/libvncserver/sockets.c b/libvncserver/sockets.c
index bbc3d90d..4874d4b6 100644
--- a/libvncserver/sockets.c
+++ b/libvncserver/sockets.c
@@ -126,6 +126,9 @@ int deny_severity=LOG_WARNING;
int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has
gone away - needed to stop us hanging */
+static rfbBool
+rfbHasPendingOnSocket(rfbClientPtr cl);
+
static rfbBool
rfbNewConnectionFromSock(rfbScreenInfoPtr rfbScreen, int sock)
{
@@ -370,16 +373,20 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
tv.tv_usec = usec;
nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv);
if (nfds == 0) {
+ rfbBool hasPendingData = FALSE;
+
/* timed out, check for async events */
i = rfbGetClientIterator(rfbScreen);
while((cl = rfbClientIteratorNext(i))) {
if (cl->onHold)
continue;
+ hasPendingData |= rfbHasPendingOnSocket(cl);
if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
rfbSendFileTransferChunk(cl);
}
rfbReleaseClientIterator(i);
- return result;
+ if (!hasPendingData)
+ return result;
}
if (nfds < 0) {
@@ -455,9 +462,11 @@ rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
if (cl->onHold)
continue;
- if (FD_ISSET(cl->sock, &(rfbScreen->allFds)))
+ if (rfbHasPendingOnSocket (cl) ||
+ FD_ISSET(cl->sock, &(rfbScreen->allFds)))
{
- if (FD_ISSET(cl->sock, &fds))
+ if (rfbHasPendingOnSocket (cl) ||
+ FD_ISSET(cl->sock, &fds))
{
#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
do {
@@ -589,6 +598,30 @@ rfbConnect(rfbScreenInfoPtr rfbScreen,
return sock;
}
+int
+rfbDefaultReadFromSocket(rfbClientPtr cl, char *buf, int len)
+{
+ return read(cl->sock, buf, len);
+}
+
+static int
+rfbReadFromSocket(rfbClientPtr cl, char *buf, int len)
+{
+ return cl->readFromSocket(cl, buf, len);
+}
+
+rfbBool
+rfbDefaultHasPendingOnSocket(rfbClientPtr cl)
+{
+ return FALSE;
+}
+
+static rfbBool
+rfbHasPendingOnSocket(rfbClientPtr cl)
+{
+ return cl->hasPendingOnSocket(cl);
+}
+
/*
* ReadExact reads an exact number of bytes from a client. Returns 1 if
* those bytes have been read, 0 if the other end has closed, or -1 if an error
@@ -610,10 +643,10 @@ rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
} else if (cl->sslctx) {
n = rfbssl_read(cl, buf, len);
} else {
- n = read(sock, buf, len);
+ n = rfbReadFromSocket(cl, buf, len);
}
#else
- n = read(sock, buf, len);
+ n = rfbReadFromSocket(cl, buf, len);
#endif
if (n > 0) {
@@ -645,6 +678,10 @@ rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
continue;
}
#endif
+
+ if (rfbHasPendingOnSocket(cl))
+ continue;
+
FD_ZERO(&fds);
FD_SET(sock, &fds);
tv.tv_sec = timeout / 1000;
@@ -681,6 +718,18 @@ int rfbReadExact(rfbClientPtr cl,char* buf,int len)
return(rfbReadExactTimeout(cl,buf,len,rfbMaxClientWait));
}
+int
+rfbDefaultPeekAtSocket(rfbClientPtr cl, char *buf, int len)
+{
+ return recv(cl->sock, buf, len, MSG_PEEK);
+}
+
+int
+rfbPeekAtSocket(rfbClientPtr cl, char *buf, int len)
+{
+ cl->peekAtSocket(cl, buf, len);
+}
+
/*
* PeekExact peeks at an exact number of bytes from a client. Returns 1 if
* those bytes have been read, 0 if the other end has closed, or -1 if an
@@ -701,7 +750,7 @@ rfbPeekExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
n = rfbssl_peek(cl, buf, len);
else
#endif
- n = recv(sock, buf, len, MSG_PEEK);
+ n = rfbPeekAtSocket(cl, buf, len);
if (n == len) {
@@ -757,6 +806,22 @@ rfbPeekExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout)
return 1;
}
+int
+rfbDefaultWriteToSocket(rfbClientPtr cl,
+ const char *buf,
+ int len)
+{
+ return write(cl->sock, buf, len);
+}
+
+static int
+rfbWriteToSocket(rfbClientPtr cl,
+ const char *buf,
+ int len)
+{
+ return cl->writeToSocket(cl, buf, len);
+}
+
/*
* WriteExact writes an exact number of bytes to a client. Returns 1 if
* those bytes have been written, or -1 if an error occurred (errno is set to
@@ -801,7 +866,7 @@ rfbWriteExact(rfbClientPtr cl,
n = rfbssl_write(cl, buf, len);
else
#endif
- n = write(sock, buf, len);
+ n = rfbWriteToSocket(cl, buf, len);
if (n > 0) {
diff --git a/rfb/rfb.h b/rfb/rfb.h
index c6edc119..2e5597a9 100644
--- a/rfb/rfb.h
+++ b/rfb/rfb.h
@@ -414,6 +414,14 @@ typedef struct sraRegion* sraRegionPtr;
typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl);
+typedef int (*ClientReadFromSocket)(struct _rfbClientRec* cl,
+ char *buf, int len);
+typedef int (*ClientPeekAtSocket)(struct _rfbClientRec* cl,
+ char *buf, int len);
+typedef rfbBool (*ClientHasPendingOnSocket)(struct _rfbClientRec* cl);
+typedef int (*ClientWriteToSocket)(struct _rfbClientRec* cl,
+ const char *buf, int len);
+
typedef struct _rfbFileTransferData {
int fd;
int compressionEnabled;
@@ -695,6 +703,11 @@ typedef struct _rfbClientRec {
wsCtx *wsctx;
char *wspath; /* Requests path component */
#endif
+
+ ClientReadFromSocket readFromSocket; /* Read data from socket */
+ ClientPeekAtSocket peekAtSocket; /* Peek at data from socket */
+ ClientHasPendingOnSocket hasPendingOnSocket; /* Peek at data from socket */
+ ClientWriteToSocket writeToSocket; /* Write data to socket */
} rfbClientRec, *rfbClientPtr;
/**
@@ -747,8 +760,12 @@ extern void rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen);
extern void rfbCloseClient(rfbClientPtr cl);
extern int rfbReadExact(rfbClientPtr cl, char *buf, int len);
extern int rfbReadExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout);
+extern int rfbDefaultReadFromSocket(rfbClientPtr cl, char *buf, int len);
extern int rfbPeekExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout);
+extern int rfbDefaultPeekAtSocket(rfbClientPtr cl, char *buf, int len);
+extern rfbBool rfbDefaultHasPendingOnSocket(rfbClientPtr cl);
extern int rfbWriteExact(rfbClientPtr cl, const char *buf, int len);
+extern int rfbDefaultWriteToSocket(rfbClientPtr cl, const char *buf, int len);
extern int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec);
extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port);
extern int rfbConnectToTcpAddr(char* host, int port);
--
2.23.0

@ -0,0 +1,368 @@
From 5e4d810d62da0f2048ce78b3a7812e9e13968162 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Mon, 11 Jun 2018 23:50:05 +0200
Subject: [PATCH 2/2] libvncserver: Add channel security handlers
Add another type of security handler that is meant to be used initially
to set up a secure channel. Regular security handlers would be
advertised and processed after any channel security have succeeded.
For example, this, together with the custom I/O functions allows a
LibVNCServer user to implement TLS in combination with VNCAuth. This is
done by adding a single channel security handler with the rfbTLS (18)
with a handler that initiates a TLS session, and when a TLS session is
initiated, the regular security handler list is sent.
---
libvncserver/auth.c | 164 ++++++++++++++++++++++++++++++---------
libvncserver/rfbserver.c | 1 +
rfb/rfb.h | 15 +++-
3 files changed, 142 insertions(+), 38 deletions(-)
diff --git a/libvncserver/auth.c b/libvncserver/auth.c
index 814a8142..55e0b3c9 100644
--- a/libvncserver/auth.c
+++ b/libvncserver/auth.c
@@ -37,18 +37,17 @@ void rfbClientSendString(rfbClientPtr cl, const char *reason);
* Handle security types
*/
+/* Channel security handlers to set up a secure channel, e.g. TLS. */
+static rfbSecurityHandler* channelSecurityHandlers = NULL;
+
+/* Security handlers when channel security is established. */
static rfbSecurityHandler* securityHandlers = NULL;
-/*
- * This method registers a list of new security types.
- * It avoids same security type getting registered multiple times.
- * The order is not preserved if multiple security types are
- * registered at one-go.
- */
void
-rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
+rfbRegisterSecurityHandlerTo(rfbSecurityHandler* handler,
+ rfbSecurityHandler** handlerList)
{
- rfbSecurityHandler *head = securityHandlers, *next = NULL;
+ rfbSecurityHandler *head = *handlerList, *next = NULL;
if(handler == NULL)
return;
@@ -57,39 +56,35 @@ rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
while(head != NULL) {
if(head == handler) {
- rfbRegisterSecurityHandler(next);
+ rfbRegisterSecurityHandlerTo(next, handlerList);
return;
}
head = head->next;
}
- handler->next = securityHandlers;
- securityHandlers = handler;
+ handler->next = *handlerList;
+ *handlerList = handler;
- rfbRegisterSecurityHandler(next);
+ rfbRegisterSecurityHandlerTo(next, handlerList);
}
-/*
- * This method unregisters a list of security types.
- * These security types won't be available for any new
- * client connection.
- */
-void
-rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
+static void
+rfbUnregisterSecurityHandlerFrom(rfbSecurityHandler* handler,
+ rfbSecurityHandler** handlerList)
{
rfbSecurityHandler *cur = NULL, *pre = NULL;
if(handler == NULL)
return;
- if(securityHandlers == handler) {
- securityHandlers = securityHandlers->next;
- rfbUnregisterSecurityHandler(handler->next);
+ if(*handlerList == handler) {
+ *handlerList = (*handlerList)->next;
+ rfbUnregisterSecurityHandlerFrom(handler->next, handlerList);
return;
}
- cur = pre = securityHandlers;
+ cur = pre = *handlerList;
while(cur) {
if(cur == handler) {
@@ -99,7 +94,50 @@ rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
pre = cur;
cur = cur->next;
}
- rfbUnregisterSecurityHandler(handler->next);
+ rfbUnregisterSecurityHandlerFrom(handler->next, handlerList);
+}
+
+void
+rfbRegisterChannelSecurityHandler(rfbSecurityHandler* handler)
+{
+ rfbRegisterSecurityHandlerTo(handler, &channelSecurityHandlers);
+}
+
+/*
+ * This method unregisters a list of security types.
+ * These security types won't be available for any new
+ * client connection.
+ */
+
+void
+rfbUnregisterChannelSecurityHandler(rfbSecurityHandler* handler)
+{
+ rfbUnregisterSecurityHandlerFrom(handler, &channelSecurityHandlers);
+}
+
+/*
+ * This method registers a list of new security types.
+ * It avoids same security type getting registered multiple times.
+ * The order is not preserved if multiple security types are
+ * registered at one-go.
+ */
+
+void
+rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
+{
+ rfbRegisterSecurityHandlerTo(handler, &securityHandlers);
+}
+
+/*
+ * This method unregisters a list of security types.
+ * These security types won't be available for any new
+ * client connection.
+ */
+
+void
+rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
+{
+ rfbUnregisterSecurityHandlerFrom(handler, &securityHandlers);
}
/*
@@ -197,9 +235,22 @@ static rfbSecurityHandler VncSecurityHandlerNone = {
NULL
};
+static int32_t
+determinePrimarySecurityType(rfbClientPtr cl)
+{
+ if (!cl->screen->authPasswdData || cl->reverseConnection) {
+ /* chk if this condition is valid or not. */
+ return rfbSecTypeNone;
+ } else if (cl->screen->authPasswdData) {
+ return rfbSecTypeVncAuth;
+ } else {
+ return rfbSecTypeInvalid;
+ }
+}
-static void
-rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
+void
+rfbSendSecurityTypeList(rfbClientPtr cl,
+ enum rfbSecurityTag exclude)
{
/* The size of the message is the count of security types +1,
* since the first byte is the number of types. */
@@ -207,9 +258,10 @@ rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
rfbSecurityHandler* handler;
#define MAX_SECURITY_TYPES 255
uint8_t buffer[MAX_SECURITY_TYPES+1];
-
+ int32_t primaryType;
/* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */
+ primaryType = determinePrimarySecurityType(cl);
switch (primaryType) {
case rfbSecTypeNone:
rfbRegisterSecurityHandler(&VncSecurityHandlerNone);
@@ -221,6 +273,9 @@ rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
for (handler = securityHandlers;
handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
+ if (exclude && (handler->securityTags & exclude))
+ continue;
+
buffer[size] = handler->type;
size++;
}
@@ -249,7 +304,29 @@ rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
cl->state = RFB_SECURITY_TYPE;
}
+static void
+rfbSendChannelSecurityTypeList(rfbClientPtr cl)
+{
+ int size = 1;
+ rfbSecurityHandler* handler;
+ uint8_t buffer[MAX_SECURITY_TYPES+1];
+
+ for (handler = channelSecurityHandlers;
+ handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
+ buffer[size] = handler->type;
+ size++;
+ }
+ buffer[0] = (unsigned char)size-1;
+
+ if (rfbWriteExact(cl, (char *)buffer, size) < 0) {
+ rfbLogPerror("rfbSendSecurityTypeList: write");
+ rfbCloseClient(cl);
+ return;
+ }
+ /* Dispatch client input to rfbProcessClientChannelSecurityType. */
+ cl->state = RFB_CHANNEL_SECURITY_TYPE;
+}
/*
@@ -297,18 +374,19 @@ rfbSendSecurityType(rfbClientPtr cl, int32_t securityType)
void
rfbAuthNewClient(rfbClientPtr cl)
{
- int32_t securityType = rfbSecTypeInvalid;
+ int32_t securityType;
- if (!cl->screen->authPasswdData || cl->reverseConnection) {
- /* chk if this condition is valid or not. */
- securityType = rfbSecTypeNone;
- } else if (cl->screen->authPasswdData) {
- securityType = rfbSecTypeVncAuth;
- }
+ securityType = determinePrimarySecurityType(cl);
if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7)
{
/* Make sure we use only RFB 3.3 compatible security types. */
+ if (channelSecurityHandlers) {
+ rfbLog("VNC channel security enabled - RFB 3.3 client rejected\n");
+ rfbClientConnFailed(cl, "Your viewer cannot hnadler required "
+ "security methods");
+ return;
+ }
if (securityType == rfbSecTypeInvalid) {
rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n");
rfbClientConnFailed(cl, "Your viewer cannot handle required "
@@ -316,9 +394,13 @@ rfbAuthNewClient(rfbClientPtr cl)
return;
}
rfbSendSecurityType(cl, securityType);
+ } else if (channelSecurityHandlers) {
+ rfbLog("Send channel security type list\n");
+ rfbSendChannelSecurityTypeList(cl);
} else {
/* Here it's ok when securityType is set to rfbSecTypeInvalid. */
- rfbSendSecurityTypeList(cl, securityType);
+ rfbLog("Send channel security type 'none'\n");
+ rfbSendSecurityTypeList(cl, RFB_SECURITY_TAG_NONE);
}
}
@@ -332,6 +414,7 @@ rfbProcessClientSecurityType(rfbClientPtr cl)
int n;
uint8_t chosenType;
rfbSecurityHandler* handler;
+ rfbSecurityHandler* handlerListHead;
/* Read the security type. */
n = rfbReadExact(cl, (char *)&chosenType, 1);
@@ -344,8 +427,17 @@ rfbProcessClientSecurityType(rfbClientPtr cl)
return;
}
+ switch (cl->state) {
+ case RFB_CHANNEL_SECURITY_TYPE:
+ handlerListHead = channelSecurityHandlers;
+ break;
+ case RFB_SECURITY_TYPE:
+ handlerListHead = securityHandlers;
+ break;
+ }
+
/* Make sure it was present in the list sent by the server. */
- for (handler = securityHandlers; handler; handler = handler->next) {
+ for (handler = handlerListHead; handler; handler = handler->next) {
if (chosenType == handler->type) {
rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType);
handler->handler(cl);
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index 0c8ee735..421d8c7f 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -640,6 +640,7 @@ rfbProcessClientMessage(rfbClientPtr cl)
case RFB_PROTOCOL_VERSION:
rfbProcessClientProtocolVersion(cl);
return;
+ case RFB_CHANNEL_SECURITY_TYPE:
case RFB_SECURITY_TYPE:
rfbProcessClientSecurityType(cl);
return;
diff --git a/rfb/rfb.h b/rfb/rfb.h
index 2e5597a9..d2a7c9fb 100644
--- a/rfb/rfb.h
+++ b/rfb/rfb.h
@@ -181,6 +181,11 @@ typedef struct {
} data; /**< there have to be count*3 entries */
} rfbColourMap;
+enum rfbSecurityTag {
+ RFB_SECURITY_TAG_NONE = 0,
+ RFB_SECURITY_TAG_CHANNEL = 1 << 0
+};
+
/**
* Security handling (RFB protocol version 3.7)
*/
@@ -189,6 +194,7 @@ typedef struct _rfbSecurity {
uint8_t type;
void (*handler)(struct _rfbClientRec* cl);
struct _rfbSecurity* next;
+ enum rfbSecurityTag securityTags;
} rfbSecurityHandler;
/**
@@ -505,7 +511,7 @@ typedef struct _rfbClientRec {
/** Possible client states: */
enum {
RFB_PROTOCOL_VERSION, /**< establishing protocol version */
- RFB_SECURITY_TYPE, /**< negotiating security (RFB v.3.7) */
+ RFB_SECURITY_TYPE, /**< negotiating security (RFB v.3.7) */
RFB_AUTHENTICATION, /**< authenticating */
RFB_INITIALISATION, /**< sending initialisation messages */
RFB_NORMAL, /**< normal protocol messages */
@@ -513,7 +519,9 @@ typedef struct _rfbClientRec {
/* Ephemeral internal-use states that will never be seen by software
* using LibVNCServer to provide services: */
- RFB_INITIALISATION_SHARED /**< sending initialisation messages with implicit shared-flag already true */
+ RFB_INITIALISATION_SHARED, /**< sending initialisation messages with implicit shared-flag already true */
+
+ RFB_CHANNEL_SECURITY_TYPE, /**< negotiating security (RFB v.3.7) */
} state;
rfbBool reverseConnection;
@@ -854,6 +862,9 @@ extern void rfbProcessClientSecurityType(rfbClientPtr cl);
extern void rfbAuthProcessClientMessage(rfbClientPtr cl);
extern void rfbRegisterSecurityHandler(rfbSecurityHandler* handler);
extern void rfbUnregisterSecurityHandler(rfbSecurityHandler* handler);
+extern void rfbRegisterChannelSecurityHandler(rfbSecurityHandler* handler);
+extern void rfbUnregisterChannelSecurityHandler(rfbSecurityHandler* handler);
+extern void rfbSendSecurityTypeList(rfbClientPtr cl, enum rfbSecurityTag exclude);
/* rre.c */
--
2.23.0

@ -0,0 +1,28 @@
From 75f04c14e49e084e41bdd5491edad8823773a08c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?= <github@kempniu.pl>
Date: Tue, 14 Feb 2017 12:42:04 +0100
Subject: [PATCH 40/98] Ensure compatibility with gtk-vnc 0.7.0+
---
libvncserver/websockets.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libvncserver/websockets.c b/libvncserver/websockets.c
index 72396c2..0b2d46f 100644
--- a/libvncserver/websockets.c
+++ b/libvncserver/websockets.c
@@ -245,7 +245,10 @@ webSocketsCheck (rfbClientPtr cl)
return FALSE;
}
- if (strncmp(bbuf, "<", 1) == 0) {
+ if (strncmp(bbuf, "RFB ", 4) == 0) {
+ rfbLog("Normal socket connection\n");
+ return TRUE;
+ } else if (strncmp(bbuf, "<", 1) == 0) {
rfbLog("Got Flash policy request, sending response\n");
if (rfbWriteExact(cl, FLASH_POLICY_RESPONSE,
SZ_FLASH_POLICY_RESPONSE) < 0) {
--
2.9.4

@ -0,0 +1,26 @@
diff -Naur libvncserver-LibVNCServer-0.9.10.old/libvncclient/tls_gnutls.c libvncserver-LibVNCServer-0.9.10/libvncclient/tls_gnutls.c
--- libvncserver-LibVNCServer-0.9.10.old/libvncclient/tls_gnutls.c 2015-12-12 00:14:37.269157918 +0100
+++ libvncserver-LibVNCServer-0.9.10/libvncclient/tls_gnutls.c 2015-12-12 11:23:29.391385234 +0100
@@ -31,8 +31,8 @@
#include "tls.h"
-static const char *rfbTLSPriority = "NORMAL:+DHE-DSS:+RSA:+DHE-RSA:+SRP";
-static const char *rfbAnonTLSPriority= "NORMAL:+ANON-DH";
+static const char *rfbTLSPriority = "@SYSTEM";
+static const char *rfbAnonTLSPriority= "@SYSTEM:+ANON-DH";
#define DH_BITS 1024
static gnutls_dh_params_t rfbDHParams;
diff -Naur libvncserver-LibVNCServer-0.9.10.old/libvncserver/rfbssl_gnutls.c libvncserver-LibVNCServer-0.9.10/libvncserver/rfbssl_gnutls.c
--- libvncserver-LibVNCServer-0.9.10.old/libvncserver/rfbssl_gnutls.c 2015-12-12 00:14:37.270157930 +0100
+++ libvncserver-LibVNCServer-0.9.10/libvncserver/rfbssl_gnutls.c 2015-12-12 11:14:49.966830581 +0100
@@ -54,7 +54,7 @@
if (!GNUTLS_E_SUCCESS == (ret = gnutls_init(&session, GNUTLS_SERVER))) {
/* */
- } else if (!GNUTLS_E_SUCCESS == (ret = gnutls_priority_set_direct(session, "EXPORT", NULL))) {
+ } else if (!GNUTLS_E_SUCCESS == (ret = gnutls_set_default_priority(session))) {
/* */
} else if (!GNUTLS_E_SUCCESS == (ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, ctx->x509_cred))) {
/* */

@ -0,0 +1,20 @@
diff -up LibVNCServer-0.9.1/libvncserver-config.in.multilib LibVNCServer-0.9.1/libvncserver-config.in
--- LibVNCServer-0.9.1/libvncserver-config.in.multilib 2007-05-26 21:28:25.000000000 -0500
+++ LibVNCServer-0.9.1/libvncserver-config.in 2008-01-22 14:51:08.000000000 -0600
@@ -4,7 +4,6 @@ prefix=@prefix@
exec_prefix=@exec_prefix@
exec_prefix_set=no
includedir=@includedir@
-libdir=@libdir@
# if this script is in the same directory as libvncserver-config.in, assume not installed
if [ -f "`dirname "$0"`/libvncserver-config.in" ]; then
@@ -63,7 +62,7 @@ while test $# -gt 0; do
libs="$libs -R$dir"
fi
done
- echo "$libs" -lvncserver -lvncclient @LIBS@ @WSOCKLIB@
+ echo "$libs" -lvncserver -lvncclient
;;
--link)
echo @CC@

@ -0,0 +1,694 @@
Backport of:
From aac95a9dcf4bbba87b76c72706c3221a842ca433 Mon Sep 17 00:00:00 2001
From: Andreas Weigel <andreaswe@securepoint.de>
Date: Wed, 15 Feb 2017 12:31:05 +0100
Subject: [PATCH] fix overflow and refactor websockets decode (Hybi)
fix critical heap-based buffer overflow which allowed easy modification
of a return address via an overwritten function pointer
fix bug causing connections to fail due a "one websocket frame = one
ws_read" assumption, which failed with LibVNCServer-0.9.11
refactor websocket Hybi decode to use a simple state machine for
decoding of websocket frames
[Ubuntu note: Renamed b64_pton to __b64_pton in patch to ensure patch can be
applied.
-- Avital]
---
libvncserver/websockets.c | 595 +++++++++++++++++++++++++++++---------
1 file changed, 463 insertions(+), 132 deletions(-)
--- a/libvncserver/websockets.c
+++ b/libvncserver/websockets.c
@@ -62,6 +62,9 @@
#define B64LEN(__x) (((__x + 2) / 3) * 12 / 3)
#define WSHLENMAX 14 /* 2 + sizeof(uint64_t) + sizeof(uint32_t) */
+#define WS_HYBI_MASK_LEN 4
+
+#define ARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))) / (size_t)(!(sizeof(a) % sizeof((a[0])))))
enum {
WEBSOCKETS_VERSION_HIXIE,
@@ -78,20 +81,20 @@ static int gettid() {
typedef int (*wsEncodeFunc)(rfbClientPtr cl, const char *src, int len, char **dst);
typedef int (*wsDecodeFunc)(rfbClientPtr cl, char *dst, int len);
-typedef struct ws_ctx_s {
- char codeBufDecode[B64LEN(UPDATE_BUF_SIZE) + WSHLENMAX]; /* base64 + maximum frame header length */
- char codeBufEncode[B64LEN(UPDATE_BUF_SIZE) + WSHLENMAX]; /* base64 + maximum frame header length */
- char readbuf[8192];
- int readbufstart;
- int readbuflen;
- int dblen;
- char carryBuf[3]; /* For base64 carry-over */
- int carrylen;
- int version;
- int base64;
- wsEncodeFunc encode;
- wsDecodeFunc decode;
-} ws_ctx_t;
+
+enum {
+ /* header not yet received completely */
+ WS_HYBI_STATE_HEADER_PENDING,
+ /* data available */
+ WS_HYBI_STATE_DATA_AVAILABLE,
+ WS_HYBI_STATE_DATA_NEEDED,
+ /* received a complete frame */
+ WS_HYBI_STATE_FRAME_COMPLETE,
+ /* received part of a 'close' frame */
+ WS_HYBI_STATE_CLOSE_REASON_PENDING,
+ /* */
+ WS_HYBI_STATE_ERR
+};
typedef union ws_mask_s {
char c[4];
@@ -119,6 +122,38 @@ typedef struct __attribute__ ((__packed_
} u;
} ws_header_t;
+typedef struct ws_header_data_s {
+ ws_header_t *data;
+ /** bytes read */
+ int nRead;
+ /** mask value */
+ ws_mask_t mask;
+ /** length of frame header including payload len, but without mask */
+ int headerLen;
+ /** length of the payload data */
+ int payloadLen;
+ /** opcode */
+ unsigned char opcode;
+} ws_header_data_t;
+
+typedef struct ws_ctx_s {
+ char codeBufDecode[B64LEN(UPDATE_BUF_SIZE) + WSHLENMAX]; /* base64 + maximum frame header length */
+ char codeBufEncode[B64LEN(UPDATE_BUF_SIZE) + WSHLENMAX]; /* base64 + maximum frame header length */
+ char *writePos;
+ unsigned char *readPos;
+ int readlen;
+ int hybiDecodeState;
+ char carryBuf[3]; /* For base64 carry-over */
+ int carrylen;
+ int version;
+ int base64;
+ ws_header_data_t header;
+ int nReadRaw;
+ int nToRead;
+ wsEncodeFunc encode;
+ wsDecodeFunc decode;
+} ws_ctx_t;
+
enum
{
WS_OPCODE_CONTINUATION = 0x0,
@@ -179,6 +214,8 @@ static int webSocketsEncodeHixie(rfbClie
static int webSocketsDecodeHybi(rfbClientPtr cl, char *dst, int len);
static int webSocketsDecodeHixie(rfbClientPtr cl, char *dst, int len);
+static void hybiDecodeCleanup(ws_ctx_t *wsctx);
+
static int
min (int a, int b) {
return a < b ? a : b;
@@ -440,10 +477,11 @@ webSocketsHandshake(rfbClientPtr cl, cha
wsctx->decode = webSocketsDecodeHixie;
}
wsctx->base64 = base64;
+ hybiDecodeCleanup(wsctx);
cl->wsctx = (wsCtx *)wsctx;
return TRUE;
}
-
+
void
webSocketsGenMd5(char * target, char *key1, char *key2, char *key3)
{
@@ -635,146 +673,439 @@ webSocketsDecodeHixie(rfbClientPtr cl, c
}
static int
-webSocketsDecodeHybi(rfbClientPtr cl, char *dst, int len)
+hybiRemaining(ws_ctx_t *wsctx)
{
- char *buf, *payload;
- uint32_t *payload32;
- int ret = -1, result = -1;
- int total = 0;
- ws_mask_t mask;
- ws_header_t *header;
- int i;
- unsigned char opcode;
- ws_ctx_t *wsctx = (ws_ctx_t *)cl->wsctx;
- int flength, fhlen;
- /* int fin; */ /* not used atm */
+ return wsctx->nToRead - wsctx->nReadRaw;
+}
- /* rfbLog(" <== %s[%d]: %d cl: %p, wsctx: %p-%p (%d)\n", __func__, gettid(), len, cl, wsctx, (char *)wsctx + sizeof(ws_ctx_t), sizeof(ws_ctx_t)); */
+static void
+hybiDecodeCleanup(ws_ctx_t *wsctx)
+{
+ wsctx->header.payloadLen = 0;
+ wsctx->header.mask.u = 0;
+ wsctx->nReadRaw = 0;
+ wsctx->nToRead= 0;
+ wsctx->carrylen = 0;
+ wsctx->readPos = (unsigned char *)wsctx->codeBufDecode;
+ wsctx->readlen = 0;
+ wsctx->hybiDecodeState = WS_HYBI_STATE_HEADER_PENDING;
+ wsctx->writePos = NULL;
+ rfbLog("cleaned up wsctx\n");
+}
- if (wsctx->readbuflen) {
- /* simply return what we have */
- if (wsctx->readbuflen > len) {
- memcpy(dst, wsctx->readbuf + wsctx->readbufstart, len);
- result = len;
- wsctx->readbuflen -= len;
- wsctx->readbufstart += len;
+/**
+ * Return payload data that has been decoded/unmasked from
+ * a websocket frame.
+ *
+ * @param[out] dst destination buffer
+ * @param[in] len bytes to copy to destination buffer
+ * @param[in,out] wsctx internal state of decoding procedure
+ * @param[out] number of bytes actually written to dst buffer
+ * @return next hybi decoding state
+ */
+static int
+hybiReturnData(char *dst, int len, ws_ctx_t *wsctx, int *nWritten)
+{
+ int nextState = WS_HYBI_STATE_ERR;
+
+ /* if we have something already decoded copy and return */
+ if (wsctx->readlen > 0) {
+ /* simply return what we have */
+ if (wsctx->readlen > len) {
+ rfbLog("copy to %d bytes to dst buffer; readPos=%p, readLen=%d\n", len, wsctx->readPos, wsctx->readlen);
+ memcpy(dst, wsctx->readPos, len);
+ *nWritten = len;
+ wsctx->readlen -= len;
+ wsctx->readPos += len;
+ nextState = WS_HYBI_STATE_DATA_AVAILABLE;
+ } else {
+ rfbLog("copy to %d bytes to dst buffer; readPos=%p, readLen=%d\n", wsctx->readlen, wsctx->readPos, wsctx->readlen);
+ memcpy(dst, wsctx->readPos, wsctx->readlen);
+ *nWritten = wsctx->readlen;
+ wsctx->readlen = 0;
+ wsctx->readPos = NULL;
+ if (hybiRemaining(wsctx) == 0) {
+ nextState = WS_HYBI_STATE_FRAME_COMPLETE;
} else {
- memcpy(dst, wsctx->readbuf + wsctx->readbufstart, wsctx->readbuflen);
- result = wsctx->readbuflen;
- wsctx->readbuflen = 0;
- wsctx->readbufstart = 0;
+ nextState = WS_HYBI_STATE_DATA_NEEDED;
}
- goto spor;
}
+ rfbLog("after copy: readPos=%p, readLen=%d\n", wsctx->readPos, wsctx->readlen);
+ } else if (wsctx->hybiDecodeState == WS_HYBI_STATE_CLOSE_REASON_PENDING) {
+ nextState = WS_HYBI_STATE_CLOSE_REASON_PENDING;
+ }
+ return nextState;
+}
- buf = wsctx->codeBufDecode;
- header = (ws_header_t *)wsctx->codeBufDecode;
+/**
+ * Read an RFC 6455 websocket frame (IETF hybi working group).
+ *
+ * Internal state is updated according to bytes received and the
+ * decoding of header information.
+ *
+ * @param[in] cl client ptr with ptr to raw socket and ws_ctx_t ptr
+ * @param[out] sockRet emulated recv return value
+ * @return next hybi decoding state; WS_HYBI_STATE_HEADER_PENDING indicates
+ * that the header was not received completely.
+ */
+static int
+hybiReadHeader(rfbClientPtr cl, int *sockRet)
+{
+ int ret;
+ ws_ctx_t *wsctx = (ws_ctx_t *)cl->wsctx;
+ char *headerDst = wsctx->codeBufDecode + wsctx->nReadRaw;
+ int n = WSHLENMAX - wsctx->nReadRaw;
+
+ rfbLog("header_read to %p with len=%d\n", headerDst, n);
+ ret = ws_read(cl, headerDst, n);
+ rfbLog("read %d bytes from socket\n", ret);
+ if (ret <= 0) {
+ if (-1 == ret) {
+ /* save errno because rfbErr() will tamper it */
+ int olderrno = errno;
+ rfbErr("%s: peek; %m\n", __func__);
+ errno = olderrno;
+ *sockRet = -1;
+ } else {
+ *sockRet = 0;
+ }
+ return WS_HYBI_STATE_ERR;
+ }
- ret = ws_peek(cl, buf, B64LEN(len) + WSHLENMAX);
+ wsctx->nReadRaw += ret;
+ if (wsctx->nReadRaw < 2) {
+ /* cannot decode header with less than two bytes */
+ errno = EAGAIN;
+ *sockRet = -1;
+ return WS_HYBI_STATE_HEADER_PENDING;
+ }
+
+ /* first two header bytes received; interpret header data and get rest */
+ wsctx->header.data = (ws_header_t *)wsctx->codeBufDecode;
+
+ wsctx->header.opcode = wsctx->header.data->b0 & 0x0f;
+
+ /* fin = (header->b0 & 0x80) >> 7; */ /* not used atm */
+ wsctx->header.payloadLen = wsctx->header.data->b1 & 0x7f;
+ rfbLog("first header bytes received; opcode=%d lenbyte=%d\n", wsctx->header.opcode, wsctx->header.payloadLen);
+
+ /*
+ * 4.3. Client-to-Server Masking
+ *
+ * The client MUST mask all frames sent to the server. A server MUST
+ * close the connection upon receiving a frame with the MASK bit set to 0.
+ **/
+ if (!(wsctx->header.data->b1 & 0x80)) {
+ rfbErr("%s: got frame without mask ret=%d\n", __func__, ret);
+ errno = EIO;
+ *sockRet = -1;
+ return WS_HYBI_STATE_ERR;
+ }
+
+ if (wsctx->header.payloadLen < 126 && wsctx->nReadRaw >= 6) {
+ wsctx->header.headerLen = 2 + WS_HYBI_MASK_LEN;
+ wsctx->header.mask = wsctx->header.data->u.m;
+ } else if (wsctx->header.payloadLen == 126 && 8 <= wsctx->nReadRaw) {
+ wsctx->header.headerLen = 4 + WS_HYBI_MASK_LEN;
+ wsctx->header.payloadLen = WS_NTOH16(wsctx->header.data->u.s16.l16);
+ wsctx->header.mask = wsctx->header.data->u.s16.m16;
+ } else if (wsctx->header.payloadLen == 127 && 14 <= wsctx->nReadRaw) {
+ wsctx->header.headerLen = 10 + WS_HYBI_MASK_LEN;
+ wsctx->header.payloadLen = WS_NTOH64(wsctx->header.data->u.s64.l64);
+ wsctx->header.mask = wsctx->header.data->u.s64.m64;
+ } else {
+ /* Incomplete frame header, try again */
+ rfbErr("%s: incomplete frame header; ret=%d\n", __func__, ret);
+ errno = EAGAIN;
+ *sockRet = -1;
+ return WS_HYBI_STATE_HEADER_PENDING;
+ }
+
+ /* absolute length of frame */
+ wsctx->nToRead = wsctx->header.headerLen + wsctx->header.payloadLen;
- if (ret < 2) {
- /* save errno because rfbErr() will tamper it */
- if (-1 == ret) {
- int olderrno = errno;
- rfbErr("%s: peek; %m\n", __func__);
- errno = olderrno;
- } else if (0 == ret) {
- result = 0;
- } else {
- errno = EAGAIN;
- }
- goto spor;
- }
+ /* set payload pointer just after header */
+ wsctx->writePos = wsctx->codeBufDecode + wsctx->nReadRaw;
- opcode = header->b0 & 0x0f;
- /* fin = (header->b0 & 0x80) >> 7; */ /* not used atm */
- flength = header->b1 & 0x7f;
+ wsctx->readPos = (unsigned char *)(wsctx->codeBufDecode + wsctx->header.headerLen);
- /*
- * 4.3. Client-to-Server Masking
- *
- * The client MUST mask all frames sent to the server. A server MUST
- * close the connection upon receiving a frame with the MASK bit set to 0.
- **/
- if (!(header->b1 & 0x80)) {
- rfbErr("%s: got frame without mask\n", __func__, ret);
- errno = EIO;
- goto spor;
- }
-
- if (flength < 126) {
- fhlen = 2;
- mask = header->u.m;
- } else if (flength == 126 && 4 <= ret) {
- flength = WS_NTOH16(header->u.s16.l16);
- fhlen = 4;
- mask = header->u.s16.m16;
- } else if (flength == 127 && 10 <= ret) {
- flength = WS_NTOH64(header->u.s64.l64);
- fhlen = 10;
- mask = header->u.s64.m64;
- } else {
- /* Incomplete frame header */
- rfbErr("%s: incomplete frame header\n", __func__, ret);
- errno = EIO;
- goto spor;
- }
+ rfbLog("header complete: state=%d flen=%d writeTo=%p\n", wsctx->hybiDecodeState, wsctx->nToRead, wsctx->writePos);
+
+ return WS_HYBI_STATE_DATA_NEEDED;
+}
- /* absolute length of frame */
- total = fhlen + flength + 4;
- payload = buf + fhlen + 4; /* header length + mask */
+static int
+hybiWsFrameComplete(ws_ctx_t *wsctx)
+{
+ return wsctx != NULL && hybiRemaining(wsctx) == 0;
+}
- if (-1 == (ret = ws_read(cl, buf, total))) {
+static char *
+hybiPayloadStart(ws_ctx_t *wsctx)
+{
+ return wsctx->codeBufDecode + wsctx->header.headerLen;
+}
+
+
+/**
+ * Read the remaining payload bytes from associated raw socket.
+ *
+ * - try to read remaining bytes from socket
+ * - unmask all multiples of 4
+ * - if frame incomplete but some bytes are left, these are copied to
+ * the carry buffer
+ * - if opcode is TEXT: Base64-decode all unmasked received bytes
+ * - set state for reading decoded data
+ * - reset write position to begin of buffer (+ header)
+ * --> before we retrieve more data we let the caller clear all bytes
+ * from the reception buffer
+ * - execute return data routine
+ *
+ * Sets errno corresponding to what it gets from the underlying
+ * socket or EIO if some internal sanity check fails.
+ *
+ * @param[in] cl client ptr with raw socket reference
+ * @param[out] dst destination buffer
+ * @param[in] len size of destination buffer
+ * @param[out] sockRet emulated recv return value
+ * @return next hybi decode state
+ */
+static int
+hybiReadAndDecode(rfbClientPtr cl, char *dst, int len, int *sockRet)
+{
+ int n;
+ int i;
+ int toReturn;
+ int toDecode;
+ int bufsize;
+ int nextRead;
+ unsigned char *data;
+ uint32_t *data32;
+ ws_ctx_t *wsctx = (ws_ctx_t *)cl->wsctx;
+
+ /* if data was carried over, copy to start of buffer */
+ memcpy(wsctx->writePos, wsctx->carryBuf, wsctx->carrylen);
+ wsctx->writePos += wsctx->carrylen;
+
+ /* -1 accounts for potential '\0' terminator for base64 decoding */
+ bufsize = wsctx->codeBufDecode + ARRAYSIZE(wsctx->codeBufDecode) - wsctx->writePos - 1;
+ if (hybiRemaining(wsctx) > bufsize) {
+ nextRead = bufsize;
+ } else {
+ nextRead = hybiRemaining(wsctx);
+ }
+
+ rfbLog("calling read with buf=%p and len=%d (decodebuf=%p headerLen=%d\n)", wsctx->writePos, nextRead, wsctx->codeBufDecode, wsctx->header.headerLen);
+
+ if (wsctx->nReadRaw < wsctx->nToRead) {
+ /* decode more data */
+ if (-1 == (n = ws_read(cl, wsctx->writePos, nextRead))) {
int olderrno = errno;
rfbErr("%s: read; %m", __func__);
errno = olderrno;
- return ret;
- } else if (ret < total) {
- /* GT TODO: hmm? */
- rfbLog("%s: read; got partial data\n", __func__);
- } else {
- buf[ret] = '\0';
- }
+ *sockRet = -1;
+ return WS_HYBI_STATE_ERR;
+ } else if (n == 0) {
+ *sockRet = 0;
+ return WS_HYBI_STATE_ERR;
+ }
+ wsctx->nReadRaw += n;
+ rfbLog("read %d bytes from socket; nRead=%d\n", n, wsctx->nReadRaw);
+ } else {
+ n = 0;
+ }
+
+ wsctx->writePos += n;
+
+ if (wsctx->nReadRaw >= wsctx->nToRead) {
+ if (wsctx->nReadRaw > wsctx->nToRead) {
+ rfbErr("%s: internal error, read past websocket frame", __func__);
+ errno=EIO;
+ *sockRet = -1;
+ return WS_HYBI_STATE_ERR;
+ }
+ }
+
+ toDecode = wsctx->writePos - hybiPayloadStart(wsctx);
+ rfbLog("toDecode=%d from n=%d carrylen=%d headerLen=%d\n", toDecode, n, wsctx->carrylen, wsctx->header.headerLen);
+ if (toDecode < 0) {
+ rfbErr("%s: internal error; negative number of bytes to decode: %d", __func__, toDecode);
+ errno=EIO;
+ *sockRet = -1;
+ return WS_HYBI_STATE_ERR;
+ }
+
+ /* for a possible base64 decoding, we decode multiples of 4 bytes until
+ * the whole frame is received and carry over any remaining bytes in the carry buf*/
+ data = (unsigned char *)hybiPayloadStart(wsctx);
+ data32= (uint32_t *)data;
+
+ for (i = 0; i < (toDecode >> 2); i++) {
+ data32[i] ^= wsctx->header.mask.u;
+ }
+ rfbLog("mask decoding; i=%d toDecode=%d\n", i, toDecode);
- /* process 1 frame (32 bit op) */
- payload32 = (uint32_t *)payload;
- for (i = 0; i < flength / 4; i++) {
- payload32[i] ^= mask.u;
- }
+ if (wsctx->hybiDecodeState == WS_HYBI_STATE_FRAME_COMPLETE) {
/* process the remaining bytes (if any) */
- for (i*=4; i < flength; i++) {
- payload[i] ^= mask.c[i % 4];
+ for (i*=4; i < toDecode; i++) {
+ data[i] ^= wsctx->header.mask.c[i % 4];
}
- switch (opcode) {
- case WS_OPCODE_CLOSE:
- rfbLog("got closure, reason %d\n", WS_NTOH16(((uint16_t *)payload)[0]));
- errno = ECONNRESET;
- break;
- case WS_OPCODE_TEXT_FRAME:
- if (-1 == (flength = __b64_pton(payload, (unsigned char *)wsctx->codeBufDecode, sizeof(wsctx->codeBufDecode)))) {
- rfbErr("%s: Base64 decode error; %m\n", __func__);
- break;
- }
- payload = wsctx->codeBufDecode;
- /* fall through */
- case WS_OPCODE_BINARY_FRAME:
- if (flength > len) {
- memcpy(wsctx->readbuf, payload + len, flength - len);
- wsctx->readbufstart = 0;
- wsctx->readbuflen = flength - len;
- flength = len;
- }
- memcpy(dst, payload, flength);
- result = flength;
- break;
+ /* all data is here, no carrying */
+ wsctx->carrylen = 0;
+ } else {
+ /* carry over remaining, non-multiple-of-four bytes */
+ wsctx->carrylen = toDecode - (i * 4);
+ if (wsctx->carrylen < 0 || wsctx->carrylen > ARRAYSIZE(wsctx->carryBuf)) {
+ rfbErr("%s: internal error, invalid carry over size: carrylen=%d, toDecode=%d, i=%d", __func__, wsctx->carrylen, toDecode, i);
+ *sockRet = -1;
+ errno = EIO;
+ return WS_HYBI_STATE_ERR;
+ }
+ rfbLog("carrying over %d bytes from %p to %p\n", wsctx->carrylen, wsctx->writePos + (i * 4), wsctx->carryBuf);
+ memcpy(wsctx->carryBuf, data + (i * 4), wsctx->carrylen);
+ }
+
+ toReturn = toDecode - wsctx->carrylen;
+
+ switch (wsctx->header.opcode) {
+ case WS_OPCODE_CLOSE:
+
+ /* this data is not returned as payload data */
+ if (hybiWsFrameComplete(wsctx)) {
+ rfbLog("got closure, reason %d\n", WS_NTOH16(((uint16_t *)data)[0]));
+ errno = ECONNRESET;
+ *sockRet = -1;
+ return WS_HYBI_STATE_FRAME_COMPLETE;
+ } else {
+ rfbErr("%s: close reason with long frame not supported", __func__);
+ errno = EIO;
+ *sockRet = -1;
+ return WS_HYBI_STATE_ERR;
+ }
+ break;
+ case WS_OPCODE_TEXT_FRAME:
+ data[toReturn] = '\0';
+ rfbLog("Initiate Base64 decoding in %p with max size %d and '\\0' at %p\n", data, bufsize, data + toReturn);
+ if (-1 == (wsctx->readlen = __b64_pton((char *)data, data, bufsize))) {
+ rfbErr("Base64 decode error in %s; data=%p bufsize=%d", __func__, data, bufsize);
+ rfbErr("%s: Base64 decode error; %m\n", __func__);
+ }
+ wsctx->writePos = hybiPayloadStart(wsctx);
+ break;
+ case WS_OPCODE_BINARY_FRAME:
+ wsctx->readlen = toReturn;
+ wsctx->writePos = hybiPayloadStart(wsctx);
+ break;
+ default:
+ rfbErr("%s: unhandled opcode %d, b0: %02x, b1: %02x\n", __func__, (int)wsctx->header.opcode, wsctx->header.data->b0, wsctx->header.data->b1);
+ }
+ wsctx->readPos = data;
+
+ return hybiReturnData(dst, len, wsctx, sockRet);
+}
+
+/**
+ * Read function for websocket-socket emulation.
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-------+-+-------------+-------------------------------+
+ * |F|R|R|R| opcode|M| Payload len | Extended payload length |
+ * |I|S|S|S| (4) |A| (7) | (16/64) |
+ * |N|V|V|V| |S| | (if payload len==126/127) |
+ * | |1|2|3| |K| | |
+ * +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+ * | Extended payload length continued, if payload len == 127 |
+ * + - - - - - - - - - - - - - - - +-------------------------------+
+ * | |Masking-key, if MASK set to 1 |
+ * +-------------------------------+-------------------------------+
+ * | Masking-key (continued) | Payload Data |
+ * +-------------------------------- - - - - - - - - - - - - - - - +
+ * : Payload Data continued ... :
+ * + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+ * | Payload Data continued ... |
+ * +---------------------------------------------------------------+
+ *
+ * Using the decode buffer, this function:
+ * - reads the complete header from the underlying socket
+ * - reads any remaining data bytes
+ * - unmasks the payload data using the provided mask
+ * - decodes Base64 encoded text data
+ * - copies len bytes of decoded payload data into dst
+ *
+ * Emulates a read call on a socket.
+ */
+static int
+webSocketsDecodeHybi(rfbClientPtr cl, char *dst, int len)
+{
+ int result = -1;
+ ws_ctx_t *wsctx = (ws_ctx_t *)cl->wsctx;
+ /* int fin; */ /* not used atm */
+
+ /* rfbLog(" <== %s[%d]: %d cl: %p, wsctx: %p-%p (%d)\n", __func__, gettid(), len, cl, wsctx, (char *)wsctx + sizeof(ws_ctx_t), sizeof(ws_ctx_t)); */
+ rfbLog("%s_enter: len=%d; "
+ "CTX: readlen=%d readPos=%p "
+ "writeTo=%p "
+ "state=%d toRead=%d remaining=%d "
+ " nReadRaw=%d carrylen=%d carryBuf=%p\n",
+ __func__, len,
+ wsctx->readlen, wsctx->readPos,
+ wsctx->writePos,
+ wsctx->hybiDecodeState, wsctx->nToRead, hybiRemaining(wsctx),
+ wsctx->nReadRaw, wsctx->carrylen, wsctx->carryBuf);
+
+ switch (wsctx->hybiDecodeState){
+ case WS_HYBI_STATE_HEADER_PENDING:
+ wsctx->hybiDecodeState = hybiReadHeader(cl, &result);
+ if (wsctx->hybiDecodeState == WS_HYBI_STATE_ERR) {
+ goto spor;
+ }
+ if (wsctx->hybiDecodeState != WS_HYBI_STATE_HEADER_PENDING) {
+
+ /* when header is complete, try to read some more data */
+ wsctx->hybiDecodeState = hybiReadAndDecode(cl, dst, len, &result);
+ }
+ break;
+ case WS_HYBI_STATE_DATA_AVAILABLE:
+ wsctx->hybiDecodeState = hybiReturnData(dst, len, wsctx, &result);
+ break;
+ case WS_HYBI_STATE_DATA_NEEDED:
+ wsctx->hybiDecodeState = hybiReadAndDecode(cl, dst, len, &result);
+ break;
+ case WS_HYBI_STATE_CLOSE_REASON_PENDING:
+ wsctx->hybiDecodeState = hybiReadAndDecode(cl, dst, len, &result);
+ break;
default:
- rfbErr("%s: unhandled opcode %d, b0: %02x, b1: %02x\n", __func__, (int)opcode, header->b0, header->b1);
+ /* invalid state */
+ rfbErr("%s: called with invalid state %d\n", wsctx->hybiDecodeState);
+ result = -1;
+ errno = EIO;
+ wsctx->hybiDecodeState = WS_HYBI_STATE_ERR;
}
/* single point of return, if someone has questions :-) */
spor:
/* rfbLog("%s: ret: %d/%d\n", __func__, result, len); */
+ if (wsctx->hybiDecodeState == WS_HYBI_STATE_FRAME_COMPLETE) {
+ rfbLog("frame received successfully, cleaning up: read=%d hlen=%d plen=%d\n", wsctx->header.nRead, wsctx->header.headerLen, wsctx->header.payloadLen);
+ /* frame finished, cleanup state */
+ hybiDecodeCleanup(wsctx);
+ } else if (wsctx->hybiDecodeState == WS_HYBI_STATE_ERR) {
+ hybiDecodeCleanup(wsctx);
+ }
+ rfbLog("%s_exit: len=%d; "
+ "CTX: readlen=%d readPos=%p "
+ "writePos=%p "
+ "state=%d toRead=%d remaining=%d "
+ "nRead=%d carrylen=%d carryBuf=%p "
+ "result=%d\n",
+ __func__, len,
+ wsctx->readlen, wsctx->readPos,
+ wsctx->writePos,
+ wsctx->hybiDecodeState, wsctx->nToRead, hybiRemaining(wsctx),
+ wsctx->nReadRaw, wsctx->carrylen, wsctx->carryBuf,
+ result);
return result;
}
@@ -924,7 +1255,7 @@ webSocketsHasDataInBuffer(rfbClientPtr c
{
ws_ctx_t *wsctx = (ws_ctx_t *)cl->wsctx;
- if (wsctx && wsctx->readbuflen)
+ if (wsctx && wsctx->readlen)
return TRUE;
return (cl->sslctx && rfbssl_pending(cl) > 0);

@ -0,0 +1,35 @@
From d87d25516b3992e52cf79e3cd6bd331b0baceecf Mon Sep 17 00:00:00 2001
From: Christian Beier <dontmind@freeshell.org>
Date: Sun, 17 Nov 2019 16:21:18 +0100
Subject: [PATCH] When connecting to a repeater, make sure to not leak memory
Really closes #253
---
examples/repeater.c | 1 +
libvncclient/rfbproto.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/examples/repeater.c b/examples/repeater.c
index cf0350ff..7047578d 100644
--- a/examples/repeater.c
+++ b/examples/repeater.c
@@ -23,6 +23,7 @@ int main(int argc,char** argv)
"Usage: %s <id> <repeater-host> [<repeater-port>]\n", argv[0]);
exit(1);
}
+ memset(id, 0, sizeof(id));
snprintf(id, sizeof(id) - 1, "ID:%s", argv[1]);
repeaterHost = argv[2];
repeaterPort = argc < 4 ? 5500 : atoi(argv[3]);
diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c
index 6c07d97e..675248fa 100644
--- a/libvncclient/rfbproto.c
+++ b/libvncclient/rfbproto.c
@@ -402,6 +402,7 @@ rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int rep
rfbClientLog("Connected to VNC repeater, using protocol version %d.%d\n", major, minor);
+ memset(tmphost, 0, sizeof(tmphost));
snprintf(tmphost, sizeof(tmphost), "%s:%d", destHost, destPort);
if (!WriteToRFBServer(client, tmphost, sizeof(tmphost)))
return FALSE;

@ -0,0 +1,25 @@
From 3fd03977c9b35800d73a865f167338cb4d05b0c1 Mon Sep 17 00:00:00 2001
From: Christian Beier <dontmind@freeshell.org>
Date: Sat, 6 Apr 2019 20:23:12 +0200
Subject: [PATCH] libvncclient: bail out if unix socket name would overflow
Closes #291
---
libvncclient/sockets.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libvncclient/sockets.c b/libvncclient/sockets.c
index f042472f..821f85ca 100644
--- a/libvncclient/sockets.c
+++ b/libvncclient/sockets.c
@@ -461,6 +461,10 @@ ConnectClientToUnixSock(const char *sockFile)
int sock;
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
+ if(strlen(sockFile) + 1 > sizeof(addr.sun_path)) {
+ rfbClientErr("ConnectToUnixSock: socket file name too long\n");
+ return -1;
+ }
strcpy(addr.sun_path, sockFile);
sock = socket(AF_UNIX, SOCK_STREAM, 0);

@ -0,0 +1,40 @@
Backport of:
From 0cf1400c61850065de590d403f6d49e32882fd76 Mon Sep 17 00:00:00 2001
From: Rolf Eike Beer <eike@sf-mail.de>
Date: Tue, 28 May 2019 18:30:46 +0200
Subject: [PATCH] fix crash because of unaligned accesses in
hybiReadAndDecode()
[Ubuntu note: patch backported to apply on libvncserver/websockets.c instead of
libvncserver/ws_decode.c
-- Avital]
---
libvncserver/ws_decode.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
--- a/libvncserver/websockets.c
+++ b/libvncserver/websockets.c
@@ -880,7 +880,6 @@ hybiReadAndDecode(rfbClientPtr cl, char
int bufsize;
int nextRead;
unsigned char *data;
- uint32_t *data32;
ws_ctx_t *wsctx = (ws_ctx_t *)cl->wsctx;
/* if data was carried over, copy to start of buffer */
@@ -938,10 +937,12 @@ hybiReadAndDecode(rfbClientPtr cl, char
/* for a possible base64 decoding, we decode multiples of 4 bytes until
* the whole frame is received and carry over any remaining bytes in the carry buf*/
data = (unsigned char *)hybiPayloadStart(wsctx);
- data32= (uint32_t *)data;
for (i = 0; i < (toDecode >> 2); i++) {
- data32[i] ^= wsctx->header.mask.u;
+ uint32_t tmp;
+ memcpy(&tmp, data + i * sizeof(tmp), sizeof(tmp));
+ tmp ^= wsctx->header.mask.u;
+ memcpy(data + i * sizeof(tmp), &tmp, sizeof(tmp));
}
rfbLog("mask decoding; i=%d toDecode=%d\n", i, toDecode);

@ -0,0 +1,80 @@
From 416d7662a3f3ac5131014c6011bf1364d57a27e2 Mon Sep 17 00:00:00 2001
From: Tobias Junghans <tobydox@veyon.io>
Date: Tue, 3 Nov 2020 13:58:36 -0600
Subject: [PATCH] libvncserver: add missing NULL pointer checks
---
libvncserver/rfbregion.c | 26 ++++++++++++++++----------
libvncserver/rfbserver.c | 4 +++-
2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/libvncserver/rfbregion.c b/libvncserver/rfbregion.c
index 1947d7c4..1e59646a 100644
--- a/libvncserver/rfbregion.c
+++ b/libvncserver/rfbregion.c
@@ -50,24 +50,30 @@ sraSpanDup(const sraSpan *src) {
static void
sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) {
- newspan->_next = after->_next;
- newspan->_prev = after;
- after->_next->_prev = newspan;
- after->_next = newspan;
+ if (newspan && after) {
+ newspan->_next = after->_next;
+ newspan->_prev = after;
+ after->_next->_prev = newspan;
+ after->_next = newspan;
+ }
}
static void
sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) {
- newspan->_next = before;
- newspan->_prev = before->_prev;
- before->_prev->_next = newspan;
- before->_prev = newspan;
+ if (newspan && before) {
+ newspan->_next = before;
+ newspan->_prev = before->_prev;
+ before->_prev->_next = newspan;
+ before->_prev = newspan;
+ }
}
static void
sraSpanRemove(sraSpan *span) {
- span->_prev->_next = span->_next;
- span->_next->_prev = span->_prev;
+ if (span) {
+ span->_prev->_next = span->_next;
+ span->_next->_prev = span->_prev;
+ }
}
static void
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index 1b4dd975..1f4230f2 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -218,6 +218,8 @@ rfbClientIteratorHead(rfbClientIteratorPtr i)
rfbClientPtr
rfbClientIteratorNext(rfbClientIteratorPtr i)
{
+ if (!i)
+ return NULL;
if(i->next == 0) {
LOCK(rfbClientListMutex);
i->next = i->screen->clientHead;
@@ -242,7 +244,7 @@ rfbClientIteratorNext(rfbClientIteratorPtr i)
void
rfbReleaseClientIterator(rfbClientIteratorPtr iterator)
{
- IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next));
+ IF_PTHREADS(if(iterator && iterator->next) rfbDecrClientRef(iterator->next));
free(iterator);
}
--
2.28.0

@ -0,0 +1,38 @@
From 483dd0834167b86833ec6d756168b426ff8b4304 Mon Sep 17 00:00:00 2001
From: Christian Beier <dontmind@freeshell.org>
Date: Tue, 3 Nov 2020 13:44:14 -0600
Subject: [PATCH] libvncclient/rfbproto: limit max textchat size
Addresses GitHub Security Lab (GHSL) Vulnerability Report
`GHSL-2020-063`.
Re #275
---
libvncclient/rfbproto.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c
index 94751a22..7ba00b55 100644
--- a/libvncclient/rfbproto.c
+++ b/libvncclient/rfbproto.c
@@ -73,6 +73,8 @@
# define snprintf _snprintf /* MSVC went straight to the underscored syntax */
#endif
+#define MAX_TEXTCHAT_SIZE 10485760 /* 10MB */
+
/*
* rfbClientLog prints a time-stamped message to the log file (stderr).
*/
@@ -2285,6 +2287,8 @@ HandleRFBServerMessage(rfbClient* client)
client->HandleTextChat(client, (int)rfbTextChatFinished, NULL);
break;
default:
+ if(msg.tc.length > MAX_TEXTCHAT_SIZE)
+ return FALSE;
buffer=malloc(msg.tc.length+1);
if (!ReadFromRFBServer(client, buffer, msg.tc.length))
{
--
2.28.0

@ -0,0 +1,24 @@
From 673c07a75ed844d74676f3ccdcfdc706a7052dba Mon Sep 17 00:00:00 2001
From: Christian Beier <dontmind@freeshell.org>
Date: Sun, 17 May 2020 13:47:21 +0200
Subject: [PATCH] libvncserver/rfbserver: fix possible divide-by-zero
Closes #409
---
libvncserver/rfbserver.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index 269a0137..9cc29c52 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -3369,6 +3369,9 @@ rfbSendRectEncodingRaw(rfbClientPtr cl,
char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y)
+ (x * (cl->scaledScreen->bitsPerPixel / 8)));
+ if(!h || !w)
+ return TRUE; /* nothing to send */
+
/* Flush the buffer to guarantee correct alignment for translateFn(). */
if (cl->ublen > 0) {
if (!rfbSendUpdateBuf(cl))

@ -0,0 +1,82 @@
From d9a832a2edbf95d664b07791f77a22ac3dfb95f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Thu, 10 Jan 2019 12:11:04 +0100
Subject: [PATCH] Fix CVE-2018-15127 (Heap out-of-bounds write in
rfbserver.c:rfbProcessFileTransferReadBuffer())
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch contains the following three upstream patches squashed
together and ported to 0.9.11 version:
commit 502821828ed00b4a2c4bef90683d0fd88ce495de
Author: Christian Beier <dontmind@freeshell.org>
Date: Sun Oct 21 20:21:30 2018 +0200
LibVNCServer: fix heap out-of-bound write access
Closes #243
commit 15bb719c03cc70f14c36a843dcb16ed69b405707
Author: Christian Beier <dontmind@freeshell.org>
Date: Sun Jan 6 15:13:56 2019 +0100
Error out in rfbProcessFileTransferReadBuffer if length can not be allocated
re #273
commit 09e8fc02f59f16e2583b34fe1a270c238bd9ffec
Author: Petr Písař <ppisar@redhat.com>
Date: Mon Jan 7 10:40:01 2019 +0100
Limit lenght to INT_MAX bytes in rfbProcessFileTransferReadBuffer()
This ammends 15bb719c03cc70f14c36a843dcb16ed69b405707 fix for a heap
out-of-bound write access in rfbProcessFileTransferReadBuffer() when
reading a transfered file content in a server. The former fix did not
work on platforms with a 32-bit int type (expected by rfbReadExact()).
CVE-2018-15127
<https://github.com/LibVNC/libvncserver/issues/243>
<https://github.com/LibVNC/libvncserver/issues/273>
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libvncserver/rfbserver.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index b50a7f4..1b4dd97 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -1471,11 +1471,24 @@ char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length)
int n=0;
FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, NULL);
+
/*
- rfbLog("rfbProcessFileTransferReadBuffer(%dlen)\n", length);
+ We later alloc length+1, which might wrap around on 32-bit systems if length equals
+ 0XFFFFFFFF, i.e. SIZE_MAX for 32-bit systems. On 64-bit systems, a length of 0XFFFFFFFF
+ will safely be allocated since this check will never trigger and malloc() can digest length+1
+ without problems as length is a uint32_t.
+ We also later pass length to rfbReadExact() that expects a signed int type and
+ that might wrap on platforms with a 32-bit int type if length is bigger
+ than 0X7FFFFFFF.
*/
+ if(length == SIZE_MAX || length > INT_MAX) {
+ rfbErr("rfbProcessFileTransferReadBuffer: too big file transfer length requested: %u", (unsigned int)length);
+ rfbCloseClient(cl);
+ return NULL;
+ }
+
if (length>0) {
- buffer=malloc(length+1);
+ buffer=malloc((size_t)length+1);
if (buffer!=NULL) {
if ((n = rfbReadExact(cl, (char *)buffer, length)) <= 0) {
if (n != 0)
--
2.17.2

@ -0,0 +1,40 @@
From e7d578afbb16592ccee8f13aedd65b2220e220ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Tue, 6 Mar 2018 11:58:02 +0100
Subject: [PATCH] Limit client cut text length to 1 MB
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch constrains client text length to 1 MB. Otherwise a client
could make server allocate 2 GB of memory and that seems to be to much
to classify it as denial of service.
I keep the previous checks for maximal type values intentionally as
a course of defensive coding. (You cannot never know how small the
types are. And as a warning for people patching out this change not to
introduce CVE-2018-7225 again.)
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libvncserver/rfbserver.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index a9561fc..0027343 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -2587,7 +2587,9 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
* argument. Here we check that the value fits into all of them to
* prevent from misinterpretation and thus from accessing uninitialized
* memory. CVE-2018-7225 */
- if (msg.cct.length > SIZE_MAX || msg.cct.length > INT_MAX - sz_rfbClientCutTextMsg) {
+ /* But first to prevent from a denial-of-service by allocating to much
+ * memory in the server, we impose a limit of 1 MB. */
+ if (msg.cct.length > 1<<20 || msg.cct.length > SIZE_MAX || msg.cct.length > INT_MAX - sz_rfbClientCutTextMsg) {
rfbLog("rfbClientCutText: too big cut text length requested: %" PRIu32 "\n",
msg.cct.length);
rfbCloseClient(cl);
--
2.13.6

@ -0,0 +1,76 @@
From 0073e4f694d5a51bb72ff12a5e8364b6e752e094 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Mon, 26 Feb 2018 13:48:00 +0100
Subject: [PATCH] Validate client cut text length
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Client-provided unsigned 32-bit cut text length is passed to various
functions that expects argument of a different type.
E.g. "RFB 003.003\n\001\006\0\0\0\xff\xff\xff\xff" string sent to the
RFB server leads to 4294967295 msg.cct.length value that in turn is
interpreted as -1 by rfbReadExact() and thus uninitialized str buffer
with potentially sensitive data is passed to subsequent functions.
This patch fixes it by checking for a maximal value that still can be
processed correctly. It also corrects accepting length value of zero
(malloc(0) is interpreted on differnet systems differently).
Whether a client can make the server allocate up to 2 GB and cause
a denial of service on memory-tight systems is kept without answer.
A possible solution would be adding an arbitrary memory limit that is
deemed safe.
CVE-2018-7225
<https://github.com/LibVNC/libvncserver/issues/218>
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libvncserver/rfbserver.c | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index 116c488..a9561fc 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -88,6 +88,12 @@
#include <errno.h>
/* strftime() */
#include <time.h>
+/* SIZE_MAX */
+#include <stdint.h>
+/* PRIu32 */
+#include <inttypes.h>
+/* INT_MAX */
+#include <limits.h>
#ifdef LIBVNCSERVER_WITH_WEBSOCKETS
#include "rfbssl.h"
@@ -2575,7 +2581,21 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
msg.cct.length = Swap32IfLE(msg.cct.length);
- str = (char *)malloc(msg.cct.length);
+ /* uint32_t input is passed to malloc()'s size_t argument,
+ * to rfbReadExact()'s int argument, to rfbStatRecordMessageRcvd()'s int
+ * argument increased of sz_rfbClientCutTextMsg, and to setXCutText()'s int
+ * argument. Here we check that the value fits into all of them to
+ * prevent from misinterpretation and thus from accessing uninitialized
+ * memory. CVE-2018-7225 */
+ if (msg.cct.length > SIZE_MAX || msg.cct.length > INT_MAX - sz_rfbClientCutTextMsg) {
+ rfbLog("rfbClientCutText: too big cut text length requested: %" PRIu32 "\n",
+ msg.cct.length);
+ rfbCloseClient(cl);
+ return;
+ }
+
+ /* Allow zero-length client cut text. */
+ str = (char *)malloc(msg.cct.length ? msg.cct.length : 1);
if (str == NULL) {
rfbLogPerror("rfbProcessClientNormalMessage: not enough memory");
rfbCloseClient(cl);
--
2.13.6

@ -0,0 +1,44 @@
From 54220248886b5001fbbb9fa73c4e1a2cb9413fed Mon Sep 17 00:00:00 2001
From: Christian Beier <dontmind@freeshell.org>
Date: Sun, 17 Nov 2019 17:18:35 +0100
Subject: [PATCH] libvncclient/cursor: limit width/height input values
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Avoids a possible heap overflow reported by Pavel Cheremushkin
<Pavel.Cheremushkin@kaspersky.com>.
re #275
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libvncclient/cursor.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/libvncclient/cursor.c b/libvncclient/cursor.c
index 67f45726..40ffb3b0 100644
--- a/libvncclient/cursor.c
+++ b/libvncclient/cursor.c
@@ -28,6 +28,8 @@
#define OPER_SAVE 0
#define OPER_RESTORE 1
+#define MAX_CURSOR_SIZE 1024
+
#define RGB24_TO_PIXEL(bpp,r,g,b) \
((((uint##bpp##_t)(r) & 0xFF) * client->format.redMax + 127) / 255 \
<< client->format.redShift | \
@@ -54,6 +56,9 @@ rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int h
if (width * height == 0)
return TRUE;
+ if (width >= MAX_CURSOR_SIZE || height >= MAX_CURSOR_SIZE)
+ return FALSE;
+
/* Allocate memory for pixel data and temporary mask data. */
if(client->rcSource)
free(client->rcSource);
--
2.21.1

@ -0,0 +1,22 @@
diff -up libvncserver-LibVNCServer-0.9.11/libvncclient/Makefile.am.soname libvncserver-LibVNCServer-0.9.11/libvncclient/Makefile.am
--- libvncserver-LibVNCServer-0.9.11/libvncclient/Makefile.am.soname 2017-05-16 10:21:51.500768946 -0500
+++ libvncserver-LibVNCServer-0.9.11/libvncclient/Makefile.am 2017-05-17 11:26:44.383312391 -0500
@@ -25,5 +25,5 @@ EXTRA_DIST=corre.c hextile.c rre.c tight
$(libvncclient_la_OBJECTS): ../rfb/rfbclient.h
lib_LTLIBRARIES=libvncclient.la
-libvncclient_la_LDFLAGS = -version-info 1:0:0
+libvncclient_la_LDFLAGS = -version-info 0:0:0
diff -up libvncserver-LibVNCServer-0.9.11/libvncserver/Makefile.am.soname libvncserver-LibVNCServer-0.9.11/libvncserver/Makefile.am
--- libvncserver-LibVNCServer-0.9.11/libvncserver/Makefile.am.soname 2017-05-16 10:21:51.500768946 -0500
+++ libvncserver-LibVNCServer-0.9.11/libvncserver/Makefile.am 2017-05-17 11:27:02.259459683 -0500
@@ -66,7 +66,7 @@ libvncserver_la_LIBADD += $(LIBSYSTEMD_L
endif
lib_LTLIBRARIES=libvncserver.la
-libvncserver_la_LDFLAGS = -version-info 1:0:0
+libvncserver_la_LDFLAGS = -version-info 0:0:0
if HAVE_RPM
$(PACKAGE)-$(VERSION).tar.gz: dist

@ -0,0 +1,55 @@
diff -up libvncserver-LibVNCServer-0.9.11/libvncclient/Makefile.am.system_minilzo libvncserver-LibVNCServer-0.9.11/libvncclient/Makefile.am
--- libvncserver-LibVNCServer-0.9.11/libvncclient/Makefile.am.system_minilzo 2017-02-14 10:54:54.308402791 -0600
+++ libvncserver-LibVNCServer-0.9.11/libvncclient/Makefile.am 2017-02-14 10:56:28.007379315 -0600
@@ -13,8 +13,8 @@ endif
endif
-libvncclient_la_SOURCES=cursor.c listen.c rfbproto.c sockets.c vncviewer.c ../common/minilzo.c $(TLSSRCS)
-libvncclient_la_LIBADD=$(TLSLIBS)
+libvncclient_la_SOURCES=cursor.c listen.c rfbproto.c sockets.c vncviewer.c $(TLSSRCS)
+libvncclient_la_LIBADD=$(TLSLIBS) -lminilzo
noinst_HEADERS=../common/lzodefs.h ../common/lzoconf.h ../common/minilzo.h tls.h
diff -up libvncserver-LibVNCServer-0.9.11/libvncclient/rfbproto.c.system_minilzo libvncserver-LibVNCServer-0.9.11/libvncclient/rfbproto.c
--- libvncserver-LibVNCServer-0.9.11/libvncclient/rfbproto.c.system_minilzo 2016-12-30 07:01:28.000000000 -0600
+++ libvncserver-LibVNCServer-0.9.11/libvncclient/rfbproto.c 2017-02-14 10:54:54.309402801 -0600
@@ -66,7 +66,7 @@
#include <gcrypt.h>
#endif
-#include "minilzo.h"
+#include <lzo/minilzo.h>
#include "tls.h"
#ifdef _MSC_VER
diff -up libvncserver-LibVNCServer-0.9.11/libvncserver/Makefile.am.system_minilzo libvncserver-LibVNCServer-0.9.11/libvncserver/Makefile.am
--- libvncserver-LibVNCServer-0.9.11/libvncserver/Makefile.am.system_minilzo 2017-02-14 10:54:54.309402801 -0600
+++ libvncserver-LibVNCServer-0.9.11/libvncserver/Makefile.am 2017-02-14 10:57:28.495009713 -0600
@@ -53,11 +53,11 @@ endif
LIB_SRCS = main.c rfbserver.c rfbregion.c auth.c sockets.c $(WEBSOCKETSSRCS) \
stats.c corre.c hextile.c rre.c translate.c cutpaste.c \
httpd.c cursor.c font.c \
- draw.c selbox.c ../common/d3des.c ../common/vncauth.c cargs.c ../common/minilzo.c ultra.c scale.c \
+ draw.c selbox.c ../common/d3des.c ../common/vncauth.c cargs.c ultra.c scale.c \
$(ZLIBSRCS) $(TIGHTSRCS) $(TIGHTVNCFILETRANSFERSRCS)
libvncserver_la_SOURCES=$(LIB_SRCS)
-libvncserver_la_LIBADD=$(WEBSOCKETSSSLLIBS)
+libvncserver_la_LIBADD=$(WEBSOCKETSSSLLIBS) -lminilzo
if WITH_SYSTEMD
AM_CPPFLAGS += -DLIBVNCSERVER_WITH_SYSTEMD
diff -up libvncserver-LibVNCServer-0.9.11/libvncserver/ultra.c.system_minilzo libvncserver-LibVNCServer-0.9.11/libvncserver/ultra.c
--- libvncserver-LibVNCServer-0.9.11/libvncserver/ultra.c.system_minilzo 2016-12-30 07:01:28.000000000 -0600
+++ libvncserver-LibVNCServer-0.9.11/libvncserver/ultra.c 2017-02-14 10:54:54.309402801 -0600
@@ -8,7 +8,7 @@
*/
#include <rfb/rfb.h>
-#include "minilzo.h"
+#include <lzo/minilzo.h>
/*
* cl->beforeEncBuf contains pixel data in the client's format.

@ -0,0 +1,319 @@
Summary: Library to make writing a VNC server easy
Name: libvncserver
Version: 0.9.11
Release: 17%{?dist}
# NOTE: --with-filetransfer => GPLv2
License: GPLv2+
URL: http://libvnc.github.io/
Source0: https://github.com/LibVNC/libvncserver/archive/LibVNCServer-%{version}.tar.gz
## upstream patches
Patch4: 0040-Ensure-compatibility-with-gtk-vnc-0.7.0.patch
## TLS security type enablement patches
# https://github.com/LibVNC/libvncserver/pull/234
Patch10: 0001-libvncserver-Add-API-to-add-custom-I-O-entry-points.patch
Patch11: 0002-libvncserver-Add-channel-security-handlers.patch
## Add API needed by gnome-remote-desktop to handle settings changes
# rhbz#1684729
Patch12: 0001-auth-Add-API-to-unregister-built-in-security-handler.patch
## downstream patches
Patch100: libvncserver-0.9.11-system_minilzo.patch
Patch101: libvncserver-0.9.1-multilib.patch
Patch102: LibVNCServer-0.9.10-system-crypto-policy.patch
# revert soname bump
Patch103: libvncserver-0.9.11-soname.patch
# 1/2 Fix CVE-2018-7225, bug #1546860
Patch104: libvncserver-0.9.11-Validate-client-cut-text-length.patch
# 2/2 Fix CVE-2018-7225, bug #1546860
Patch105: libvncserver-0.9.11-Limit-client-cut-text-length-to-1-MB.patch
# Fix CVE-2018-15127 (Heap out-of-bounds write in
# rfbserver.c:rfbProcessFileTransferReadBuffer()), bug #1662997, upstream bugs
# <https://github.com/LibVNC/libvncserver/issues/243>
# <https://github.com/LibVNC/libvncserver/issues/273>
# <https://github.com/LibVNC/libvncserver/issues/276>
# fixed in upstream after 0.9.12
Patch106: libvncserver-0.9.11-Fix-CVE-2018-15127-Heap-out-of-bounds-write-in-rfbse.patch
# Fix CVE-2019-15690 (an integer overflow in HandleCursorShape() in a client),
# bug #1814343, <https://github.com/LibVNC/libvncserver/issues/275>,
# in upstream after 0.9.12
Patch107: libvncserver-0.9.11-libvncclient-cursor-limit-width-height-input-values.patch
# https://github.com/LibVNC/libvncserver/commit/aac95a9dcf4bbba87b76c72706c3221a842ca433
Patch108: libvncserver-0.9.11-CVE-2017-18922.patch
# https://github.com/LibVNC/libvncserver/pull/308
Patch109: libvncserver-0.9.11-CVE-2019-20840.patch
# https://github.com/LibVNC/libvncserver/issues/291
Patch110: libvncserver-0.9.11-CVE-2019-20839.patch
# https://github.com/LibVNC/libvncserver/issues/253
Patch111: libvncserver-0.9.11-CVE-2018-21247.patch
# https://github.com/LibVNC/libvncserver/issues/275
Patch112: libvncserver-0.9.11-CVE-2020-14405.patch
# https://github.com/LibVNC/libvncserver/pull/416
Patch113: libvncserver-0.9.11-CVE-2020-14397.patch
# https://github.com/LibVNC/libvncserver/issues/409
Patch114: libvncserver-0.9.11-CVE-2020-25708.patch
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: libgcrypt-devel
BuildRequires: libjpeg-devel
BuildRequires: libtool
BuildRequires: lzo-devel
BuildRequires: lzo-minilzo
BuildRequires: pkgconfig(gnutls)
BuildRequires: pkgconfig(libcrypto)
BuildRequires: pkgconfig(libpng)
BuildRequires: pkgconfig(libssl)
# Additional deps for --with-x11vnc, see https://bugzilla.redhat.com/show_bug.cgi?id=864947
BuildRequires: pkgconfig(avahi-client)
BuildRequires: pkgconfig(ice)
BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(xdamage)
BuildRequires: pkgconfig(xext)
BuildRequires: pkgconfig(xfixes)
BuildRequires: pkgconfig(xi)
BuildRequires: pkgconfig(xinerama)
BuildRequires: pkgconfig(xrandr)
BuildRequires: pkgconfig(xtst)
# For %%check
BuildRequires: xorg-x11-xauth
BuildRequires: zlib-devel
%description
LibVNCServer makes writing a VNC server (or more correctly, a program exporting
a frame-buffer via the Remote Frame Buffer protocol) easy.
It hides the programmer from the tedious task of managing clients and
compression schemata.
%package devel
Summary: Development files for %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
# libvncserver-config deps
Requires: coreutils
%description devel
The %{name}-devel package contains libraries and header files for
developing applications that use %{name}.
%prep
%autosetup -p1 -n %{name}-LibVNCServer-%{version}
# Fix encoding
for file in ChangeLog ; do
mv ${file} ${file}.OLD && \
iconv -f ISO_8859-1 -t UTF8 ${file}.OLD > ${file} && \
touch --reference ${file}.OLD $file
done
# Needed by patch 1 (and to nuke rpath's)
autoreconf -vif
%build
%configure \
--disable-silent-rules \
--disable-static \
--without-filetransfer \
--with-gcrypt \
--with-png \
--with-x11vnc
# Hack to omit unused-direct-shlib-dependencies
sed -i -e 's! -shared ! -Wl,--as-needed\0!g' libtool
make %{?_smp_mflags}
%install
%make_install
# Unpackaged files
rm -fv %{buildroot}%{_bindir}/linuxvnc
rm -fv %{buildroot}%{_libdir}/lib*.a
rm -fv %{buildroot}%{_libdir}/lib*.la
%check
make -C test test ||:
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%files
%license COPYING
%doc AUTHORS ChangeLog NEWS README TODO
%{_libdir}/libvncclient.so.0*
%{_libdir}/libvncserver.so.0*
%files devel
%{_bindir}/libvncserver-config
%{_includedir}/rfb/
%{_libdir}/libvncclient.so
%{_libdir}/libvncserver.so
%{_libdir}/pkgconfig/libvncclient.pc
%{_libdir}/pkgconfig/libvncserver.pc
%changelog
* Tue Nov 24 2020 Michael Catanzaro <mcatanzaro@redhat.com> - 0.9.11-17
- Fix CVE-2020-25708
Resolves: #1898078
* Tue Nov 03 2020 Michael Catanzaro <mcatanzaro@redhat.com> - 0.9.11-16
- Fix CVE-2019-20839
Resolves: #1851032
- Fix CVE-2018-21247
Resolves: #1852516
- Fix CVE-2020-14405
Resolves: #1860527
- Fix CVE-2020-14397
Resolves: #1861152
* Mon Jul 27 2020 Michael Catanzaro <mcatanzaro@redhat.com> - 0.9.11-15
- Fix CVE-2017-18922
Resolves: #1852356
* Wed Mar 18 2020 Petr Pisar <ppisar@redhat.com> - 0.9.11-14
- Fix CVE-2019-15690 (an integer overflow in HandleCursorShape() in a client)
(bug #1814343)
* Thu Nov 28 2019 Jonas Ådahl <jadahl@redhat.com> - 0.9.11-13
- Manually apply new patch
Resolves: #1684729
* Wed Nov 27 2019 Jonas Ådahl <jadahl@redhat.com> - 0.9.11-12
- Add API needed by gnome-remote-desktop to handle settings changes
Resolves: #1684729
* Wed Nov 27 2019 Tomas Pelka <tpelka@redhat.com> - 0.9.11-11
- Enable gating through gnome-remote-desktop for now
Resolves: #1765448
* Wed Nov 27 2019 Jonas Ådahl <jadahl@redhat.com> - 0.9.11-10
- Update TLS security type enablement patches
Resolves: #1765448
* Thu Jan 10 2019 Petr Pisar <ppisar@redhat.com> - 0.9.11-9
- Fix CVE-2018-15127 (Heap out-of-bounds write in
rfbserver.c:rfbProcessFileTransferReadBuffer()) (bug #1662997)
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.11-8
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Tue Jun 19 2018 Jonas Ådahl <jadahl@redhat.com> - 0.9.11-7
- Add API to enable implementing TLS security type
* Mon Feb 26 2018 Petr Pisar <ppisar@redhat.com> - 0.9.11-6
- Fix CVE-2018-7225 (bug #1546860)
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.11-5.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.11-4.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.11-3.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Wed May 17 2017 Rex Dieter <rdieter@fedoraproject.org> - 0.9.11-2.1
- revert soname bump for < f26
* Tue May 16 2017 Rex Dieter <rdieter@fedoraproject.org> - 0.9.11-2
- libvncclient sets +SRP in priority string (#1449605)
- libvncserver blocks gtk-vnc clients >= 0.7.0 (#1451321)
* Tue Feb 14 2017 Rex Dieter <rdieter@fedoraproject.org> - 0.9.11-1
- 0.9.11 (#1421948)
* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.10-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
* Thu Feb 18 2016 Than Ngo <than@redhat.com> - 0.9.10-5
- fix conflict with max() macro with gcc6, which causes build failure in KDE/Qt
like krfb
* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.10-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
* Thu Dec 17 2015 Simone Caronni <negativo17@gmail.com> - 0.9.10-3
- Update crypto policies patch.
* Sat Dec 12 2015 Simone Caronni <negativo17@gmail.com> - 0.9.10-2
- Add patch for using system crypto policies (#1179318).
* Fri Dec 11 2015 Simone Caronni <negativo17@gmail.com> - 0.9.10-1
- Update to official 0.9.10 release, update configure parameters and remove
upstreamed patches.
- Trim changelog.
- Clean up SPEC file.
- Add license macro.
- Remove very old obsolete/provides on pacakge with camel case (LibVNCServer).
* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.9.10-0.7.20140718git9453be42
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
* Thu Sep 25 2014 Rex Dieter <rdieter@fedoraproject.org> 0.9.10-0.6.20140718git9453be42
- Security fixes (#1145878) ...
- CVE-2014-6051 (#1144287)
- CVE-2014-6052 (#1144288)
- CVE-2014-6053 (#1144289)
- CVE-2014-6054 (#1144291)
- CVE-2014-6055 (#1144293)
* Sun Aug 17 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.9.10-0.5.20140718git9453be42
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
* Sun Aug 03 2014 Rex Dieter <rdieter@fedoraproject.org> 0.9.10-0.4.20140718git9453be42
- 20140718git9453be42 snapshot
* Sun Aug 03 2014 Rex Dieter <rdieter@fedoraproject.org> 0.9.10-0.3.20140405git646f844f
- include krfb patches (upstream pull request #16)
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.9.10-0.2.20140405git646f844f
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
* Tue Apr 29 2014 Rex Dieter <rdieter@fedoraproject.org> 0.9.10-0.1.20140405git646f844f
- Update to the latest git commit 646f844 (#1092245)
* Mon Mar 31 2014 Rex Dieter <rdieter@fedoraproject.org> 0.9.9-11
- x11vnc crash when client connect (#972618)
pull in some upstream commits that may help
* Sat Dec 21 2013 Rex Dieter <rdieter@fedoraproject.org> - 0.9.9-10
- include additional dependencies for x11vnc (#864947)
- %%build: --disable-silent-rules
- cleanup spec, drop support for old rpm (el5)
* Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.9.9-9
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
* Tue Jul 23 2013 Rex Dieter <rdieter@fedoraproject.org> 0.9.9-8
- Automagic dependencies, explitictly build --with-gcrypt --with-png (#852660)
* Thu Feb 14 2013 Rex Dieter <rdieter@fedoraproject.org> 0.9.9-7
- pkgconfig love (#854111)
* Thu Feb 14 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.9.9-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
* Fri Jan 18 2013 Adam Tkac <atkac redhat com> - 0.9.9-5
- rebuild due to "jpeg8-ABI" feature drop
* Fri Dec 21 2012 Adam Tkac <atkac redhat com> - 0.9.9-4
- rebuild against new libjpeg
* Thu Jul 26 2012 Rex Dieter <rdieter@fedoraproject.org> 0.9.9-3
- libvncserver fails to build in mock with selinux enabled (#843603)
* Thu Jul 19 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.9.9-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
* Mon May 07 2012 Rex Dieter <rdieter@fedoraproject.org> 0.9.9-1
- 0.9.9
Loading…
Cancel
Save