Skip to content

Commit 30b947d

Browse files
committed
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.
1 parent 450f4a5 commit 30b947d

File tree

3 files changed

+142
-38
lines changed

3 files changed

+142
-38
lines changed

libvncserver/auth.c

Lines changed: 128 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,17 @@ void rfbClientSendString(rfbClientPtr cl, const char *reason);
3737
* Handle security types
3838
*/
3939

40+
/* Channel security handlers to set up a secure channel, e.g. TLS. */
41+
static rfbSecurityHandler* channelSecurityHandlers = NULL;
42+
43+
/* Security handlers when channel security is established. */
4044
static rfbSecurityHandler* securityHandlers = NULL;
4145

42-
/*
43-
* This method registers a list of new security types.
44-
* It avoids same security type getting registered multiple times.
45-
* The order is not preserved if multiple security types are
46-
* registered at one-go.
47-
*/
4846
void
49-
rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
47+
rfbRegisterSecurityHandlerTo(rfbSecurityHandler* handler,
48+
rfbSecurityHandler** handlerList)
5049
{
51-
rfbSecurityHandler *head = securityHandlers, *next = NULL;
50+
rfbSecurityHandler *head = *handlerList, *next = NULL;
5251

5352
if(handler == NULL)
5453
return;
@@ -57,39 +56,35 @@ rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
5756

5857
while(head != NULL) {
5958
if(head == handler) {
60-
rfbRegisterSecurityHandler(next);
59+
rfbRegisterSecurityHandlerTo(next, handlerList);
6160
return;
6261
}
6362

6463
head = head->next;
6564
}
6665

67-
handler->next = securityHandlers;
68-
securityHandlers = handler;
66+
handler->next = *handlerList;
67+
*handlerList = handler;
6968

70-
rfbRegisterSecurityHandler(next);
69+
rfbRegisterSecurityHandlerTo(next, handlerList);
7170
}
7271

73-
/*
74-
* This method unregisters a list of security types.
75-
* These security types won't be available for any new
76-
* client connection.
77-
*/
78-
void
79-
rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
72+
static void
73+
rfbUnregisterSecurityHandlerFrom(rfbSecurityHandler* handler,
74+
rfbSecurityHandler** handlerList)
8075
{
8176
rfbSecurityHandler *cur = NULL, *pre = NULL;
8277

8378
if(handler == NULL)
8479
return;
8580

86-
if(securityHandlers == handler) {
87-
securityHandlers = securityHandlers->next;
88-
rfbUnregisterSecurityHandler(handler->next);
81+
if(*handlerList == handler) {
82+
*handlerList = (*handlerList)->next;
83+
rfbUnregisterSecurityHandlerFrom(handler->next, handlerList);
8984
return;
9085
}
9186

92-
cur = pre = securityHandlers;
87+
cur = pre = *handlerList;
9388

9489
while(cur) {
9590
if(cur == handler) {
@@ -99,7 +94,50 @@ rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
9994
pre = cur;
10095
cur = cur->next;
10196
}
102-
rfbUnregisterSecurityHandler(handler->next);
97+
rfbUnregisterSecurityHandlerFrom(handler->next, handlerList);
98+
}
99+
100+
void
101+
rfbRegisterChannelSecurityHandler(rfbSecurityHandler* handler)
102+
{
103+
rfbRegisterSecurityHandlerTo(handler, &channelSecurityHandlers);
104+
}
105+
106+
/*
107+
* This method unregisters a list of security types.
108+
* These security types won't be available for any new
109+
* client connection.
110+
*/
111+
112+
void
113+
rfbUnregisterChannelSecurityHandler(rfbSecurityHandler* handler)
114+
{
115+
rfbUnregisterSecurityHandlerFrom(handler, &channelSecurityHandlers);
116+
}
117+
118+
/*
119+
* This method registers a list of new security types.
120+
* It avoids same security type getting registered multiple times.
121+
* The order is not preserved if multiple security types are
122+
* registered at one-go.
123+
*/
124+
125+
void
126+
rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
127+
{
128+
rfbRegisterSecurityHandlerTo(handler, &securityHandlers);
129+
}
130+
131+
/*
132+
* This method unregisters a list of security types.
133+
* These security types won't be available for any new
134+
* client connection.
135+
*/
136+
137+
void
138+
rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
139+
{
140+
rfbUnregisterSecurityHandlerFrom(handler, &securityHandlers);
103141
}
104142

105143
/*
@@ -197,19 +235,33 @@ static rfbSecurityHandler VncSecurityHandlerNone = {
197235
NULL
198236
};
199237

238+
static int32_t
239+
determinePrimarySecurityType(rfbClientPtr cl)
240+
{
241+
if (!cl->screen->authPasswdData || cl->reverseConnection) {
242+
/* chk if this condition is valid or not. */
243+
return rfbSecTypeNone;
244+
} else if (cl->screen->authPasswdData) {
245+
return rfbSecTypeVncAuth;
246+
} else {
247+
return rfbSecTypeInvalid;
248+
}
249+
}
200250

