home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / rpc / auth_des.c next >
Encoding:
C/C++ Source or Header  |  1994-09-15  |  10.6 KB  |  415 lines

  1. #if defined(LIBC_SCCS) && !defined(lint)
  2. static char sccsid[] =     "@(#)auth_des.c    2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI";
  3. #endif
  4. /*
  5.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  6.  * unrestricted use provided that this legend is included on all tape
  7.  * media and as a part of the software program in whole or part.  Users
  8.  * may copy or modify Sun RPC without charge, but are not authorized
  9.  * to license or distribute it to anyone else except as part of a product or
  10.  * program developed by the user.
  11.  * 
  12.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  13.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  14.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  15.  * 
  16.  * Sun RPC is provided with no support and without any obligation on the
  17.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  18.  * modification or enhancement.
  19.  * 
  20.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  21.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  22.  * OR ANY PART THEREOF.
  23.  * 
  24.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  25.  * or profits or other special, indirect and consequential damages, even if
  26.  * Sun has been advised of the possibility of such damages.
  27.  * 
  28.  * Sun Microsystems, Inc.
  29.  * 2550 Garcia Avenue
  30.  * Mountain View, California  94043
  31.  */
  32. /*
  33.  * Copyright (c) 1988 by Sun Microsystems, Inc.
  34.  */
  35. /*
  36.  * auth_des.c, client-side implementation of DES authentication
  37.  */
  38.  
  39. #include <des_crypt.h>
  40. #include <rpc/types.h>
  41. #include <rpc/auth.h>
  42. #include <rpc/auth_des.h>
  43. #include <rpc/xdr.h>
  44. #include <netinet/in.h>    /* XXX: just to get htonl() and ntohl() */
  45. #include <sys/socket.h>
  46.  
  47. #define MILLION        1000000L
  48. #define RTIME_TIMEOUT 5        /* seconds to wait for sync */
  49.  
  50. #define AUTH_PRIVATE(auth)    (struct ad_private *) auth->ah_private
  51. #define ALLOC(object_type)    (object_type *) mem_alloc(sizeof(object_type))
  52. #define FREE(ptr, size)        mem_free((char *)(ptr), (int) size)
  53. #define ATTEMPT(xdr_op)        if (!(xdr_op)) return (FALSE)
  54.  
  55. #define debug(msg)         /*printf("%s\n", msg) */
  56.  
  57. /* 
  58.  * DES authenticator operations vector
  59.  */
  60. static void    authdes_nextverf();
  61. static bool_t    authdes_marshal();
  62. static bool_t    authdes_validate();
  63. static bool_t    authdes_refresh();
  64. static void    authdes_destroy();
  65.  
  66. static bool_t   synchronize();
  67.  
  68. static struct auth_ops authdes_ops = {
  69.     authdes_nextverf,
  70.     authdes_marshal,
  71.     authdes_validate,
  72.     authdes_refresh,
  73.     authdes_destroy
  74. };
  75.  
  76.  
  77. /*
  78.  * This struct is pointed to by the ah_private field of an "AUTH *"
  79.  */
  80. struct ad_private {
  81.     char *ad_fullname;         /* client's full name */
  82.     u_int ad_fullnamelen;        /* length of name, rounded up */
  83.     char *ad_servername;         /* server's full name */
  84.     u_int ad_servernamelen;        /* length of name, rounded up */
  85.     u_int ad_window;          /* client specified window */
  86.     bool_t ad_dosync;        /* synchronize? */        
  87.     struct sockaddr ad_syncaddr;    /* remote host to synch with */
  88.     struct timeval ad_timediff;    /* server's time - client's time */
  89.     u_long ad_nickname;        /* server's nickname for client */
  90.     struct authdes_cred ad_cred;    /* storage for credential */
  91.     struct authdes_verf ad_verf;    /* storage for verifier */
  92.     struct timeval ad_timestamp;    /* timestamp sent */
  93.     des_block ad_xkey;        /* encrypted conversation key */
  94. };
  95.     
  96.  
  97. /*
  98.  * Create the client des authentication object
  99.  */    
  100. AUTH *
  101. authdes_create(servername, window, syncaddr, ckey)
  102.     char *servername;        /* network name of server */
  103.     u_int window;            /* time to live */
  104.     struct sockaddr *syncaddr;    /* optional addr of host to sync with */
  105.     des_block *ckey;        /* optional conversation key to use*/
  106. {
  107.  
  108.     AUTH *auth;
  109.     struct ad_private *ad;
  110.     char namebuf[MAXNETNAMELEN+1];
  111.  
  112.     /*
  113.       * Allocate everything now
  114.      */
  115.     auth = ALLOC(AUTH);
  116.     ad = ALLOC(struct ad_private);
  117.     (void) getnetname(namebuf);
  118.  
  119.     ad->ad_fullnamelen = RNDUP(strlen(namebuf));
  120.     ad->ad_fullname = mem_alloc(ad->ad_fullnamelen + 1);
  121.  
  122.     ad->ad_servernamelen = strlen(servername);
  123.     ad->ad_servername = mem_alloc(ad->ad_servernamelen + 1);
  124.  
  125.     if (auth == NULL || ad == NULL || ad->ad_fullname == NULL ||
  126.         ad->ad_servername == NULL) {
  127.         debug("authdes_create: out of memory");
  128.         goto failed;
  129.     }
  130.  
  131.     /* 
  132.      * Set up private data
  133.      */
  134.     bcopy(namebuf, ad->ad_fullname, ad->ad_fullnamelen + 1);
  135.     bcopy(servername, ad->ad_servername, ad->ad_servernamelen + 1);
  136.     if (syncaddr != NULL) {
  137.         ad->ad_syncaddr = *syncaddr;
  138.         ad->ad_dosync = TRUE;
  139.     } else {
  140.         ad->ad_dosync = FALSE;
  141.     }
  142.     ad->ad_window = window;
  143.     if (ckey == NULL) {
  144.         if (key_gendes(&auth->ah_key) < 0) {
  145.             debug("authdes_create: unable to gen conversation key");
  146.             return (NULL);
  147.         }
  148.     } else {
  149.         auth->ah_key = *ckey;
  150.     }
  151.  
  152.     /*
  153.      * Set up auth handle
  154.      */ 
  155.     auth->ah_cred.oa_flavor = AUTH_DES;
  156.     auth->ah_verf.oa_flavor = AUTH_DES;
  157.     auth->ah_ops = &authdes_ops;
  158.     auth->ah_private = (caddr_t)ad;
  159.  
  160.     if (!authdes_refresh(auth)) {
  161.         goto failed;
  162.     }    
  163.     return (auth);
  164.  
  165. failed:
  166.     if (auth != NULL) 
  167.         FREE(auth, sizeof(AUTH)); 
  168.     if (ad != NULL) 
  169.         FREE(ad, sizeof(struct ad_private));
  170.     if (ad->ad_fullname != NULL) 
  171.         FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
  172.     if (ad->ad_servername != NULL) 
  173.         FREE(ad->ad_servername, ad->ad_servernamelen + 1);
  174.     return (NULL);
  175. }
  176.  
  177. /*
  178.  * Implement the five authentication operations
  179.  */
  180.  
  181.  
  182. /*
  183.  * 1. Next Verifier
  184.  */    
  185. /*ARGSUSED*/
  186. static void
  187. authdes_nextverf(auth)
  188.     AUTH *auth;
  189. {
  190.     /* what the heck am I supposed to do??? */
  191. }
  192.         
  193.  
  194.  
  195. /*
  196.  * 2. Marshal
  197.  */
  198. static bool_t
  199. authdes_marshal(auth, xdrs)
  200.     AUTH *auth;
  201.     XDR *xdrs;
  202. {
  203.     struct ad_private *ad = AUTH_PRIVATE(auth);
  204.     struct authdes_cred *cred = &ad->ad_cred;
  205.     struct authdes_verf *verf = &ad->ad_verf;
  206.     des_block cryptbuf[2];    
  207.     des_block ivec;
  208.     int status;
  209.     int len;
  210.     register long *ixdr;
  211.  
  212.     /*
  213.      * Figure out the "time", accounting for any time difference
  214.      * with the server if necessary.
  215.      */
  216.     (void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL);
  217.     ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
  218.     ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
  219.     if (ad->ad_timestamp.tv_usec >= MILLION) {
  220.         ad->ad_timestamp.tv_usec -= MILLION;
  221.         ad->ad_timestamp.tv_sec += 1;
  222.     }
  223.  
  224.     /*
  225.      * XDR the timestamp and possibly some other things, then
  226.      * encrypt them.
  227.      */
  228.     ixdr = (long *)cryptbuf;
  229.     IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_sec);
  230.     IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_usec);
  231.     if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
  232.         IXDR_PUT_U_LONG(ixdr, ad->ad_window);
  233.         IXDR_PUT_U_LONG(ixdr, ad->ad_window - 1);
  234.         ivec.key.high = ivec.key.low = 0;    
  235.         status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf, 
  236.             2*sizeof(des_block), DES_ENCRYPT | DES_HW, (char *)&ivec);
  237.     } else {
  238.         status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf, 
  239.             sizeof(des_block), DES_ENCRYPT | DES_HW);
  240.     }
  241.     if (DES_FAILED(status)) {
  242.         debug("authdes_marshal: DES encryption failure");
  243.         return (FALSE);
  244.     }
  245.     ad->ad_verf.adv_xtimestamp = cryptbuf[0];
  246.     if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
  247.         ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
  248.         ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
  249.     } else {
  250.         ad->ad_cred.adc_nickname = ad->ad_nickname;
  251.         ad->ad_verf.adv_winverf = 0;
  252.     }
  253.  
  254.     /*
  255.      * Serialize the credential and verifier into opaque
  256.      * authentication data.
  257.      */
  258.     if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
  259.         len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
  260.     } else {
  261.         len = (1 + 1)*BYTES_PER_XDR_UNIT;
  262.     }
  263.  
  264.     if (ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT)) {
  265.         IXDR_PUT_LONG(ixdr, AUTH_DES);
  266.         IXDR_PUT_LONG(ixdr, len);
  267.     } else {
  268.         ATTEMPT(xdr_putlong(xdrs, &auth->ah_cred.oa_flavor)); 
  269.         ATTEMPT(xdr_putlong(xdrs, &len)); 
  270.     }
  271.     ATTEMPT(xdr_authdes_cred(xdrs, cred));
  272.  
  273.     len = (2 + 1)*BYTES_PER_XDR_UNIT; 
  274.     if (ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT)) {
  275.         IXDR_PUT_LONG(ixdr, AUTH_DES);
  276.         IXDR_PUT_LONG(ixdr, len);
  277.     } else {
  278.         ATTEMPT(xdr_putlong(xdrs, &auth->ah_verf.oa_flavor)); 
  279.         ATTEMPT(xdr_putlong(xdrs, &len)); 
  280.     }
  281.     ATTEMPT(xdr_authdes_verf(xdrs, verf));
  282.     return (TRUE);
  283. }
  284.  
  285.  
  286. /*
  287.  * 3. Validate
  288.  */
  289. static bool_t
  290. authdes_validate(auth, rverf)
  291.     AUTH *auth;
  292.     struct opaque_auth *rverf;
  293. {
  294.     struct ad_private *ad = AUTH_PRIVATE(auth);
  295.     struct authdes_verf verf;
  296.     int status;
  297.     register u_long *ixdr;
  298.  
  299.     if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
  300.         return (FALSE);
  301.     }
  302.     ixdr = (u_long *)rverf->oa_base;
  303.     verf.adv_xtimestamp.key.high = (u_long)*ixdr++;
  304.     verf.adv_xtimestamp.key.low = (u_long)*ixdr++;
  305.     verf.adv_int_u = (u_long)*ixdr++;    /* nickname not XDR'd ! */
  306.  
  307.     /*
  308.      * Decrypt the timestamp
  309.      */
  310.     status = ecb_crypt((char *)&auth->ah_key, (char *)&verf.adv_xtimestamp,
  311.         sizeof(des_block), DES_DECRYPT | DES_HW);
  312.  
  313.     if (DES_FAILED(status)) {
  314.         debug("authdes_validate: DES decryption failure");
  315.         return (FALSE);
  316.     }
  317.  
  318.     /*
  319.      * xdr the decrypted timestamp 
  320.      */
  321.     ixdr = (u_long *)verf.adv_xtimestamp.c;
  322.     verf.adv_timestamp.tv_sec = IXDR_GET_LONG(ixdr) + 1;
  323.     verf.adv_timestamp.tv_usec = IXDR_GET_LONG(ixdr);
  324.  
  325.     /*
  326.      * validate
  327.      */
  328.     if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
  329.          sizeof(struct timeval)) != 0) {
  330.         debug("authdes_validate: verifier mismatch\n");
  331.         return (FALSE);
  332.     }
  333.  
  334.     /*
  335.      * We have a nickname now, let's use it
  336.      */
  337.     ad->ad_nickname = verf.adv_nickname;    
  338.     ad->ad_cred.adc_namekind = ADN_NICKNAME; 
  339.     return (TRUE);    
  340. }
  341.  
  342. /*
  343.  * 4. Refresh
  344.  */
  345. static bool_t
  346. authdes_refresh(auth)
  347.     AUTH *auth;
  348. {
  349.     struct ad_private *ad = AUTH_PRIVATE(auth);
  350.     struct authdes_cred *cred = &ad->ad_cred;
  351.  
  352.     if (ad->ad_dosync && 
  353.             !synchronize(&ad->ad_syncaddr, &ad->ad_timediff)) {
  354.         /*
  355.          * Hope the clocks are synced!
  356.          */
  357.         ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0;
  358.         debug("authdes_refresh: unable to synchronize with server");
  359.     }
  360.     ad->ad_xkey = auth->ah_key;
  361.     if (key_encryptsession(ad->ad_servername, &ad->ad_xkey) < 0) {
  362.         debug("authdes_create: unable to encrypt conversation key");
  363.         return (FALSE);
  364.     }
  365.     cred->adc_fullname.key = ad->ad_xkey;
  366.     cred->adc_namekind = ADN_FULLNAME;
  367.     cred->adc_fullname.name = ad->ad_fullname;
  368.     return (TRUE);
  369. }
  370.  
  371.  
  372. /*
  373.  * 5. Destroy
  374.  */
  375. static void
  376. authdes_destroy(auth)
  377.     AUTH *auth;
  378. {
  379.     struct ad_private *ad = AUTH_PRIVATE(auth);
  380.  
  381.     FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
  382.     FREE(ad->ad_servername, ad->ad_servernamelen + 1);
  383.     FREE(ad, sizeof(struct ad_private));
  384.     FREE(auth, sizeof(AUTH));
  385. }
  386.     
  387.  
  388.  
  389. /*
  390.  * Synchronize with the server at the given address, that is,
  391.  * adjust timep to reflect the delta between our clocks
  392.  */
  393. static bool_t
  394. synchronize(syncaddr, timep)
  395.     struct sockaddr *syncaddr;
  396.     struct timeval *timep;
  397. {
  398.     struct timeval mytime;
  399.     struct timeval timeout;
  400.  
  401.     timeout.tv_sec = RTIME_TIMEOUT;
  402.     timeout.tv_usec = 0;
  403.     if (rtime((struct sockaddr_in *)syncaddr, timep, &timeout) < 0) {
  404.         return (FALSE);
  405.     }
  406.     (void) gettimeofday(&mytime, (struct timezone *)NULL);
  407.     timep->tv_sec -= mytime.tv_sec;
  408.     if (mytime.tv_usec > timep->tv_usec) {
  409.         timep->tv_sec -= 1;
  410.         timep->tv_usec += MILLION;
  411.     }
  412.     timep->tv_usec -= mytime.tv_usec;
  413.     return (TRUE);
  414. }
  415.