~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to os/xdmauth.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Xorg: xdmauth.c,v 1.4 2001/02/09 02:05:24 xorgcvs Exp $ */
 
2
/*
 
3
 
 
4
Copyright 1988, 1998  The Open Group
 
5
 
 
6
Permission to use, copy, modify, distribute, and sell this software and its
 
7
documentation for any purpose is hereby granted without fee, provided that
 
8
the above copyright notice appear in all copies and that both that
 
9
copyright notice and this permission notice appear in supporting
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included
 
13
in all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
16
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
18
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
 
19
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 
20
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
21
OTHER DEALINGS IN THE SOFTWARE.
 
22
 
 
23
Except as contained in this notice, the name of The Open Group shall
 
24
not be used in advertising or otherwise to promote the sale, use or
 
25
other dealings in this Software without prior written authorization
 
26
from The Open Group.
 
27
 
 
28
*/
 
29
/* $XFree86: xdmauth.c,v 1.7 2002/11/05 05:50:34 keithp Exp $ */
 
30
 
 
31
/*
 
32
 * XDM-AUTHENTICATION-1 (XDMCP authentication) and
 
33
 * XDM-AUTHORIZATION-1 (client authorization) protocols
 
34
 *
 
35
 * Author:  Keith Packard, MIT X Consortium
 
36
 */
 
37
 
 
38
#ifdef HAVE_DIX_CONFIG_H
 
39
#include <dix-config.h>
 
40
#endif
 
41
 
 
42
#include <stdio.h>
 
43
#include <X11/X.h>
 
44
#include <X11/Xtrans/Xtrans.h>
 
45
#include "os.h"
 
46
#include "osdep.h"
 
47
#include "dixstruct.h"
 
48
 
 
49
#ifdef HASXDMAUTH
 
50
 
 
51
static Bool authFromXDMCP;
 
52
 
 
53
#ifdef XDMCP
 
54
#include <X11/Xmd.h>
 
55
#undef REQUEST
 
56
#include <X11/Xdmcp.h>
 
57
 
 
58
/* XDM-AUTHENTICATION-1 */
 
59
 
 
60
static XdmAuthKeyRec    privateKey;
 
61
static char XdmAuthenticationName[] = "XDM-AUTHENTICATION-1";
 
62
#define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
 
63
static XdmAuthKeyRec    rho;
 
64
 
 
65
static Bool 
 
66
XdmAuthenticationValidator (ARRAY8Ptr privateData, ARRAY8Ptr incomingData, 
 
67
    xdmOpCode packet_type)
 
68
{
 
69
    XdmAuthKeyPtr       incoming;
 
70
 
 
71
    XdmcpUnwrap (incomingData->data, &privateKey,
 
72
                              incomingData->data,incomingData->length);
 
73
    switch (packet_type)
 
74
    {
 
75
    case ACCEPT:
 
76
        if (incomingData->length != 8)
 
77
            return FALSE;
 
78
        incoming = (XdmAuthKeyPtr) incomingData->data;
 
79
        XdmcpDecrementKey (incoming);
 
80
        return XdmcpCompareKeys (incoming, &rho);
 
81
    }
 
82
    return FALSE;
 
83
}
 
84
 
 
85
static Bool
 
86
XdmAuthenticationGenerator (ARRAY8Ptr privateData, ARRAY8Ptr outgoingData, 
 
87
    xdmOpCode packet_type)
 
88
{
 
89
    outgoingData->length = 0;
 
90
    outgoingData->data = 0;
 
91
    switch (packet_type)
 
92
    {
 
93
    case REQUEST:
 
94
        if (XdmcpAllocARRAY8 (outgoingData, 8))
 
95
            XdmcpWrap (&rho, &privateKey, outgoingData->data, 8);
 
96
    }
 
97
    return TRUE;
 
98
}
 
99
 
 
100
static Bool
 
101
XdmAuthenticationAddAuth (int name_len, char *name, 
 
102
    int data_len, char *data)
 
103
{
 
104
    Bool    ret;
 
105
    XdmcpUnwrap (data, (unsigned char *)&privateKey, data, data_len);
 
106
    authFromXDMCP = TRUE;
 
107
    ret = AddAuthorization (name_len, name, data_len, data);
 
108
    authFromXDMCP = FALSE;
 
109
    return ret;
 
110
}
 
111
 
 
112
 
 
113
#define atox(c) ('0' <= c && c <= '9' ? c - '0' : \
 
114
                 'a' <= c && c <= 'f' ? c - 'a' + 10 : \
 
115
                 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
 
116
 
 
117
static int
 
118
HexToBinary (char *in, char *out, int len)
 
