home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / server / os / xdmauth.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-21  |  9.6 KB  |  450 lines

  1. /*
  2.  * XDM-AUTHENTICATION-1 (XDMCP authentication) and
  3.  * XDM-AUTHORIZATION-1 (client authorization) protocols
  4.  *
  5.  * $XConsortium: xdmauth.c,v 1.6 92/05/19 17:24:20 keith Exp $
  6.  *
  7.  * Copyright 1988 Massachusetts Institute of Technology
  8.  *
  9.  * Permission to use, copy, modify, and distribute this software and its
  10.  * documentation for any purpose and without fee is hereby granted, provided
  11.  * that the above copyright notice appear in all copies and that both that
  12.  * copyright notice and this permission notice appear in supporting
  13.  * documentation, and that the name of M.I.T. not be used in advertising or
  14.  * publicity pertaining to distribution of the software without specific,
  15.  * written prior permission.  M.I.T. makes no representations about the
  16.  * suitability of this software for any purpose.  It is provided "as is"
  17.  * without express or implied warranty.
  18.  *
  19.  * Author:  Keith Packard, MIT X Consortium
  20.  */
  21.  
  22. #include "X.h"
  23. #include "os.h"
  24.  
  25. #ifdef HASXDMAUTH
  26.  
  27. static Bool authFromXDMCP;
  28.  
  29. #ifdef XDMCP
  30. #include "Xmd.h"
  31. #include "Xdmcp.h"
  32.  
  33. /* XDM-AUTHENTICATION-1 */
  34.  
  35. static XdmAuthKeyRec    privateKey;
  36. static char XdmAuthenticationName[] = "XDM-AUTHENTICATION-1";
  37. #define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
  38. static XdmAuthKeyRec    rho;
  39.  
  40. static Bool XdmAuthenticationValidator (privateData, incomingData, packet_type)
  41.     ARRAY8Ptr    privateData, incomingData;
  42.     xdmOpCode    packet_type;
  43. {
  44.     XdmAuthKeyPtr    incoming;
  45.  
  46.     XdmcpUnwrap (incomingData->data, &privateKey,
  47.                   incomingData->data,incomingData->length);
  48.     switch (packet_type)
  49.     {
  50.     case ACCEPT:
  51.         if (incomingData->length != 8)
  52.         return FALSE;
  53.         incoming = (XdmAuthKeyPtr) incomingData->data;
  54.         XdmcpDecrementKey (incoming);
  55.         return XdmcpCompareKeys (incoming, &rho);
  56.     }
  57.     return FALSE;
  58. }
  59.  
  60. static Bool
  61. XdmAuthenticationGenerator (privateData, outgoingData, packet_type)
  62.     ARRAY8Ptr    privateData, outgoingData;
  63.     xdmOpCode    packet_type;
  64. {
  65.     outgoingData->length = 0;
  66.     outgoingData->data = 0;
  67.     switch (packet_type)
  68.     {
  69.     case REQUEST:
  70.     if (XdmcpAllocARRAY8 (outgoingData, 8))
  71.         XdmcpWrap (&rho, &privateKey, outgoingData->data, 8);
  72.     }
  73.     return TRUE;
  74. }
  75.  
  76. static Bool
  77. XdmAuthenticationAddAuth (name_len, name, data_len, data)
  78.     int        name_len, data_len;
  79.     char    *name, *data;
  80. {
  81.     Bool    ret;
  82.     XdmcpUnwrap (data, &privateKey, data, data_len);
  83.     authFromXDMCP = TRUE;
  84.     ret = AddAuthorization (name_len, name, data_len, data);
  85.     authFromXDMCP = FALSE;
  86.     return ret;
  87. }
  88.  
  89.  
  90. #define atox(c)    ('0' <= c && c <= '9' ? c - '0' : \
  91.          'a' <= c && c <= 'f' ? c - 'a' + 10 : \
  92.          'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
  93.  
  94. static
  95. HexToBinary (in, out, len)
  96.     char    *out, *in;
  97. {
  98.     int        top, bottom;
  99.  
  100.     while (len > 0)
  101.     {
  102.     top = atox(in[0]);
  103.     if (top == -1)
  104.         return 0;
  105.     bottom = atox(in[1]);
  106.     if (bottom == -1)
  107.         return 0;
  108.     *out++ = (top << 4) | bottom;
  109.     in += 2;
  110.     len -= 2;
  111.     }
  112.     if (len)
  113.     return 0;
  114.     *out++ = '\0';
  115.     return 1;
  116. }
  117.  
  118. XdmAuthenticationInit (cookie, cookie_len)
  119.     char    *cookie;
  120.     int        cookie_len;
  121. {
  122.     bzero (privateKey.data, 8);
  123.     if (!strncmp (cookie, "0x", 2) || !strncmp (cookie, "0X", 2))
  124.     {
  125.     if (cookie_len > 2 + 2 * 8)
  126.         cookie_len = 2 + 2 * 8;
  127.     HexToBinary (cookie + 2, privateKey.data, cookie_len - 2);
  128.     }
  129.     else
  130.     {
  131.         if (cookie_len > 7)
  132.         cookie_len = 7;
  133.         bcopy (cookie, privateKey.data + 1, cookie_len);
  134.     }
  135.     XdmcpGenerateKey (&rho);
  136.     XdmcpRegisterAuthentication (XdmAuthenticationName, XdmAuthenticationNameLen,
  137.                  &rho,
  138.                  sizeof (rho),
  139.                  XdmAuthenticationValidator,
  140.                  XdmAuthenticationGenerator,
  141.                  XdmAuthenticationAddAuth);
  142. }
  143.  
  144. #endif /* XDMCP */
  145.  
  146. /* XDM-AUTHORIZATION-1 */
  147. typedef struct _XdmAuthorization {
  148.     struct _XdmAuthorization    *next;
  149.     XdmAuthKeyRec        rho;
  150.     XdmAuthKeyRec        key;
  151.     XID                id;
  152. } XdmAuthorizationRec, *XdmAuthorizationPtr;
  153.  
  154. XdmAuthorizationPtr xdmAuth;
  155.  
  156. typedef struct _XdmClientAuth {
  157.     struct _XdmClientAuth   *next;
  158.     XdmAuthKeyRec        rho;
  159.     char            client[6];
  160.     long            time;
  161. } XdmClientAuthRec, *XdmClientAuthPtr;
  162.  
  163. XdmClientAuthPtr    xdmClients;
  164. static long        clockOffset;
  165. static Bool        gotClock;
  166.  
  167. #define TwentyMinutes    (20 * 60)
  168.  
  169. static Bool
  170. XdmClientAuthCompare (a, b)
  171.     XdmClientAuthPtr    a, b;
  172. {
  173.     int    i;
  174.  
  175.     if (!XdmcpCompareKeys (&a->rho, &b->rho))
  176.     return FALSE;
  177.     for (i = 0; i < 6; i++)
  178.     if (a->client[i] != b->client[i])
  179.         return FALSE;
  180.     return a->time == b->time;
  181. }
  182.  
  183. static
  184. XdmClientAuthDecode (plain, auth)
  185.     unsigned char    *plain;
  186.     XdmClientAuthPtr    auth;
  187. {
  188.     int        i, j;
  189.  
  190.     j = 0;
  191.     for (i = 0; i < 8; i++)
  192.     {
  193.     auth->rho.data[i] = plain[j];
  194.     ++j;
  195.     }
  196.     for (i = 0; i < 6; i++)
  197.     {
  198.     auth->client[i] = plain[j];
  199.     ++j;
  200.     }
  201.     auth->time = 0;
  202.     for (i = 0; i < 4; i++)
  203.     {
  204.     auth->time |= plain[j] << ((3 - i) << 3);
  205.     j++;
  206.     }
  207. }
  208.  
  209. XdmClientAuthTimeout (now)
  210.     long    now;
  211. {
  212.     XdmClientAuthPtr    client, next, prev;
  213.  
  214.     prev = 0;
  215.     for (client = xdmClients; client; client=next)
  216.     {
  217.     next = client->next;
  218.     if (abs (now - client->time) > TwentyMinutes)
  219.     {
  220.         if (prev)
  221.         prev->next = next;
  222.         else
  223.         xdmClients = next;
  224.         xfree (client);
  225.     }
  226.     else
  227.         prev = client;
  228.     }
  229. }
  230.  
  231. static XdmClientAuthPtr
  232. XdmAuthorizationValidate (plain, length, rho)
  233.     char        *plain;
  234.     int            length;
  235.     XdmAuthKeyPtr    rho;
  236. {
  237.     XdmClientAuthPtr    client, existing;
  238.     long        now;
  239.  
  240.     if (length != (192 / 8))
  241.     return NULL;
  242.     client = (XdmClientAuthPtr) xalloc (sizeof (XdmClientAuthRec));
  243.     if (!client)
  244.     return NULL;
  245.     XdmClientAuthDecode (plain, client);
  246.     if (!XdmcpCompareKeys (&client->rho, rho))
  247.     {
  248.     xfree (client);
  249.     return NULL;
  250.     }
  251.     now = time(0);
  252.     if (!gotClock)
  253.     {
  254.     clockOffset = client->time - now;
  255.     gotClock = TRUE;
  256.     }
  257.     now += clockOffset;
  258.     XdmClientAuthTimeout (now);
  259.     if (abs (client->time - now) > TwentyMinutes)
  260.     {
  261.     xfree (client);
  262.     return NULL;
  263.     }
  264.     for (existing = xdmClients; existing; existing=existing->next)
  265.     {
  266.     if (XdmClientAuthCompare (existing, client))
  267.     {
  268.         xfree (client);
  269.         return NULL;
  270.     }
  271.     }
  272.     return client;
  273. }
  274.  
  275. int
  276. XdmAddCookie (data_length, data, id)
  277. unsigned short    data_length;
  278. char    *data;
  279. XID    id;
  280. {
  281.     XdmAuthorizationPtr    new;
  282.     unsigned char    *rho_bits, *key_bits;
  283.  
  284.     switch (data_length)
  285.     {
  286.     case 16:            /* auth from files is 16 bytes long */
  287.     if (authFromXDMCP)
  288.     {
  289.         /* R5 xdm sent bogus authorization data in the accept packet,
  290.          * but we can recover */
  291.         rho_bits = rho.data;
  292.         key_bits = (unsigned char *) data;
  293.         key_bits[0] = '\0';
  294.     }
  295.     else
  296.     {
  297.         rho_bits = (unsigned char *) data;
  298.         key_bits = (unsigned char *) (data + 8);
  299.     }
  300.     break;
  301.     case 8:            /* auth from XDMCP is 8 bytes long */
  302.     rho_bits = rho.data;
  303.     key_bits = (unsigned char *) data;
  304.     break;
  305.     default:
  306.     return 0;
  307.     }
  308.     /* the first octet of the key must be zero */
  309.     if (key_bits[0] != '\0')
  310.     return 0;
  311.     new = (XdmAuthorizationPtr) xalloc (sizeof (XdmAuthorizationRec));
  312.     if (!new)
  313.     return 0;
  314.     new->next = xdmAuth;
  315.     xdmAuth = new;
  316.     bcopy (key_bits, new->key.data, (int) 8);
  317.     bcopy (rho_bits, new->rho.data, (int) 8);
  318.     new->id = id;
  319.     return 1;
  320. }
  321.  
  322. XID
  323. XdmCheckCookie (cookie_length, cookie)
  324. unsigned short    cookie_length;
  325. char    *cookie;
  326. {
  327.     XdmAuthorizationPtr    auth;
  328.     XdmClientAuthPtr    client;
  329.     char        *plain;
  330.  
  331.     /* Auth packets must be a multiple of 8 bytes long */
  332.     if (cookie_length & 7)
  333.     return (XID) -1;
  334.     plain = (char *) xalloc (cookie_length);
  335.     if (!plain)
  336.     return (XID) -1;
  337.     for (auth = xdmAuth; auth; auth=auth->next) {
  338.     XdmcpUnwrap (cookie, &auth->key, plain, cookie_length);
  339.     if (client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho))
  340.     {
  341.         client->next = xdmClients;
  342.         xdmClients = client;
  343.         xfree (plain);
  344.         return auth->id;
  345.     }
  346.     }
  347.     xfree (plain);
  348.     return (XID) -1;
  349. }
  350.  
  351. int
  352. XdmResetCookie ()
  353. {
  354.     XdmAuthorizationPtr    auth, next_auth;
  355.     XdmClientAuthPtr    client, next_client;
  356.  
  357.     for (auth = xdmAuth; auth; auth=next_auth)
  358.     {
  359.     next_auth = auth->next;
  360.     xfree (auth);
  361.     }
  362.     xdmAuth = 0;
  363.     for (client = xdmClients; client; client=next_client)
  364.     {
  365.     next_client = client->next;
  366.     xfree (client);
  367.     }
  368.     xdmClients = (XdmClientAuthPtr) 0;
  369. }
  370.  
  371. XID
  372. XdmToID (cookie_length, cookie)
  373. unsigned short    cookie_length;
  374. char    *cookie;
  375. {
  376.     XdmAuthorizationPtr    auth;
  377.     XdmClientAuthPtr    client;
  378.     char        *plain;
  379.  
  380.     plain = (char *) xalloc (cookie_length);
  381.     if (!plain)
  382.     return (XID) -1;
  383.     for (auth = xdmAuth; auth; auth=auth->next) {
  384.     XdmcpUnwrap (cookie, &auth->key, plain, cookie_length);
  385.     if (client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho))
  386.     {
  387.         xfree (client);
  388.         xfree (cookie);
  389.         return auth->id;
  390.     }
  391.     }
  392.     xfree (cookie);
  393.     return (XID) -1;
  394. }
  395.  
  396. XdmFromID (id, data_lenp, datap)
  397. XID id;
  398. unsigned short    *data_lenp;
  399. char    **datap;
  400. {
  401.     XdmAuthorizationPtr    auth;
  402.  
  403.     for (auth = xdmAuth; auth; auth=auth->next) {
  404.     if (id == auth->id) {
  405.         *data_lenp = 16;
  406.         *datap = (char *) &auth->rho;
  407.         return 1;
  408.     }
  409.     }
  410.     return 0;
  411. }
  412.  
  413. XdmRemoveCookie (data_length, data)
  414. unsigned short    data_length;
  415. char    *data;
  416. {
  417.     XdmAuthorizationPtr    auth, prev;
  418.     XdmAuthKeyPtr    key_bits, rho_bits;
  419.  
  420.     prev = 0;
  421.     switch (data_length)
  422.     {
  423.     case 16:
  424.     rho_bits = (XdmAuthKeyPtr) data;
  425.     key_bits = (XdmAuthKeyPtr) (data + 8);
  426.     break;
  427.     case 8:
  428.     rho_bits = ρ
  429.     key_bits = (XdmAuthKeyPtr) data;
  430.     break;
  431.     default:
  432.     return;
  433.     }
  434.     for (auth = xdmAuth; auth; auth=auth->next) {
  435.     if (XdmcpCompareKeys (rho_bits, &auth->rho) &&
  436.         XdmcpCompareKeys (key_bits, &auth->key))
  437.      {
  438.         if (prev)
  439.         prev->next = auth->next;
  440.         else
  441.         xdmAuth = auth->next;
  442.         xfree (auth);
  443.         return 1;
  444.     }
  445.     }
  446.     return 0;
  447. }
  448.  
  449. #endif
  450.