Home | History | Annotate | Line # | Download | only in xdm
      1 /*
      2 
      3 Copyright 1988, 1998  The Open Group
      4 
      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
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included
     12 in all copies or substantial portions of the Software.
     13 
     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.
     21 
     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
     25 from The Open Group.
     26 
     27 */
     28 /*
     29  * xdm - display manager daemon
     30  * Author:  Keith Packard, MIT X Consortium
     31  *
     32  * xdmauth
     33  *
     34  * generate authorization data for XDM-AUTHORIZATION-1 as per XDMCP spec
     35  */
     36 
     37 #include "dm.h"
     38 #include "dm_auth.h"
     39 #include "dm_error.h"
     40 
     41 #ifdef HASXDMAUTH
     42 
     43 static char	auth_name[256];
     44 static int	auth_name_len;
     45 
     46 static void
     47 XdmPrintDataHex (const char *s, const char *a, int l)
     48 {
     49     int	i;
     50 
     51     Debug ("%s", s);
     52     for (i = 0; i < l; i++)
     53 	Debug (" %02x", a[i] & 0xff);
     54     Debug ("\n");
     55 }
     56 
     57 # ifdef XDMCP
     58 static void
     59 XdmPrintArray8Hex (const char *s, ARRAY8Ptr a)
     60 {
     61     XdmPrintDataHex (s, (char *) a->data, a->length);
     62 }
     63 # endif
     64 
     65 void
     66 XdmInitAuth (unsigned short name_len, char *name)
     67 {
     68     if (name_len > 256)
     69 	name_len = 256;
     70     auth_name_len = name_len;
     71     memmove( auth_name, name, name_len);
     72 }
     73 
     74 /*
     75  * Generate authorization for XDM-AUTHORIZATION-1
     76  *
     77  * When being used with XDMCP, 8 bytes are generated for the session key
     78  * (sigma), as the random number (rho) is already shared between xdm and
     79  * the server.  Otherwise, we'll prepend a random number to pass in the file
     80  * between xdm and the server (16 bytes total)
     81  */
     82 
     83 static Xauth *
     84 XdmGetAuthHelper (unsigned short namelen, char *name, int includeRho)
     85 {
     86     Xauth   *new;
     87     new = malloc (sizeof (Xauth));
     88 
     89     if (!new)
     90 	return (Xauth *) 0;
     91     new->family = FamilyWild;
     92     new->address_length = 0;
     93     new->address = NULL;
     94     new->number_length = 0;
     95     new->number = NULL;
     96     if (includeRho)
     97 	new->data_length = 16;
     98     else
     99 	new->data_length = 8;
    100 
    101     new->data = malloc (new->data_length);
    102     if (!new->data)
    103     {
    104 	free (new);
    105 	return (Xauth *) 0;
    106     }
    107     new->name = malloc (namelen);
    108     if (!new->name)
    109     {
    110 	free (new->data);
    111 	free (new);
    112 	return (Xauth *) 0;
    113     }
    114     memcpy(new->name, name, namelen);
    115     new->name_length = namelen;
    116     if (!GenerateAuthData ((char *)new->data, new->data_length))
    117     {
    118 	free (new->name);
    119 	free (new->data);
    120 	free (new);
    121 	return (Xauth *) 0;
    122     }
    123     /*
    124      * set the first byte of the session key to zero as it
    125      * is a DES key and only uses 56 bits
    126      */
    127     ((char *)new->data)[new->data_length - 8] = '\0';
    128     XdmPrintDataHex ("Local server auth", (char *)new->data, new->data_length);
    129     return new;
    130 }
    131 
    132 Xauth *
    133 XdmGetAuth (unsigned short namelen, char *name)
    134 {
    135     return XdmGetAuthHelper (namelen, name, TRUE);
    136 }
    137 
    138 # ifdef XDMCP
    139 
    140 void
    141 XdmGetXdmcpAuth (struct protoDisplay *pdpy,
    142     unsigned short authorizationNameLen, char *authorizationName)
    143 {
    144     Xauth   *fileauth, *xdmcpauth;
    145 
    146     if (pdpy->fileAuthorization && pdpy->xdmcpAuthorization)
    147 	return;
    148     xdmcpauth = XdmGetAuthHelper (authorizationNameLen, authorizationName, FALSE);
    149     if (!xdmcpauth)
    150 	return;
    151     fileauth = malloc (sizeof (Xauth));
    152     if (!fileauth)
    153     {
    154 	XauDisposeAuth(xdmcpauth);
    155 	return;
    156     }
    157     /* build the file auth from the XDMCP auth */
    158     *fileauth = *xdmcpauth;
    159     fileauth->name = malloc (xdmcpauth->name_length);
    160     fileauth->data = malloc (16);
    161     fileauth->data_length = 16;
    162     if (!fileauth->name || !fileauth->data)
    163     {
    164 	XauDisposeAuth (xdmcpauth);
    165 	free (fileauth->name);
    166 	free (fileauth->data);
    167 	free (fileauth);
    168 	return;
    169     }
    170     /*
    171      * for the file authorization, prepend the random number (rho)
    172      * which is simply the number we've been passing back and
    173      * forth via XDMCP
    174      */
    175     memcpy(fileauth->name, xdmcpauth->name, xdmcpauth->name_length);
    176     memcpy(fileauth->data, pdpy->authenticationData.data, 8);
    177     memcpy(fileauth->data + 8, xdmcpauth->data, 8);
    178     XdmPrintDataHex ("Accept packet auth", xdmcpauth->data, xdmcpauth->data_length);
    179     XdmPrintDataHex ("Auth file auth", fileauth->data, fileauth->data_length);
    180     /* encrypt the session key for its trip back to the server */
    181     XdmcpWrap ((unsigned char *)xdmcpauth->data, (unsigned char *)&pdpy->key,
    182 	       (unsigned char *)xdmcpauth->data, 8);
    183     pdpy->fileAuthorization = fileauth;
    184     pdpy->xdmcpAuthorization = xdmcpauth;
    185 }
    186 
    187 #  define atox(c)	('0' <= c && c <= '9' ? c - '0' : \
    188 		 'a' <= c && c <= 'f' ? c - 'a' + 10 : \
    189 		 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
    190 
    191 static int
    192 HexToBinary(char *key)
    193 {
    194     char    *out, *in;
    195     int	    top, bottom;
    196 
    197     in = key + 2;
    198     out= key;
    199     while (in[0] && in[1])
    200     {
    201 	top = atox(in[0]);
    202 	if (top == -1)
    203 	    return 0;
    204 	bottom = atox(in[1]);
    205 	if (bottom == -1)
    206 	    return 0;
    207 	*out++ = (top << 4) | bottom;
    208 	in += 2;
    209     }
    210     if (in[0])
    211 	return 0;
    212     *out++ = '\0';
    213     return 1;
    214 }
    215 
    216 /*
    217  * Search the Keys file for the entry matching this display.  This
    218  * routine accepts either plain ascii strings for keys, or hex-encoded numbers
    219  */
    220 
    221 static int
    222 XdmGetKey(struct protoDisplay *pdpy, ARRAY8Ptr displayID)
    223 {
    224     FILE    *keys;
    225     char    line[1024], id[1024], key[1024];
    226     int	    keylen;
    227 
    228     Debug ("Lookup key for %*.*s\n", displayID->length, displayID->length, displayID->data);
    229     keys = fopen (keyFile, "r");
    230     if (!keys)
    231 	return FALSE;
    232     while (fgets (line, sizeof (line) -  1, keys))
    233     {
    234 	if (line[0] == '#' || sscanf (line, "%s %s", id, key) != 2)
    235 	    continue;
    236 	bzero(line, sizeof(line));
    237 	Debug ("Key entry for \"%s\" %zu bytes\n", id, strlen(key));
    238 	if (strlen (id) == displayID->length &&
    239 	    !strncmp (id, (char *)displayID->data, displayID->length))
    240 	{
    241 	    if (!strncmp (key, "0x", 2) || !strncmp (key, "0X", 2))
    242 		if (!HexToBinary (key))
    243 		    break;
    244 	    keylen = strlen (key);
    245 	    while (keylen < 7)
    246 		key[keylen++] = '\0';
    247 	    pdpy->key.data[0] = '\0';
    248 	    memcpy(pdpy->key.data + 1, key, 7);
    249 	    bzero(key, sizeof(key));
    250 	    fclose (keys);
    251 	    return TRUE;
    252 	}
    253     }
    254     bzero(line, sizeof(line));
    255     bzero(key, sizeof(key));
    256     fclose (keys);
    257     return FALSE;
    258 }
    259 
    260 /*ARGSUSED*/
    261 int
    262 XdmCheckAuthentication(struct protoDisplay *pdpy, ARRAY8Ptr displayID,
    263     ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData)
    264 {
    265     XdmAuthKeyPtr   incoming;
    266 
    267     if (!XdmGetKey (pdpy, displayID))
    268 	return FALSE;
    269     if (authenticationData->length != 8)
    270 	return FALSE;
    271     XdmcpUnwrap (authenticationData->data, (unsigned char *)&pdpy->key,
    272 		  authenticationData->data, 8);
    273     XdmPrintArray8Hex ("Request packet auth", authenticationData);
    274     if (!XdmcpCopyARRAY8(authenticationData, &pdpy->authenticationData))
    275 	return FALSE;
    276     incoming = (XdmAuthKeyPtr) authenticationData->data;
    277     XdmcpIncrementKey (incoming);
    278     XdmcpWrap (authenticationData->data, (unsigned char *)&pdpy->key,
    279 		  authenticationData->data, 8);
    280     return TRUE;
    281 }
    282 
    283 # endif /* XDMCP */
    284 #endif /* HASXDMAUTH (covering the entire file) */
    285