~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to ica/x11/libvncserver/auth.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20080617134654-2y5m7ki93r5c1ysf
Tags: upstream-1.0.9~rc3
ImportĀ upstreamĀ versionĀ 1.0.9~rc3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#if 0
 
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
#endif
 
279
 
 
280
    if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7)
 
281
    {
 
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");
 
287
            return;
 
288
        }
 
289
        rfbSendSecurityType(cl, securityType);
 
290
    } else {
 
291
        /* Here it's ok when securityType is set to rfbSecTypeInvalid. */
 
292
        rfbSendSecurityTypeList(cl, securityType);
 
293
    }
 
294
}
 
295
 
 
296
/*
 
297
 * Read the security type chosen by the client (protocol 3.7).
 
298
 */
 
299
 
 
300
void
 
301
rfbProcessClientSecurityType(rfbClientPtr cl)
 
302
{
 
303
    int n;
 
304
    uint8_t chosenType;
 
305
    rfbSecurityHandler* handler;
 
306
    
 
307
    /* Read the security type. */
 
308
    n = rfbReadExact(cl, (char *)&chosenType, 1);
 
309
    if (n <= 0) {
 
310
        if (n == 0)
 
311
            rfbLog("rfbProcessClientSecurityType: client gone\n");
 
312
        else
 
313
            rfbLogPerror("rfbProcessClientSecurityType: read");
 
314
        rfbCloseClient(cl);
 
315
        return;
 
316
    }
 
317
 
 
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);
 
323
              return;
 
324
        }
 
325
    }
 
326
 
 
327
    rfbLog("rfbProcessClientSecurityType: wrong security type (%d) requested\n", chosenType);
 
328
    rfbCloseClient(cl);
 
329
}
 
330
 
 
331
 
 
332
 
 
333
/*
 
334
 * rfbAuthProcessClientMessage is called when the client sends its
 
335
 * authentication response.
 
336
 */
 
337
 
 
338
void
 
339
rfbAuthProcessClientMessage(rfbClientPtr cl)
 
340
{
 
341
    int n;
 
342
    uint8_t response[CHALLENGESIZE];
 
343
    uint32_t authResult;
 
344
 
 
345
    if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) {
 
346
        if (n != 0)
 
347
            rfbLogPerror("rfbAuthProcessClientMessage: read");
 
348
        rfbCloseClient(cl);
 
349
        return;
 
350
    }
 
351
 
 
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");
 
357
        }
 
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!");
 
361
        }
 
362
        else
 
363
            rfbCloseClient(cl);
 
364
        return;
 
365
    }
 
366
 
 
367
    authResult = Swap32IfLE(rfbVncAuthOK);
 
368
 
 
369
    if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) {
 
370
        rfbLogPerror("rfbAuthProcessClientMessage: write");
 
371
        rfbCloseClient(cl);
 
372
        return;
 
373
    }
 
374
 
 
375
    cl->state = RFB_INITIALISATION;
 
376
}