summaryrefslogtreecommitdiffstats
path: root/src/lib/krb4/mk_auth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/krb4/mk_auth.c')
-rw-r--r--src/lib/krb4/mk_auth.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/lib/krb4/mk_auth.c b/src/lib/krb4/mk_auth.c
new file mode 100644
index 0000000000..60444dcf16
--- /dev/null
+++ b/src/lib/krb4/mk_auth.c
@@ -0,0 +1,218 @@
+/*
+ * mk_auth.c
+ *
+ * CopKRB4_32right 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Derived from sendauth.c by John Gilmore, 10 October 1994.
+ */
+
+#include "mit-copyright.h"
+
+#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */
+#include "krb.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */
+/*
+ * If the protocol changes, you will need to change the version string
+ * and make appropriate changes in recvauth.c and sendauth.c.
+ */
+
+/*
+ * This file contains two routines: krb_mk_auth() and krb_check_auth().
+ *
+ * krb_mk_auth() packages a ticket for transmission to an application
+ * server.
+ *
+ * krb_krb_check_auth() validates a mutual-authentication response from
+ * the application server.
+ *
+ * These routines are portable versions that implement a protocol
+ * compatible with the original Unix "sendauth".
+ */
+
+/*
+ * The first argument to krb_mk_auth() contains a bitfield of
+ * options (the options are defined in "krb.h"):
+ *
+ * KOPT_DONT_CANON Don't canonicalize instance as a hostname.
+ * (If this option is not chosen, krb_get_phost()
+ * is called to canonicalize it.)
+ *
+ * KOPT_DONT_MK_REQ Don't request server ticket from Kerberos.
+ * A ticket must be supplied in the "ticket"
+ * argument.
+ * (If this option is not chosen, and there
+ * is no ticket for the given server in the
+ * ticket cache, one will be fetched using
+ * krb_mk_req() and returned in "ticket".)
+ *
+ * KOPT_DO_MUTUAL Do mutual authentication, requiring that the
+ * receiving server return the checksum+1 encrypted
+ * in the session key. The mutual authentication
+ * is done using krb_mk_priv() on the other side
+ * (see "recvauth.c") and krb_rd_priv() on this
+ * side.
+ *
+ * The "ticket" argument is used to store the new ticket
+ * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is
+ * chosen, the ticket must be supplied in the "ticket" argument.
+ * The "service", "inst", and "realm" arguments identify the ticket.
+ * If "realm" is null, the local realm is used.
+ *
+ * The following argument is only needed if the KOPT_DO_MUTUAL option
+ * is chosen:
+ *
+ * The "checksum" argument is a number that the server will add 1 to
+ * to authenticate itself back to the client.
+ *
+ * The application protocol version number (of up to KRB_SENDAUTH_VLEN
+ * characters) is passed in "version".
+ *
+ * The ticket is packaged into a message in the buffer pointed to by
+ * the argument "buf".
+ *
+ * If all goes well, KSUCCESS is returned, otherwise some error code.
+ *
+ * The format of the message packaged to send to the application server is:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * KRB_SENDAUTH_VLEN KRB_SENDAUTH_VER sendauth protocol
+ * bytes version number
+ *
+ * KRB_SENDAUTH_VLEN version application protocol
+ * bytes version number
+ *
+ * 4 bytes ticket->length length of ticket
+ *
+ * ticket->length ticket->dat ticket itself
+ */
+
+/*
+ * Build a "sendauth" packet compatible with Unix sendauth/recvauth.
+ */
+int INTERFACE
+krb_mk_auth(options, ticket, service, inst, realm, checksum, version, buf)
+ long options; /* bit-pattern of options */
+ KTEXT ticket; /* where to put ticket (return); or
+ supplied in case of KOPT_DONT_MK_REQ */
+ char *service; /* service name */
+ char *inst; /* instance (OUTPUT canonicalized) */
+ char *realm; /* realm */
+ unsigned KRB4_32 checksum; /* checksum to include in request */
+ char *version; /* version string */
+ KTEXT buf; /* Output buffer to fill */
+{
+ int rem, i;
+ char krb_realm[REALM_SZ];
+ KRB4_32 tkt_len;
+
+ rem=KSUCCESS;
+
+ /* get current realm if not passed in */
+ if (!realm) {
+ rem = krb_get_lrealm(krb_realm,1);
+ if (rem != KSUCCESS)
+ return(rem);
+ realm = krb_realm;
+ }
+
+ if (!(options & KOPT_DONT_CANON))
+ (void) strncpy(inst, krb_get_phost(inst), INST_SZ);
+
+ /* get the ticket if desired */
+ if (!(options & KOPT_DONT_MK_REQ)) {
+ rem = krb_mk_req(ticket, service, inst, realm, checksum);
+ if (rem != KSUCCESS)
+ return(rem);
+ }
+
+#ifdef ATHENA_COMPAT
+ /* this is only for compatibility with old servers */
+ if (options & KOPT_DO_OLDSTYLE) {
+ (void) sprintf(buf->dat,"%d ",ticket->length);
+ (void) write(fd, buf, strlen(buf));
+ (void) write(fd, (char *) ticket->dat, ticket->length);
+ return(rem);
+ }
+#endif /* ATHENA_COMPAT */
+
+ /* zero the buffer */
+ (void) memset(buf->dat, 0, MAX_KTXT_LEN);
+
+ /* insert version strings */
+ (void) strncpy((char *)buf->dat, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN);
+ (void) strncpy((char *)buf->dat+KRB_SENDAUTH_VLEN, version,
+ KRB_SENDAUTH_VLEN);
+
+ /* increment past vers strings */
+ i = 2*KRB_SENDAUTH_VLEN;
+
+ /* put ticket length into buffer */
+ tkt_len = htonl((unsigned KRB4_32) ticket->length);
+ (void) memcpy(buf->dat+i, (char *) &tkt_len, sizeof(tkt_len));
+ i += sizeof(tkt_len);
+
+ /* put ticket into buffer */
+ (void) memcpy(buf->dat+i, (char *) ticket->dat, ticket->length);
+ i += ticket->length;
+
+ buf->length = i;
+ return KSUCCESS;
+}
+
+
+
+/*
+ * For mutual authentication using mk_auth, check the server's response
+ * to validate that we're really talking to the server which holds the
+ * key that we obtained from the Kerberos key server.
+ *
+ * The "buf" argument is the response we received from the app server.
+ * The "checksum" argument is a number that the server has added 1 to
+ * to authenticate itself back to the client (us); the "msg_data" argument
+ * returns the returned mutual-authentication message from the server
+ * (i.e., the checksum+1); "session" holds the
+ * session key of the server, extracted from the ticket file, for use
+ * in decrypting the mutual authentication message from the server;
+ * and "schedule" returns the key schedule for that decryption. The
+ * the local and server addresses are given in "laddr" and "faddr".
+ */
+int INTERFACE
+krb_check_auth (buf, checksum, msg_data, session, schedule, laddr, faddr)
+ KTEXT buf; /* The response we read from app server */
+ unsigned KRB4_32 checksum; /* checksum we included in request */
+ MSG_DAT *msg_data; /* mutual auth MSG_DAT (return) */
+ C_Block session; /* credentials (input) */
+ Key_schedule schedule; /* key schedule (return) */
+ struct sockaddr_in *laddr; /* local address */
+ struct sockaddr_in *faddr; /* address of foreign host on fd */
+{
+ int cc;
+ unsigned KRB4_32 cksum;
+
+ /* decrypt it */
+#ifndef NOENCRYPTION
+ key_sched(session, schedule);
+#endif /* !NOENCRYPTION */
+ if (cc = krb_rd_priv(buf->dat, buf->length, schedule,
+ (C_Block *)session, faddr, laddr, msg_data))
+ return(cc);
+
+ /* fetch the (incremented) checksum that we supplied in the request */
+ (void) memcpy((char *)&cksum, (char *)msg_data->app_data,
+ sizeof(cksum));
+ cksum = ntohl(cksum);
+
+ /* if it doesn't match, fail -- reply wasn't from our real server. */
+ if (cksum != checksum + 1)
+ return(KFAILURE); /* XXX */
+ return(KSUCCESS);
+}