home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / kerberosIV / krb / recvauth.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-11  |  9.1 KB  |  287 lines

  1. /*
  2.  * $Source: /usr/src/kerberosIV/src/lib/krb/RCS/recvauth.c,v $
  3.  * $Author: kfall $
  4.  *
  5.  * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
  6.  *
  7.  * For copying and distribution information, please see the file
  8.  * <mit-copyright.h>.
  9.  */
  10.  
  11. #ifndef    lint
  12. static char rcsid_recvauth_c[] =
  13. "$Header: /usr/src/kerberosIV/src/lib/krb/RCS/recvauth.c,v 4.4 90/05/12 00:58:56 kfall Exp $";
  14. #endif    lint
  15.  
  16. #include <mit-copyright.h>
  17.  
  18. #include <des.h>
  19. #include <krb.h>
  20. #include <sys/types.h>
  21. #include <netinet/in.h>
  22. #include <syslog.h>
  23. #include <errno.h>
  24. #include <stdio.h>
  25. #include <strings.h>
  26.  
  27.  
  28. #define    KRB_SENDAUTH_VERS    "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
  29.                           chars */
  30.  
  31. /*
  32.  * If the protocol changes, you will need to change the version string
  33.  * and make appropriate changes in krb_sendauth.c
  34.  * be sure to support old versions of krb_sendauth!
  35.  */
  36.  
  37. extern int errno;
  38.  
  39. /*
  40.  * krb_recvauth() reads (and optionally responds to) a message sent
  41.  * using krb_sendauth().  The "options" argument is a bit-field of
  42.  * selected options (see "sendauth.c" for options description).
  43.  * The only option relevant to krb_recvauth() is KOPT_DO_MUTUAL
  44.  * (mutual authentication requested).  The "fd" argument supplies
  45.  * a file descriptor to read from (and write to, if mutual authenti-
  46.  * cation is requested).
  47.  *
  48.  * Part of the received message will be a Kerberos ticket sent by the
  49.  * client; this is read into the "ticket" argument.  The "service" and
  50.  * "instance" arguments supply the server's Kerberos name.  If the
  51.  * "instance" argument is the string "*", it is treated as a wild card
  52.  * and filled in during the krb_rd_req() call (see read_service_key()).
  53.  *
  54.  * The "faddr" and "laddr" give the sending (client) and receiving
  55.  * (local server) network addresses.  ("laddr" may be left NULL unless
  56.  * mutual authentication is requested, in which case it must be set.)
  57.  *
  58.  * The authentication information extracted from the message is returned
  59.  * in "kdata".  The "filename" argument indicates the file where the
  60.  * server's key can be found.  (It is passed on to krb_rd_req().)  If
  61.  * left null, the default "/etc/srvtab" will be used.
  62.  *
  63.  * If mutual authentication is requested, the session key schedule must
  64.  * be computed in order to reply; this schedule is returned in the
  65.  * "schedule" argument.  A string containing the application version
  66.  * number from the received message is returned in "version", which
  67.  * should be large enough to hold a KRB_SENDAUTH_VLEN-character string.
  68.  *
  69.  * See krb_sendauth() for the format of the received client message.
  70.  *
  71.  * This routine supports another client format, for backward
  72.  * compatibility, consisting of:
  73.  *
  74.  * Size            Variable        Field
  75.  * ----            --------        -----
  76.  *
  77.  * string        tmp_buf, tkt_len    length of ticket, in
  78.  *                         ascii
  79.  *
  80.  * char            ' ' (space char)    separator
  81.  *
  82.  * tkt_len        ticket->dat        the ticket
  83.  *
  84.  * This old-style version does not support mutual authentication.
  85.  *
  86.  * krb_recvauth() first reads the protocol version string from the
  87.  * given file descriptor.  If it doesn't match the current protocol
  88.  * version (KRB_SENDAUTH_VERS), the old-style format is assumed.  In
  89.  * that case, the string of characters up to the first space is read
  90.  * and interpreted as the ticket length, then the ticket is read.
  91.  *
  92.  * If the first string did match KRB_SENDAUTH_VERS, krb_recvauth()
  93.  * next reads the application protocol version string.  Then the
  94.  * ticket length and ticket itself are read.
  95.  *
  96.  * The ticket is decrypted and checked by the call to krb_rd_req().
  97.  * If no mutual authentication is required, the result of the
  98.  * krb_rd_req() call is retured by this routine.  If mutual authenti-
  99.  * cation is required, a message in the following format is returned
  100.  * on "fd":
  101.  *
  102.  * Size            Variable        Field
  103.  * ----            --------        -----
  104.  *
  105.  * 4 bytes        tkt_len            length of ticket or -1
  106.  *                        if error occurred
  107.  *
  108.  * priv_len        tmp_buf            "private" message created
  109.  *                        by krb_mk_priv() which
  110.  *                        contains the incremented
  111.  *                        checksum sent by the client
  112.  *                        encrypted in the session
  113.  *                        key.  (This field is not
  114.  *                        present in case of error.)
  115.  *
  116.  * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some
  117.  * other error code is returned.
  118.  */
  119.  
  120. int
  121. krb_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata,
  122.          filename, schedule, version)
  123. long options;             /* bit-pattern of options */
  124. int fd;                 /* file descr. to read from */
  125. KTEXT ticket;             /* storage for client's ticket */
  126. char *service;             /* service expected */
  127. char *instance;             /* inst expected (may be filled in) */
  128. struct sockaddr_in *faddr;     /* address of foreign host on fd */
  129. struct sockaddr_in *laddr;     /* local address */
  130. AUTH_DAT *kdata;         /* kerberos data (returned) */
  131. char *filename;             /* name of file with service keys */
  132. Key_schedule schedule;         /* key schedule (return) */
  133. char *version;             /* version string (filled in) */
  134. {
  135.  
  136.     int i, cc, old_vers = 0;
  137.     char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */
  138.     char *cp;
  139.     int rem;
  140.     long tkt_len, priv_len;
  141.     u_long cksum;
  142.     u_char tmp_buf[1024];
  143.  
  144.     /* read the protocol version number */
  145.     if (krb_net_read(fd, krb_vers, KRB_SENDAUTH_VLEN) !=
  146.     KRB_SENDAUTH_VLEN)
  147.         return(errno);
  148.     krb_vers[KRB_SENDAUTH_VLEN] = '\0';
  149.  
  150.     /* check version string */
  151.     if (strcmp(krb_vers,KRB_SENDAUTH_VERS)) {
  152.     /* Assume the old version of sendkerberosdata: send ascii
  153.        length, ' ', and ticket. */
  154.     if (options & KOPT_DO_MUTUAL)
  155.         return(KFAILURE);     /* XXX can't do old style with mutual auth */
  156.     old_vers = 1;
  157.  
  158.     /* copy what we have read into tmp_buf */
  159.     (void) bcopy(krb_vers, (char *) tmp_buf, KRB_SENDAUTH_VLEN);
  160.  
  161.     /* search for space, and make it a null */
  162.     for (i = 0; i < KRB_SENDAUTH_VLEN; i++)
  163.         if (tmp_buf[i]== ' ') {
  164.         tmp_buf[i] = '\0';
  165.         /* point cp to the beginning of the real ticket */
  166.         cp = (char *) &tmp_buf[i+1];
  167.         break;
  168.         }
  169.  
  170.     if (i == KRB_SENDAUTH_VLEN)
  171.         /* didn't find the space, keep reading to find it */
  172.         for (; i<20; i++) {
  173.         if (read(fd, (char *)&tmp_buf[i], 1) != 1) {
  174.             return(KFAILURE);
  175.         }
  176.         if (tmp_buf[i] == ' ') {
  177.             tmp_buf[i] = '\0';
  178.             /* point cp to the beginning of the real ticket */
  179.             cp = (char *) &tmp_buf[i+1];
  180.             break;
  181.         }
  182.         }
  183.  
  184.     tkt_len = (long) atoi((char *) tmp_buf);
  185.  
  186.     /* sanity check the length */
  187.     if ((i==20)||(tkt_len<=0)||(tkt_len>MAX_KTXT_LEN))
  188.         return(KFAILURE);
  189.  
  190.     if (i < KRB_SENDAUTH_VLEN) {
  191.         /* since we already got the space, and part of the ticket,
  192.            we read fewer bytes to get the rest of the ticket */
  193.         if (krb_net_read(fd, (char *)(tmp_buf+KRB_SENDAUTH_VLEN),
  194.                  (int) (tkt_len - KRB_SENDAUTH_VLEN + 1 + i))
  195.         != (int)(tkt_len - KRB_SENDAUTH_VLEN + 1 + i))
  196.         return(errno);
  197.     } else {
  198.         if (krb_net_read(fd, (char *)(tmp_buf+i), (int)tkt_len) !=
  199.         (int) tkt_len)
  200.         return(errno);
  201.     }
  202.     ticket->length = tkt_len;
  203.     /* copy the ticket into the struct */
  204.     (void) bcopy(cp, (char *) ticket->dat, ticket->length);
  205.  
  206.     } else {
  207.     /* read the application version string */
  208.     if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) !=
  209.         KRB_SENDAUTH_VLEN)
  210.         return(errno);
  211.     version[KRB_SENDAUTH_VLEN] = '\0';
  212.  
  213.     /* get the length of the ticket */
  214.     if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) !=
  215.         sizeof(tkt_len))
  216.         return(errno);
  217.     
  218.     /* sanity check */
  219.     ticket->length = ntohl((unsigned long)tkt_len);
  220.     if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) {
  221.         if (options & KOPT_DO_MUTUAL) {
  222.         rem = KFAILURE;
  223.         goto mutual_fail;
  224.         } else
  225.         return(KFAILURE); /* XXX there may still be junk on the fd? */
  226.     }
  227.  
  228.     /* read the ticket */
  229.     if (krb_net_read(fd, (char *) ticket->dat, ticket->length)
  230.         != ticket->length)
  231.         return(errno);
  232.     }
  233.     /*
  234.      * now have the ticket.  decrypt it to get the authenticated
  235.      * data.
  236.      */
  237.     rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr,
  238.              kdata,filename);
  239.  
  240.     if (old_vers) return(rem);     /* XXX can't do mutual with old client */
  241.  
  242.     /* if we are doing mutual auth, compose a response */
  243.     if (options & KOPT_DO_MUTUAL) {
  244.     if (rem != KSUCCESS)
  245.         /* the krb_rd_req failed */
  246.         goto mutual_fail;
  247.  
  248.     /* add one to the (formerly) sealed checksum, and re-seal it
  249.        for return to the client */
  250.     cksum = kdata->checksum + 1;
  251.     cksum = htonl(cksum);
  252. #ifndef NOENCRYPTION
  253.     key_sched(kdata->session,schedule);
  254. #endif /* !NOENCRYPTION */
  255.     priv_len = krb_mk_priv((unsigned char *)&cksum,
  256.                    tmp_buf,
  257.                    (unsigned long) sizeof(cksum),
  258.                    schedule,
  259.                    kdata->session,
  260.                    laddr,
  261.                    faddr);
  262.     if (priv_len < 0) {
  263.         /* re-sealing failed; notify the client */
  264.         rem = KFAILURE;     /* XXX */
  265. mutual_fail:
  266.         priv_len = -1;
  267.         tkt_len = htonl((unsigned long) priv_len);
  268.         /* a length of -1 is interpreted as an authentication
  269.            failure by the client */
  270.         if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
  271.         != sizeof(tkt_len))
  272.         return(cc);
  273.         return(rem);
  274.     } else {
  275.         /* re-sealing succeeded, send the private message */
  276.         tkt_len = htonl((unsigned long)priv_len);
  277.         if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
  278.          != sizeof(tkt_len))
  279.         return(cc);
  280.         if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len))
  281.         != (int) priv_len)
  282.         return(cc);
  283.     }
  284.     }
  285.     return(rem);
  286. }
  287.