119
{
 
120
    int     top, bottom;
 
121
 
 
122
    while (len > 0)
 
123
    {
 
124
        top = atox(in[0]);
 
125
        if (top == -1)
 
126
            return 0;
 
127
        bottom = atox(in[1]);
 
128
        if (bottom == -1)
 
129
            return 0;
 
130
        *out++ = (top << 4) | bottom;
 
131
        in += 2;
 
132
        len -= 2;
 
133
    }
 
134
    if (len)
 
135
        return 0;
 
136
    *out++ = '\0';
 
137
    return 1;
 
138
}
 
139
 
 
140
void
 
141
XdmAuthenticationInit (char *cookie, int cookie_len)
 
142
{
 
143
    bzero (privateKey.data, 8);
 
144
    if (!strncmp (cookie, "0x", 2) || !strncmp (cookie, "0X", 2))
 
145
    {
 
146
        if (cookie_len > 2 + 2 * 8)
 
147
            cookie_len = 2 + 2 * 8;
 
148
        HexToBinary (cookie + 2, (char *)privateKey.data, cookie_len - 2);
 
149
    }
 
150
    else
 
151
    {
 
152
        if (cookie_len > 7)
 
153
            cookie_len = 7;
 
154
        memmove (privateKey.data + 1, cookie, cookie_len);
 
155
    }
 
156
    XdmcpGenerateKey (&rho);
 
157
    XdmcpRegisterAuthentication (XdmAuthenticationName, XdmAuthenticationNameLen,
 
158
                                 (unsigned char *)&rho,
 
159
                                 sizeof (rho),
 
160
                                 XdmAuthenticationValidator,
 
161
                                 XdmAuthenticationGenerator,
 
162
                                 XdmAuthenticationAddAuth);
 
163
}
 
164
 
 
165
#endif /* XDMCP */
 
166
 
 
167
/* XDM-AUTHORIZATION-1 */
 
168
typedef struct _XdmAuthorization {
 
169
    struct _XdmAuthorization    *next;
 
170
    XdmAuthKeyRec               rho;
 
171
    XdmAuthKeyRec               key;
 
172
    XID                         id;
 
173
} XdmAuthorizationRec, *XdmAuthorizationPtr;
 
174
 
 
175
static XdmAuthorizationPtr xdmAuth;
 
176
 
 
177
typedef struct _XdmClientAuth {
 
178
    struct _XdmClientAuth   *next;
 
179
    XdmAuthKeyRec           rho;
 
180
    char                    client[6];
 
181
    long                    time;
 
182
} XdmClientAuthRec, *XdmClientAuthPtr;
 
183
 
 
184
static XdmClientAuthPtr    xdmClients;
 
185
static long         clockOffset;
 
186
static Bool         gotClock;
 
187
 
 
188
#define TwentyMinutes   (20 * 60)
 
189
#define TwentyFiveMinutes (25 * 60)
 
190
 
 
191
static Bool
 
192
XdmClientAuthCompare (XdmClientAuthPtr a, XdmClientAuthPtr b)
 
193
{
 
194
    int i;
 
195
 
 
196
    if (!XdmcpCompareKeys (&a->rho, &b->rho))
 
197
        return FALSE;
 
198
    for (i = 0; i < 6; i++)
 
199
        if (a->client[i] != b->client[i])
 
200
            return FALSE;
 
201
    return a->time == b->time;
 
202
}
 
203
 
 
204
static void
 
205
XdmClientAuthDecode (unsigned char *plain, XdmClientAuthPtr auth)
 
206
{
 
207
    int     i, j;
 
208
 
 
209
    j = 0;
 
210
    for (i = 0; i < 8; i++)
 
211
    {
 
212
        auth->rho.data[i] = plain[j];
 
213
        ++j;
 
214
    }
 
215
    for (i = 0; i < 6; i++)
 
216
    {
 
217
        auth->client[i] = plain[j];
 
218
        ++j;
 
219
    }
 
220
    auth->time = 0;
 
221
    for (i = 0; i < 4; i++)
 
222
    {
 
223
        auth->time |= plain[j] << ((3 - i) << 3);
 
224
        j++;
 
225
    }
 
226
}
 
227
 
 
228
static void
 
229
XdmClientAuthTimeout (long now)
 
230
{
 
231
    XdmClientAuthPtr    client, next, prev;
 
232
 
 
233
    prev = 0;
 
234
    for (client = xdmClients; client; client=next)
 
235
    {
 
236
        next = client->next;
 
237
        if (abs (now - client->time) > TwentyFiveMinutes)
 
238
        {
 
239
            if (prev)
 
240
                prev->next = next;
 
241
            else
 
242
                xdmClients = next;
 
243
            xfree (client);
 
244
        }
 
245
        else
 
246
            prev = client;
 
247
    }
 
248
}
 
249
 
 
250
static XdmClientAuthPtr
 
