2
* auth.c - deal with authentication.
4
* This file implements the VNC authentication protocol when setting up an RFB
9
* Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
10
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
11
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
12
* All Rights Reserved.
14
* This is free software; you can redistribute it and/or modify
15
* it under the terms of the GNU General Public License as published by
16
* the Free Software Foundation; either version 2 of the License, or
17
* (at your option) any later version.
19
* This software is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this software; if not, write to the Free Software
26
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
32
/* RFB 3.8 clients are well informed */
33
void rfbClientSendString(rfbClientPtr cl, char *reason);
37
* Handle security types
40
static rfbSecurityHandler* securityHandlers = NULL;
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.
49
rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
51
rfbSecurityHandler *head = securityHandlers, *next = NULL;
60
rfbRegisterSecurityHandler(next);
67
handler->next = securityHandlers;
68
securityHandlers = handler;
70
rfbRegisterSecurityHandler(next);
74
* This method unregisters a list of security types.
75
* These security types won't be available for any new
79
rfbUnregisterSecurityHandler(rfbSecurityHandler* handler)
81
rfbSecurityHandler *cur = NULL, *pre = NULL;
86
if(securityHandlers == handler) {
87
securityHandlers = securityHandlers->next;
88
rfbUnregisterSecurityHandler(handler->next);
92
cur = pre = securityHandlers;
96
pre->next = cur->next;
102
rfbUnregisterSecurityHandler(handler->next);
106
* Send the authentication challenge.
110
rfbVncAuthSendChallenge(rfbClientPtr cl)
113
/* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth
114
(same as rfbVncAuth). Just send the challenge. */
115
rfbRandomBytes(cl->authChallenge);
116
if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) {
117
rfbLogPerror("rfbAuthNewClient: write");
122
/* Dispatch client input to rfbVncAuthProcessResponse. */
123
cl->state = RFB_AUTHENTICATION;
127
* Send the NO AUTHENTICATION. SCARR
131
rfbVncAuthNone(rfbClientPtr cl)
135
if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7) {
136
rfbLog("rfbProcessClientSecurityType: returning securityResult for client rfb version >= 3.8\n");
137
authResult = Swap32IfLE(rfbVncAuthOK);
138
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
139
rfbLogPerror("rfbAuthProcessClientMessage: write");
144
cl->state = RFB_INITIALISATION;
150
* Advertise the supported security types (protocol 3.7). Here before sending
151
* the list of security types to the client one more security type is added
152
* to the list if primaryType is not set to rfbSecTypeInvalid. This security
153
* type is the standard vnc security type which does the vnc authentication
154
* or it will be security type for no authentication.
155
* Different security types will be added by applications using this library.
158
static rfbSecurityHandler VncSecurityHandlerVncAuth = {
160
rfbVncAuthSendChallenge,
164
static rfbSecurityHandler VncSecurityHandlerNone = {
172
rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
174
/* The size of the message is the count of security types +1,
175
* since the first byte is the number of types. */
177
rfbSecurityHandler* handler;
178
#define MAX_SECURITY_TYPES 255
179
uint8_t buffer[MAX_SECURITY_TYPES+1];
182
/* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */
183
switch (primaryType) {
185
rfbRegisterSecurityHandler(&VncSecurityHandlerNone);
187
case rfbSecTypeVncAuth:
188
rfbRegisterSecurityHandler(&VncSecurityHandlerVncAuth);
192
for (handler = securityHandlers;
193
handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
194
buffer[size] = handler->type;
197
buffer[0] = (unsigned char)size-1;
200
if (rfbWriteExact(cl, (char *)buffer, size) < 0) {
201
rfbLogPerror("rfbSendSecurityTypeList: write");
207
* if count is 0, we need to send the reason and close the connection.
210
/* This means total count is Zero and so reason msg should be sent */
211
/* The execution should never reach here */
212
char* reason = "No authentication mode is registered!";
214
rfbClientSendString(cl, reason);
218
/* Dispatch client input to rfbProcessClientSecurityType. */
219
cl->state = RFB_SECURITY_TYPE;
226
* Tell the client what security type will be used (protocol 3.3).
229
rfbSendSecurityType(rfbClientPtr cl, int32_t securityType)
233
/* Send the value. */
234
value32 = Swap32IfLE(securityType);
235
if (rfbWriteExact(cl, (char *)&value32, 4) < 0) {
236
rfbLogPerror("rfbSendSecurityType: write");
241
/* Decide what to do next. */
242
switch (securityType) {
244
/* Dispatch client input to rfbProcessClientInitMessage. */
245
cl->state = RFB_INITIALISATION;
247
case rfbSecTypeVncAuth:
248
/* Begin the standard VNC authentication procedure. */
249
rfbVncAuthSendChallenge(cl);
252
/* Impossible case (hopefully). */
253
rfbLogPerror("rfbSendSecurityType: assertion failed");
261
* rfbAuthNewClient is called right after negotiating the protocol
262
* version. Depending on the protocol version, we send either a code
263
* for authentication scheme to be used (protocol 3.3), or a list of
264
* possible "security types" (protocol 3.7).
268
rfbAuthNewClient(rfbClientPtr cl)
270
int32_t securityType = rfbSecTypeInvalid;
272
if (!cl->screen->authPasswdData || cl->reverseConnection) {
273
/* chk if this condition is valid or not. */
274
securityType = rfbSecTypeNone;
275
} else if (cl->screen->authPasswdData) {
276
securityType = rfbSecTypeVncAuth;
280
if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7)
282
/* Make sure we use only RFB 3.3 compatible security types. */
283
if (securityType == rfbSecTypeInvalid) {
284
rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n");
285
rfbClientConnFailed(cl, "Your viewer cannot handle required "
286
"authentication methods");
289
rfbSendSecurityType(cl, securityType);
291
/* Here it's ok when securityType is set to rfbSecTypeInvalid. */
292
rfbSendSecurityTypeList(cl, securityType);
297
* Read the security type chosen by the client (protocol 3.7).
301
rfbProcessClientSecurityType(rfbClientPtr cl)
305
rfbSecurityHandler* handler;
307
/* Read the security type. */
308
n = rfbReadExact(cl, (char *)&chosenType, 1);
311
rfbLog("rfbProcessClientSecurityType: client gone\n");
313
rfbLogPerror("rfbProcessClientSecurityType: read");
318
/* Make sure it was present in the list sent by the server. */
319
for (handler = securityHandlers; handler; handler = handler->next) {
320
if (chosenType == handler->type) {
321
rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType);
322
handler->handler(cl);
327
rfbLog("rfbProcessClientSecurityType: wrong security type (%d) requested\n", chosenType);
334
* rfbAuthProcessClientMessage is called when the client sends its
335
* authentication response.
339
rfbAuthProcessClientMessage(rfbClientPtr cl)
342
uint8_t response[CHALLENGESIZE];
345
if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) {
347
rfbLogPerror("rfbAuthProcessClientMessage: read");
352
if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) {
353
rfbErr("rfbAuthProcessClientMessage: password check failed\n");
354
authResult = Swap32IfLE(rfbVncAuthFailed);
355
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
356
rfbLogPerror("rfbAuthProcessClientMessage: write");
358
/* support RFB 3.8 clients, they expect a reason *why* it was disconnected */
359
if (cl->protocolMinorVersion > 7) {
360
rfbClientSendString(cl, "password check failed!");
367
authResult = Swap32IfLE(rfbVncAuthOK);
369
if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
370
rfbLogPerror("rfbAuthProcessClientMessage: write");
375
cl->state = RFB_INITIALISATION;