105b261ecSmrg/*
205b261ecSmrg
305b261ecSmrgCopyright 1988, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included
1205b261ecSmrgin all copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1505b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1605b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1705b261ecSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
1805b261ecSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1905b261ecSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2005b261ecSmrgOTHER DEALINGS IN THE SOFTWARE.
2105b261ecSmrg
2205b261ecSmrgExcept as contained in this notice, the name of The Open Group shall
2305b261ecSmrgnot be used in advertising or otherwise to promote the sale, use or
2405b261ecSmrgother dealings in this Software without prior written authorization
2505b261ecSmrgfrom The Open Group.
2605b261ecSmrg
2705b261ecSmrg*/
2805b261ecSmrg
2905b261ecSmrg/*
3005b261ecSmrg * XDM-AUTHENTICATION-1 (XDMCP authentication) and
3105b261ecSmrg * XDM-AUTHORIZATION-1 (client authorization) protocols
3205b261ecSmrg *
3305b261ecSmrg * Author:  Keith Packard, MIT X Consortium
3405b261ecSmrg */
3505b261ecSmrg
3605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3705b261ecSmrg#include <dix-config.h>
3805b261ecSmrg#endif
3905b261ecSmrg
4005b261ecSmrg#include <stdio.h>
4105b261ecSmrg#include <X11/X.h>
4205b261ecSmrg#define XSERV_t
4305b261ecSmrg#define TRANS_SERVER
4405b261ecSmrg#define TRANS_REOPEN
4505b261ecSmrg#include <X11/Xtrans/Xtrans.h>
4605b261ecSmrg#include "os.h"
4705b261ecSmrg#include "osdep.h"
4805b261ecSmrg#include "dixstruct.h"
4905b261ecSmrg
5005b261ecSmrg#ifdef HASXDMAUTH
5105b261ecSmrg
5205b261ecSmrgstatic Bool authFromXDMCP;
5305b261ecSmrg
5405b261ecSmrg#ifdef XDMCP
5505b261ecSmrg#include <X11/Xmd.h>
5605b261ecSmrg#undef REQUEST
5705b261ecSmrg#include <X11/Xdmcp.h>
5805b261ecSmrg
5905b261ecSmrg/* XDM-AUTHENTICATION-1 */
6005b261ecSmrg
6135c4bbdfSmrgstatic XdmAuthKeyRec privateKey;
6205b261ecSmrgstatic char XdmAuthenticationName[] = "XDM-AUTHENTICATION-1";
6335c4bbdfSmrg
6405b261ecSmrg#define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
6535c4bbdfSmrgstatic XdmAuthKeyRec global_rho;
6605b261ecSmrg
6735c4bbdfSmrgstatic Bool
6835c4bbdfSmrgXdmAuthenticationValidator(ARRAY8Ptr privateData, ARRAY8Ptr incomingData,
6935c4bbdfSmrg                           xdmOpCode packet_type)
7005b261ecSmrg{
7135c4bbdfSmrg    XdmAuthKeyPtr incoming;
7205b261ecSmrg
7335c4bbdfSmrg    XdmcpUnwrap(incomingData->data, (unsigned char *) &privateKey,
7435c4bbdfSmrg                incomingData->data, incomingData->length);
7505b261ecSmrg    if (packet_type == ACCEPT) {
7635c4bbdfSmrg        if (incomingData->length != 8)
7735c4bbdfSmrg            return FALSE;
7835c4bbdfSmrg        incoming = (XdmAuthKeyPtr) incomingData->data;
7935c4bbdfSmrg        XdmcpDecrementKey(incoming);
8035c4bbdfSmrg        return XdmcpCompareKeys(incoming, &global_rho);
8105b261ecSmrg    }
8205b261ecSmrg    return FALSE;
8305b261ecSmrg}
8405b261ecSmrg
8505b261ecSmrgstatic Bool
8635c4bbdfSmrgXdmAuthenticationGenerator(ARRAY8Ptr privateData, ARRAY8Ptr outgoingData,
8735c4bbdfSmrg                           xdmOpCode packet_type)
8805b261ecSmrg{
8905b261ecSmrg    outgoingData->length = 0;
9005b261ecSmrg    outgoingData->data = 0;
9105b261ecSmrg    if (packet_type == REQUEST) {
9235c4bbdfSmrg        if (XdmcpAllocARRAY8(outgoingData, 8))
9335c4bbdfSmrg            XdmcpWrap((unsigned char *) &global_rho, (unsigned char *) &privateKey,
9435c4bbdfSmrg                      outgoingData->data, 8);
9505b261ecSmrg    }
9605b261ecSmrg    return TRUE;
9705b261ecSmrg}
9805b261ecSmrg
9905b261ecSmrgstatic Bool
10035c4bbdfSmrgXdmAuthenticationAddAuth(int name_len, const char *name,
10135c4bbdfSmrg                         int data_len, char *data)
10205b261ecSmrg{
10335c4bbdfSmrg    Bool ret;
10435c4bbdfSmrg
10535c4bbdfSmrg    XdmcpUnwrap((unsigned char *) data, (unsigned char *) &privateKey,
10635c4bbdfSmrg                (unsigned char *) data, data_len);
10705b261ecSmrg    authFromXDMCP = TRUE;
10835c4bbdfSmrg    ret = AddAuthorization(name_len, name, data_len, data);
10905b261ecSmrg    authFromXDMCP = FALSE;
11005b261ecSmrg    return ret;
11105b261ecSmrg}
11205b261ecSmrg
11305b261ecSmrg#define atox(c)	('0' <= c && c <= '9' ? c - '0' : \
11405b261ecSmrg		 'a' <= c && c <= 'f' ? c - 'a' + 10 : \
11505b261ecSmrg		 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
11605b261ecSmrg
11705b261ecSmrgstatic int
11835c4bbdfSmrgHexToBinary(const char *in, char *out, int len)
11905b261ecSmrg{
12035c4bbdfSmrg    int top, bottom;
12135c4bbdfSmrg
12235c4bbdfSmrg    while (len > 0) {
12335c4bbdfSmrg        top = atox(in[0]);
12435c4bbdfSmrg        if (top == -1)
12535c4bbdfSmrg            return 0;
12635c4bbdfSmrg        bottom = atox(in[1]);
12735c4bbdfSmrg        if (bottom == -1)
12835c4bbdfSmrg            return 0;
12935c4bbdfSmrg        *out++ = (top << 4) | bottom;
13035c4bbdfSmrg        in += 2;
13135c4bbdfSmrg        len -= 2;
13205b261ecSmrg    }
13305b261ecSmrg    if (len)
13435c4bbdfSmrg        return 0;
13505b261ecSmrg    *out++ = '\0';
13605b261ecSmrg    return 1;
13705b261ecSmrg}
13805b261ecSmrg
13905b261ecSmrgvoid
14035c4bbdfSmrgXdmAuthenticationInit(const char *cookie, int cookie_len)
14105b261ecSmrg{
1426747b715Smrg    memset(privateKey.data, 0, 8);
14335c4bbdfSmrg    if (!strncmp(cookie, "0x", 2) || !strncmp(cookie, "0X", 2)) {
14435c4bbdfSmrg        if (cookie_len > 2 + 2 * 8)
14535c4bbdfSmrg            cookie_len = 2 + 2 * 8;
14635c4bbdfSmrg        HexToBinary(cookie + 2, (char *) privateKey.data, cookie_len - 2);
14705b261ecSmrg    }
14835c4bbdfSmrg    else {
14935c4bbdfSmrg        if (cookie_len > 7)
15035c4bbdfSmrg            cookie_len = 7;
15135c4bbdfSmrg        memmove(privateKey.data + 1, cookie, cookie_len);
15205b261ecSmrg    }
15335c4bbdfSmrg    XdmcpGenerateKey(&global_rho);
15435c4bbdfSmrg    XdmcpRegisterAuthentication(XdmAuthenticationName, XdmAuthenticationNameLen,
15535c4bbdfSmrg                                (char *) &global_rho,
15635c4bbdfSmrg                                sizeof(global_rho),
15735c4bbdfSmrg                                (ValidatorFunc) XdmAuthenticationValidator,
15835c4bbdfSmrg                                (GeneratorFunc) XdmAuthenticationGenerator,
15935c4bbdfSmrg                                (AddAuthorFunc) XdmAuthenticationAddAuth);
16005b261ecSmrg}
16105b261ecSmrg
16235c4bbdfSmrg#endif                          /* XDMCP */
16305b261ecSmrg
16405b261ecSmrg/* XDM-AUTHORIZATION-1 */
16505b261ecSmrgtypedef struct _XdmAuthorization {
16635c4bbdfSmrg    struct _XdmAuthorization *next;
16735c4bbdfSmrg    XdmAuthKeyRec rho;
16835c4bbdfSmrg    XdmAuthKeyRec key;
16935c4bbdfSmrg    XID id;
17005b261ecSmrg} XdmAuthorizationRec, *XdmAuthorizationPtr;
17105b261ecSmrg
17205b261ecSmrgstatic XdmAuthorizationPtr xdmAuth;
17305b261ecSmrg
17405b261ecSmrgtypedef struct _XdmClientAuth {
17535c4bbdfSmrg    struct _XdmClientAuth *next;
17635c4bbdfSmrg    XdmAuthKeyRec rho;
17735c4bbdfSmrg    char client[6];
17835c4bbdfSmrg    long time;
17905b261ecSmrg} XdmClientAuthRec, *XdmClientAuthPtr;
18005b261ecSmrg
18135c4bbdfSmrgstatic XdmClientAuthPtr xdmClients;
18235c4bbdfSmrgstatic long clockOffset;
18335c4bbdfSmrgstatic Bool gotClock;
18405b261ecSmrg
18505b261ecSmrg#define TwentyMinutes	(20 * 60)
18605b261ecSmrg#define TwentyFiveMinutes (25 * 60)
18705b261ecSmrg
18805b261ecSmrgstatic Bool
18935c4bbdfSmrgXdmClientAuthCompare(const XdmClientAuthPtr a, const XdmClientAuthPtr b)
19005b261ecSmrg{
19135c4bbdfSmrg    int i;
19205b261ecSmrg
19335c4bbdfSmrg    if (!XdmcpCompareKeys(&a->rho, &b->rho))
19435c4bbdfSmrg        return FALSE;
19505b261ecSmrg    for (i = 0; i < 6; i++)
19635c4bbdfSmrg        if (a->client[i] != b->client[i])
19735c4bbdfSmrg            return FALSE;
19805b261ecSmrg    return a->time == b->time;
19905b261ecSmrg}
20005b261ecSmrg
20105b261ecSmrgstatic void
20235c4bbdfSmrgXdmClientAuthDecode(const unsigned char *plain, XdmClientAuthPtr auth)
20305b261ecSmrg{
20435c4bbdfSmrg    int i, j;
20505b261ecSmrg
20605b261ecSmrg    j = 0;
20735c4bbdfSmrg    for (i = 0; i < 8; i++) {
20835c4bbdfSmrg        auth->rho.data[i] = plain[j];
20935c4bbdfSmrg        ++j;
21005b261ecSmrg    }
21135c4bbdfSmrg    for (i = 0; i < 6; i++) {
21235c4bbdfSmrg        auth->client[i] = plain[j];
21335c4bbdfSmrg        ++j;
21405b261ecSmrg    }
21505b261ecSmrg    auth->time = 0;
21635c4bbdfSmrg    for (i = 0; i < 4; i++) {
21735c4bbdfSmrg        auth->time |= plain[j] << ((3 - i) << 3);
21835c4bbdfSmrg        j++;
21905b261ecSmrg    }
22005b261ecSmrg}
22105b261ecSmrg
22205b261ecSmrgstatic void
22335c4bbdfSmrgXdmClientAuthTimeout(long now)
22405b261ecSmrg{
22535c4bbdfSmrg    XdmClientAuthPtr client, next, prev;
22605b261ecSmrg
22705b261ecSmrg    prev = 0;
22835c4bbdfSmrg    for (client = xdmClients; client; client = next) {
22935c4bbdfSmrg        next = client->next;
23035c4bbdfSmrg        if (labs(now - client->time) > TwentyFiveMinutes) {
23135c4bbdfSmrg            if (prev)
23235c4bbdfSmrg                prev->next = next;
23335c4bbdfSmrg            else
23435c4bbdfSmrg                xdmClients = next;
23535c4bbdfSmrg            free(client);
23635c4bbdfSmrg        }
23735c4bbdfSmrg        else
23835c4bbdfSmrg            prev = client;
23905b261ecSmrg    }
24005b261ecSmrg}
24105b261ecSmrg
24205b261ecSmrgstatic XdmClientAuthPtr
24335c4bbdfSmrgXdmAuthorizationValidate(unsigned char *plain, int length,
24435c4bbdfSmrg                         XdmAuthKeyPtr rho, ClientPtr xclient,
24535c4bbdfSmrg                         const char **reason)
24605b261ecSmrg{
24735c4bbdfSmrg    XdmClientAuthPtr client, existing;
24835c4bbdfSmrg    long now;
24935c4bbdfSmrg    int i;
25005b261ecSmrg
25105b261ecSmrg    if (length != (192 / 8)) {
25235c4bbdfSmrg        if (reason)
25335c4bbdfSmrg            *reason = "Bad XDM authorization key length";
25435c4bbdfSmrg        return NULL;
25505b261ecSmrg    }
25635c4bbdfSmrg    client = malloc(sizeof(XdmClientAuthRec));
25705b261ecSmrg    if (!client)
25835c4bbdfSmrg        return NULL;
25935c4bbdfSmrg    XdmClientAuthDecode(plain, client);
26035c4bbdfSmrg    if (!XdmcpCompareKeys(&client->rho, rho)) {
26135c4bbdfSmrg        free(client);
26235c4bbdfSmrg        if (reason)
26335c4bbdfSmrg            *reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)";
26435c4bbdfSmrg        return NULL;
26505b261ecSmrg    }
26605b261ecSmrg    for (i = 18; i < 24; i++)
26735c4bbdfSmrg        if (plain[i] != 0) {
26835c4bbdfSmrg            free(client);
26935c4bbdfSmrg            if (reason)
27035c4bbdfSmrg                *reason = "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)";
27135c4bbdfSmrg            return NULL;
27235c4bbdfSmrg        }
27305b261ecSmrg    if (xclient) {
27435c4bbdfSmrg        int family, addr_len;
27535c4bbdfSmrg        Xtransaddr *addr;
27605b261ecSmrg
27735c4bbdfSmrg        if (_XSERVTransGetPeerAddr(((OsCommPtr) xclient->osPrivate)->trans_conn,
27835c4bbdfSmrg                                   &family, &addr_len, &addr) == 0
27935c4bbdfSmrg            && _XSERVTransConvertAddress(&family, &addr_len, &addr) == 0) {
2807e31ba66Smrg#if defined(TCPCONN)
28135c4bbdfSmrg            if (family == FamilyInternet &&
28235c4bbdfSmrg                memcmp((char *) addr, client->client, 4) != 0) {
28335c4bbdfSmrg                free(client);
28435c4bbdfSmrg                free(addr);
28535c4bbdfSmrg                if (reason)
28635c4bbdfSmrg                    *reason =
28735c4bbdfSmrg                        "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)";
28835c4bbdfSmrg                return NULL;
28935c4bbdfSmrg
29035c4bbdfSmrg            }
29105b261ecSmrg#endif
29235c4bbdfSmrg            free(addr);
29335c4bbdfSmrg        }
29405b261ecSmrg    }
29505b261ecSmrg    now = time(0);
29635c4bbdfSmrg    if (!gotClock) {
29735c4bbdfSmrg        clockOffset = client->time - now;
29835c4bbdfSmrg        gotClock = TRUE;
29905b261ecSmrg    }
30005b261ecSmrg    now += clockOffset;
30135c4bbdfSmrg    XdmClientAuthTimeout(now);
30235c4bbdfSmrg    if (labs(client->time - now) > TwentyMinutes) {
30335c4bbdfSmrg        free(client);
30435c4bbdfSmrg        if (reason)
30535c4bbdfSmrg            *reason = "Excessive XDM-AUTHORIZATION-1 time offset";
30635c4bbdfSmrg        return NULL;
30705b261ecSmrg    }
30835c4bbdfSmrg    for (existing = xdmClients; existing; existing = existing->next) {
30935c4bbdfSmrg        if (XdmClientAuthCompare(existing, client)) {
31035c4bbdfSmrg            free(client);
31135c4bbdfSmrg            if (reason)
31235c4bbdfSmrg                *reason = "XDM authorization key matches an existing client!";
31335c4bbdfSmrg            return NULL;
31435c4bbdfSmrg        }
31505b261ecSmrg    }
31605b261ecSmrg    return client;
31705b261ecSmrg}
31805b261ecSmrg
31905b261ecSmrgint
32035c4bbdfSmrgXdmAddCookie(unsigned short data_length, const char *data, XID id)
32105b261ecSmrg{
32235c4bbdfSmrg    XdmAuthorizationPtr new;
32335c4bbdfSmrg    unsigned char *rho_bits, *key_bits;
32405b261ecSmrg
32535c4bbdfSmrg    switch (data_length) {
32635c4bbdfSmrg    case 16:                   /* auth from files is 16 bytes long */
32705b261ecSmrg#ifdef XDMCP
32835c4bbdfSmrg        if (authFromXDMCP) {
32935c4bbdfSmrg            /* R5 xdm sent bogus authorization data in the accept packet,
33035c4bbdfSmrg             * but we can recover */
33135c4bbdfSmrg            rho_bits = global_rho.data;
33235c4bbdfSmrg            key_bits = (unsigned char *) data;
33335c4bbdfSmrg            key_bits[0] = '\0';
33435c4bbdfSmrg        }
33535c4bbdfSmrg        else
33605b261ecSmrg#endif
33735c4bbdfSmrg        {
33835c4bbdfSmrg            rho_bits = (unsigned char *) data;
33935c4bbdfSmrg            key_bits = (unsigned char *) (data + 8);
34035c4bbdfSmrg        }
34135c4bbdfSmrg        break;
34205b261ecSmrg#ifdef XDMCP
34335c4bbdfSmrg    case 8:                    /* auth from XDMCP is 8 bytes long */
34435c4bbdfSmrg        rho_bits = global_rho.data;
34535c4bbdfSmrg        key_bits = (unsigned char *) data;
34635c4bbdfSmrg        break;
34705b261ecSmrg#endif
34805b261ecSmrg    default:
34935c4bbdfSmrg        return 0;
35005b261ecSmrg    }
35105b261ecSmrg    /* the first octet of the key must be zero */
35205b261ecSmrg    if (key_bits[0] != '\0')
35335c4bbdfSmrg        return 0;
35435c4bbdfSmrg    new = malloc(sizeof(XdmAuthorizationRec));
35505b261ecSmrg    if (!new)
35635c4bbdfSmrg        return 0;
35705b261ecSmrg    new->next = xdmAuth;
35805b261ecSmrg    xdmAuth = new;
35935c4bbdfSmrg    memmove(new->key.data, key_bits, (int) 8);
36035c4bbdfSmrg    memmove(new->rho.data, rho_bits, (int) 8);
36105b261ecSmrg    new->id = id;
36205b261ecSmrg    return 1;
36305b261ecSmrg}
36405b261ecSmrg
36505b261ecSmrgXID
36635c4bbdfSmrgXdmCheckCookie(unsigned short cookie_length, const char *cookie,
36735c4bbdfSmrg               ClientPtr xclient, const char **reason)
36805b261ecSmrg{
36935c4bbdfSmrg    XdmAuthorizationPtr auth;
37035c4bbdfSmrg    XdmClientAuthPtr client;
37135c4bbdfSmrg    unsigned char *plain;
37205b261ecSmrg
37305b261ecSmrg    /* Auth packets must be a multiple of 8 bytes long */
37405b261ecSmrg    if (cookie_length & 7)
37535c4bbdfSmrg        return (XID) -1;
3766747b715Smrg    plain = malloc(cookie_length);
37705b261ecSmrg    if (!plain)
37835c4bbdfSmrg        return (XID) -1;
37935c4bbdfSmrg    for (auth = xdmAuth; auth; auth = auth->next) {
38035c4bbdfSmrg        XdmcpUnwrap((unsigned char *) cookie, (unsigned char *) &auth->key,
38135c4bbdfSmrg                    plain, cookie_length);
38235c4bbdfSmrg        if ((client =
38335c4bbdfSmrg             XdmAuthorizationValidate(plain, cookie_length, &auth->rho, xclient,
38435c4bbdfSmrg                                      reason)) != NULL) {
38535c4bbdfSmrg            client->next = xdmClients;
38635c4bbdfSmrg            xdmClients = client;
38735c4bbdfSmrg            free(plain);
38835c4bbdfSmrg            return auth->id;
38935c4bbdfSmrg        }
39005b261ecSmrg    }
3916747b715Smrg    free(plain);
39205b261ecSmrg    return (XID) -1;
39305b261ecSmrg}
39405b261ecSmrg
39505b261ecSmrgint
39635c4bbdfSmrgXdmResetCookie(void)
39705b261ecSmrg{
39835c4bbdfSmrg    XdmAuthorizationPtr auth, next_auth;
39935c4bbdfSmrg    XdmClientAuthPtr client, next_client;
40005b261ecSmrg
40135c4bbdfSmrg    for (auth = xdmAuth; auth; auth = next_auth) {
40235c4bbdfSmrg        next_auth = auth->next;
40335c4bbdfSmrg        free(auth);
40405b261ecSmrg    }
40505b261ecSmrg    xdmAuth = 0;
40635c4bbdfSmrg    for (client = xdmClients; client; client = next_client) {
40735c4bbdfSmrg        next_client = client->next;
40835c4bbdfSmrg        free(client);
40905b261ecSmrg    }
41005b261ecSmrg    xdmClients = (XdmClientAuthPtr) 0;
41105b261ecSmrg    return 1;
41205b261ecSmrg}
41305b261ecSmrg
41405b261ecSmrgint
41535c4bbdfSmrgXdmFromID(XID id, unsigned short *data_lenp, char **datap)
41605b261ecSmrg{
41735c4bbdfSmrg    XdmAuthorizationPtr auth;
41835c4bbdfSmrg
41935c4bbdfSmrg    for (auth = xdmAuth; auth; auth = auth->next) {
42035c4bbdfSmrg        if (id == auth->id) {
42135c4bbdfSmrg            *data_lenp = 16;
42235c4bbdfSmrg            *datap = (char *) &auth->rho;
42335c4bbdfSmrg            return 1;
42435c4bbdfSmrg        }
42505b261ecSmrg    }
42605b261ecSmrg    return 0;
42705b261ecSmrg}
42805b261ecSmrg
42905b261ecSmrgint
43035c4bbdfSmrgXdmRemoveCookie(unsigned short data_length, const char *data)
43105b261ecSmrg{
43235c4bbdfSmrg    XdmAuthorizationPtr auth;
43335c4bbdfSmrg    XdmAuthKeyPtr key_bits, rho_bits;
43405b261ecSmrg
43535c4bbdfSmrg    switch (data_length) {
43605b261ecSmrg    case 16:
43735c4bbdfSmrg        rho_bits = (XdmAuthKeyPtr) data;
43835c4bbdfSmrg        key_bits = (XdmAuthKeyPtr) (data + 8);
43935c4bbdfSmrg        break;
44005b261ecSmrg#ifdef XDMCP
44105b261ecSmrg    case 8:
44235c4bbdfSmrg        rho_bits = &global_rho;
44335c4bbdfSmrg        key_bits = (XdmAuthKeyPtr) data;
44435c4bbdfSmrg        break;
44505b261ecSmrg#endif
44605b261ecSmrg    default:
44735c4bbdfSmrg        return 0;
44805b261ecSmrg    }
44935c4bbdfSmrg    for (auth = xdmAuth; auth; auth = auth->next) {
45035c4bbdfSmrg        if (XdmcpCompareKeys(rho_bits, &auth->rho) &&
45135c4bbdfSmrg            XdmcpCompareKeys(key_bits, &auth->key)) {
45235c4bbdfSmrg            xdmAuth = auth->next;
45335c4bbdfSmrg            free(auth);
45435c4bbdfSmrg            return 1;
45535c4bbdfSmrg        }
45605b261ecSmrg    }
45705b261ecSmrg    return 0;
45805b261ecSmrg}
45905b261ecSmrg
46005b261ecSmrg#endif
461