251
XdmAuthorizationValidate (unsigned char *plain, int length, 
 
252
    XdmAuthKeyPtr rho, ClientPtr xclient, char **reason)
 
253
{
 
254
    XdmClientAuthPtr    client, existing;
 
255
    long                now;
 
256
    int                 i;
 
257
 
 
258
    if (length != (192 / 8)) {
 
259
        if (reason)
 
260
            *reason = "Bad XDM authorization key length";
 
261
        return NULL;
 
262
    }
 
263
    client = (XdmClientAuthPtr) xalloc (sizeof (XdmClientAuthRec));
 
264
    if (!client)
 
265
        return NULL;
 
266
    XdmClientAuthDecode (plain, client);
 
267
    if (!XdmcpCompareKeys (&client->rho, rho))
 
268
    {
 
269
        xfree (client);
 
270
        if (reason)
 
271
            *reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)";
 
272
        return NULL;
 
273
    }
 
274
    for (i = 18; i < 24; i++)
 
275
        if (plain[i] != 0) {
 
276
            xfree (client);
 
277
            if (reason)
 
278
                *reason = "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)";
 
279
            return NULL;
 
280
        }
 
281
    if (xclient) {
 
282
        int family, addr_len;
 
283
        Xtransaddr *addr;
 
284
 
 
285
        if (_XSERVTransGetPeerAddr(((OsCommPtr)xclient->osPrivate)->trans_conn,
 
286
                                   &family, &addr_len, &addr) == 0
 
287
            && _XSERVTransConvertAddress(&family, &addr_len, &addr) == 0) {
 
288
#if defined(TCPCONN) || defined(STREAMSCONN)
 
289
            if (family == FamilyInternet &&
 
290
                memcmp((char *)addr, client->client, 4) != 0) {
 
291
                xfree (client);
 
292
                xfree (addr);
 
293
                if (reason)
 
294
                    *reason = "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)";
 
295
                return NULL;
 
296
 
 
297
            }
 
298
#endif
 
299
            xfree (addr);
 
300
        }
 
301
    }
 
302
    now = time(0);
 
303
    if (!gotClock)
 
304
    {
 
305
        clockOffset = client->time - now;
 
306
        gotClock = TRUE;
 
307
    }
 
308
    now += clockOffset;
 
309
    XdmClientAuthTimeout (now);
 
310
    if (abs (client->time - now) > TwentyMinutes)
 
311
    {
 
312
        xfree (client);
 
313
        if (reason)
 
314
            *reason = "Excessive XDM-AUTHORIZATION-1 time offset";
 
315
        return NULL;
 
316
    }
 
317
    for (existing = xdmClients; existing; existing=existing->next)
 
318
    {
 
319
        if (XdmClientAuthCompare (existing, client))
 
320
        {
 
321
            xfree (client);
 
322
            if (reason)
 
323
                *reason = "XDM authorization key matches an existing client!";
 
324
            return NULL;
 
325
        }
 
326
    }
 
327
    return client;
 
328
}
 
329
 
 
330
int
 
331
XdmAddCookie (unsigned short data_length, char *data, XID id)
 
332
{
 
333
    XdmAuthorizationPtr new;
 
334
    unsigned char       *rho_bits, *key_bits;
 
335
 
 
336
    switch (data_length)
 
337
    {
 
338
    case 16:                /* auth from files is 16 bytes long */
 
339
#ifdef XDMCP
 
340
        if (authFromXDMCP)
 
341
        {
 
342
            /* R5 xdm sent bogus authorization data in the accept packet,
 
343
             * but we can recover */
 
344
            rho_bits = rho.data;
 
345
            key_bits = (unsigned char *) data;
 
346
            key_bits[0] = '\0';
 
347
        }
 
348
        else
 
349
#endif
 
350
        {
 
351
            rho_bits = (unsigned char *) data;
 
352
            key_bits = (unsigned char *) (data + 8);
 
353
        }
 
354
        break;
 
355
#ifdef XDMCP
 
356
    case 8:                 /* auth from XDMCP is 8 bytes long */
 
357
        rho_bits = rho.data;
 
358
        key_bits = (unsigned char *) data;
 
359
        break;
 
360
#endif
 
361
    default:
 
362
        return 0;
 
363
    }
 
364
    /* the first octet of the key must be zero */
 
365
    if (key_bits[0] != '\0')
 
366
        return 0;
 
367
    new = (XdmAuthorizationPtr) xalloc (sizeof (XdmAuthorizationRec));
 
368
    if (!new)
 
369
        return 0;
 
370
    new->next = xdmAuth;
 
371
    xdmAuth = new;
 
372
    memmove (new->key.data, key_bits, (int) 8);
 
373
    memmove (new->rho.data, rho_bits, (int) 8);
 
374
    new->id = id;
 
375
    return 1;
 
376
}
 
