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