201-
static void
202-
rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
251+
void
252+
rfbSendSecurityTypeList(rfbClientPtr cl,
253+
enum rfbSecurityTag exclude)
203254
{
204255
/* The size of the message is the count of security types +1,
205256
* since the first byte is the number of types. */
206257
int size = 1;
207258
rfbSecurityHandler* handler;
208259
#define MAX_SECURITY_TYPES 255
209260
uint8_t buffer[MAX_SECURITY_TYPES+1];
210-
261+
int32_t primaryType;
211262

212263
/* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */
264+
primaryType = determinePrimarySecurityType(cl);
213265
switch (primaryType) {
214266
case rfbSecTypeNone:
215267
rfbRegisterSecurityHandler(&VncSecurityHandlerNone);
@@ -221,6 +273,9 @@ rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
221273

222274
for (handler = securityHandlers;
223275
handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
276+
if (exclude && (handler->securityTags & exclude))
277+
continue;
278+
224279
buffer[size] = handler->type;
225280
size++;
226281
}
@@ -249,7 +304,29 @@ rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
249304
cl->state = RFB_SECURITY_TYPE;
250305
}
251306

307+
static void
308+
rfbSendChannelSecurityTypeList(rfbClientPtr cl)
309+
{
310+
int size = 1;
311+
rfbSecurityHandler* handler;
312+
uint8_t buffer[MAX_SECURITY_TYPES+1];
313+
314+
for (handler = channelSecurityHandlers;
315+
handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
316+
buffer[size] = handler->type;
317+
size++;
318+
}
319+
buffer[0] = (unsigned char)size-1;
320+
321+
if (rfbWriteExact(cl, (char *)buffer, size) < 0) {
322+
rfbLogPerror("rfbSendSecurityTypeList: write");
323+
rfbCloseClient(cl);
324+
return;
325+
}
252326

327+
/* Dispatch client input to rfbProcessClientChannelSecurityType. */
328+
cl->state = RFB_CHANNEL_SECURITY_TYPE;
329+
}
253330

254331

255332
/*
@@ -297,28 +374,33 @@ rfbSendSecurityType(rfbClientPtr cl, int32_t securityType)
297374
void
298375
rfbAuthNewClient(rfbClientPtr cl)
299376
{
300-
int32_t securityType = rfbSecTypeInvalid;
377+
int32_t securityType;
301378

302-
if (!cl->screen->authPasswdData || cl->reverseConnection) {
303-
/* chk if this condition is valid or not. */
304-
securityType = rfbSecTypeNone;
305-
} else if (cl->screen->authPasswdData) {
306-
securityType = rfbSecTypeVncAuth;
307-
}
379+
securityType = determinePrimarySecurityType(cl);
308380

309381
if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7)
310382
{
311383
/* Make sure we use only RFB 3.3 compatible security types. */
384+
if (channelSecurityHandlers) {
385+
rfbLog("VNC channel security enabled - RFB 3.3 client rejected\n");
386+
rfbClientConnFailed(cl, "Your viewer cannot hnadler required "
387+
"security methods");
388+
return;
389+
}
312390
if (securityType == rfbSecTypeInvalid) {
313391
rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n");
314392
rfbClientConnFailed(cl, "Your viewer cannot handle required "
315393
"authentication methods");
316394
return;
317395
}
318396
rfbSendSecurityType(cl, securityType);
397+
} else if (channelSecurityHandlers) {
398+
rfbLog("Send channel security type list\n");
399+
rfbSendChannelSecurityTypeList(cl);
319400
} else {
320401
/* Here it's ok when securityType is set to rfbSecTypeInvalid. */
321-
rfbSendSecurityTypeList(cl, securityType);
402+
rfbLog("Send channel security type 'none'\n");
403+
rfbSendSecurityTypeList(cl, RFB_SECURITY_TAG_NONE);
322404
}
323405
}
324406