377
 
 
378
XID
 
379
XdmCheckCookie (unsigned short cookie_length, char *cookie, 
 
380
    ClientPtr xclient, char **reason)
 
381
{
 
382
    XdmAuthorizationPtr auth;
 
383
    XdmClientAuthPtr    client;
 
384
    unsigned char       *plain;
 
385
 
 
386
    /* Auth packets must be a multiple of 8 bytes long */
 
387
    if (cookie_length & 7)
 
388
        return (XID) -1;
 
389
    plain = (unsigned char *) xalloc (cookie_length);
 
390
    if (!plain)
 
391
        return (XID) -1;
 
392
    for (auth = xdmAuth; auth; auth=auth->next) {
 
393
        XdmcpUnwrap (cookie, (unsigned char *)&auth->key, plain, cookie_length);
 
394
        if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, xclient, reason)) != NULL)
 
395
        {
 
396
            client->next = xdmClients;
 
397
            xdmClients = client;
 
398
            xfree (plain);
 
399
            return auth->id;
 
400
        }
 
401
    }
 
402
    xfree (plain);
 
403
    return (XID) -1;
 
404
}
 
405
 
 
406
int
 
407
XdmResetCookie (void)
 
408
{
 
409
    XdmAuthorizationPtr auth, next_auth;
 
410
    XdmClientAuthPtr    client, next_client;
 
411
 
 
412
    for (auth = xdmAuth; auth; auth=next_auth)
 
413
    {
 
414
        next_auth = auth->next;
 
415
        xfree (auth);
 
416
    }
 
417
    xdmAuth = 0;
 
418
    for (client = xdmClients; client; client=next_client)
 
419
    {
 
420
        next_client = client->next;
 
421
        xfree (client);
 
422
    }
 
423
    xdmClients = (XdmClientAuthPtr) 0;
 
424
    return 1;
 
425
}
 
426
 
 
427
XID
 
428
XdmToID (unsigned short cookie_length, char *cookie)
 
429
{
 
430
    XdmAuthorizationPtr auth;
 
431
    XdmClientAuthPtr    client;
 
432
    unsigned char       *plain;
 
433
 
 
434
    plain = (unsigned char *) xalloc (cookie_length);
 
435
    if (!plain)
 
436
        return (XID) -1;
 
437
    for (auth = xdmAuth; auth; auth=auth->next) {
 
438
        XdmcpUnwrap (cookie, (unsigned char *)&auth->key, plain, cookie_length);
 
439
        if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, NULL, NULL)) != NULL)
 
440
        {
 
441
            xfree (client);
 
442
            xfree (cookie);
 
443
            return auth->id;
 
444
        }
 
445
    }
 
446
    xfree (cookie);
 
447
    return (XID) -1;
 
448
}
 
449
 
 
450
int
 
451
XdmFromID (XID id, unsigned short *data_lenp, char **datap)
 
452
{
 
453
    XdmAuthorizationPtr auth;
 
454
 
 
455
    for (auth = xdmAuth; auth; auth=auth->next) {
 
456
        if (id == auth->id) {
 
457
            *data_lenp = 16;
 
458
            *datap = (char *) &auth->rho;
 
459
            return 1;
 
460
        }
 
461
    }
 
462
    return 0;
 
463
}
 
464
 
 
465
int
 
466
XdmRemoveCookie (unsigned short data_length, char *data)
 
467
{
 
468
    XdmAuthorizationPtr auth, prev;
 
469
    XdmAuthKeyPtr       key_bits, rho_bits;
 
470
 
 
471
    prev = 0;
 
472
    switch (data_length)
 
473
    {
 
474
    case 16:
 
475
        rho_bits = (XdmAuthKeyPtr) data;
 
476
        key_bits = (XdmAuthKeyPtr) (data + 8);
 
477
        break;
 
478
#ifdef XDMCP
 
479
    case 8:
 
480
        rho_bits = &rho;
 
481
        key_bits = (XdmAuthKeyPtr) data;
 
482
        break;
 
483
#endif
 
484
    default:
 
485
        return 0;
 
486
    }
 
487
    for (auth = xdmAuth; auth; auth=auth->next) {
 
488
        if (XdmcpCompareKeys (rho_bits, &auth->rho) &&
 
489
            XdmcpCompareKeys (key_bits, &auth->key))
 
490
        {
 
491
            if (prev)
 
492
                prev->next = auth->next;
 
493
            else
 
494
                xdmAuth = auth->next;
 
495
            xfree (auth);
 
496
            return 1;
 
497
        }
 
498
    }
 
499
    return 0;
 
500
}
 
501
 
 
502
#endif