diff options
Diffstat (limited to '0002-libvncserver-Add-channel-security-handlers.patch')
-rw-r--r-- | 0002-libvncserver-Add-channel-security-handlers.patch | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/0002-libvncserver-Add-channel-security-handlers.patch b/0002-libvncserver-Add-channel-security-handlers.patch new file mode 100644 index 0000000..eb2aa9f --- /dev/null +++ b/0002-libvncserver-Add-channel-security-handlers.patch @@ -0,0 +1,368 @@ +From c9131a78878a785c3de21e9d49521d7b68400ad7 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/4] 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 72e9ba79..48eada64 100644 +--- a/libvncserver/rfbserver.c ++++ b/libvncserver/rfbserver.c +@@ -652,6 +652,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 3c0b25a3..d136f884 100644 +--- a/rfb/rfb.h ++++ b/rfb/rfb.h +@@ -144,6 +144,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) + */ +@@ -152,6 +157,7 @@ typedef struct _rfbSecurity { + uint8_t type; + void (*handler)(struct _rfbClientRec* cl); + struct _rfbSecurity* next; ++ enum rfbSecurityTag securityTags; + } rfbSecurityHandler; + + /** +@@ -480,7 +486,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 */ +@@ -488,7 +494,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; +@@ -840,6 +848,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.28.0 + |