add libvncserver
[presencevnc] / libvnc / libvncserver / auth.c
1 /*
2  * auth.c - deal with authentication.
3  *
4  * This file implements the VNC authentication protocol when setting up an RFB
5  * connection.
6  */
7
8 /*
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.
13  *
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.
18  *
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.
23  *
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,
27  *  USA.
28  */
29
30 #include <rfb/rfb.h>
31
32 /* RFB 3.8 clients are well informed */
33 void rfbClientSendString(rfbClientPtr cl, char *reason);
34
35
36 /*
37  * Handle security types
38  */
39
40 static rfbSecurityHandler* securityHandlers = NULL;
41
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  */
48 void
49 rfbRegisterSecurityHandler(rfbSecurityHandler* handler)
50 {
51         rfbSecurityHandler *head = securityHandlers, *next = NULL;
52
53         if(handler == NULL)
54                 return;
55
56         next = handler->next;
57
58         while(head != NULL) {
59                 if(head == handler) {
60                         rfbRegisterSecurityHandler(next);
61                         return;
62                 }
63
64                 head = head->next;
65         }
66
67         handler->next = securityHandlers;
68         securityHandlers = handler;
69
70         rfbRegisterSecurityHandler(next);
71 }
72
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)
80 {
81         rfbSecurityHandler *cur = NULL, *pre = NULL;
82
83         if(handler == NULL)
84                 return;
85
86         if(securityHandlers == handler) {
87                 securityHandlers = securityHandlers->next;
88                 rfbUnregisterSecurityHandler(handler->next);
89                 return;
90         }
91
92         cur = pre = securityHandlers;
93
94         while(cur) {
95                 if(cur == handler) {
96                         pre->next = cur->next;
97                         break;
98                 }
99                 pre = cur;
100                 cur = cur->next;
101         }
102         rfbUnregisterSecurityHandler(handler->next);
103 }
104
105 /*
106  * Send the authentication challenge.
107  */
108
109 static void
110 rfbVncAuthSendChallenge(rfbClientPtr cl)
111 {
112         
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");
118         rfbCloseClient(cl);
119         return;
120     }
121     
122     /* Dispatch client input to rfbVncAuthProcessResponse. */
123     cl->state = RFB_AUTHENTICATION;
124 }
125
126 /*
127  * Send the NO AUTHENTICATION. SCARR
128  */
129
130 static void
131 rfbVncAuthNone(rfbClientPtr cl)
132 {
133     uint32_t authResult;
134
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");
140             rfbCloseClient(cl);
141             return;
142         }
143     }
144     cl->state = RFB_INITIALISATION;
145     return;
146 }
147
148
149 /*
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.
156  */
157
158 static rfbSecurityHandler VncSecurityHandlerVncAuth = {
159     rfbSecTypeVncAuth,
160     rfbVncAuthSendChallenge,
161     NULL
162 };
163
164 static rfbSecurityHandler VncSecurityHandlerNone = {
165     rfbSecTypeNone,
166     rfbVncAuthNone,
167     NULL
168 };
169                         
170
171 static void
172 rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType)
173 {
174     /* The size of the message is the count of security types +1,
175      * since the first byte is the number of types. */
176     int size = 1;
177     rfbSecurityHandler* handler;
178 #define MAX_SECURITY_TYPES 255
179     uint8_t buffer[MAX_SECURITY_TYPES+1];
180
181
182     /* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */
183     switch (primaryType) {
184     case rfbSecTypeNone:
185         rfbRegisterSecurityHandler(&VncSecurityHandlerNone);
186         break;
187     case rfbSecTypeVncAuth:
188         rfbRegisterSecurityHandler(&VncSecurityHandlerVncAuth);
189         break;
190     }
191
192     for (handler = securityHandlers;
193             handler && size<MAX_SECURITY_TYPES; handler = handler->next) {
194         buffer[size] = handler->type;
195         size++;
196     }
197     buffer[0] = (unsigned char)size-1;
198
199     /* Send the list. */
200     if (rfbWriteExact(cl, (char *)buffer, size) < 0) {
201         rfbLogPerror("rfbSendSecurityTypeList: write");
202         rfbCloseClient(cl);
203         return;
204     }
205
206     /*
207       * if count is 0, we need to send the reason and close the connection.
208       */
209     if(size <= 1) {
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!";
213
214         rfbClientSendString(cl, reason);
215         return;
216     }
217
218     /* Dispatch client input to rfbProcessClientSecurityType. */
219     cl->state = RFB_SECURITY_TYPE;
220 }
221
222
223
224
225 /*
226  * Tell the client what security type will be used (protocol 3.3).
227  */
228 static void
229 rfbSendSecurityType(rfbClientPtr cl, int32_t securityType)
230 {
231     uint32_t value32;
232
233     /* Send the value. */
234     value32 = Swap32IfLE(securityType);
235     if (rfbWriteExact(cl, (char *)&value32, 4) < 0) {
236         rfbLogPerror("rfbSendSecurityType: write");
237         rfbCloseClient(cl);
238         return;
239     }
240
241     /* Decide what to do next. */
242     switch (securityType) {
243     case rfbSecTypeNone:
244         /* Dispatch client input to rfbProcessClientInitMessage. */
245         cl->state = RFB_INITIALISATION;
246         break;
247     case rfbSecTypeVncAuth:
248         /* Begin the standard VNC authentication procedure. */
249         rfbVncAuthSendChallenge(cl);
250         break;
251     default:
252         /* Impossible case (hopefully). */
253         rfbLogPerror("rfbSendSecurityType: assertion failed");
254         rfbCloseClient(cl);
255     }
256 }
257
258
259
260 /*
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).
265  */
266
267 void
268 rfbAuthNewClient(rfbClientPtr cl)
269 {
270     int32_t securityType = rfbSecTypeInvalid;
271
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;
277     }
278
279     if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7)
280     {
281         /* Make sure we use only RFB 3.3 compatible security types. */
282         if (securityType == rfbSecTypeInvalid) {
283             rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n");
284             rfbClientConnFailed(cl, "Your viewer cannot handle required "
285                                 "authentication methods");
286             return;
287         }
288         rfbSendSecurityType(cl, securityType);
289     } else {
290         /* Here it's ok when securityType is set to rfbSecTypeInvalid. */
291         rfbSendSecurityTypeList(cl, securityType);
292     }
293 }
294
295 /*
296  * Read the security type chosen by the client (protocol 3.7).
297  */
298
299 void
300 rfbProcessClientSecurityType(rfbClientPtr cl)
301 {
302     int n;
303     uint8_t chosenType;
304     rfbSecurityHandler* handler;
305     
306     /* Read the security type. */
307     n = rfbReadExact(cl, (char *)&chosenType, 1);
308     if (n <= 0) {
309         if (n == 0)
310             rfbLog("rfbProcessClientSecurityType: client gone\n");
311         else
312             rfbLogPerror("rfbProcessClientSecurityType: read");
313         rfbCloseClient(cl);
314         return;
315     }
316
317     /* Make sure it was present in the list sent by the server. */
318     for (handler = securityHandlers; handler; handler = handler->next) {
319         if (chosenType == handler->type) {
320               rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType);
321               handler->handler(cl);
322               return;
323         }
324     }
325
326     rfbLog("rfbProcessClientSecurityType: wrong security type (%d) requested\n", chosenType);
327     rfbCloseClient(cl);
328 }
329
330
331
332 /*
333  * rfbAuthProcessClientMessage is called when the client sends its
334  * authentication response.
335  */
336
337 void
338 rfbAuthProcessClientMessage(rfbClientPtr cl)
339 {
340     int n;
341     uint8_t response[CHALLENGESIZE];
342     uint32_t authResult;
343
344     if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) {
345         if (n != 0)
346             rfbLogPerror("rfbAuthProcessClientMessage: read");
347         rfbCloseClient(cl);
348         return;
349     }
350
351     if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) {
352         rfbErr("rfbAuthProcessClientMessage: password check failed\n");
353         authResult = Swap32IfLE(rfbVncAuthFailed);
354         if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
355             rfbLogPerror("rfbAuthProcessClientMessage: write");
356         }
357         /* support RFB 3.8 clients, they expect a reason *why* it was disconnected */
358         if (cl->protocolMinorVersion > 7) {
359             rfbClientSendString(cl, "password check failed!");
360         }
361         else
362             rfbCloseClient(cl);
363         return;
364     }
365
366     authResult = Swap32IfLE(rfbVncAuthOK);
367
368     if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
369         rfbLogPerror("rfbAuthProcessClientMessage: write");
370         rfbCloseClient(cl);
371         return;
372     }
373
374     cl->state = RFB_INITIALISATION;
375 }