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