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

  1. /*
  2.  * $Source: /usr/src/kerberosIV/krb/RCS/sendauth.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.  
  12. #ifndef    lint
  13. static char rcsid_sendauth_c[] =
  14. "$Header: /usr/src/kerberosIV/krb/RCS/sendauth.c,v 4.5 90/06/25 20:57:24 kfall Exp Locker: kfall $";
  15. #endif    lint
  16.  
  17. #include <mit-copyright.h>
  18.  
  19. #include <des.h>
  20. #include <krb.h>
  21. #include <sys/types.h>
  22. #include <netinet/in.h>
  23. #include <syslog.h>
  24. #include <errno.h>
  25. #include <stdio.h>
  26. #include <strings.h>
  27.  
  28. #define    KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */
  29. /*
  30.  * If the protocol changes, you will need to change the version string
  31.  * and make appropriate changes in krb_recvauth.c
  32.  */
  33.  
  34. extern int errno;
  35.  
  36. extern char *krb_get_phost();
  37.  
  38. /*
  39.  * This file contains two routines: krb_sendauth() and krb_sendsrv().
  40.  *
  41.  * krb_sendauth() transmits a ticket over a file descriptor for a
  42.  * desired service, instance, and realm, doing mutual authentication
  43.  * with the server if desired.
  44.  *
  45.  * krb_sendsvc() sends a service name to a remote knetd server.
  46.  */
  47.  
  48. /*
  49.  * The first argument to krb_sendauth() contains a bitfield of
  50.  * options (the options are defined in "krb.h"):
  51.  *
  52.  * KOPT_DONT_CANON    Don't canonicalize instance as a hostname.
  53.  *            (If this option is not chosen, krb_get_phost()
  54.  *            is called to canonicalize it.)
  55.  *
  56.  * KOPT_DONT_MK_REQ     Don't request server ticket from Kerberos.
  57.  *            A ticket must be supplied in the "ticket"
  58.  *            argument.
  59.  *            (If this option is not chosen, and there
  60.  *            is no ticket for the given server in the
  61.  *            ticket cache, one will be fetched using
  62.  *            krb_mk_req() and returned in "ticket".)
  63.  *
  64.  * KOPT_DO_MUTUAL    Do mutual authentication, requiring that the
  65.  *             receiving server return the checksum+1 encrypted
  66.  *            in the session key.  The mutual authentication
  67.  *            is done using krb_mk_priv() on the other side
  68.  *            (see "recvauth.c") and krb_rd_priv() on this
  69.  *            side.
  70.  *
  71.  * The "fd" argument is a file descriptor to write to the remote
  72.  * server on.  The "ticket" argument is used to store the new ticket
  73.  * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is
  74.  * chosen, the ticket must be supplied in the "ticket" argument.
  75.  * The "service", "inst", and "realm" arguments identify the ticket.
  76.  * If "realm" is null, the local realm is used.
  77.  *
  78.  * The following arguments are only needed if the KOPT_DO_MUTUAL option
  79.  * is chosen:
  80.  *
  81.  *   The "checksum" argument is a number that the server will add 1 to
  82.  *   to authenticate itself back to the client; the "msg_data" argument
  83.  *   holds the returned mutual-authentication message from the server
  84.  *   (i.e., the checksum+1); the "cred" structure is used to hold the
  85.  *   session key of the server, extracted from the ticket file, for use
  86.  *   in decrypting the mutual authentication message from the server;
  87.  *   and "schedule" holds the key schedule for that decryption.  The
  88.  *   the local and server addresses are given in "laddr" and "faddr".
  89.  *
  90.  * The application protocol version number (of up to KRB_SENDAUTH_VLEN
  91.  * characters) is passed in "version".
  92.  *
  93.  * If all goes well, KSUCCESS is returned, otherwise some error code.
  94.  *
  95.  * The format of the message sent to the server is:
  96.  *
  97.  * Size            Variable        Field
  98.  * ----            --------        -----
  99.  *
  100.  * KRB_SENDAUTH_VLEN    KRB_SENDAUTH_VER    sendauth protocol
  101.  * bytes                    version number
  102.  *
  103.  * KRB_SENDAUTH_VLEN    version            application protocol
  104.  * bytes                    version number
  105.  *
  106.  * 4 bytes        ticket->length        length of ticket
  107.  *
  108.  * ticket->length    ticket->dat        ticket itself
  109.  */
  110.  
  111. /*
  112.  * XXX: Note that krb_rd_priv() is coded in such a way that
  113.  * "msg_data->app_data" will be pointing into "priv_buf", which
  114.  * will disappear when krb_sendauth() returns.
  115.  */
  116.  
  117. int
  118. krb_sendauth(options, fd, ticket, service, inst, realm, checksum,
  119.     msg_data, cred, schedule, laddr, faddr, version)
  120. long options;             /* bit-pattern of options */
  121. int fd;                 /* file descriptor to write onto */
  122. KTEXT ticket;             /* where to put ticket (return); or
  123.                   * supplied in case of KOPT_DONT_MK_REQ */
  124. char *service, *inst, *realm;     /* service name, instance, realm */
  125. u_long checksum;         /* checksum to include in request */
  126. MSG_DAT *msg_data;         /* mutual auth MSG_DAT (return) */
  127. CREDENTIALS *cred;         /* credentials (return) */
  128. Key_schedule schedule;         /* key schedule (return) */
  129. struct sockaddr_in *laddr;     /* local address */
  130. struct sockaddr_in *faddr;     /* address of foreign host on fd */
  131. char *version;             /* version string */
  132. {
  133.     int rem, i, cc;
  134.     char srv_inst[INST_SZ];
  135.     char krb_realm[REALM_SZ];
  136.     char buf[BUFSIZ];
  137.     long tkt_len;
  138.     u_char priv_buf[1024];
  139.     u_long cksum;
  140.  
  141.     rem=KSUCCESS;
  142.  
  143.     /* get current realm if not passed in */
  144.     if (!realm) {
  145.     rem = krb_get_lrealm(krb_realm,0);
  146.     if (rem != KSUCCESS)
  147.         return(rem);
  148.     realm = krb_realm;
  149.     }
  150.  
  151.     /* copy instance into local storage, canonicalizing if desired */
  152.     if (options & KOPT_DONT_CANON)
  153.     (void) strncpy(srv_inst, inst, INST_SZ);
  154.     else
  155.     (void) strncpy(srv_inst, krb_get_phost(inst), INST_SZ);
  156.  
  157.     /* get the ticket if desired */
  158.     if (!(options & KOPT_DONT_MK_REQ)) {
  159.     rem = krb_mk_req(ticket, service, srv_inst, realm, checksum);
  160.     if (rem != KSUCCESS)
  161.         return(rem);
  162.     }
  163.  
  164. #ifdef ATHENA_COMPAT
  165.     /* this is only for compatibility with old servers */
  166.     if (options & KOPT_DO_OLDSTYLE) {
  167.     (void) sprintf(buf,"%d ",ticket->length);
  168.     (void) write(fd, buf, strlen(buf));
  169.     (void) write(fd, (char *) ticket->dat, ticket->length);
  170.     return(rem);
  171.     }
  172. #endif ATHENA_COMPAT
  173.     /* if mutual auth, get credentials so we have service session
  174.        keys for decryption below */
  175.     if (options & KOPT_DO_MUTUAL)
  176.     if (cc = krb_get_cred(service, srv_inst, realm, cred))
  177.         return(cc);
  178.  
  179.     /* zero the buffer */
  180.     (void) bzero(buf, BUFSIZ);
  181.  
  182.     /* insert version strings */
  183.     (void) strncpy(buf, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN);
  184.     (void) strncpy(buf+KRB_SENDAUTH_VLEN, version, KRB_SENDAUTH_VLEN);
  185.  
  186.     /* increment past vers strings */
  187.     i = 2*KRB_SENDAUTH_VLEN;
  188.  
  189.     /* put ticket length into buffer */
  190.     tkt_len = htonl((unsigned long) ticket->length);
  191.     (void) bcopy((char *) &tkt_len, buf+i, sizeof(tkt_len));
  192.     i += sizeof(tkt_len);
  193.  
  194.     /* put ticket into buffer */
  195.     (void) bcopy((char *) ticket->dat, buf+i, ticket->length);
  196.     i += ticket->length;
  197.  
  198.     /* write the request to the server */
  199.     if ((cc = krb_net_write(fd, buf, i)) != i)
  200.     return(cc);
  201.  
  202.     /* mutual authentication, if desired */
  203.     if (options & KOPT_DO_MUTUAL) {
  204.     /* get the length of the reply */
  205.     if (krb_net_read(fd, (char *) &tkt_len, sizeof(tkt_len)) !=
  206.         sizeof(tkt_len))
  207.         return(errno);
  208.     tkt_len = ntohl((unsigned long)tkt_len);
  209.  
  210.     /* if the length is negative, the server failed to recognize us. */
  211.     if (tkt_len < 0)
  212.         return(KFAILURE);     /* XXX */
  213.     /* read the reply... */
  214.     if (krb_net_read(fd, (char *)priv_buf, (int) tkt_len) != (int) tkt_len)
  215.         return(errno);
  216.  
  217.     /* ...and decrypt it */
  218. #ifndef NOENCRYPTION
  219.       key_sched(cred->session, schedule);
  220. #endif /* !NOENCRYPTION */
  221.     if (cc = krb_rd_priv(priv_buf,(unsigned long) tkt_len, schedule,
  222.                  cred->session, faddr, laddr, msg_data))
  223.         return(cc);
  224.  
  225.     /* fetch the (modified) checksum */
  226.     (void) bcopy((char *)msg_data->app_data, (char *)&cksum,
  227.              sizeof(cksum));
  228.     cksum = ntohl(cksum);
  229.  
  230.     /* if it doesn't match, fail */
  231.     if (cksum != checksum + 1)
  232.         return(KFAILURE);     /* XXX */
  233.     }
  234.     return(KSUCCESS);
  235. }
  236.  
  237. #ifdef ATHENA_COMPAT
  238. /*
  239.  * krb_sendsvc
  240.  */
  241.  
  242. int
  243. krb_sendsvc(fd, service)
  244. int fd;
  245. char *service;
  246. {
  247.     /* write the service name length and then the service name to
  248.        the fd */
  249.     long serv_length;
  250.     int cc;
  251.  
  252.     serv_length = htonl((unsigned long)strlen(service));
  253.     if ((cc = krb_net_write(fd, (char *) &serv_length,
  254.     sizeof(serv_length)))
  255.     != sizeof(serv_length))
  256.     return(cc);
  257.     if ((cc = krb_net_write(fd, service, strlen(service)))
  258.     != strlen(service))
  259.     return(cc);
  260.     return(KSUCCESS);
  261. }
  262. #endif ATHENA_COMPAT
  263.