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 #include <dix-config.h>
43 #include <X11/Xtrans/Xtrans.h>
51 #include "dixstruct.h"
55 static Bool authFromXDMCP
;
60 #include <X11/Xdmcp.h>
62 /* XDM-AUTHENTICATION-1 */
64 static XdmAuthKeyRec privateKey
;
65 static char XdmAuthenticationName
[] = "XDM-AUTHENTICATION-1";
67 #define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
68 static XdmAuthKeyRec global_rho
;
71 XdmAuthenticationValidator(ARRAY8Ptr privateData
, ARRAY8Ptr incomingData
,
72 xdmOpCode packet_type
)
74 XdmAuthKeyPtr incoming
;
76 XdmcpUnwrap(incomingData
->data
, (unsigned char *) &privateKey
,
77 incomingData
->data
, incomingData
->length
);
78 if (packet_type
== ACCEPT
) {
79 if (incomingData
->length
!= 8)
81 incoming
= (XdmAuthKeyPtr
) incomingData
->data
;
82 XdmcpDecrementKey(incoming
);
83 return XdmcpCompareKeys(incoming
, &global_rho
);
89 XdmAuthenticationGenerator(ARRAY8Ptr privateData
, ARRAY8Ptr outgoingData
,
90 xdmOpCode packet_type
)
92 outgoingData
->length
= 0;
93 outgoingData
->data
= 0;
94 if (packet_type
== REQUEST
) {
95 if (XdmcpAllocARRAY8(outgoingData
, 8))
96 XdmcpWrap((unsigned char *) &global_rho
, (unsigned char *) &privateKey
,
97 outgoingData
->data
, 8);
103 XdmAuthenticationAddAuth(int name_len
, const char *name
,
104 int data_len
, char *data
)
108 XdmcpUnwrap((unsigned char *) data
, (unsigned char *) &privateKey
,
109 (unsigned char *) data
, data_len
);
110 authFromXDMCP
= TRUE
;
111 ret
= AddAuthorization(name_len
, name
, data_len
, data
);
112 authFromXDMCP
= FALSE
;
116 #define atox(c) ('0' <= c && c <= '9' ? c - '0' : \
117 'a' <= c && c <= 'f' ? c - 'a' + 10 : \
118 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
121 HexToBinary(const char *in
, char *out
, int len
)
129 bottom
= atox(in
[1]);
132 *out
++ = (top
<< 4) | bottom
;
143 XdmAuthenticationInit(const char *cookie
, int cookie_len
)
145 memset(privateKey
.data
, 0, 8);
146 if (!strncmp(cookie
, "0x", 2) || !strncmp(cookie
, "0X", 2)) {
147 if (cookie_len
> 2 + 2 * 8)
148 cookie_len
= 2 + 2 * 8;
149 HexToBinary(cookie
+ 2, (char *) privateKey
.data
, cookie_len
- 2);
154 memmove(privateKey
.data
+ 1, cookie
, cookie_len
);
156 XdmcpGenerateKey(&global_rho
);
157 XdmcpRegisterAuthentication(XdmAuthenticationName
, XdmAuthenticationNameLen
,
158 (char *) &global_rho
,
160 (ValidatorFunc
) XdmAuthenticationValidator
,
161 (GeneratorFunc
) XdmAuthenticationGenerator
,
162 (AddAuthorFunc
) XdmAuthenticationAddAuth
);
167 /* XDM-AUTHORIZATION-1 */
168 typedef struct _XdmAuthorization
{
169 struct _XdmAuthorization
*next
;
173 } XdmAuthorizationRec
, *XdmAuthorizationPtr
;
175 static XdmAuthorizationPtr xdmAuth
;
177 typedef struct _XdmClientAuth
{
178 struct _XdmClientAuth
*next
;
182 } XdmClientAuthRec
, *XdmClientAuthPtr
;
184 static XdmClientAuthPtr xdmClients
;
185 static long clockOffset
;
186 static Bool gotClock
;
188 #define TwentyMinutes (20 * 60)
189 #define TwentyFiveMinutes (25 * 60)
192 XdmClientAuthCompare(const XdmClientAuthPtr a
, const XdmClientAuthPtr b
)
196 if (!XdmcpCompareKeys(&a
->rho
, &b
->rho
))
198 for (i
= 0; i
< 6; i
++)
199 if (a
->client
[i
] != b
->client
[i
])
201 return a
->time
== b
->time
;
205 XdmClientAuthDecode(const unsigned char *plain
, XdmClientAuthPtr auth
)
210 for (i
= 0; i
< 8; i
++) {
211 auth
->rho
.data
[i
] = plain
[j
];
214 for (i
= 0; i
< 6; i
++) {
215 auth
->client
[i
] = plain
[j
];
219 for (i
= 0; i
< 4; i
++) {
220 auth
->time
|= plain
[j
] << ((3 - i
) << 3);
226 XdmClientAuthTimeout(long now
)
228 XdmClientAuthPtr client
, next
, prev
;
231 for (client
= xdmClients
; client
; client
= next
) {
233 if (labs(now
- client
->time
) > TwentyFiveMinutes
) {
245 static XdmClientAuthPtr
246 XdmAuthorizationValidate(unsigned char *plain
, int length
,
247 XdmAuthKeyPtr rho
, ClientPtr xclient
,
250 XdmClientAuthPtr client
, existing
;
254 if (length
!= (192 / 8)) {
256 *reason
= "Bad XDM authorization key length";
259 client
= malloc(sizeof(XdmClientAuthRec
));
262 XdmClientAuthDecode(plain
, client
);
263 if (!XdmcpCompareKeys(&client
->rho
, rho
)) {
266 *reason
= "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)";
269 for (i
= 18; i
< 24; i
++)
273 *reason
= "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)";
277 int family
, addr_len
;
280 if (_XSERVTransGetPeerAddr(((OsCommPtr
) xclient
->osPrivate
)->trans_conn
,
281 &family
, &addr_len
, &addr
) == 0
282 && _XSERVTransConvertAddress(&family
, &addr_len
, &addr
) == 0) {
284 if (family
== FamilyInternet
&&
285 memcmp((char *) addr
, client
->client
, 4) != 0) {
290 "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)";
300 clockOffset
= client
->time
- now
;
304 XdmClientAuthTimeout(now
);
305 if (labs(client
->time
- now
) > TwentyMinutes
) {
308 *reason
= "Excessive XDM-AUTHORIZATION-1 time offset";
311 for (existing
= xdmClients
; existing
; existing
= existing
->next
) {
312 if (XdmClientAuthCompare(existing
, client
)) {
315 *reason
= "XDM authorization key matches an existing client!";
323 XdmAddCookie(unsigned short data_length
, const char *data
, XID id
)
325 XdmAuthorizationPtr
new;
326 unsigned char *rho_bits
, *key_bits
;
328 switch (data_length
) {
329 case 16: /* auth from files is 16 bytes long */
332 /* R5 xdm sent bogus authorization data in the accept packet,
333 * but we can recover */
334 rho_bits
= global_rho
.data
;
335 key_bits
= (unsigned char *) data
;
341 rho_bits
= (unsigned char *) data
;
342 key_bits
= (unsigned char *) (data
+ 8);
346 case 8: /* auth from XDMCP is 8 bytes long */
347 rho_bits
= global_rho
.data
;
348 key_bits
= (unsigned char *) data
;
354 /* the first octet of the key must be zero */
355 if (key_bits
[0] != '\0')
357 new = malloc(sizeof(XdmAuthorizationRec
));
362 memcpy(new->key
.data
, key_bits
, 8);
363 memcpy(new->rho
.data
, rho_bits
, 8);
369 XdmCheckCookie(unsigned short cookie_length
, const char *cookie
,
370 ClientPtr xclient
, const char **reason
)
372 XdmAuthorizationPtr auth
;
373 XdmClientAuthPtr client
;
374 unsigned char *plain
;
376 /* Auth packets must be a multiple of 8 bytes long */
377 if (cookie_length
& 7)
379 plain
= malloc(cookie_length
);
382 for (auth
= xdmAuth
; auth
; auth
= auth
->next
) {
383 XdmcpUnwrap((unsigned char *) cookie
, (unsigned char *) &auth
->key
,
384 plain
, cookie_length
);
386 XdmAuthorizationValidate(plain
, cookie_length
, &auth
->rho
, xclient
,
388 client
->next
= xdmClients
;
401 XdmAuthorizationPtr auth
, next_auth
;
402 XdmClientAuthPtr client
, next_client
;
404 for (auth
= xdmAuth
; auth
; auth
= next_auth
) {
405 next_auth
= auth
->next
;
409 for (client
= xdmClients
; client
; client
= next_client
) {
410 next_client
= client
->next
;
413 xdmClients
= (XdmClientAuthPtr
) 0;
418 XdmFromID(XID id
, unsigned short *data_lenp
, char **datap
)
420 XdmAuthorizationPtr auth
;
422 for (auth
= xdmAuth
; auth
; auth
= auth
->next
) {
423 if (id
== auth
->id
) {
425 *datap
= (char *) &auth
->rho
;
433 XdmRemoveCookie(unsigned short data_length
, const char *data
)
435 XdmAuthorizationPtr auth
;
436 XdmAuthKeyPtr key_bits
, rho_bits
;
438 switch (data_length
) {
440 rho_bits
= (XdmAuthKeyPtr
) data
;
441 key_bits
= (XdmAuthKeyPtr
) (data
+ 8);
445 rho_bits
= &global_rho
;
446 key_bits
= (XdmAuthKeyPtr
) data
;
452 for (auth
= xdmAuth
; auth
; auth
= auth
->next
) {
453 if (XdmcpCompareKeys(rho_bits
, &auth
->rho
) &&
454 XdmcpCompareKeys(key_bits
, &auth
->key
)) {
455 xdmAuth
= auth
->next
;