commit 586007f669b51090b6d4ec734a2699bb219c3079 Author: CentOS Sources Date: Tue May 18 02:40:59 2021 -0400 import libvncserver-0.9.11-17.el8 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..77f3f36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/LibVNCServer-0.9.11.tar.gz diff --git a/.libvncserver.metadata b/.libvncserver.metadata new file mode 100644 index 0000000..01e5bd8 --- /dev/null +++ b/.libvncserver.metadata @@ -0,0 +1 @@ +d844a2c9e69465d104a8468dce515a49e4db9585 SOURCES/LibVNCServer-0.9.11.tar.gz diff --git a/SOURCES/0001-auth-Add-API-to-unregister-built-in-security-handler.patch b/SOURCES/0001-auth-Add-API-to-unregister-built-in-security-handler.patch new file mode 100644 index 0000000..882b993 --- /dev/null +++ b/SOURCES/0001-auth-Add-API-to-unregister-built-in-security-handler.patch @@ -0,0 +1,47 @@ +From b793e8c51ab253c0951e43a84e9d448416462887 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +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 + diff --git a/SOURCES/0001-libvncserver-Add-API-to-add-custom-I-O-entry-points.patch b/SOURCES/0001-libvncserver-Add-API-to-add-custom-I-O-entry-points.patch new file mode 100644 index 0000000..1f7b94c --- /dev/null +++ b/SOURCES/0001-libvncserver-Add-API-to-add-custom-I-O-entry-points.patch @@ -0,0 +1,241 @@ +From fb4b12407e869c3da33df65ed3a43ef87aeae1c4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +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 + diff --git a/SOURCES/0002-libvncserver-Add-channel-security-handlers.patch b/SOURCES/0002-libvncserver-Add-channel-security-handlers.patch new file mode 100644 index 0000000..8b9cca6 --- /dev/null +++ b/SOURCES/0002-libvncserver-Add-channel-security-handlers.patch @@ -0,0 +1,368 @@ +From 5e4d810d62da0f2048ce78b3a7812e9e13968162 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +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 && sizenext) { ++ 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 && sizenext) { ++ 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 + diff --git a/SOURCES/0040-Ensure-compatibility-with-gtk-vnc-0.7.0.patch b/SOURCES/0040-Ensure-compatibility-with-gtk-vnc-0.7.0.patch new file mode 100644 index 0000000..a814328 --- /dev/null +++ b/SOURCES/0040-Ensure-compatibility-with-gtk-vnc-0.7.0.patch @@ -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?= +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 + diff --git a/SOURCES/LibVNCServer-0.9.10-system-crypto-policy.patch b/SOURCES/LibVNCServer-0.9.10-system-crypto-policy.patch new file mode 100644 index 0000000..47d540b --- /dev/null +++ b/SOURCES/LibVNCServer-0.9.10-system-crypto-policy.patch @@ -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))) { + /* */ diff --git a/SOURCES/libvncserver-0.9.1-multilib.patch b/SOURCES/libvncserver-0.9.1-multilib.patch new file mode 100644 index 0000000..d54a470 --- /dev/null +++ b/SOURCES/libvncserver-0.9.1-multilib.patch @@ -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@ diff --git a/SOURCES/libvncserver-0.9.11-CVE-2017-18922.patch b/SOURCES/libvncserver-0.9.11-CVE-2017-18922.patch new file mode 100644 index 0000000..0dca451 --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-CVE-2017-18922.patch @@ -0,0 +1,694 @@ +Backport of: +From aac95a9dcf4bbba87b76c72706c3221a842ca433 Mon Sep 17 00:00:00 2001 +From: Andreas Weigel +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); diff --git a/SOURCES/libvncserver-0.9.11-CVE-2018-21247.patch b/SOURCES/libvncserver-0.9.11-CVE-2018-21247.patch new file mode 100644 index 0000000..1cc92b6 --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-CVE-2018-21247.patch @@ -0,0 +1,35 @@ +From d87d25516b3992e52cf79e3cd6bd331b0baceecf Mon Sep 17 00:00:00 2001 +From: Christian Beier +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 []\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; diff --git a/SOURCES/libvncserver-0.9.11-CVE-2019-20839.patch b/SOURCES/libvncserver-0.9.11-CVE-2019-20839.patch new file mode 100644 index 0000000..1f3b61a --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-CVE-2019-20839.patch @@ -0,0 +1,25 @@ +From 3fd03977c9b35800d73a865f167338cb4d05b0c1 Mon Sep 17 00:00:00 2001 +From: Christian Beier +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); diff --git a/SOURCES/libvncserver-0.9.11-CVE-2019-20840.patch b/SOURCES/libvncserver-0.9.11-CVE-2019-20840.patch new file mode 100644 index 0000000..b32616f --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-CVE-2019-20840.patch @@ -0,0 +1,40 @@ +Backport of: +From 0cf1400c61850065de590d403f6d49e32882fd76 Mon Sep 17 00:00:00 2001 +From: Rolf Eike Beer +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); + diff --git a/SOURCES/libvncserver-0.9.11-CVE-2020-14397.patch b/SOURCES/libvncserver-0.9.11-CVE-2020-14397.patch new file mode 100644 index 0000000..17c3be7 --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-CVE-2020-14397.patch @@ -0,0 +1,80 @@ +From 416d7662a3f3ac5131014c6011bf1364d57a27e2 Mon Sep 17 00:00:00 2001 +From: Tobias Junghans +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 + diff --git a/SOURCES/libvncserver-0.9.11-CVE-2020-14405.patch b/SOURCES/libvncserver-0.9.11-CVE-2020-14405.patch new file mode 100644 index 0000000..df80cbc --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-CVE-2020-14405.patch @@ -0,0 +1,38 @@ +From 483dd0834167b86833ec6d756168b426ff8b4304 Mon Sep 17 00:00:00 2001 +From: Christian Beier +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 + diff --git a/SOURCES/libvncserver-0.9.11-CVE-2020-25708.patch b/SOURCES/libvncserver-0.9.11-CVE-2020-25708.patch new file mode 100644 index 0000000..7876eec --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-CVE-2020-25708.patch @@ -0,0 +1,24 @@ +From 673c07a75ed844d74676f3ccdcfdc706a7052dba Mon Sep 17 00:00:00 2001 +From: Christian Beier +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)) diff --git a/SOURCES/libvncserver-0.9.11-Fix-CVE-2018-15127-Heap-out-of-bounds-write-in-rfbse.patch b/SOURCES/libvncserver-0.9.11-Fix-CVE-2018-15127-Heap-out-of-bounds-write-in-rfbse.patch new file mode 100644 index 0000000..3140fcb --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-Fix-CVE-2018-15127-Heap-out-of-bounds-write-in-rfbse.patch @@ -0,0 +1,82 @@ +From d9a832a2edbf95d664b07791f77a22ac3dfb95f5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= +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 + Date: Sun Oct 21 20:21:30 2018 +0200 + + LibVNCServer: fix heap out-of-bound write access + + Closes #243 + + commit 15bb719c03cc70f14c36a843dcb16ed69b405707 + Author: Christian Beier + 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ř + 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 + + + +Signed-off-by: Petr Písař +--- + 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 + diff --git a/SOURCES/libvncserver-0.9.11-Limit-client-cut-text-length-to-1-MB.patch b/SOURCES/libvncserver-0.9.11-Limit-client-cut-text-length-to-1-MB.patch new file mode 100644 index 0000000..2a71f7f --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-Limit-client-cut-text-length-to-1-MB.patch @@ -0,0 +1,40 @@ +From e7d578afbb16592ccee8f13aedd65b2220e220ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= +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ř +--- + 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 + diff --git a/SOURCES/libvncserver-0.9.11-Validate-client-cut-text-length.patch b/SOURCES/libvncserver-0.9.11-Validate-client-cut-text-length.patch new file mode 100644 index 0000000..dc89cdf --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-Validate-client-cut-text-length.patch @@ -0,0 +1,76 @@ +From 0073e4f694d5a51bb72ff12a5e8364b6e752e094 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= +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 + + +Signed-off-by: Petr Písař +--- + 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 + /* strftime() */ + #include ++/* SIZE_MAX */ ++#include ++/* PRIu32 */ ++#include ++/* INT_MAX */ ++#include + + #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 + diff --git a/SOURCES/libvncserver-0.9.11-libvncclient-cursor-limit-width-height-input-values.patch b/SOURCES/libvncserver-0.9.11-libvncclient-cursor-limit-width-height-input-values.patch new file mode 100644 index 0000000..87edf44 --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-libvncclient-cursor-limit-width-height-input-values.patch @@ -0,0 +1,44 @@ +From 54220248886b5001fbbb9fa73c4e1a2cb9413fed Mon Sep 17 00:00:00 2001 +From: Christian Beier +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 +. + +re #275 + +Signed-off-by: Petr Písař +--- + 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 + diff --git a/SOURCES/libvncserver-0.9.11-soname.patch b/SOURCES/libvncserver-0.9.11-soname.patch new file mode 100644 index 0000000..3b45b34 --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-soname.patch @@ -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 diff --git a/SOURCES/libvncserver-0.9.11-system_minilzo.patch b/SOURCES/libvncserver-0.9.11-system_minilzo.patch new file mode 100644 index 0000000..c513c40 --- /dev/null +++ b/SOURCES/libvncserver-0.9.11-system_minilzo.patch @@ -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 + #endif + +-#include "minilzo.h" ++#include + #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 +-#include "minilzo.h" ++#include + + /* + * cl->beforeEncBuf contains pixel data in the client's format. diff --git a/SPECS/libvncserver.spec b/SPECS/libvncserver.spec new file mode 100644 index 0000000..a913ff6 --- /dev/null +++ b/SPECS/libvncserver.spec @@ -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 +# +# +# +# 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, , +# 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 - 0.9.11-17 +- Fix CVE-2020-25708 + Resolves: #1898078 + +* Tue Nov 03 2020 Michael Catanzaro - 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 - 0.9.11-15 +- Fix CVE-2017-18922 + Resolves: #1852356 + +* Wed Mar 18 2020 Petr Pisar - 0.9.11-14 +- Fix CVE-2019-15690 (an integer overflow in HandleCursorShape() in a client) + (bug #1814343) + +* Thu Nov 28 2019 Jonas Ådahl - 0.9.11-13 +- Manually apply new patch + Resolves: #1684729 + +* Wed Nov 27 2019 Jonas Ådahl - 0.9.11-12 +- Add API needed by gnome-remote-desktop to handle settings changes + Resolves: #1684729 + +* Wed Nov 27 2019 Tomas Pelka - 0.9.11-11 +- Enable gating through gnome-remote-desktop for now + Resolves: #1765448 + +* Wed Nov 27 2019 Jonas Ådahl - 0.9.11-10 +- Update TLS security type enablement patches + Resolves: #1765448 + +* Thu Jan 10 2019 Petr Pisar - 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 - 0.9.11-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Tue Jun 19 2018 Jonas Ådahl - 0.9.11-7 +- Add API to enable implementing TLS security type + +* Mon Feb 26 2018 Petr Pisar - 0.9.11-6 +- Fix CVE-2018-7225 (bug #1546860) + +* Wed Feb 07 2018 Fedora Release Engineering - 0.9.11-5.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Aug 03 2017 Fedora Release Engineering - 0.9.11-4.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 0.9.11-3.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed May 17 2017 Rex Dieter - 0.9.11-2.1 +- revert soname bump for < f26 + +* Tue May 16 2017 Rex Dieter - 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 - 0.9.11-1 +- 0.9.11 (#1421948) + +* Fri Feb 10 2017 Fedora Release Engineering - 0.9.10-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Feb 18 2016 Than Ngo - 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 - 0.9.10-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Dec 17 2015 Simone Caronni - 0.9.10-3 +- Update crypto policies patch. + +* Sat Dec 12 2015 Simone Caronni - 0.9.10-2 +- Add patch for using system crypto policies (#1179318). + +* Fri Dec 11 2015 Simone Caronni - 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 - 0.9.10-0.7.20140718git9453be42 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Thu Sep 25 2014 Rex Dieter 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 - 0.9.10-0.5.20140718git9453be42 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sun Aug 03 2014 Rex Dieter 0.9.10-0.4.20140718git9453be42 +- 20140718git9453be42 snapshot + +* Sun Aug 03 2014 Rex Dieter 0.9.10-0.3.20140405git646f844f +- include krfb patches (upstream pull request #16) + +* Sat Jun 07 2014 Fedora Release Engineering - 0.9.10-0.2.20140405git646f844f +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue Apr 29 2014 Rex Dieter 0.9.10-0.1.20140405git646f844f +- Update to the latest git commit 646f844 (#1092245) + +* Mon Mar 31 2014 Rex Dieter 0.9.9-11 +- x11vnc crash when client connect (#972618) + pull in some upstream commits that may help + +* Sat Dec 21 2013 Rex Dieter - 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 - 0.9.9-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Tue Jul 23 2013 Rex Dieter 0.9.9-8 +- Automagic dependencies, explitictly build --with-gcrypt --with-png (#852660) + +* Thu Feb 14 2013 Rex Dieter 0.9.9-7 +- pkgconfig love (#854111) + +* Thu Feb 14 2013 Fedora Release Engineering - 0.9.9-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Fri Jan 18 2013 Adam Tkac - 0.9.9-5 +- rebuild due to "jpeg8-ABI" feature drop + +* Fri Dec 21 2012 Adam Tkac - 0.9.9-4 +- rebuild against new libjpeg + +* Thu Jul 26 2012 Rex Dieter 0.9.9-3 +- libvncserver fails to build in mock with selinux enabled (#843603) + +* Thu Jul 19 2012 Fedora Release Engineering - 0.9.9-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Mon May 07 2012 Rex Dieter 0.9.9-1 +- 0.9.9