50b1097643
Almost all of the places the string is assigned point to a literal string constant, so use const char * for those, and const char ** for function calls that return it via an argument. Fortunately the top level function, ClientAuthorized, which returns the string as its return value is called from only one place, ProcEstablishConnection. ProcEstablishConnection stores either that return value or a string literal in char *reason. It only uses reason as an argument to SendConnSetup. SendConnSetup passes the reason argument to strlen & WriteToClient, both of which already have const qualifiers on their args. Thus added const to the reason variable in ProcEstablishConnection and the reason argument to SendConnSetup. Fixes gcc warnings: dispatch.c: In function 'ProcEstablishConnection': dispatch.c:3711:9: warning: assignment discards qualifiers from pointer target type auth.c: In function 'CheckAuthorization': auth.c:218:14: warning: assignment discards qualifiers from pointer target type auth.c:220:20: warning: assignment discards qualifiers from pointer target type connection.c: In function 'ClientAuthorized': connection.c:683:3: warning: return discards qualifiers from pointer target type mitauth.c: In function 'MitCheckCookie': mitauth.c:88:13: warning: assignment discards qualifiers from pointer target type xdmauth.c:259:14: warning: assignment discards qualifiers from pointer target type xdmauth.c:270:14: warning: assignment discards qualifiers from pointer target type xdmauth.c:277:11: warning: assignment discards qualifiers from pointer target type xdmauth.c:293:15: warning: assignment discards qualifiers from pointer target type xdmauth.c:313:14: warning: assignment discards qualifiers from pointer target type xdmauth.c:322:11: warning: assignment discards qualifiers from pointer target type rpcauth.c: In function 'SecureRPCCheck': rpcauth.c:136:10: warning: assignment discards qualifiers from pointer target type Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> Reviewed-by: Jamey Sharp <jamey@minilop.net> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
500 lines
11 KiB
C
500 lines
11 KiB
C
/*
|
|
|
|
Copyright 1988, 1998 The Open Group
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
the above copyright notice appear in all copies and that both that
|
|
copyright notice and this permission notice appear in supporting
|
|
documentation.
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of The Open Group shall
|
|
not be used in advertising or otherwise to promote the sale, use or
|
|
other dealings in this Software without prior written authorization
|
|
from The Open Group.
|
|
|
|
*/
|
|
|
|
/*
|
|
* XDM-AUTHENTICATION-1 (XDMCP authentication) and
|
|
* XDM-AUTHORIZATION-1 (client authorization) protocols
|
|
*
|
|
* Author: Keith Packard, MIT X Consortium
|
|
*/
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <X11/X.h>
|
|
#define XSERV_t
|
|
#define TRANS_SERVER
|
|
#define TRANS_REOPEN
|
|
#include <X11/Xtrans/Xtrans.h>
|
|
#include "os.h"
|
|
#include "osdep.h"
|
|
#include "dixstruct.h"
|
|
|
|
#ifdef HASXDMAUTH
|
|
|
|
static Bool authFromXDMCP;
|
|
|
|
#ifdef XDMCP
|
|
#include <X11/Xmd.h>
|
|
#undef REQUEST
|
|
#include <X11/Xdmcp.h>
|
|
|
|
/* XDM-AUTHENTICATION-1 */
|
|
|
|
static XdmAuthKeyRec privateKey;
|
|
static char XdmAuthenticationName[] = "XDM-AUTHENTICATION-1";
|
|
#define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
|
|
static XdmAuthKeyRec rho;
|
|
|
|
static Bool
|
|
XdmAuthenticationValidator (ARRAY8Ptr privateData, ARRAY8Ptr incomingData,
|
|
xdmOpCode packet_type)
|
|
{
|
|
XdmAuthKeyPtr incoming;
|
|
|
|
XdmcpUnwrap (incomingData->data, (unsigned char *)&privateKey,
|
|
incomingData->data,incomingData->length);
|
|
if (packet_type == ACCEPT) {
|
|
if (incomingData->length != 8)
|
|
return FALSE;
|
|
incoming = (XdmAuthKeyPtr) incomingData->data;
|
|
XdmcpDecrementKey (incoming);
|
|
return XdmcpCompareKeys (incoming, &rho);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static Bool
|
|
XdmAuthenticationGenerator (ARRAY8Ptr privateData, ARRAY8Ptr outgoingData,
|
|
xdmOpCode packet_type)
|
|
{
|
|
outgoingData->length = 0;
|
|
outgoingData->data = 0;
|
|
if (packet_type == REQUEST) {
|
|
if (XdmcpAllocARRAY8 (outgoingData, 8))
|
|
XdmcpWrap ((unsigned char *)&rho, (unsigned char *)&privateKey,
|
|
outgoingData->data, 8);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
XdmAuthenticationAddAuth (int name_len, const char *name,
|
|
int data_len, char *data)
|
|
{
|
|
Bool ret;
|
|
XdmcpUnwrap ((unsigned char *)data, (unsigned char *)&privateKey,
|
|
(unsigned char *)data, data_len);
|
|
authFromXDMCP = TRUE;
|
|
ret = AddAuthorization (name_len, name, data_len, data);
|
|
authFromXDMCP = FALSE;
|
|
return ret;
|
|
}
|
|
|
|
|
|
#define atox(c) ('0' <= c && c <= '9' ? c - '0' : \
|
|
'a' <= c && c <= 'f' ? c - 'a' + 10 : \
|
|
'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
|
|
|
|
static int
|
|
HexToBinary (const char *in, char *out, int len)
|
|
{
|
|
int top, bottom;
|
|
|
|
while (len > 0)
|
|
{
|
|
top = atox(in[0]);
|
|
if (top == -1)
|
|
return 0;
|
|
bottom = atox(in[1]);
|
|
if (bottom == -1)
|
|
return 0;
|
|
*out++ = (top << 4) | bottom;
|
|
in += 2;
|
|
len -= 2;
|
|
}
|
|
if (len)
|
|
return 0;
|
|
*out++ = '\0';
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
XdmAuthenticationInit (const char *cookie, int cookie_len)
|
|
{
|
|
memset(privateKey.data, 0, 8);
|
|
if (!strncmp (cookie, "0x", 2) || !strncmp (cookie, "0X", 2))
|
|
{
|
|
if (cookie_len > 2 + 2 * 8)
|
|
cookie_len = 2 + 2 * 8;
|
|
HexToBinary (cookie + 2, (char *)privateKey.data, cookie_len - 2);
|
|
}
|
|
else
|
|
{
|
|
if (cookie_len > 7)
|
|
cookie_len = 7;
|
|
memmove (privateKey.data + 1, cookie, cookie_len);
|
|
}
|
|
XdmcpGenerateKey (&rho);
|
|
XdmcpRegisterAuthentication (XdmAuthenticationName, XdmAuthenticationNameLen,
|
|
(char *)&rho,
|
|
sizeof (rho),
|
|
(ValidatorFunc)XdmAuthenticationValidator,
|
|
(GeneratorFunc)XdmAuthenticationGenerator,
|
|
(AddAuthorFunc)XdmAuthenticationAddAuth);
|
|
}
|
|
|
|
#endif /* XDMCP */
|
|
|
|
/* XDM-AUTHORIZATION-1 */
|
|
typedef struct _XdmAuthorization {
|
|
struct _XdmAuthorization *next;
|
|
XdmAuthKeyRec rho;
|
|
XdmAuthKeyRec key;
|
|
XID id;
|
|
} XdmAuthorizationRec, *XdmAuthorizationPtr;
|
|
|
|
static XdmAuthorizationPtr xdmAuth;
|
|
|
|
typedef struct _XdmClientAuth {
|
|
struct _XdmClientAuth *next;
|
|
XdmAuthKeyRec rho;
|
|
char client[6];
|
|
long time;
|
|
} XdmClientAuthRec, *XdmClientAuthPtr;
|
|
|
|
static XdmClientAuthPtr xdmClients;
|
|
static long clockOffset;
|
|
static Bool gotClock;
|
|
|
|
#define TwentyMinutes (20 * 60)
|
|
#define TwentyFiveMinutes (25 * 60)
|
|
|
|
static Bool
|
|
XdmClientAuthCompare (const XdmClientAuthPtr a, const XdmClientAuthPtr b)
|
|
{
|
|
int i;
|
|
|
|
if (!XdmcpCompareKeys (&a->rho, &b->rho))
|
|
return FALSE;
|
|
for (i = 0; i < 6; i++)
|
|
if (a->client[i] != b->client[i])
|
|
return FALSE;
|
|
return a->time == b->time;
|
|
}
|
|
|
|
static void
|
|
XdmClientAuthDecode (const unsigned char *plain, XdmClientAuthPtr auth)
|
|
{
|
|
int i, j;
|
|
|
|
j = 0;
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
auth->rho.data[i] = plain[j];
|
|
++j;
|
|
}
|
|
for (i = 0; i < 6; i++)
|
|
{
|
|
auth->client[i] = plain[j];
|
|
++j;
|
|
}
|
|
auth->time = 0;
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
auth->time |= plain[j] << ((3 - i) << 3);
|
|
j++;
|
|
}
|
|
}
|
|
|
|
static void
|
|
XdmClientAuthTimeout (long now)
|
|
{
|
|
XdmClientAuthPtr client, next, prev;
|
|
|
|
prev = 0;
|
|
for (client = xdmClients; client; client=next)
|
|
{
|
|
next = client->next;
|
|
if (abs (now - client->time) > TwentyFiveMinutes)
|
|
{
|
|
if (prev)
|
|
prev->next = next;
|
|
else
|
|
xdmClients = next;
|
|
free(client);
|
|
}
|
|
else
|
|
prev = client;
|
|
}
|
|
}
|
|
|
|
static XdmClientAuthPtr
|
|
XdmAuthorizationValidate (unsigned char *plain, int length,
|
|
XdmAuthKeyPtr rho, ClientPtr xclient, const char **reason)
|
|
{
|
|
XdmClientAuthPtr client, existing;
|
|
long now;
|
|
int i;
|
|
|
|
if (length != (192 / 8)) {
|
|
if (reason)
|
|
*reason = "Bad XDM authorization key length";
|
|
return NULL;
|
|
}
|
|
client = malloc(sizeof (XdmClientAuthRec));
|
|
if (!client)
|
|
return NULL;
|
|
XdmClientAuthDecode (plain, client);
|
|
if (!XdmcpCompareKeys (&client->rho, rho))
|
|
{
|
|
free(client);
|
|
if (reason)
|
|
*reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)";
|
|
return NULL;
|
|
}
|
|
for (i = 18; i < 24; i++)
|
|
if (plain[i] != 0) {
|
|
free(client);
|
|
if (reason)
|
|
*reason = "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)";
|
|
return NULL;
|
|
}
|
|
if (xclient) {
|
|
int family, addr_len;
|
|
Xtransaddr *addr;
|
|
|
|
if (_XSERVTransGetPeerAddr(((OsCommPtr)xclient->osPrivate)->trans_conn,
|
|
&family, &addr_len, &addr) == 0
|
|
&& _XSERVTransConvertAddress(&family, &addr_len, &addr) == 0) {
|
|
#if defined(TCPCONN) || defined(STREAMSCONN)
|
|
if (family == FamilyInternet &&
|
|
memcmp((char *)addr, client->client, 4) != 0) {
|
|
free(client);
|
|
free(addr);
|
|
if (reason)
|
|
*reason = "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)";
|
|
return NULL;
|
|
|
|
}
|
|
#endif
|
|
free(addr);
|
|
}
|
|
}
|
|
now = time(0);
|
|
if (!gotClock)
|
|
{
|
|
clockOffset = client->time - now;
|
|
gotClock = TRUE;
|
|
}
|
|
now += clockOffset;
|
|
XdmClientAuthTimeout (now);
|
|
if (abs (client->time - now) > TwentyMinutes)
|
|
{
|
|
free(client);
|
|
if (reason)
|
|
*reason = "Excessive XDM-AUTHORIZATION-1 time offset";
|
|
return NULL;
|
|
}
|
|
for (existing = xdmClients; existing; existing=existing->next)
|
|
{
|
|
if (XdmClientAuthCompare (existing, client))
|
|
{
|
|
free(client);
|
|
if (reason)
|
|
*reason = "XDM authorization key matches an existing client!";
|
|
return NULL;
|
|
}
|
|
}
|
|
return client;
|
|
}
|
|
|
|
int
|
|
XdmAddCookie (unsigned short data_length, const char *data, XID id)
|
|
{
|
|
XdmAuthorizationPtr new;
|
|
unsigned char *rho_bits, *key_bits;
|
|
|
|
switch (data_length)
|
|
{
|
|
case 16: /* auth from files is 16 bytes long */
|
|
#ifdef XDMCP
|
|
if (authFromXDMCP)
|
|
{
|
|
/* R5 xdm sent bogus authorization data in the accept packet,
|
|
* but we can recover */
|
|
rho_bits = rho.data;
|
|
key_bits = (unsigned char *) data;
|
|
key_bits[0] = '\0';
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
rho_bits = (unsigned char *) data;
|
|
key_bits = (unsigned char *) (data + 8);
|
|
}
|
|
break;
|
|
#ifdef XDMCP
|
|
case 8: /* auth from XDMCP is 8 bytes long */
|
|
rho_bits = rho.data;
|
|
key_bits = (unsigned char *) data;
|
|
break;
|
|
#endif
|
|
default:
|
|
return 0;
|
|
}
|
|
/* the first octet of the key must be zero */
|
|
if (key_bits[0] != '\0')
|
|
return 0;
|
|
new = malloc(sizeof (XdmAuthorizationRec));
|
|
if (!new)
|
|
return 0;
|
|
new->next = xdmAuth;
|
|
xdmAuth = new;
|
|
memmove (new->key.data, key_bits, (int) 8);
|
|
memmove (new->rho.data, rho_bits, (int) 8);
|
|
new->id = id;
|
|
return 1;
|
|
}
|
|
|
|
XID
|
|
XdmCheckCookie (unsigned short cookie_length, const char *cookie,
|
|
ClientPtr xclient, const char **reason)
|
|
{
|
|
XdmAuthorizationPtr auth;
|
|
XdmClientAuthPtr client;
|
|
unsigned char *plain;
|
|
|
|
/* Auth packets must be a multiple of 8 bytes long */
|
|
if (cookie_length & 7)
|
|
return (XID) -1;
|
|
plain = malloc(cookie_length);
|
|
if (!plain)
|
|
return (XID) -1;
|
|
for (auth = xdmAuth; auth; auth=auth->next) {
|
|
XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length);
|
|
if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, xclient, reason)) != NULL)
|
|
{
|
|
client->next = xdmClients;
|
|
xdmClients = client;
|
|
free(plain);
|
|
return auth->id;
|
|
}
|
|
}
|
|
free(plain);
|
|
return (XID) -1;
|
|
}
|
|
|
|
int
|
|
XdmResetCookie (void)
|
|
{
|
|
XdmAuthorizationPtr auth, next_auth;
|
|
XdmClientAuthPtr client, next_client;
|
|
|
|
for (auth = xdmAuth; auth; auth=next_auth)
|
|
{
|
|
next_auth = auth->next;
|
|
free(auth);
|
|
}
|
|
xdmAuth = 0;
|
|
for (client = xdmClients; client; client=next_client)
|
|
{
|
|
next_client = client->next;
|
|
free(client);
|
|
}
|
|
xdmClients = (XdmClientAuthPtr) 0;
|
|
return 1;
|
|
}
|
|
|
|
XID
|
|
XdmToID (unsigned short cookie_length, char *cookie)
|
|
{
|
|
XdmAuthorizationPtr auth;
|
|
XdmClientAuthPtr client;
|
|
unsigned char *plain;
|
|
|
|
plain = malloc(cookie_length);
|
|
if (!plain)
|
|
return (XID) -1;
|
|
for (auth = xdmAuth; auth; auth=auth->next) {
|
|
XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length);
|
|
if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, NULL, NULL)) != NULL)
|
|
{
|
|
free(client);
|
|
free(cookie);
|
|
free(plain);
|
|
return auth->id;
|
|
}
|
|
}
|
|
free(cookie);
|
|
free(plain);
|
|
return (XID) -1;
|
|
}
|
|
|
|
int
|
|
XdmFromID (XID id, unsigned short *data_lenp, char **datap)
|
|
{
|
|
XdmAuthorizationPtr auth;
|
|
|
|
for (auth = xdmAuth; auth; auth=auth->next) {
|
|
if (id == auth->id) {
|
|
*data_lenp = 16;
|
|
*datap = (char *) &auth->rho;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
XdmRemoveCookie (unsigned short data_length, const char *data)
|
|
{
|
|
XdmAuthorizationPtr auth;
|
|
XdmAuthKeyPtr key_bits, rho_bits;
|
|
|
|
switch (data_length)
|
|
{
|
|
case 16:
|
|
rho_bits = (XdmAuthKeyPtr) data;
|
|
key_bits = (XdmAuthKeyPtr) (data + 8);
|
|
break;
|
|
#ifdef XDMCP
|
|
case 8:
|
|
rho_bits = ρ
|
|
key_bits = (XdmAuthKeyPtr) data;
|
|
break;
|
|
#endif
|
|
default:
|
|
return 0;
|
|
}
|
|
for (auth = xdmAuth; auth; auth=auth->next) {
|
|
if (XdmcpCompareKeys (rho_bits, &auth->rho) &&
|
|
XdmcpCompareKeys (key_bits, &auth->key))
|
|
{
|
|
xdmAuth = auth->next;
|
|
free(auth);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif
|