@@ -332,6 +414,7 @@ rfbProcessClientSecurityType(rfbClientPtr cl)
332414
int n;
333415
uint8_t chosenType;
334416
rfbSecurityHandler* handler;
417+
rfbSecurityHandler* handlerListHead;
335418

336419
/* Read the security type. */
337420
n = rfbReadExact(cl, (char *)&chosenType, 1);
@@ -344,8 +427,17 @@ rfbProcessClientSecurityType(rfbClientPtr cl)
344427
return;
345428
}
346429

430+
switch (cl->state) {
431+
case RFB_CHANNEL_SECURITY_TYPE:
432+
handlerListHead = channelSecurityHandlers;
433+
break;
434+
case RFB_SECURITY_TYPE:
435+
handlerListHead = securityHandlers;
436+
break;
437+
}
438+
347439
/* Make sure it was present in the list sent by the server. */
348-
for (handler = securityHandlers; handler; handler = handler->next) {
440+
for (handler = handlerListHead; handler; handler = handler->next) {
349441
if (chosenType == handler->type) {
350442
rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType);
351443
handler->handler(cl);

libvncserver/rfbserver.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,7 @@ rfbProcessClientMessage(rfbClientPtr cl)
654654
case RFB_PROTOCOL_VERSION:
655655
rfbProcessClientProtocolVersion(cl);
656656
return;
657+
case RFB_CHANNEL_SECURITY_TYPE:
657658
case RFB_SECURITY_TYPE:
658659
rfbProcessClientSecurityType(cl);
659660
return;

rfb/rfb.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ typedef struct {
144144
} data; /**< there have to be count*3 entries */
145145
} rfbColourMap;
146146

147+
enum rfbSecurityTag {
148+
RFB_SECURITY_TAG_NONE = 0,
149+
RFB_SECURITY_TAG_CHANNEL = 1 << 0
150+
};
151+
147152
/**
148153
* Security handling (RFB protocol version 3.7)
149154
*/
@@ -152,6 +157,7 @@ typedef struct _rfbSecurity {
152157
uint8_t type;
153158
void (*handler)(struct _rfbClientRec* cl);
154159
struct _rfbSecurity* next;
160+
enum rfbSecurityTag securityTags;
155161
} rfbSecurityHandler;
156162

157163
/**
@@ -480,15 +486,17 @@ typedef struct _rfbClientRec {
480486
/** Possible client states: */
481487
enum {
482488
RFB_PROTOCOL_VERSION, /**< establishing protocol version */
483-
RFB_SECURITY_TYPE, /**< negotiating security (RFB v.3.7) */
489+
RFB_SECURITY_TYPE, /**< negotiating security (RFB v.3.7) */
484490
RFB_AUTHENTICATION, /**< authenticating */
485491
RFB_INITIALISATION, /**< sending initialisation messages */
486492
RFB_NORMAL, /**< normal protocol messages */
487493

488494
/* Ephemeral internal-use states that will never be seen by software
489495
* using LibVNCServer to provide services: */
490496

491-
RFB_INITIALISATION_SHARED /**< sending initialisation messages with implicit shared-flag already true */
497+
RFB_INITIALISATION_SHARED, /**< sending initialisation messages with implicit shared-flag already true */
498+
499+
RFB_CHANNEL_SECURITY_TYPE, /**< negotiating security (RFB v.3.7) */
492500
} state;
493501

494502
rfbBool reverseConnection;
@@ -840,6 +848,9 @@ extern void rfbProcessClientSecurityType(rfbClientPtr cl);
840848
extern void rfbAuthProcessClientMessage(rfbClientPtr cl);
841849
extern void rfbRegisterSecurityHandler(rfbSecurityHandler* handler);
842850
extern void rfbUnregisterSecurityHandler(rfbSecurityHandler* handler);
851+
extern void rfbRegisterChannelSecurityHandler(rfbSecurityHandler* handler);
852+
extern void rfbUnregisterChannelSecurityHandler(rfbSecurityHandler* handler);
853+
extern void rfbSendSecurityTypeList(rfbClientPtr cl, enum rfbSecurityTag exclude);
843854

844855
/* rre.c */
845856

0 commit comments

Comments
 (0)