3 Copyright 1988, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
30 * XDM-AUTHENTICATION-1 (XDMCP authentication) and
31 * XDM-AUTHORIZATION-1 (client authorization) protocols
33 * Author: Keith Packard, MIT X Consortium
36 #ifdef HAVE_DIX_CONFIG_H
37 #include <dix-config.h>
45 #include <X11/Xtrans/Xtrans.h>
48 #include "dixstruct.h"
52 static Bool authFromXDMCP
;
57 #include <X11/Xdmcp.h>
59 /* XDM-AUTHENTICATION-1 */
61 static XdmAuthKeyRec privateKey
;
62 static char XdmAuthenticationName
[] = "XDM-AUTHENTICATION-1";
64 #define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
65 static XdmAuthKeyRec rho
;
68 XdmAuthenticationValidator(ARRAY8Ptr privateData
, ARRAY8Ptr incomingData
,
69 xdmOpCode packet_type
)
71 XdmAuthKeyPtr incoming
;
73 XdmcpUnwrap(incomingData
->data
, (unsigned char *) &privateKey
,
74 incomingData
->data
, incomingData
->length
);
75 if (packet_type
== ACCEPT
) {
76 if (incomingData
->length
!= 8)
78 incoming
= (XdmAuthKeyPtr
) incomingData
->data
;
79 XdmcpDecrementKey(incoming
);
80 return XdmcpCompareKeys(incoming
, &rho
);
86 XdmAuthenticationGenerator(ARRAY8Ptr privateData
, ARRAY8Ptr outgoingData
,
87 xdmOpCode packet_type
)
89 outgoingData
->length
= 0;
90 outgoingData
->data
= 0;
91 if (packet_type
== REQUEST
) {
92 if (XdmcpAllocARRAY8(outgoingData
, 8))
93 XdmcpWrap((unsigned char *) &rho
, (unsigned char *) &privateKey
,
94 outgoingData
->data
, 8);
100 XdmAuthenticationAddAuth(int name_len
, const char *name
,
101 int data_len
, char *data
)
105 XdmcpUnwrap((unsigned char *) data
, (unsigned char *) &privateKey
,
106 (unsigned char *) data
, data_len
);
107 authFromXDMCP
= TRUE
;
108 ret
= AddAuthorization(name_len
, name
, data_len
, data
);
109 authFromXDMCP
= FALSE
;
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)
118 HexToBinary(const char *in
, char *out
, int len
)
126 bottom
= atox(in
[1]);
129 *out
++ = (top
<< 4) | bottom
;
140 XdmAuthenticationInit(const char *cookie
, int cookie_len
)
142 memset(privateKey
.data
, 0, 8);
143 if (!strncmp(cookie
, "0x", 2) || !strncmp(cookie
, "0X", 2)) {
144 if (cookie_len
> 2 + 2 * 8)
145 cookie_len
= 2 + 2 * 8;
146 HexToBinary(cookie
+ 2, (char *) privateKey
.data
, cookie_len
- 2);
151 memmove(privateKey
.data
+ 1, cookie
, cookie_len
);
153 XdmcpGenerateKey(&rho
);
154 XdmcpRegisterAuthentication(XdmAuthenticationName
, XdmAuthenticationNameLen
,
157 (ValidatorFunc
) XdmAuthenticationValidator
,
158 (GeneratorFunc
) XdmAuthenticationGenerator
,
159 (AddAuthorFunc
) XdmAuthenticationAddAuth
);
164 /* XDM-AUTHORIZATION-1 */
165 typedef struct _XdmAuthorization
{
166 struct _XdmAuthorization
*next
;
170 } XdmAuthorizationRec
, *XdmAuthorizationPtr
;
172 static XdmAuthorizationPtr xdmAuth
;
174 typedef struct _XdmClientAuth
{
175 struct _XdmClientAuth
*next
;
179 } XdmClientAuthRec
, *XdmClientAuthPtr
;
181 static XdmClientAuthPtr xdmClients
;
182 static long clockOffset
;
183 static Bool gotClock
;
185 #define TwentyMinutes (20 * 60)
186 #define TwentyFiveMinutes (25 * 60)
189 XdmClientAuthCompare(const XdmClientAuthPtr a
, const XdmClientAuthPtr b
)
193 if (!XdmcpCompareKeys(&a
->rho
, &b
->rho
))
195 for (i
= 0; i
< 6; i
++)
196 if (a
->client
[i
] != b
->client
[i
])
198 return a
->time
== b
->time
;
202 XdmClientAuthDecode(const unsigned char *plain
, XdmClientAuthPtr auth
)
207 for (i
= 0; i
< 8; i
++) {
208 auth
->rho
.data
[i
] = plain
[j
];
211 for (i
= 0; i
< 6; i
++) {
212 auth
->client
[i
] = plain
[j
];
216 for (i
= 0; i
< 4; i
++) {
217 auth
->time
|= plain
[j
] << ((3 - i
) << 3);
223 XdmClientAuthTimeout(long now
)
225 XdmClientAuthPtr client
, next
, prev
;
228 for (client
= xdmClients
; client
; client
= next
) {
230 if (abs(now
- client
->time
) > TwentyFiveMinutes
) {
242 static XdmClientAuthPtr
243 XdmAuthorizationValidate(unsigned char *plain
, int length
,
244 XdmAuthKeyPtr rho
, ClientPtr xclient
,
247 XdmClientAuthPtr client
, existing
;
251 if (length
!= (192 / 8)) {
253 *reason
= "Bad XDM authorization key length";
256 client
= malloc(sizeof(XdmClientAuthRec
));
259 XdmClientAuthDecode(plain
, client
);
260 if (!XdmcpCompareKeys(&client
->rho
, rho
)) {
263 *reason
= "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)";
266 for (i
= 18; i
< 24; i
++)
270 *reason
= "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)";
274 int family
, addr_len
;
277 if (_XSERVTransGetPeerAddr(((OsCommPtr
) xclient
->osPrivate
)->trans_conn
,
278 &family
, &addr_len
, &addr
) == 0
279 && _XSERVTransConvertAddress(&family
, &addr_len
, &addr
) == 0) {
280 #if defined(TCPCONN) || defined(STREAMSCONN)
281 if (family
== FamilyInternet
&&
282 memcmp((char *) addr
, client
->client
, 4) != 0) {
287 "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)";
297 clockOffset
= client
->time
- now
;
301 XdmClientAuthTimeout(now
);
302 if (abs(client
->time
- now
) > TwentyMinutes
) {
305 *reason
= "Excessive XDM-AUTHORIZATION-1 time offset";
308 for (existing
= xdmClients
; existing
; existing
= existing
->next
) {
309 if (XdmClientAuthCompare(existing
, client
)) {
312 *reason
= "XDM authorization key matches an existing client!";
320 XdmAddCookie(unsigned short data_length
, const char *data
, XID id
)
322 XdmAuthorizationPtr
new;
323 unsigned char *rho_bits
, *key_bits
;
325 switch (data_length
) {
326 case 16: /* auth from files is 16 bytes long */
329 /* R5 xdm sent bogus authorization data in the accept packet,
330 * but we can recover */
332 key_bits
= (unsigned char *) data
;
338 rho_bits
= (unsigned char *) data
;
339 key_bits
= (unsigned char *) (data
+ 8);
343 case 8: /* auth from XDMCP is 8 bytes long */
345 key_bits
= (unsigned char *) data
;
351 /* the first octet of the key must be zero */
352 if (key_bits
[0] != '\0')
354 new = malloc(sizeof(XdmAuthorizationRec
));
359 memmove(new->key
.data
, key_bits
, (int) 8);
360 memmove(new->rho
.data
, rho_bits
, (int) 8);
366 XdmCheckCookie(unsigned short cookie_length
, const char *cookie
,
367 ClientPtr xclient
, const char **reason
)
369 XdmAuthorizationPtr auth
;
370 XdmClientAuthPtr client
;
371 unsigned char *plain
;
373 /* Auth packets must be a multiple of 8 bytes long */
374 if (cookie_length
& 7)
376 plain
= malloc(cookie_length
);
379 for (auth
= xdmAuth
; auth
; auth
= auth
->next
) {
380 XdmcpUnwrap((unsigned char *) cookie
, (unsigned char *) &auth
->key
,
381 plain
, cookie_length
);
383 XdmAuthorizationValidate(plain
, cookie_length
, &auth
->rho
, xclient
,
385 client
->next
= xdmClients
;
398 XdmAuthorizationPtr auth
, next_auth
;
399 XdmClientAuthPtr client
, next_client
;
401 for (auth
= xdmAuth
; auth
; auth
= next_auth
) {
402 next_auth
= auth
->next
;
406 for (client
= xdmClients
; client
; client
= next_client
) {
407 next_client
= client
->next
;
410 xdmClients
= (XdmClientAuthPtr
) 0;
415 XdmToID(unsigned short cookie_length
, char *cookie
)
417 XdmAuthorizationPtr auth
;
418 XdmClientAuthPtr client
;
419 unsigned char *plain
;
421 plain
= malloc(cookie_length
);
424 for (auth
= xdmAuth
; auth
; auth
= auth
->next
) {
425 XdmcpUnwrap((unsigned char *) cookie
, (unsigned char *) &auth
->key
,
426 plain
, cookie_length
);
428 XdmAuthorizationValidate(plain
, cookie_length
, &auth
->rho
, NULL
,
442 XdmFromID(XID id
, unsigned short *data_lenp
, char **datap
)
444 XdmAuthorizationPtr auth
;
446 for (auth
= xdmAuth
; auth
; auth
= auth
->next
) {
447 if (id
== auth
->id
) {
449 *datap
= (char *) &auth
->rho
;
457 XdmRemoveCookie(unsigned short data_length
, const char *data
)
459 XdmAuthorizationPtr auth
;
460 XdmAuthKeyPtr key_bits
, rho_bits
;
462 switch (data_length
) {
464 rho_bits
= (XdmAuthKeyPtr
) data
;
465 key_bits
= (XdmAuthKeyPtr
) (data
+ 8);
470 key_bits
= (XdmAuthKeyPtr
) data
;
476 for (auth
= xdmAuth
; auth
; auth
= auth
->next
) {
477 if (XdmcpCompareKeys(rho_bits
, &auth
->rho
) &&
478 XdmcpCompareKeys(key_bits
, &auth
->key
)) {
479 xdmAuth
= auth
->next
;