--- /dev/null
+# from @(#)Makefile 5.1 (Berkeley) 6/25/90
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:32 tholo Exp $
+
+# do compile_et and mk_cmds first, used by other directories
+
+.ifmake install
+SUBDIR= include
+.else
+SUBDIR= compile_et mk_cmds
+.endif
+
+SUBDIR+=acl com_err des krb kadm kafs kdb ss
+
+SUBDIR+=ext_srvtab kadmin kadmind kdb_destroy kdb_edit kdb_init kdb_util \
+ kdestroy kerberos kinit klist kpasswdd kprop kpropd ksrvtgt ksrvutil \
+ kstash make_keypair register registerd
+
+SUBDIR+=man
+
+.include <bsd.subdir.mk>
--- /dev/null
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/1/93
+# $Id: Makefile.inc,v 1.1.1.1 1995/12/14 06:52:32 tholo Exp $
+
+CFLAGS+=-I${.CURDIR}/../include
+BINDIR?=/usr/sbin
+
+.if exists(${.CURDIR}/../mk_cmds/obj)
+MK_CMDS=${.CURDIR}/../mk_cmds/obj/mk_cmds
+.else
+MK_CMDS=${.CURDIR}/../mk_cmds/mk_cmds
+.endif
+
+.if exists(${.CURDIR}/../compile_et/obj)
+COMPILE_ET=${.CURDIR}/../compile_et/obj/compile_et
+.else
+COMPILE_ET=${.CURDIR}/../compile_et/compile_et
+.endif
+
+.if exists(${.CURDIR}/../com_err/obj)
+COM_ERR=-L${.CURDIR}/../com_err/obj -lcom_err_pic
+.else
+COM_ERR=-L${.CURDIR}/../com_err -lcom_err_pic
+.endif
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $
+
+LIB= acl
+SRCS= acl_files.c
+MAN= acl_check.3
+MLINKS+=acl_check.3 acl_canonicalize_principal.3 \
+ acl_check.3 acl_exact_match.3 \
+ acl_check.3 acl_add.3 acl_check.3 acl_delete.3 \
+ acl_check.3 acl_initialize.3
+
+.include <bsd.lib.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: acl_check.3,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $
+.TH ACL_CHECK 3 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+acl_canonicalize_principal, acl_check, acl_exact_match, acl_add,
+acl_delete, acl_initialize \- Access control list routines
+.SH SYNOPSIS
+.nf
+.nj
+.ft B
+cc <files> \-lacl \-lkrb
+.PP
+.ft B
+#include <krb.h>
+.PP
+.ft B
+acl_canonicalize_principal(principal, buf)
+char *principal;
+char *buf;
+.PP
+.ft B
+acl_check(acl, principal)
+char *acl;
+char *principal;
+.PP
+.ft B
+acl_exact_match(acl, principal)
+char *acl;
+char *principal;
+.PP
+.ft B
+acl_add(acl, principal)
+char *acl;
+char *principal;
+.PP
+.ft B
+acl_delete(acl, principal)
+char *acl;
+char *principal;
+.PP
+.ft B
+acl_initialize(acl_file, mode)
+char *acl_file;
+int mode;
+.fi
+.ft R
+.SH DESCRIPTION
+.SS Introduction
+.PP
+An access control list (ACL) is a list of principals, where each
+principal is represented by a text string which cannot contain
+whitespace. The library allows application programs to refer to named
+access control lists to test membership and to atomically add and
+delete principals using a natural and intuitive interface. At
+present, the names of access control lists are required to be Unix
+filenames, and refer to human-readable Unix files; in the future, when
+a networked ACL server is implemented, the names may refer to a
+different namespace specific to the ACL service.
+.PP
+.SS Principal Names
+.PP
+Principal names have the form
+.nf
+.in +5n
+<name>[.<instance>][@<realm>]
+.in -5n
+e.g.:
+.in +5n
+asp
+asp.root
+asp@ATHENA.MIT.EDU
+asp.@ATHENA.MIT.EDU
+asp.root@ATHENA.MIT.EDU
+.in -5n
+.fi
+It is possible for principals to be underspecified. If an instance is
+missing, it is assumed to be "". If realm is missing, it is assumed
+to be the local realm as determined by
+.IR krb_get_lrealm (3).
+The canonical form contains all of name, instance,
+and realm; the acl_add and acl_delete routines will always
+leave the file in that form. Note that the canonical form of
+asp@ATHENA.MIT.EDU is actually asp.@ATHENA.MIT.EDU.
+.SS Routines
+.PP
+.I acl_canonicalize_principal
+stores the canonical form of
+.I principal
+in
+.IR buf .
+.I Buf
+must contain enough
+space to store a principal, given the limits on the sizes of name,
+instance, and realm specified as ANAME_SZ, INST_SZ, and REALM_SZ,
+respectively, in
+.IR /usr/include/krb.h .
+.PP
+.I acl_check
+returns nonzero if
+.I principal
+appears in
+.IR acl .
+Returns 0 if principal
+does not appear in acl, or if an error occurs. Canonicalizes
+principal before checking, and allows the ACL to contain wildcards. The
+only supported wildcards are entries of the form
+name.*@realm, *.*@realm, and *.*@*. An asterisk matches any value for the
+its component field. For example, "jtkohl.*@*" would match principal
+jtkohl, with any instance and any realm.
+.PP
+.I acl_exact_match
+performs like
+.IR acl_check ,
+but does no canonicalization or wildcard matching.
+.PP
+.I acl_add
+atomically adds
+.I principal
+to
+.IR acl .
+Returns 0 if successful, nonzero otherwise. It is considered a failure
+if
+.I principal
+is already in
+.IR acl .
+This routine will canonicalize
+.IR principal ,
+but will treat wildcards literally.
+.PP
+.I acl_delete
+atomically deletes
+.I principal
+from
+.IR acl .
+Returns 0 if successful,
+nonzero otherwise. It is considered a failure if
+.I principal
+is not
+already in
+.IR acl .
+This routine will canonicalize
+.IR principal ,
+but will treat wildcards literally.
+.PP
+.I acl_initialize
+initializes
+.IR acl_file .
+If the file
+.I acl_file
+does not exist,
+.I acl_initialize
+creates it with mode
+.IR mode .
+If the file
+.I acl_file
+exists,
+.I acl_initialize
+removes all members. Returns 0 if successful,
+nonzero otherwise. WARNING: Mode argument is likely to change with
+the eventual introduction of an ACL service.
+.SH NOTES
+In the presence of concurrency, there is a very small chance that
+.I acl_add
+or
+.I acl_delete
+could report success even though it would have
+had no effect. This is a necessary side effect of using lock files
+for concurrency control rather than flock(2), which is not supported
+by NFS.
+.PP
+The current implementation caches ACLs in memory in a hash-table
+format for increased efficiency in checking membership; one effect of
+the caching scheme is that one file descriptor will be kept open for
+each ACL cached, up to a maximum of 8.
+.SH SEE ALSO
+kerberos(3), krb_get_lrealm(3)
+.SH AUTHOR
+James Aspnes (MIT Project Athena)
--- /dev/null
+/* $Id: acl_files.c,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#include <kerberosIV/site.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <ctype.h>
+
+#include <kerberosIV/krb.h>
+#include <kerberosIV/acl.h>
+
+/*** Routines for manipulating access control list files ***/
+
+/* "aname.inst@realm" */
+#define MAX_PRINCIPAL_SIZE (ANAME_SZ + INST_SZ + REALM_SZ + 3)
+#define INST_SEP '.'
+#define REALM_SEP '@'
+
+#define LINESIZE 2048 /* Maximum line length in an acl file */
+
+#define NEW_FILE "%s.~NEWACL~" /* Format for name of altered acl file */
+#define WAIT_TIME 300 /* Maximum time allowed write acl file */
+
+#define CACHED_ACLS 8 /* How many acls to cache */
+ /* Each acl costs 1 open file descriptor */
+#define ACL_LEN 16 /* Twice a reasonable acl length */
+
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+#define COR(a,b) ((a!=NULL)?(a):(b))
+
+/* Canonicalize a principal name */
+/* If instance is missing, it becomes "" */
+/* If realm is missing, it becomes the local realm */
+/* Canonicalized form is put in canon, which must be big enough to hold
+ MAX_PRINCIPAL_SIZE characters */
+void
+acl_canonicalize_principal(principal, canon)
+ char *principal;
+ char *canon;
+{
+ char *dot, *atsign, *end;
+ int len;
+
+ dot = strchr(principal, INST_SEP);
+ atsign = strchr(principal, REALM_SEP);
+
+ /* Maybe we're done already */
+ if(dot != NULL && atsign != NULL) {
+ if(dot < atsign) {
+ /* It's for real */
+ /* Copy into canon */
+ strncpy(canon, principal, MAX_PRINCIPAL_SIZE);
+ canon[MAX_PRINCIPAL_SIZE-1] = '\0';
+ return;
+ } else {
+ /* Nope, it's part of the realm */
+ dot = NULL;
+ }
+ }
+
+ /* No such luck */
+ end = principal + strlen(principal);
+
+ /* Get the principal name */
+ len = MIN(ANAME_SZ, COR(dot, COR(atsign, end)) - principal);
+ strncpy(canon, principal, len);
+ canon += len;
+
+ /* Add INST_SEP */
+ *canon++ = INST_SEP;
+
+ /* Get the instance, if it exists */
+ if(dot != NULL) {
+ ++dot;
+ len = MIN(INST_SZ, COR(atsign, end) - dot);
+ strncpy(canon, dot, len);
+ canon += len;
+ }
+
+ /* Add REALM_SEP */
+ *canon++ = REALM_SEP;
+
+ /* Get the realm, if it exists */
+ /* Otherwise, default to local realm */
+ if(atsign != NULL) {
+ ++atsign;
+ len = MIN(REALM_SZ, end - atsign);
+ strncpy(canon, atsign, len);
+ canon += len;
+ *canon++ = '\0';
+ } else if(krb_get_lrealm(canon, 1) != KSUCCESS) {
+ strcpy(canon, KRB_REALM);
+ }
+}
+
+/* Get a lock to modify acl_file */
+/* Return new FILE pointer */
+/* or NULL if file cannot be modified */
+/* REQUIRES WRITE PERMISSION TO CONTAINING DIRECTORY */
+static FILE *
+acl_lock_file(acl_file)
+ char *acl_file;
+{
+ struct stat s;
+ char new[LINESIZE];
+ int nfd;
+ FILE *nf;
+ int mode;
+
+ if(stat(acl_file, &s) < 0) return(NULL);
+ mode = s.st_mode;
+ sprintf(new, NEW_FILE, acl_file);
+ for(;;) {
+ /* Open the new file */
+ if((nfd = open(new, O_WRONLY|O_CREAT|O_EXCL, mode)) < 0) {
+ if(errno == EEXIST) {
+ /* Maybe somebody got here already, maybe it's just old */
+ if(stat(new, &s) < 0) return(NULL);
+ if(time(0) - s.st_ctime > WAIT_TIME) {
+ /* File is stale, kill it */
+ unlink(new);
+ continue;
+ } else {
+ /* Wait and try again */
+ sleep(1);
+ continue;
+ }
+ } else {
+ /* Some other error, we lose */
+ return(NULL);
+ }
+ }
+
+ /* If we got to here, the lock file is ours and ok */
+ /* Reopen it under stdio */
+ if((nf = fdopen(nfd, "w")) == NULL) {
+ /* Oops, clean up */
+ unlink(new);
+ }
+ return(nf);
+ }
+}
+
+/* Abort changes to acl_file written onto FILE *f */
+/* Returns 0 if successful, < 0 otherwise */
+/* Closes f */
+static int
+acl_abort(acl_file, f)
+ char *acl_file;
+ FILE *f;
+{
+ char new[LINESIZE];
+ int ret;
+ struct stat s;
+
+ /* make sure we aren't nuking someone else's file */
+ if(fstat(fileno(f), &s) < 0
+ || s.st_nlink == 0) {
+ fclose(f);
+ return(-1);
+ } else {
+ sprintf(new, NEW_FILE, acl_file);
+ ret = unlink(new);
+ fclose(f);
+ return(ret);
+ }
+}
+
+/* Commit changes to acl_file written onto FILE *f */
+/* Returns zero if successful */
+/* Returns > 0 if lock was broken */
+/* Returns < 0 if some other error occurs */
+/* Closes f */
+static int
+acl_commit(acl_file, f)
+ char *acl_file;
+ FILE *f;
+{
+ char new[LINESIZE];
+ int ret;
+ struct stat s;
+
+ sprintf(new, NEW_FILE, acl_file);
+ if(fflush(f) < 0
+ || fstat(fileno(f), &s) < 0
+ || s.st_nlink == 0) {
+ acl_abort(acl_file, f);
+ return(-1);
+ }
+
+ ret = rename(new, acl_file);
+ fclose(f);
+ return(ret);
+}
+
+/* Initialize an acl_file */
+/* Creates the file with permissions perm if it does not exist */
+/* Erases it if it does */
+/* Returns return value of acl_commit */
+int
+acl_initialize(acl_file, perm)
+ char *acl_file;
+ int perm;
+{
+ FILE *new;
+ int fd;
+
+ /* Check if the file exists already */
+ if((new = acl_lock_file(acl_file)) != NULL) {
+ return(acl_commit(acl_file, new));
+ } else {
+ /* File must be readable and writable by owner */
+ if((fd = open(acl_file, O_CREAT|O_EXCL, perm|0600)) < 0) {
+ return(-1);
+ } else {
+ close(fd);
+ return(0);
+ }
+ }
+}
+
+/* Eliminate all whitespace character in buf */
+/* Modifies its argument */
+static void
+nuke_whitespace(buf)
+ char *buf;
+{
+ register char *pin, *pout;
+
+ for(pin = pout = buf; *pin != '\0'; pin++)
+ if(!isspace(*pin)) *pout++ = *pin;
+ *pout = '\0'; /* Terminate the string */
+}
+
+/* Hash table stuff */
+
+struct hashtbl {
+ int size; /* Max number of entries */
+ int entries; /* Actual number of entries */
+ char **tbl; /* Pointer to start of table */
+};
+
+/* Make an empty hash table of size s */
+static struct hashtbl *
+make_hash(size)
+ int size;
+{
+ struct hashtbl *h;
+
+ if(size < 1) size = 1;
+ h = (struct hashtbl *) malloc(sizeof(struct hashtbl));
+ h->size = size;
+ h->entries = 0;
+ h->tbl = (char **) calloc(size, sizeof(char *));
+ return(h);
+}
+
+/* Destroy a hash table */
+static void
+destroy_hash(h)
+ struct hashtbl *h;
+{
+ int i;
+
+ for(i = 0; i < h->size; i++) {
+ if(h->tbl[i] != NULL) free(h->tbl[i]);
+ }
+ free(h->tbl);
+ free(h);
+}
+
+/* Compute hash value for a string */
+static unsigned int
+hashval(s)
+ register char *s;
+{
+ register unsigned hv;
+
+ for(hv = 0; *s != '\0'; s++) {
+ hv ^= ((hv << 3) ^ *s);
+ }
+ return(hv);
+}
+
+/* Add an element to a hash table */
+static void
+add_hash(h, el)
+ struct hashtbl *h;
+ char *el;
+{
+ unsigned hv;
+ char *s;
+ char **old;
+ int i;
+
+ /* Make space if it isn't there already */
+ if(h->entries + 1 > (h->size >> 1)) {
+ old = h->tbl;
+ h->tbl = (char **) calloc(h->size << 1, sizeof(char *));
+ for(i = 0; i < h->size; i++) {
+ if(old[i] != NULL) {
+ hv = hashval(old[i]) % (h->size << 1);
+ while(h->tbl[hv] != NULL) hv = (hv+1) % (h->size << 1);
+ h->tbl[hv] = old[i];
+ }
+ }
+ h->size = h->size << 1;
+ free(old);
+ }
+
+ hv = hashval(el) % h->size;
+ while(h->tbl[hv] != NULL && strcmp(h->tbl[hv], el)) hv = (hv+1) % h->size;
+ s = malloc(strlen(el)+1);
+ strcpy(s, el);
+ h->tbl[hv] = s;
+ h->entries++;
+}
+
+/* Returns nonzero if el is in h */
+static int
+check_hash(h, el)
+ struct hashtbl *h;
+ char *el;
+{
+ unsigned hv;
+
+ for(hv = hashval(el) % h->size;
+ h->tbl[hv] != NULL;
+ hv = (hv + 1) % h->size) {
+ if(!strcmp(h->tbl[hv], el)) return(1);
+ }
+ return(0);
+}
+
+struct acl {
+ char filename[LINESIZE]; /* Name of acl file */
+ int fd; /* File descriptor for acl file */
+ struct stat status; /* File status at last read */
+ struct hashtbl *acl; /* Acl entries */
+};
+
+static struct acl acl_cache[CACHED_ACLS];
+
+static int acl_cache_count = 0;
+static int acl_cache_next = 0;
+
+/* Returns < 0 if unsuccessful in loading acl */
+/* Returns index into acl_cache otherwise */
+/* Note that if acl is already loaded, this is just a lookup */
+static int
+acl_load(name)
+ char *name;
+{
+ int i;
+ FILE *f;
+ struct stat s;
+ char buf[MAX_PRINCIPAL_SIZE];
+ char canon[MAX_PRINCIPAL_SIZE];
+
+ /* See if it's there already */
+ for(i = 0; i < acl_cache_count; i++) {
+ if(!strcmp(acl_cache[i].filename, name)
+ && acl_cache[i].fd >= 0) goto got_it;
+ }
+
+ /* It isn't, load it in */
+ /* maybe there's still room */
+ if(acl_cache_count < CACHED_ACLS) {
+ i = acl_cache_count++;
+ } else {
+ /* No room, clean one out */
+ i = acl_cache_next;
+ acl_cache_next = (acl_cache_next + 1) % CACHED_ACLS;
+ close(acl_cache[i].fd);
+ if(acl_cache[i].acl) {
+ destroy_hash(acl_cache[i].acl);
+ acl_cache[i].acl = (struct hashtbl *) 0;
+ }
+ }
+
+ /* Set up the acl */
+ strcpy(acl_cache[i].filename, name);
+ if((acl_cache[i].fd = open(name, O_RDONLY, 0)) < 0) return(-1);
+ /* Force reload */
+ acl_cache[i].acl = (struct hashtbl *) 0;
+
+ got_it:
+ /*
+ * See if the stat matches
+ *
+ * Use stat(), not fstat(), as the file may have been re-created by
+ * acl_add or acl_delete. If this happens, the old inode will have
+ * no changes in the mod-time and the following test will fail.
+ */
+ if(stat(acl_cache[i].filename, &s) < 0) return(-1);
+ if(acl_cache[i].acl == (struct hashtbl *) 0
+ || s.st_nlink != acl_cache[i].status.st_nlink
+ || s.st_mtime != acl_cache[i].status.st_mtime
+ || s.st_ctime != acl_cache[i].status.st_ctime) {
+ /* Gotta reload */
+ if(acl_cache[i].fd >= 0) close(acl_cache[i].fd);
+ if((acl_cache[i].fd = open(name, O_RDONLY, 0)) < 0) return(-1);
+ if((f = fdopen(acl_cache[i].fd, "r")) == NULL) return(-1);
+ if(acl_cache[i].acl) destroy_hash(acl_cache[i].acl);
+ acl_cache[i].acl = make_hash(ACL_LEN);
+ while(fgets(buf, sizeof(buf), f) != NULL) {
+ nuke_whitespace(buf);
+ acl_canonicalize_principal(buf, canon);
+ add_hash(acl_cache[i].acl, canon);
+ }
+ fclose(f);
+ acl_cache[i].status = s;
+ }
+ return(i);
+}
+
+/* Returns nonzero if it can be determined that acl contains principal */
+/* Principal is not canonicalized, and no wildcarding is done */
+int
+acl_exact_match(acl, principal)
+ char *acl;
+ char *principal;
+{
+ int idx;
+
+ return((idx = acl_load(acl)) >= 0
+ && check_hash(acl_cache[idx].acl, principal));
+}
+
+/* Returns nonzero if it can be determined that acl contains principal */
+/* Recognizes wildcards in acl of the form
+ name.*@realm, *.*@realm, and *.*@* */
+int
+acl_check(acl, principal)
+ char *acl;
+ char *principal;
+{
+ char buf[MAX_PRINCIPAL_SIZE];
+ char canon[MAX_PRINCIPAL_SIZE];
+ char *realm;
+
+ acl_canonicalize_principal(principal, canon);
+
+ /* Is it there? */
+ if(acl_exact_match(acl, canon)) return(1);
+
+ /* Try the wildcards */
+ realm = strchr(canon, REALM_SEP);
+ *strchr(canon, INST_SEP) = '\0'; /* Chuck the instance */
+
+ sprintf(buf, "%s.*%s", canon, realm);
+ if(acl_exact_match(acl, buf)) return(1);
+
+ sprintf(buf, "*.*%s", realm);
+ if(acl_exact_match(acl, buf) || acl_exact_match(acl, "*.*@*")) return(1);
+
+ return(0);
+}
+
+/* Adds principal to acl */
+/* Wildcards are interpreted literally */
+int
+acl_add(acl, principal)
+ char *acl;
+ char *principal;
+{
+ int idx;
+ int i;
+ FILE *new;
+ char canon[MAX_PRINCIPAL_SIZE];
+
+ acl_canonicalize_principal(principal, canon);
+
+ if((new = acl_lock_file(acl)) == NULL) return(-1);
+ if((acl_exact_match(acl, canon))
+ || (idx = acl_load(acl)) < 0) {
+ acl_abort(acl, new);
+ return(-1);
+ }
+ /* It isn't there yet, copy the file and put it in */
+ for(i = 0; i < acl_cache[idx].acl->size; i++) {
+ if(acl_cache[idx].acl->tbl[i] != NULL) {
+ if(fputs(acl_cache[idx].acl->tbl[i], new) == 0
+ || putc('\n', new) != '\n') {
+ acl_abort(acl, new);
+ return(-1);
+ }
+ }
+ }
+ fputs(canon, new);
+ putc('\n', new);
+ return(acl_commit(acl, new));
+}
+
+/* Removes principal from acl */
+/* Wildcards are interpreted literally */
+int
+acl_delete(acl, principal)
+ char *acl;
+ char *principal;
+{
+ int idx;
+ int i;
+ FILE *new;
+ char canon[MAX_PRINCIPAL_SIZE];
+
+ acl_canonicalize_principal(principal, canon);
+
+ if((new = acl_lock_file(acl)) == NULL) return(-1);
+ if((!acl_exact_match(acl, canon))
+ || (idx = acl_load(acl)) < 0) {
+ acl_abort(acl, new);
+ return(-1);
+ }
+ /* It isn't there yet, copy the file and put it in */
+ for(i = 0; i < acl_cache[idx].acl->size; i++) {
+ if(acl_cache[idx].acl->tbl[i] != NULL
+ && strcmp(acl_cache[idx].acl->tbl[i], canon)) {
+ fputs(acl_cache[idx].acl->tbl[i], new);
+ putc('\n', new);
+ }
+ }
+ return(acl_commit(acl, new));
+}
--- /dev/null
+major=4
+minor=0
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $
+
+LIB= com_err
+SRCS= com_err.c error_message.c et_name.c init_et.c
+CFLAGS+=-I${.CURDIR}
+MAN= com_err.3
+
+.include <bsd.lib.mk>
--- /dev/null
+.\" Copyright (c) 1988 Massachusetts Institute of Technology,
+.\" Student Information Processing Board. All rights reserved.
+.\"
+.\" $Id: com_err.3,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $
+.TH COM_ERR 3 "22 Nov 1988" SIPB
+.SH NAME
+com_err \- common error display routine
+.SH SYNOPSIS
+.nf
+ #include <com_err.h>
+.PP
+void com_err (whoami, code, format, ...);
+ const char *whoami;
+ long code;
+ const char *format;
+.PP
+proc = set_com_err_hook (proc);
+.fi
+void (*
+.I proc
+) (const char *, long, const char *, va_list);
+.nf
+.PP
+proc = reset_com_err_hook ();
+.PP
+void initialize_XXXX_error_table ();
+.fi
+.SH DESCRIPTION
+.I Com_err
+displays an error message on the standard error stream
+.I stderr
+(see
+.IR stdio (3S))
+composed of the
+.I whoami
+string, which should specify the program name or some subportion of
+a program, followed by an error message generated from the
+.I code
+value (derived from
+.IR compile_et (1)),
+and a string produced using the
+.I format
+string and any following arguments, in the same style as
+.IR fprintf (3).
+
+The behavior of
+.I com_err
+can be modified using
+.I set_com_err_hook;
+this defines a procedure which is called with the arguments passed to
+.I com_err,
+instead of the default internal procedure which sends the formatted
+text to error output. Thus the error messages from a program can all
+easily be diverted to another form of diagnostic logging, such as
+.IR syslog (3).
+.I Reset_com_err_hook
+may be used to restore the behavior of
+.I com_err
+to its default form. Both procedures return the previous ``hook''
+value. These ``hook'' procedures must have the declaration given for
+.I proc
+above in the synopsis.
+
+The
+.I initialize_XXXX_error_table
+routine is generated mechanically by
+.IR compile_et (1)
+from a source file containing names and associated strings. Each
+table has a name of up to four characters, which is used in place of
+the
+.B XXXX
+in the name of the routine. These routines should be called before
+any of the corresponding error codes are used, so that the
+.I com_err
+library will recognize error codes from these tables when they are
+used.
+
+The
+.B com_err.h
+header file should be included in any source file that uses routines
+from the
+.I com_err
+library; executable files must be linked using
+.I ``-lcom_err''
+in order to cause the
+.I com_err
+library to be included.
+
+.\" .IR for manual entries
+.\" .PP for paragraph breaks
+
+.SH "SEE ALSO"
+compile_et (1), syslog (3).
+
+Ken Raeburn, "A Common Error Description Library for UNIX".
--- /dev/null
+/* $Id: com_err.c,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+
+#if __STDC__
+# undef VARARGS
+# include <stdarg.h>
+#else
+# undef VARARGS
+# define VARARGS 1
+# include <varargs.h>
+#endif
+
+#include "kerberosIV/com_err.h"
+#include "error_table.h"
+
+/*
+ * Protect us from header version (externally visible) of com_err, so
+ * we can survive in a <varargs.h> environment. I think.
+ */
+#if VARARGS
+#define com_err com_err_external
+#include "kerberosIV/com_err.h"
+#undef com_err
+#endif
+
+#ifdef NPOSIX
+#undef vfprintf
+#define vfprintf(stream,fmt,args) _doprnt(fmt,args,stream)
+#endif
+
+#if !defined(lint)
+static const char rcsid[] =
+ "$Id: com_err.c,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $";
+#endif /* ! lint */
+
+static void
+#ifdef __STDC__
+ default_com_err_proc (const char *whoami, long code, const char *fmt, va_list args)
+#else
+ default_com_err_proc (whoami, code, fmt, args)
+ const char *whoami;
+ long code;
+ const char *fmt;
+ va_list args;
+#endif
+{
+ if (whoami) {
+ fputs(whoami, stderr);
+ fputs(": ", stderr);
+ }
+#ifdef SOLARIS
+ if (code) {
+ fputs(error_message(code), stderr);
+ fputs(" ", stderr);
+ } else {
+ vfprintf (stderr, fmt, args);
+ }
+#else
+ if (code) {
+ fputs(error_message(code), stderr);
+ fputs(" ", stderr);
+ }
+ if (fmt) {
+ vfprintf (stderr, fmt, args);
+ }
+#endif
+ putc('\n', stderr);
+ /* should do this only on a tty in raw mode */
+ putc('\r', stderr);
+ fflush(stderr);
+}
+
+typedef void (*errf) __P((const char *, long, const char *, va_list));
+
+errf com_err_hook = default_com_err_proc;
+
+void com_err_va (whoami, code, fmt, args)
+ const char *whoami;
+ long code;
+ const char *fmt;
+ va_list args;
+{
+ if (! com_err_hook)
+ com_err_hook = default_com_err_proc;
+ (*com_err_hook) (whoami, code, fmt, args);
+}
+
+#if ! VARARGS
+void com_err (const char *whoami,
+ long code,
+ const char *fmt, ...)
+{
+#else
+void com_err (va_alist)
+ va_dcl
+{
+ const char *whoami, *fmt;
+ long code;
+#endif
+ va_list pvar;
+
+ if (!com_err_hook)
+ com_err_hook = default_com_err_proc;
+#if VARARGS
+ va_start (pvar);
+ whoami = va_arg (pvar, const char *);
+ code = va_arg (pvar, long);
+ fmt = va_arg (pvar, const char *);
+#else
+ va_start(pvar, fmt);
+#endif
+ com_err_va (whoami, code, fmt, pvar);
+ va_end(pvar);
+}
+
+errf set_com_err_hook (new_proc)
+ errf new_proc;
+{
+ errf x = com_err_hook;
+
+ if (new_proc)
+ com_err_hook = new_proc;
+ else
+ com_err_hook = default_com_err_proc;
+
+ return x;
+}
+
+errf reset_com_err_hook () {
+ errf x = com_err_hook;
+ com_err_hook = default_com_err_proc;
+ return x;
+}
--- /dev/null
+/* $Id: error_message.c,v 1.1.1.1 1995/12/14 06:52:32 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "error_table.h"
+
+static const char rcsid[] =
+ "$Id: error_message.c,v 1.1.1.1 1995/12/14 06:52:32 tholo Exp $";
+static const char copyright[] =
+ "Copyright 1986, 1987, 1988 by the Student Information Processing Board\nand the department of Information Systems\nof the Massachusetts Institute of Technology";
+
+static char buffer[25];
+
+struct et_list * _et_list = (struct et_list *) NULL;
+
+const char *
+error_message (code)
+ long code;
+{
+ int offset;
+ struct et_list *et;
+ int table_num;
+ int started = 0;
+ char *cp;
+
+ offset = code & ((1<<ERRCODE_RANGE)-1);
+ table_num = code - offset;
+ if (!table_num) {
+ if (offset < sys_nerr)
+ return(sys_errlist[offset]);
+ else
+ goto oops;
+ }
+ for (et = _et_list; et; et = et->next) {
+ if (et->table->base == table_num) {
+ /* This is the right table */
+ if (et->table->n_msgs <= offset)
+ goto oops;
+ return(et->table->msgs[offset]);
+ }
+ }
+oops:
+ strcpy (buffer, "Unknown code ");
+ if (table_num) {
+ strcat (buffer, error_table_name (table_num));
+ strcat (buffer, " ");
+ }
+ for (cp = buffer; *cp; cp++)
+ ;
+ if (offset >= 100) {
+ *cp++ = '0' + offset / 100;
+ offset %= 100;
+ started++;
+ }
+ if (started || offset >= 10) {
+ *cp++ = '0' + offset / 10;
+ offset %= 10;
+ }
+ *cp++ = '0' + offset;
+ *cp = '\0';
+ return(buffer);
+}
--- /dev/null
+/* $Id: error_table.h,v 1.1.1.1 1995/12/14 06:52:32 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#ifndef _ET_H
+#define _ET_H
+
+struct error_table {
+ char const * const * msgs;
+ long base;
+ int n_msgs;
+};
+
+struct et_list {
+ struct et_list *next;
+ const struct error_table *table;
+};
+
+extern struct et_list * _et_list;
+
+#define ERRCODE_RANGE 8 /* # of bits to shift table number */
+#define BITS_PER_CHAR 6 /* # bits to shift per character in name */
+
+extern const char *error_table_name();
+
+#endif
--- /dev/null
+/* $Id: et_name.c,v 1.1.1.1 1995/12/14 06:52:32 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include "error_table.h"
+
+#ifndef lint
+static const char copyright[] =
+ "Copyright 1987,1988 by Student Information Processing Board, Massachusetts Institute of Technology";
+static const char rcsid_et_name_c[] =
+ "$Id: et_name.c,v 1.1.1.1 1995/12/14 06:52:32 tholo Exp $";
+#endif
+
+static const char char_set[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+
+static char buf[6];
+
+const char *
+error_table_name(num)
+ int num;
+{
+ int ch;
+ int i;
+ char *p;
+
+ /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
+ p = buf;
+ num >>= ERRCODE_RANGE;
+ /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
+ num &= 077777777;
+ /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
+ for (i = 4; i >= 0; i--) {
+ ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
+ if (ch != 0)
+ *p++ = char_set[ch-1];
+ }
+ *p = '\0';
+ return(buf);
+}
--- /dev/null
+/* $Id: init_et.c,v 1.1.1.1 1995/12/14 06:52:32 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "error_table.h"
+
+#ifndef __STDC__
+#define const
+#endif
+
+#ifndef lint
+static const char rcsid_init_et_c[] =
+ "$Id: init_et.c,v 1.1.1.1 1995/12/14 06:52:32 tholo Exp $";
+#endif
+
+struct foobar {
+ struct et_list etl;
+ struct error_table et;
+};
+
+extern struct et_list * _et_list;
+
+int
+init_error_table(msgs, base, count)
+ const char * const * msgs;
+ int base;
+ int count;
+{
+ struct foobar * new_et;
+
+ if (!base || !count || !msgs)
+ return 0;
+
+ new_et = (struct foobar *) malloc(sizeof(struct foobar));
+ if (!new_et)
+ return errno; /* oops */
+ new_et->etl.table = &new_et->et;
+ new_et->et.msgs = msgs;
+ new_et->et.base = base;
+ new_et->et.n_msgs= count;
+
+ new_et->etl.next = _et_list;
+ _et_list = &new_et->etl;
+ return 0;
+}
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:50 tholo Exp $
+
+PROG= compile_et
+SRCS= compile_et.c error_table.y #et_lex.lex.l
+CFLAGS+=-I. -I${.CURDIR} -I${.CURDIR}/../com_err
+DPADD= ${LIBL}
+LDADD= -ll
+CLEANFILES=error_table.c y.tab.h et_lex.lex.c
+
+beforedepend: et_lex.lex.c
+error_table.o: et_lex.lex.c
+
+install:
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright (c) 1988 Massachusetts Institute of Technology,
+.\" Student Information Processing Board. All rights reserved.
+.\"
+.\" $Id: compile_et.1,v 1.1.1.1 1995/12/14 06:52:50 tholo Exp $
+.\"
+.TH COMPILE_ET 1 "22 Nov 1988" SIPB
+.SH NAME
+compile_et \- error table compiler
+.SH SYNOPSIS
+.B compile_et
+file
+.SH DESCRIPTION
+.B Compile_et
+converts a table listing error-code names and associated messages into
+a C source file suitable for use with the
+.IR com_err (3)
+library.
+
+The source file name must end with a suffix of ``.et''; the file
+consists of a declaration supplying the name (up to four characters
+long) of the error-code table:
+
+.B error_table
+.I name
+
+followed by up to 256 entries of the form:
+
+.B error_code
+.I name,
+"
+.I string
+"
+
+and a final
+
+.B end
+
+to indicate the end of the table.
+
+The name of the table is used to construct the name of a subroutine
+.I initialize_XXXX_error_table
+which must be called in order for the
+.I com_err
+library to recognize the error table.
+
+The various error codes defined are assigned sequentially increasing
+numbers (starting with a large number computed as a hash function of
+the name of the table); thus for compatibility it is suggested that
+new codes be added only to the end of an existing table, and that no
+codes be removed from tables.
+
+The names defined in the table are placed into a C header file with
+preprocessor directives defining them as integer constants of up to
+32 bits in magnitude.
+
+A C source file is also generated which should be compiled and linked
+with the object files which reference these error codes; it contains
+the text of the messages and the initialization subroutine. Both C
+files have names derived from that of the original source file, with
+the ``.et'' suffix replaced by ``.c'' and ``.h''.
+
+A ``#'' in the source file is treated as a comment character, and all
+remaining text to the end of the source line will be ignored.
+
+.SH BUGS
+
+Since
+.B compile_et
+uses a very simple parser based on
+.IR yacc (1),
+its error recovery leaves much to be desired.
+
+.\" .IR for manual entries
+.\" .PP for paragraph breaks
+
+.SH "SEE ALSO"
+com_err (3).
+
+Ken Raeburn, "A Common Error Description Library for UNIX".
--- /dev/null
+/* $id$ */
+
+/*
+ * Copyright 1986, 1987, 1988
+ * by MIT Student Information Processing Board.
+ *
+ * For copyright info, see "mit-sipb-copyright.h".
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <string.h>
+#include <sys/param.h>
+#include "compiler.h"
+
+#ifndef __STDC__
+#define const
+#endif
+
+#ifndef lint
+static const char copyright[] =
+ "Copyright 1987,1988 by MIT Student Information Processing Board";
+
+static const char rcsid_compile_et_c[] =
+ "$Id: compile_et.c,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $";
+#endif
+
+extern char *gensym();
+extern char *current_token;
+extern int table_number, current;
+char buffer[BUFSIZ];
+char *table_name = (char *)NULL;
+FILE *hfile, *cfile;
+
+/* C library */
+extern char *malloc();
+extern int errno;
+
+/* lex stuff */
+extern FILE *yyin;
+extern unsigned lineno;
+
+char * xmalloc (size) unsigned int size; {
+ char * p = malloc (size);
+ if (!p) {
+ perror (whoami);
+ exit (1);
+ }
+ return p;
+}
+
+static int check_arg (str_list, arg) char const *const *str_list, *arg; {
+ while (*str_list)
+ if (!strcmp(arg, *str_list++))
+ return 1;
+ return 0;
+}
+
+static const char *const debug_args[] = {
+ "d",
+ "debug",
+ 0,
+};
+
+static const char *const lang_args[] = {
+ "lang",
+ "language",
+ 0,
+};
+
+static const char *const language_names[] = {
+ "C",
+ "K&R C",
+ "C++",
+ 0,
+};
+
+static const char * const c_src_prolog[] = {
+ "static const char * const text[] = {\n",
+ 0,
+};
+
+static const char * const krc_src_prolog[] = {
+ "#ifdef __STDC__\n",
+ "#define NOARGS void\n",
+ "#else\n",
+ "#define NOARGS\n",
+ "#define const\n",
+ "#endif\n\n",
+ "static const char * const text[] = {\n",
+ 0,
+};
+
+static const char *const struct_def[] = {
+ "struct error_table {\n",
+ " char const * const * msgs;\n",
+ " long base;\n",
+ " int n_msgs;\n",
+ "};\n",
+ "struct et_list {\n",
+ " struct et_list *next;\n",
+ " const struct error_table * table;\n",
+ "};\n",
+ "extern struct et_list *_et_list;\n",
+ "\n", 0,
+};
+
+static const char warning[] =
+ "/*\n * %s:\n * This file is automatically generated; please do not edit it.\n */\n";
+
+/* pathnames */
+char c_file[MAXPATHLEN]; /* output file */
+char h_file[MAXPATHLEN]; /* output */
+
+static void usage () {
+ fprintf (stderr, "%s: usage: %s ERROR_TABLE\n",
+ whoami, whoami);
+ exit (1);
+}
+
+static void dup_err (type, one, two) char const *type, *one, *two; {
+ fprintf (stderr, "%s: multiple %s specified: `%s' and `%s'\n",
+ whoami, type, one, two);
+ usage ();
+}
+
+int main (argc, argv) int argc; char **argv; {
+ char *p, *ename;
+ int len;
+ char const * const *cpp;
+ int got_language = 0;
+
+ /* argument parsing */
+ debug = 0;
+ filename = 0;
+ whoami = argv[0];
+ p = strrchr (whoami, '/');
+ if (p)
+ whoami = p+1;
+ while (argv++, --argc) {
+ char *arg = *argv;
+ if (arg[0] != '-') {
+ if (filename)
+ dup_err ("filenames", filename, arg);
+ filename = arg;
+ }
+ else {
+ arg++;
+ if (check_arg (debug_args, arg))
+ debug++;
+ else if (check_arg (lang_args, arg)) {
+ got_language++;
+ arg = *++argv, argc--;
+ if (!arg)
+ usage ();
+ if (language)
+ dup_err ("languanges", language_names[(int)language], arg);
+#define check_lang(x,v) else if (!strcasecmp(arg,x)) language = v
+ check_lang ("c", lang_C);
+ check_lang ("ansi_c", lang_C);
+ check_lang ("ansi-c", lang_C);
+ check_lang ("krc", lang_KRC);
+ check_lang ("kr_c", lang_KRC);
+ check_lang ("kr-c", lang_KRC);
+ check_lang ("k&r-c", lang_KRC);
+ check_lang ("k&r_c", lang_KRC);
+ check_lang ("c++", lang_CPP);
+ check_lang ("cplusplus", lang_CPP);
+ check_lang ("c-plus-plus", lang_CPP);
+#undef check_lang
+ else {
+ fprintf (stderr, "%s: unknown language name `%s'\n",
+ whoami, arg);
+ fprintf (stderr, "\tpick one of: C K&R-C\n");
+ exit (1);
+ }
+ }
+ else {
+ fprintf (stderr, "%s: unknown control argument -`%s'\n",
+ whoami, arg);
+ usage ();
+ }
+ }
+ }
+ if (!filename)
+ usage ();
+ if (!got_language)
+ language = lang_KRC;
+ else if (language == lang_CPP) {
+ fprintf (stderr, "%s: Sorry, C++ support is not yet finished.\n",
+ whoami);
+ exit (1);
+ }
+
+ p = xmalloc (strlen (filename) + 5);
+ strcpy (p, filename);
+ filename = p;
+ p = strrchr(filename, '/');
+ if (p == (char *)NULL)
+ p = filename;
+ else
+ p++;
+ ename = p;
+ len = strlen (ename);
+ p += len - 3;
+ if (strcmp (p, ".et"))
+ p += 3;
+ *p++ = '.';
+ /* now p points to where "et" suffix should start */
+ /* generate new filenames */
+ strcpy (p, "c");
+ strcpy (c_file, ename);
+ *p = 'h';
+ strcpy (h_file, ename);
+ strcpy (p, "et");
+
+ yyin = fopen(filename, "r");
+ if (!yyin) {
+ perror(filename);
+ exit(1);
+ }
+
+ hfile = fopen(h_file, "w");
+ if (hfile == (FILE *)NULL) {
+ perror(h_file);
+ exit(1);
+ }
+ fprintf (hfile, warning, h_file);
+
+ cfile = fopen(c_file, "w");
+ if (cfile == (FILE *)NULL) {
+ perror(c_file);
+ exit(1);
+ }
+ fprintf (cfile, warning, c_file);
+
+ /* prologue */
+ if (language == lang_C)
+ cpp = c_src_prolog;
+ else if (language == lang_KRC)
+ cpp = krc_src_prolog;
+ else
+ abort ();
+ while (*cpp)
+ fputs (*cpp++, cfile);
+
+ /* parse it */
+ yyparse();
+ fclose(yyin); /* bye bye input file */
+
+ fputs (" 0\n};\n\n", cfile);
+ for (cpp = struct_def; *cpp; cpp++)
+ fputs (*cpp, cfile);
+ fprintf(cfile,
+ "static const struct error_table et = { text, %ldL, %d };\n\n",
+ table_number, current);
+ fputs("static struct et_list link = { 0, 0 };\n\n",
+ cfile);
+ fprintf(cfile, "void initialize_%s_error_table (%s) {\n",
+ table_name, (language == lang_C) ? "void" : "NOARGS");
+ fputs(" if (!link.table) {\n", cfile);
+ fputs(" link.next = _et_list;\n", cfile);
+ fputs(" link.table = &et;\n", cfile);
+ fputs(" _et_list = &link;\n", cfile);
+ fputs(" }\n", cfile);
+ fputs("}\n", cfile);
+ fclose(cfile);
+
+ fprintf (hfile, "extern void initialize_%s_error_table ();\n",
+ table_name);
+ fprintf (hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n",
+ table_name, table_number);
+ /* compatibility... */
+ fprintf (hfile, "\n/* for compatibility with older versions... */\n");
+ fprintf (hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
+ table_name, table_name);
+ fprintf (hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n", table_name,
+ table_name);
+ fclose(hfile); /* bye bye include file */
+
+ return 0;
+}
+
+int yyerror(s) char *s; {
+ fputs(s, stderr);
+ fprintf(stderr, "\nLine number %d; last token was '%s'\n",
+ lineno, current_token);
+}
--- /dev/null
+/* $Id: compiler.h,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $ */
+
+/*
+ * definitions common to the source files of the error table compiler
+ */
+
+#ifndef __STDC__
+/* loser */
+#undef const
+#define const
+#endif
+
+enum lang {
+ lang_C, /* ANSI C (default) */
+ lang_KRC, /* C: ANSI + K&R */
+ lang_CPP /* C++ */
+};
+
+int debug; /* dump debugging info? */
+char *filename; /* error table source */
+enum lang language;
+const char *whoami;
--- /dev/null
+%{
+/* $Id: error_table.y,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+char *str_concat(), *ds(), *quote();
+char *current_token = (char *)NULL;
+extern char *table_name;
+%}
+%union {
+ char *dynstr;
+}
+
+%token ERROR_TABLE ERROR_CODE_ENTRY END
+%token <dynstr> STRING QUOTED_STRING
+%type <dynstr> ec_name description table_id
+%{
+%}
+%start error_table
+%%
+
+error_table : ERROR_TABLE table_id error_codes END
+ { table_name = ds($2);
+ current_token = table_name;
+ put_ecs(); }
+ ;
+
+table_id : STRING
+ { current_token = $1;
+ set_table_num($1);
+ $$ = $1; }
+ ;
+
+error_codes : error_codes ec_entry
+ | ec_entry
+ ;
+
+ec_entry : ERROR_CODE_ENTRY ec_name ',' description
+ { add_ec($2, $4);
+ free($2);
+ free($4); }
+ | ERROR_CODE_ENTRY ec_name '=' STRING ',' description
+ { add_ec_val($2, $4, $6);
+ free($2);
+ free($4);
+ free($6);
+ }
+ ;
+
+ec_name : STRING
+ { $$ = ds($1);
+ current_token = $$; }
+ ;
+
+description : QUOTED_STRING
+ { $$ = ds($1);
+ current_token = $$; }
+ ;
+
+%%
+/*
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include "error_table.h"
+
+#ifndef lint
+static char const rcsid_error_table_y[] =
+ "$Id: error_table.y,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $";
+#endif
+
+#include "et_lex.lex.c"
+
+extern FILE *hfile, *cfile;
+
+static long gensym_n = 0;
+char *
+gensym(x)
+ char const *x;
+{
+ char *symbol;
+ if (!gensym_n) {
+ struct timeval tv;
+ struct timezone tzp;
+ gettimeofday(&tv, &tzp);
+ gensym_n = (tv.tv_sec%10000)*100 + tv.tv_usec/10000;
+ }
+ symbol = (char *)malloc(32 * sizeof(char));
+ gensym_n++;
+ sprintf(symbol, "et%ld", gensym_n);
+ return(symbol);
+}
+
+char *
+ds(string)
+ char const *string;
+{
+ char *rv;
+ rv = (char *)malloc(strlen(string)+1);
+ strcpy(rv, string);
+ return(rv);
+}
+
+char *
+quote(string)
+ char const *string;
+{
+ char *rv;
+ rv = (char *)malloc(strlen(string)+3);
+ strcpy(rv, "\"");
+ strcat(rv, string);
+ strcat(rv, "\"");
+ return(rv);
+}
+
+long table_number;
+int current = 0;
+char **error_codes = (char **)NULL;
+
+add_ec(name, description)
+ char const *name, *description;
+{
+ fprintf(cfile, "\t\"%s\",\n", description);
+ if (error_codes == (char **)NULL) {
+ error_codes = (char **)malloc(sizeof(char *));
+ *error_codes = (char *)NULL;
+ }
+ error_codes = (char **)realloc((char *)error_codes,
+ (current + 2)*sizeof(char *));
+ error_codes[current++] = ds(name);
+ error_codes[current] = (char *)NULL;
+}
+
+add_ec_val(name, val, description)
+ char const *name, *val, *description;
+{
+ const int ncurrent = atoi(val);
+ if (ncurrent < current) {
+ printf("Error code %s (%d) out of order", name,
+ current);
+ return;
+ }
+
+ while (ncurrent > current)
+ fputs("\t(char *)NULL,\n", cfile), current++;
+
+ fprintf(cfile, "\t\"%s\",\n", description);
+ if (error_codes == (char **)NULL) {
+ error_codes = (char **)malloc(sizeof(char *));
+ *error_codes = (char *)NULL;
+ }
+ error_codes = (char **)realloc((char *)error_codes,
+ (current + 2)*sizeof(char *));
+ error_codes[current++] = ds(name);
+ error_codes[current] = (char *)NULL;
+}
+
+put_ecs()
+{
+ int i;
+ for (i = 0; i < current; i++) {
+ if (error_codes[i] != (char *)NULL)
+ fprintf(hfile, "#define %-40s (%ldL)\n",
+ error_codes[i], table_number + i);
+ }
+}
+
+/*
+ * char_to_num -- maps letters and numbers into a small numbering space
+ * uppercase -> 1-26
+ * lowercase -> 27-52
+ * digits -> 53-62
+ * underscore-> 63
+ */
+
+static const char char_set[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+
+int char_to_num(c)
+ char c;
+{
+ const char *where;
+ int diff;
+
+ where = strchr (char_set, c);
+ if (where) {
+ diff = where - char_set + 1;
+ assert (diff < (1 << ERRCODE_RANGE));
+ return diff;
+ }
+ else if (isprint (c))
+ fprintf (stderr,
+ "Illegal character `%c' in error table name\n",
+ c);
+ else
+ fprintf (stderr,
+ "Illegal character %03o in error table name\n",
+ c);
+ exit (1);
+}
+
+set_table_num(string)
+ char *string;
+{
+ if (char_to_num (string[0]) > char_to_num ('z')) {
+ fprintf (stderr, "%s%s%s%s",
+ "First character of error table name must be ",
+ "a letter; name ``",
+ string, "'' rejected\n");
+ exit (1);
+ }
+ if (strlen(string) > 4) {
+ fprintf(stderr, "Table name %s too long, truncated ",
+ string);
+ string[4] = '\0';
+ fprintf(stderr, "to %s\n", string);
+ }
+ while (*string != '\0') {
+ table_number = (table_number << BITS_PER_CHAR)
+ + char_to_num(*string);
+ string++;
+ }
+ table_number = table_number << ERRCODE_RANGE;
+}
+
--- /dev/null
+%{
+ unsigned lineno = 1;
+%}
+
+PC [^\"]
+AN [A-Z_a-z0-9]
+%%
+
+error_table return ERROR_TABLE;
+et return ERROR_TABLE;
+error_code return ERROR_CODE_ENTRY;
+ec return ERROR_CODE_ENTRY;
+end return END;
+
+[\t ] ;
+\n ++lineno;
+
+\"{PC}*\" { register char *p; yylval.dynstr = ds(yytext+1);
+ if (p=strrchr(yylval.dynstr, '"')) *p='\0';
+ return QUOTED_STRING;
+ }
+
+{AN}* { yylval.dynstr = ds(yytext); return STRING; }
+
+#.*\n ++lineno;
+
+. { return (*yytext); }
+%%
+#ifndef lint
+static char rcsid_et_lex_lex_l[] = "$Id: et_lex.lex.l,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $";
+#endif
--- /dev/null
+/* $Id: 3cbc_enc.c,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+#include "des_locl.h"
+
+static void
+xp(des_cblock *arg)
+{
+ unsigned char *a = (unsigned char *) arg;
+ int i;
+ for(i=0; i<8; i++) printf("%02X",a[i]);printf("\n");
+}
+
+int des_3cbc_encrypt(des_cblock (*input), des_cblock (*output), long int length, struct des_ks_struct *ks1, struct des_ks_struct *ks2, des_cblock (*iv1), des_cblock (*iv2), int encrypt)
+{
+ int off=length/8-1;
+ des_cblock niv1,niv2;
+
+ printf("3cbc\n");
+ xp(iv1);
+ xp(iv1);
+ xp(iv2);
+ xp(input);
+ if (encrypt == DES_ENCRYPT)
+ {
+ des_cbc_encrypt(input,output,length,ks1,iv1,encrypt);
+ if (length >= sizeof(des_cblock))
+ memcpy(niv1,output[off],sizeof(des_cblock));
+ des_cbc_encrypt(output,output,length,ks2,iv1,!encrypt);
+ des_cbc_encrypt(output,output,length,ks1,iv2, encrypt);
+ if (length >= sizeof(des_cblock))
+ memcpy(niv2,output[off],sizeof(des_cblock));
+ memcpy(*iv1,niv1,sizeof(des_cblock));
+ }
+ else
+ {
+ if (length >= sizeof(des_cblock))
+ memcpy(niv1,input[off],sizeof(des_cblock));
+ des_cbc_encrypt(input,output,length,ks1,iv1,encrypt);
+ des_cbc_encrypt(output,output,length,ks2,iv2,!encrypt);
+ if (length >= sizeof(des_cblock))
+ memcpy(niv2,output[off],sizeof(des_cblock));
+ des_cbc_encrypt(output,output,length,ks1,iv2, encrypt);
+ }
+ memcpy(iv1,niv1,sizeof(des_cblock));
+ memcpy(iv2,niv2,sizeof(des_cblock));
+ xp(iv1);
+ xp(iv1);
+ xp(iv2);
+ xp(output);
+ return(0);
+}
--- /dev/null
+/* $Id: 3ecb_enc.c,v 1.1.1.1 1995/12/14 06:52:45 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+#include "des_locl.h"
+
+int des_3ecb_encrypt(des_cblock (*input), des_cblock (*output), struct des_ks_struct *ks1, struct des_ks_struct *ks2, int encrypt)
+{
+ register u_int32_t l0,l1;
+ register unsigned char *in,*out;
+ u_int32_t ll[2];
+
+ in=(unsigned char *)input;
+ out=(unsigned char *)output;
+ c2l(in,l0);
+ c2l(in,l1);
+ ll[0]=l0;
+ ll[1]=l1;
+ des_encrypt(ll,ll,ks1,encrypt);
+ des_encrypt(ll,ll,ks2,!encrypt);
+ des_encrypt(ll,ll,ks1,encrypt);
+ l0=ll[0];
+ l1=ll[1];
+ l2c(l0,out);
+ l2c(l1,out);
+ return(0);
+}
+
--- /dev/null
+ The "Artistic License"
+
+ Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain or from the Copyright Holder. A Package
+modified in such a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as uunet.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this
+Package. You may not charge a fee for this Package itself. However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you do not advertise this Package as a
+product of your own.
+
+6. Any programs linked with this library do not automatically fall
+under the copyright of this Package, but belong to whomever generated
+them, and may be sold commercially, and may be aggregated with this
+Package.
+
+7. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+8. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ The End
--- /dev/null
+The main changes in this package since it was last posted to
+comp.sources.misc are
+
+The main changes are
+- Major changes to the Copyright restrictions.
+- Lots and lots of features added to the des(1) command, including
+ - Triple DES, both triple ECB and triple CBC options.
+ - uuencodeing/uudecoding built in to des(1).
+ - generate checksums.
+ - hex keys.
+- Cleaned up the prototypes in des.h
+- Filenames are now mostly <= 8 characters long.
+- OFB, CFB, triple ECB and triple CBC modes of DES added to the library.
+- Compiles and runs of all 64bit machines I could test the code on
+ (Cray, ETA10, DEC Alpha).
+- It really does work with kerberos v 4 now :-).
--- /dev/null
+Copyright (C) 1993 Eric Young
+
+This is a DES implementation written by Eric Young (eay@psych.psy.uq.oz.au)
+The implementation was written so as to conform with the manual entry
+for the des_crypt(3) library routines from MIT's project Athena.
+
+
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+\f
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+\f
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $
+
+LIB= des
+SRCS= 3cbc_enc.c 3ecb_enc.c cbc_cksm.c cbc_enc.c cfb_enc.c \
+ ecb_enc.c enc_read.c enc_writ.c key_par.c ofb_enc.c \
+ pcbc_enc.c qud_cksm.c random_key.c read_pwd.c rnd_keys.c \
+ set_key.c str2key.c
+CFLAGS+=-I${.CURDIR}
+MAN= des_crypt.3
+MLINKS+=des_crypt.3 des_read_password.3 des_crypt.3 des_string_to_key.3 \
+ des_crypt.3 des_random_key.3 des_crypt.3 des_set_key.3 \
+ des_crypt.3 des_ecb_encrypt.3 des_crypt.3 des_cbc_encrypt.3 \
+ des_crypt.3 des_pcbc_encrypt.3 des_crypt.3 des_cbc_cksum.3 \
+ des_crypt.3 des_quad_cksum.3
+
+.include <bsd.lib.mk>
--- /dev/null
+ libdes, Version 3.00 93/10/07
+
+ Copyright (c) 1993, Eric Young
+ All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of either:
+
+ a) the GNU General Public License as published by the Free
+ Software Foundation; either version 1, or (at your option) any
+ later version, or
+
+ b) the "Artistic License" which comes with this Kit.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either
+ the GNU General Public License or the Artistic License for more details.
+
+ You should have received a copy of the Artistic License with this
+ Kit, in the file named "Artistic". If not, I'll be glad to provide one.
+
+ You should also have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+---
+This kit builds a DES encryption library and a DES encryption program.
+It suports ecb, cbc, ofb, cfb, triple ecb, triple cbc and MIT's pcbc
+encryption modes and also has a fast implementation of crypt(3).
+It contains support routines to read keys from a terminal,
+generate a random key, generate a key from an arbitary length string,
+read/write encrypted data from/to a file descriptor.
+
+The implementation was written so as to conform with the manual entry
+for the des_crypt(3) library routines from MIT's project Athena.
+
+destest should be run after compilation to test the des routines.
+rpw should be run after compilation to test the read password routines.
+The des program is a replacement for the sun des command. I believe it
+conforms to the sun version.
+
+The Imakefile is setup for use in the kerberos distribution.
+
+These routines are best compiled with gcc or any other good
+optimising compiler.
+Just turn you optimiser up to the highest settings and run destest
+after the build to make sure everything works.
+
+I believe these routines are close to the fastest and most portable DES
+routines that use small lookup tables (4.5k) that are publicly available.
+The fcrypt routine is faster than ufc's fcrypt (when compiling with
+gcc2 -O2) on the sparc 2 (1410 vs 1270) but is not so good on other machines
+(on a sun3/260 168 vs 336).
+
+Eric Young (eay@psych.psy.uq.oz.au)
--- /dev/null
+Release apon comp.sources.misc
+Version 3.01 08/10/93
+ Added des_3cbc_encrypt()
+
+Version 3.00 07/10/93
+ Fixed up documentation.
+ quad_cksum definitly compatable with MIT's now.
+
+Version 2.30 24/08/93
+ Tripple DES now defaults to tripple cbc but can do tripple ecb
+ with the -b flag.
+ Fixed some MSDOS uuen/uudecoding problems, thanks to
+ Added prototypes.
+
+Version 2.22 29/06/93
+ Fixed a bug in des_is_weak_key() which stopped it working :-(
+ thanks to engineering@MorningStar.Com.
+
+Version 2.21 03/06/93
+ des(1) with no arguments gives quite a bit of help.
+ Added -c (generate ckecksum) flag to des(1).
+ Added -3 (tripple DES) flag to des(1).
+ Added cfb and ofb routines to the library.
+
+Version 2.20 11/03/93
+ Added -u (uuencode) flag to des(1).
+ I have been playing with byte order in quad_cksum to make it
+ compatible with MIT's version. All I can say is aviod this
+ function if possible since MIT's output is endian dependent.
+
+Version 2.12 14/10/92
+ Added MSDOS specific macro in ecb_encrypt which gives a %70
+ speed up when the code is compiled with turbo C.
+
+Version 2.11 12/10/92
+ Speedup in set_key (recoding of PC-1)
+ I now do it in 47 simple operations, down from 60.
+ Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)
+ for motivating me to look for a faster system :-)
+ The speedup is probably less that 1% but it is still 13
+ instructions less :-).
+
+Version 2.10 06/10/92
+ The code now works on the 64bit ETA10 and CRAY without modifications or
+ #defines. I believe the code should work on any machine that
+ defines long, int or short to be 8 bytes long.
+ Thanks to Shabbir J. Safdar (shabby@mentor.cc.purdue.edu)
+ for helping me fix the code to run on 64bit machines (he had
+ access to an ETA10).
+ Thanks also to John Fletcher <john_fletcher@lccmail.ocf.llnl.gov>
+ for testing the routines on a CRAY.
+ read_password.c has been renamed to read_passwd.c
+ string_to_key.c has been renamed to string2key.c
+
+Version 2.00 14/09/92
+ Made mods so that the library should work on 64bit CPU's.
+ Removed all my uchar and ulong defs. To many different
+ versions of unix define them in their header files in too many
+ different combinations :-)
+ IRIX - Sillicon Graphics mods (mostly in read_password.c).
+ Thanks to Andrew Daviel (advax@erich.triumf.ca)
+
+Version 1.99 26/08/92
+ Fixed a bug or 2 in enc_read.c
+ Fixed a bug in enc_write.c
+ Fixed a pseudo bug in fcrypt.c (very obscure).
+
+Version 1.98 31/07/92
+ Support for the ETA10. This is a strange machine that defines
+ longs and ints as 8 bytes and shorts as 4 bytes.
+ Since I do evil things with long * that assume that they are 4
+ bytes. Look in the Makefile for the option to compile for
+ this machine. quad_cksum appears to have problems but I
+ will don't have the time to fix it right now, and this is not
+ a function that uses DES and so will not effect the main uses
+ of the library.
+
+Version 1.97 20/05/92 eay
+ Fixed the Imakefile and made some changes to des.h to fix some
+ problems when building this package with Kerberos v 4.
+
+Version 1.96 18/05/92 eay
+ Fixed a small bug in string_to_key() where problems could
+ occur if des_check_key was set to true and the string
+ generated a weak key.
+
+Patch2 posted to comp.sources.misc
+Version 1.95 13/05/92 eay
+ Added an alternative version of the D_ENCRYPT macro in
+ ecb_encrypt and fcrypt. Depending on the compiler, one version or the
+ other will be faster. This was inspired by
+ Dana How <how@isl.stanford.edu>, and her pointers about doing the
+ *(ulong *)((uchar *)ptr+(value&0xfc))
+ vs
+ ptr[value&0x3f]
+ to stop the C compiler doing a <<2 to convert the long array index.
+
+Version 1.94 05/05/92 eay
+ Fixed an incompatibility between my string_to_key and the MIT
+ version. When the key is longer than 8 chars, I was wrapping
+ with a different method. To use the old version, define
+ OLD_STR_TO_KEY in the makefile. Thanks to
+ viktor@newsu.shearson.com (Viktor Dukhovni).
+
+Version 1.93 28/04/92 eay
+ Fixed the VMS mods so that echo is now turned off in
+ read_password. Thanks again to brennan@coco.cchs.su.oz.AU.
+ MSDOS support added. The routines can be compiled with
+ Turbo C (v2.0) and MSC (v5.1). Make sure MSDOS is defined.
+
+Patch1 posted to comp.sources.misc
+Version 1.92 13/04/92 eay
+ Changed D_ENCRYPT so that the rotation of R occurs outside of
+ the loop. This required rotating all the longs in sp.h (now
+ called spr.h). Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
+ speed.c has been changed so it will work without SIGALRM. If
+ times(3) is not present it will try to use ftime() instead.
+
+Version 1.91 08/04/92 eay
+ Added -E/-D options to des(1) so it can use string_to_key.
+ Added SVR4 mods suggested by witr@rwwa.COM
+ Added VMS mods suggested by brennan@coco.cchs.su.oz.AU. If
+ anyone knows how to turn of tty echo in VMS please tell me or
+ implement it yourself :-).
+ Changed FILE *IN/*OUT to *DES_IN/*DES_OUT since it appears VMS
+ does not like IN/OUT being used.
+
+Libdes posted to comp.sources.misc
+Version 1.9 24/03/92 eay
+ Now contains a fast small crypt replacement.
+ Added des(1) command.
+ Added des_rw_mode so people can use cbc encryption with
+ enc_read and enc_write.
+
+Version 1.8 15/10/91 eay
+ Bug in cbc_cksum.
+ Many thanks to Keith Reynolds (keithr@sco.COM) for pointing this
+ one out.
+
+Version 1.7 24/09/91 eay
+ Fixed set_key :-)
+ set_key is 4 times faster and takes less space.
+ There are a few minor changes that could be made.
+
+Version 1.6 19/09/1991 eay
+ Finally go IP and FP finished.
+ Now I need to fix set_key.
+ This version is quite a bit faster that 1.51
+
+Version 1.52 15/06/1991 eay
+ 20% speedup in ecb_encrypt by changing the E bit selection
+ to use 2 32bit words. This also required modification of the
+ sp table. There is still a way to speedup the IP and IP-1
+ (hints from outer@sq.com) still working on this one :-(.
+
+Version 1.51 07/06/1991 eay
+ Faster des_encrypt by loop unrolling
+ Fixed bug in quad_cksum.c (thanks to hughes@logos.ucs.indiana.edu)
+
+Version 1.50 28/05/1991 eay
+ Optimized the code a bit more for the sparc. I have improved the
+ speed of the inner des_encrypt by speeding up the initial and
+ final permutations.
+
+Version 1.40 23/10/1990 eay
+ Fixed des_random_key, it did not produce a random key :-(
+
+Version 1.30 2/10/1990 eay
+ Have made des_quad_cksum the same as MIT's, the full package
+ should be compatible with MIT's
+ Have tested on a DECstation 3100
+ Still need to fix des_set_key (make it faster).
+ Does des_cbc_encrypts at 70.5k/sec on a 3100.
+
+Version 1.20 18/09/1990 eay
+ Fixed byte order dependencies.
+ Fixed (I hope) all the word alignment problems.
+ Speedup in des_ecb_encrypt.
+
+Version 1.10 11/09/1990 eay
+ Added des_enc_read and des_enc_write.
+ Still need to fix des_quad_cksum.
+ Still need to document des_enc_read and des_enc_write.
+
+Version 1.00 27/08/1990 eay
--- /dev/null
+/* $Id: cbc_cksm.c,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+#include "des_locl.h"
+
+u_int32_t des_cbc_cksum(des_cblock (*input), des_cblock (*output), long int length, struct des_ks_struct *schedule, des_cblock (*ivec))
+{
+ register u_int32_t tout0,tout1,tin0,tin1;
+ register long l=length;
+ u_int32_t tin[2],tout[2];
+ unsigned char *in,*out,*iv;
+
+ in=(unsigned char *)input;
+ out=(unsigned char *)output;
+ iv=(unsigned char *)ivec;
+
+ c2l(iv,tout0);
+ c2l(iv,tout1);
+ for (; l>0; l-=8)
+ {
+ if (l >= 8)
+ {
+ c2l(in,tin0);
+ c2l(in,tin1);
+ }
+ else
+ c2ln(in,tin0,tin1,l);
+
+ tin0^=tout0;
+ tin1^=tout1;
+ tin[0]=tin0;
+ tin[1]=tin1;
+ des_encrypt(tin,tout,
+ schedule,DES_ENCRYPT);
+ /* fix 15/10/91 eay - thanks to keithr@sco.COM */
+ tout0=tout[0];
+ tout1=tout[1];
+ }
+ if (out != NULL)
+ {
+ l2c(tout0,out);
+ l2c(tout1,out);
+ }
+ tout0=tin0=tin1=tin[0]=tin[1]=tout[0]=tout[1]=0;
+ return(tout1);
+}
--- /dev/null
+/* $Id: cbc_enc.c,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+#include "des_locl.h"
+
+int des_cbc_encrypt(des_cblock (*input), des_cblock (*output), long int length, struct des_ks_struct *schedule, des_cblock (*ivec), int encrypt)
+{
+ register u_int32_t tin0,tin1;
+ register u_int32_t tout0,tout1,xor0,xor1;
+ register unsigned char *in,*out;
+ register long l=length;
+ u_int32_t tout[2],tin[2];
+ unsigned char *iv;
+
+ in=(unsigned char *)input;
+ out=(unsigned char *)output;
+ iv=(unsigned char *)ivec;
+
+ if (encrypt)
+ {
+ c2l(iv,tout0);
+ c2l(iv,tout1);
+ for (; l>0; l-=8)
+ {
+ if (l >= 8)
+ {
+ c2l(in,tin0);
+ c2l(in,tin1);
+ }
+ else
+ c2ln(in,tin0,tin1,l);
+ tin0^=tout0;
+ tin1^=tout1;
+ tin[0]=tin0;
+ tin[1]=tin1;
+ des_encrypt(tin,tout,
+ schedule,encrypt);
+ tout0=tout[0];
+ tout1=tout[1];
+ l2c(tout0,out);
+ l2c(tout1,out);
+ }
+ }
+ else
+ {
+ c2l(iv,xor0);
+ c2l(iv,xor1);
+ for (; l>0; l-=8)
+ {
+ c2l(in,tin0);
+ c2l(in,tin1);
+ tin[0]=tin0;
+ tin[1]=tin1;
+ des_encrypt(tin,tout,
+ schedule,encrypt);
+ tout0=tout[0]^xor0;
+ tout1=tout[1]^xor1;
+ if (l >= 8)
+ {
+ l2c(tout0,out);
+ l2c(tout1,out);
+ }
+ else
+ l2cn(tout0,tout1,out,l);
+ xor0=tin0;
+ xor1=tin1;
+ }
+ }
+ tin0=tin1=tout0=tout1=xor0=xor1=0;
+ tin[0]=tin[1]=tout[0]=tout[1]=0;
+ return(0);
+}
+
--- /dev/null
+/* $Id: cfb_enc.c,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+#include "des_locl.h"
+
+/* The input and output are loaded in multiples of 8 bits.
+ * What this means is that if you hame numbits=12 and length=2
+ * the first 12 bits will be retrieved from the first byte and half
+ * the second. The second 12 bits will come from the 3rd and half the 4th
+ * byte.
+ */
+int des_cfb_encrypt(unsigned char *in, unsigned char *out, int numbits, long int length, struct des_ks_struct *schedule, des_cblock (*ivec), int encrypt)
+{
+ register u_int32_t d0,d1,v0,v1,n=(numbits+7)/8;
+ register u_int32_t mask0,mask1;
+ register long l=length;
+ register int num=numbits;
+ u_int32_t ti[2],to[2];
+ unsigned char *iv;
+
+ if (num > 64) return(0);
+ if (num > 32)
+ {
+ mask0=0xffffffff;
+ if (num == 64)
+ mask1=mask0;
+ else
+ mask1=(1L<<(num-32))-1;
+ }
+ else
+ {
+ if (num == 32)
+ mask0=0xffffffff;
+ else
+ mask0=(1L<<num)-1;
+ mask1=0x00000000;
+ }
+
+ iv=(unsigned char *)ivec;
+ c2l(iv,v0);
+ c2l(iv,v1);
+ if (encrypt)
+ {
+ while (l-- > 0)
+ {
+ ti[0]=v0;
+ ti[1]=v1;
+ des_encrypt(ti,to,
+ schedule,DES_ENCRYPT);
+ c2ln(in,d0,d1,n);
+ in+=n;
+ d0=(d0^to[0])&mask0;
+ d1=(d1^to[1])&mask1;
+ l2cn(d0,d1,out,n);
+ out+=n;
+ if (num > 32)
+ {
+ v0=((v1>>(num-32))|(d0<<(64-num)))&0xffffffff;
+ v1=((d0>>(num-32))|(d1<<(64-num)))&0xffffffff;
+ }
+ else
+ {
+ v0=((v0>>num)|(v1<<(32-num)))&0xffffffff;
+ v1=((v1>>num)|(d0<<(32-num)))&0xffffffff;
+ }
+ }
+ }
+ else
+ {
+ while (l-- > 0)
+ {
+ ti[0]=v0;
+ ti[1]=v1;
+ des_encrypt(ti,to,
+ schedule,DES_ENCRYPT);
+ c2ln(in,d0,d1,n);
+ in+=n;
+ if (num > 32)
+ {
+ v0=((v1>>(num-32))|(d0<<(64-num)))&0xffffffff;
+ v1=((d0>>(num-32))|(d1<<(64-num)))&0xffffffff;
+ }
+ else
+ {
+ v0=((v0>>num)|(v1<<(32-num)))&0xffffffff;
+ v1=((v1>>num)|(d0<<(32-num)))&0xffffffff;
+ }
+ d0=(d0^to[0])&mask0;
+ d1=(d1^to[1])&mask1;
+ l2cn(d0,d1,out,n);
+ out+=n;
+ }
+ }
+ iv=(unsigned char *)ivec;
+ l2c(v0,iv);
+ l2c(v1,iv);
+ v0=v1=d0=d1=ti[0]=ti[1]=to[0]=to[1]=0;
+ return(0);
+}
+
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: des_crypt.3,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $
+.TH DES_CRYPT 3 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+des_read_password, des_string_to_key, des_random_key, des_set_key,
+des_ecb_encrypt, des_cbc_encrypt, des_pcbc_encrypt, des_cbc_cksum,
+des_quad_cksum, \- (new) DES encryption
+.SH SYNOPSIS
+.nf
+.nj
+.ft B
+#include <des.h>
+.PP
+.ft B
+.B int des_read_password(key,prompt,verify)
+des_cblock *key;
+char *prompt;
+int verify;
+.PP
+.ft B
+int des_string_to_key(str,key)
+char *str;
+des_cblock key;
+.PP
+.ft B
+int des_random_key(key)
+des_cblock *key;
+.PP
+.ft B
+int des_set_key(key,schedule)
+des_cblock *key;
+des_key_schedule schedule;
+.PP
+.ft B
+int des_ecb_encrypt(input,output,schedule,encrypt)
+des_cblock *input;
+des_cblock *output;
+des_key_schedule schedule;
+int encrypt;
+.PP
+.ft B
+int des_cbc_encrypt(input,output,length,schedule,ivec,encrypt)
+des_cblock *input;
+des_cblock *output;
+long length;
+des_key_schedule schedule;
+des_cblock *ivec;
+int encrypt;
+.PP
+.ft B
+int des_pcbc_encrypt(input,output,length,schedule,ivec,encrypt)
+des_cblock *input;
+des_cblock *output;
+long length;
+des_key_schedule schedule;
+des_cblock *ivec;
+int encrypt;
+.PP
+.ft B
+unsigned long des_cbc_cksum(input,output,length,schedule,ivec)
+des_cblock *input;
+des_cblock *output;
+long length;
+des_key_schedule schedule;
+des_cblock *ivec;
+.PP
+.ft B
+unsigned long quad_cksum(input,output,length,out_count,seed)
+des_cblock *input;
+des_cblock *output;
+long length;
+int out_count;
+des_cblock *seed;
+.PP
+.fi
+.SH DESCRIPTION
+This library supports various DES encryption related operations. It differs
+from the
+.I crypt, setkey, and encrypt
+library routines in that it provides
+a true DES encryption, without modifying the algorithm,
+and executes much faster.
+.PP
+For each key that may be simultaneously active, create a
+.B des_key_schedule
+struct,
+defined in "des.h". Next, create key schedules (from the 8-byte keys) as
+needed, via
+.I des_set_key,
+prior to using the encryption or checksum routines. Then
+setup the input and output areas. Make sure to note the restrictions
+on lengths being multiples of eight bytes. Finally, invoke the
+encryption/decryption routines,
+.I des_ecb_encrypt
+or
+.I des_cbc_encrypt
+or
+.I des_pcbc_encrypt,
+or, to generate a cryptographic checksum, use
+.I quad_cksum
+(fast) or
+.I des_cbc_cksum
+(slow).
+.PP
+A
+.I des_cblock
+struct is an 8 byte block used as the fundamental unit for DES data and
+keys, and is defined as:
+.PP
+.B typedef unsigned char des_cblock[8];
+.PP
+and a
+.I des_key_schedule,
+is defined as:
+.PP
+.B typedef struct des_ks_struct {des_cblock _;} des_key_schedule[16];
+.PP
+.I des_read_password
+writes the string specified by
+.I prompt
+to the standard
+output, turns off echo (if possible)
+and reads an input string from standard input until terminated with a newline.
+If
+.I verify
+is non-zero, it prompts and reads input again, for use
+in applications such as changing a password; both
+versions are compared, and the input is requested repeatedly until they
+match. Then
+.I des_read_password
+converts the input string into a valid DES key, internally
+using the
+.I des_string_to_key
+routine. The newly created key is copied to the
+area pointed to by the
+.I key
+argument.
+.I des_read_password
+returns a zero if no errors occurred, or a -1
+indicating that an error
+occurred trying to manipulate the terminal echo.
+.PP
+.PP
+.I des_string_to_key
+converts an arbitrary length null-terminated string
+to an 8 byte DES key, with odd byte parity, per FIPS specification.
+A one-way function is used to convert the string to a key, making it
+very difficult to reconstruct the string from the key.
+The
+.I str
+argument is a pointer to the string, and
+.I key
+should
+point to a
+.I des_cblock
+supplied by the caller to receive the generated key.
+No meaningful value is returned. Void is not used for compatibility with
+other compilers.
+.PP
+.PP
+.I des_random_key
+generates a random DES encryption key (eight bytes), set to odd parity per
+FIPS
+specifications.
+This routine uses the current time, process id, and a counter
+as a seed for the random number generator.
+The caller must supply space for the output key, pointed to
+by argument
+.I key,
+then after calling
+.I des_random_key
+should
+call the
+.I des_set_key
+routine when needed.
+No meaningful value is returned. Void is not used for compatibility
+with other compilers.
+.PP
+.PP
+.I des_set_key
+calculates a key schedule from all eight bytes of the input key, pointed
+to by the
+.I key
+argument, and outputs the schedule into the
+.I des_key_schedule
+indicated by the
+.I schedule
+argument. Make sure to pass a valid eight byte
+key; no padding is done. The key schedule may then be used in subsequent
+encryption/decryption/checksum operations. Many key schedules may be
+cached for later use. The user is responsible to clear keys and schedules
+as soon as no longer needed, to prevent their disclosure.
+The routine also checks the key
+parity, and returns a zero if the key parity is correct (odd), a -1
+indicating a key parity error, or a -2 indicating use of an illegal
+weak key. If an error is returned, the key schedule was not created.
+.PP
+.PP
+.I des_ecb_encrypt
+is the basic DES encryption routine that encrypts or decrypts a single 8-byte
+block in
+.B electronic code book
+mode. It always transforms the input data, pointed to by
+.I input,
+into the output data, pointed to by the
+.I output
+argument.
+.PP
+If the
+.I encrypt
+argument is non-zero, the
+.I input
+(cleartext) is encrypted into the
+.I output
+(ciphertext) using the key_schedule specified by the
+.I schedule
+argument, previously set via
+.I des_set_key
+.PP
+If encrypt is zero, the
+.I input
+(now ciphertext) is decrypted into the
+.I output
+(now cleartext).
+.PP
+Input and output may overlap.
+.PP
+No meaningful value is returned. Void is not used for compatibility
+with other compilers.
+.PP
+.PP
+.I des_cbc_encrypt
+encrypts/decrypts using the
+.B cipher-block-chaining mode of DES.
+If the
+.I encrypt
+argument is non-zero, the routine cipher-block-chain encrypts
+the cleartext data pointed to by the
+.I input
+argument into the ciphertext pointed to by the
+.I output
+argument, using the key schedule provided by the
+.I schedule
+argument, and initialization vector provided by the
+.I ivec
+argument.
+If the
+.I length
+argument is not an integral
+multiple of eight bytes, the last block is copied to a temp and zero
+filled (highest addresses). The output is ALWAYS an integral multiple
+of eight bytes.
+.PP
+If
+.I encrypt
+is zero, the routine cipher-block chain decrypts the (now) ciphertext
+data pointed to by the
+.I input
+argument into (now) cleartext pointed to by the
+.I output
+argument using the key schedule provided by the
+.I schedule
+argument, and initialization vector provided by the
+.I ivec
+argument. Decryption ALWAYS operates on integral
+multiples of 8 bytes, so it will round the
+.I length
+provided up to the
+appropriate multiple. Consequently, it will always produce the rounded-up
+number of bytes of output cleartext. The application must determine if
+the output cleartext was zero-padded due to original cleartext lengths that
+were not integral multiples of 8.
+.PP
+No errors or meaningful values are returned. Void is not used for
+compatibility with other compilers.
+.PP
+A characteristic of cbc mode is that changing a single bit of the
+cleartext, then encrypting using cbc mode,
+affects ALL the subsequent ciphertext. This makes cryptanalysis
+much more difficult. However, modifying a single bit of the ciphertext,
+then decrypting, only affects the resulting cleartext from
+the modified block and the succeeding block. Therefore,
+.I des_pcbc_encrypt
+is STRONGLY recommended for applications where
+indefinite propagation of errors is required in order to detect modifications.
+.PP
+.PP
+.I des_pcbc_encrypt
+encrypts/decrypts using a modified block chaining mode. Its calling
+sequence is identical to
+.I des_cbc_encrypt.
+It differs in its error propagation characteristics.
+.PP
+.I des_pcbc_encrypt
+is highly recommended for most encryption purposes, in that
+modification of a single bit of the ciphertext will affect ALL the
+subsequent (decrypted) cleartext. Similarly, modifying a single bit of
+the cleartext will affect ALL the subsequent (encrypted) ciphertext.
+"PCBC" mode, on encryption, "xors" both the
+cleartext of block N and the ciphertext resulting from block N with the
+cleartext for block N+1 prior to encrypting block N+1.
+.PP
+.I des_cbc_cksum
+produces an 8 byte cryptographic checksum by cipher-block-chain
+encrypting the cleartext data pointed to by the
+.I input
+argument. All of the ciphertext output is discarded, except the
+last 8-byte ciphertext block, which is written into the area pointed to by
+the
+.I output
+argument.
+It uses the key schedule,
+provided by the
+.I schedule
+argument and initialization vector provided by the
+.I ivec
+argument.
+If the
+.I length
+argument is not an integral
+multiple of eight bytes, the last cleartext block is copied to a temp and zero
+filled (highest addresses). The output is ALWAYS eight bytes.
+.PP
+The routine also returns an unsigned long, which is the last (highest address)
+half of the 8 byte checksum computed.
+.PP
+.PP
+.I quad_cksum
+produces a checksum by chaining quadratic operations on the cleartext data
+pointed to by the
+.I input
+argument. The
+.I length
+argument specifies the length of the
+input -- only exactly that many bytes are included for the checksum,
+without any padding.
+.PP
+The algorithm may be iterated over the same input data, if the
+.I out_count
+argument is 2, 3 or 4, and the optional
+.I output
+argument is a non-null pointer .
+The default is one iteration, and it will not run
+more than 4 times. Multiple iterations run slower, but provide
+a longer checksum if desired. The
+.I seed
+argument provides an 8-byte seed for the first iteration. If multiple iterations are
+requested, the results of one iteration are automatically used as
+the seed for the next iteration.
+.PP
+It returns both an unsigned long checksum value, and
+if the
+.I output
+argument is not a null pointer, up to 16 bytes of
+the computed checksum are written into the output.
+.PP
+.PP
+.SH FILES
+/usr/include/des.h
+.br
+/usr/lib/libdes.a
+.SH "SEE ALSO"
+.SH DIAGNOSTICS
+.SH BUGS
+This software has not yet been compiled or tested on machines other than the
+VAX and the IBM PC.
+.SH AUTHORS
+Steve Miller, MIT Project Athena/Digital Equipment Corporation
+.SH RESTRICTIONS
+COPYRIGHT 1985,1986 Massachusetts Institute of Technology
+.PP
+This software may not be exported outside of the US without a special
+license from the US Dept of Commerce. It may be replaced by any secret
+key block cipher with block length and key length of 8 bytes, as long
+as the interface is the same as described here.
--- /dev/null
+/* $Id: des_locl.h,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+
+#ifndef __des_locl_h
+#define __des_locl_h
+
+#include <sys/cdefs.h>
+
+#include <stdio.h>
+#include <memory.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include "kerberosIV/des.h"
+
+#define ITERATIONS 16
+#define HALF_ITERATIONS 8
+
+/* used in des_read and des_write */
+#define MAXWRITE (1024*16)
+#define BSIZE (MAXWRITE+4)
+
+#define c2l(c,l) (l =((u_int32_t)(*((c)++))) , \
+ l|=((u_int32_t)(*((c)++)))<< 8, \
+ l|=((u_int32_t)(*((c)++)))<<16, \
+ l|=((u_int32_t)(*((c)++)))<<24)
+
+/* NOTE - c is not incremented as per c2l */
+#define c2ln(c,l1,l2,n) { \
+ c+=n; \
+ l1=l2=0; \
+ switch (n) { \
+ case 8: l2|=((u_int32_t)(*(--(c))))<<24; \
+ case 7: l2|=((u_int32_t)(*(--(c))))<<16; \
+ case 6: l2|=((u_int32_t)(*(--(c))))<< 8; \
+ case 5: l2|=((u_int32_t)(*(--(c)))); \
+ case 4: l1|=((u_int32_t)(*(--(c))))<<24; \
+ case 3: l1|=((u_int32_t)(*(--(c))))<<16; \
+ case 2: l1|=((u_int32_t)(*(--(c))))<< 8; \
+ case 1: l1|=((u_int32_t)(*(--(c)))); \
+ } \
+ }
+
+#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>24)&0xff))
+
+/* replacements for htonl and ntohl since I have no idea what to do
+ * when faced with machines with 8 byte longs. */
+#define HDRSIZE 4
+
+#define n2l(c,l) (l =((u_int32_t)(*((c)++)))<<24, \
+ l|=((u_int32_t)(*((c)++)))<<16, \
+ l|=((u_int32_t)(*((c)++)))<< 8, \
+ l|=((u_int32_t)(*((c)++))))
+
+#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
+/* NOTE - c is not incremented as per l2c */
+#define l2cn(l1,l2,c,n) { \
+ c+=n; \
+ switch (n) { \
+ case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
+ case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
+ case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
+ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \
+ case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
+ case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
+ case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
+ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \
+ } \
+ }
+
+/* The changes to this macro may help or hinder, depending on the
+ * compiler and the achitecture. gcc2 always seems to do well :-).
+ * Inspired by Dana How <how@isl.stanford.edu>
+ * DO NOT use the alternative version on machines with 8 byte longs. */
+#ifdef ALT_ECB
+#define D_ENCRYPT(L,R,S) \
+ u=((R^s[S ])<<2); \
+ t= R^s[S+1]; \
+ t=((t>>2)+(t<<30)); \
+ L^= \
+ *(u_int32_t *)(des_SP+0x0100+((t )&0xfc))+ \
+ *(u_int32_t *)(des_SP+0x0300+((t>> 8)&0xfc))+ \
+ *(u_int32_t *)(des_SP+0x0500+((t>>16)&0xfc))+ \
+ *(u_int32_t *)(des_SP+0x0700+((t>>24)&0xfc))+ \
+ *(u_int32_t *)(des_SP+ ((u )&0xfc))+ \
+ *(u_int32_t *)(des_SP+0x0200+((u>> 8)&0xfc))+ \
+ *(u_int32_t *)(des_SP+0x0400+((u>>16)&0xfc))+ \
+ *(u_int32_t *)(des_SP+0x0600+((u>>24)&0xfc));
+#else /* original version */
+#ifdef MSDOS
+#define D_ENCRYPT(L,R,S) \
+ U.l=R^s[S+1]; \
+ T.s[0]=((U.s[0]>>4)|(U.s[1]<<12))&0x3f3f; \
+ T.s[1]=((U.s[1]>>4)|(U.s[0]<<12))&0x3f3f; \
+ U.l=(R^s[S ])&0x3f3f3f3f; \
+ L^= des_SPtrans[1][(T.c[0])]| \
+ des_SPtrans[3][(T.c[1])]| \
+ des_SPtrans[5][(T.c[2])]| \
+ des_SPtrans[7][(T.c[3])]| \
+ des_SPtrans[0][(U.c[0])]| \
+ des_SPtrans[2][(U.c[1])]| \
+ des_SPtrans[4][(U.c[2])]| \
+ des_SPtrans[6][(U.c[3])];
+#else
+#define D_ENCRYPT(L,R,S) \
+ u=(R^s[S ]); \
+ t=R^s[S+1]; \
+ t=((t>>4)+(t<<28)); \
+ L^= des_SPtrans[1][(t )&0x3f]| \
+ des_SPtrans[3][(t>> 8)&0x3f]| \
+ des_SPtrans[5][(t>>16)&0x3f]| \
+ des_SPtrans[7][(t>>24)&0x3f]| \
+ des_SPtrans[0][(u )&0x3f]| \
+ des_SPtrans[2][(u>> 8)&0x3f]| \
+ des_SPtrans[4][(u>>16)&0x3f]| \
+ des_SPtrans[6][(u>>24)&0x3f];
+#endif
+#endif
+
+ /* IP and FP
+ * The problem is more of a geometric problem that random bit fiddling.
+ 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6
+ 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4
+ 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2
+ 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0
+
+ 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7
+ 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5
+ 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3
+ 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1
+
+ The output has been subject to swaps of the form
+ 0 1 -> 3 1 but the odd and even bits have been put into
+ 2 3 2 0
+ different words. The main trick is to remember that
+ t=((l>>size)^r)&(mask);
+ r^=t;
+ l^=(t<<size);
+ can be used to swap and move bits between words.
+
+ So l = 0 1 2 3 r = 16 17 18 19
+ 4 5 6 7 20 21 22 23
+ 8 9 10 11 24 25 26 27
+ 12 13 14 15 28 29 30 31
+ becomes (for size == 2 and mask == 0x3333)
+ t = 2^16 3^17 -- -- l = 0 1 16 17 r = 2 3 18 19
+ 6^20 7^21 -- -- 4 5 20 21 6 7 22 23
+ 10^24 11^25 -- -- 8 9 24 25 10 11 24 25
+ 14^28 15^29 -- -- 12 13 28 29 14 15 28 29
+
+ Thanks for hints from Richard Outerbridge - he told me IP&FP
+ could be done in 15 xor, 10 shifts and 5 ands.
+ When I finally started to think of the problem in 2D
+ I first got ~42 operations without xors. When I remembered
+ how to use xors :-) I got it to its final state.
+ */
+#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
+ (b)^=(t),\
+ (a)^=((t)<<(n)))
+
+
+#endif /* __des_locl_h */
--- /dev/null
+/* $Id: ecb_enc.c,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+#include "des_locl.h"
+#include "spr.h"
+
+int des_ecb_encrypt(des_cblock (*input), des_cblock (*output), struct des_ks_struct *ks, int encrypt)
+{
+ register u_int32_t l0,l1;
+ register unsigned char *in,*out;
+ u_int32_t ll[2];
+
+ in=(unsigned char *)input;
+ out=(unsigned char *)output;
+ c2l(in,l0);
+ c2l(in,l1);
+ ll[0]=l0;
+ ll[1]=l1;
+ des_encrypt(ll,ll,ks,encrypt);
+ l0=ll[0];
+ l1=ll[1];
+ l2c(l0,out);
+ l2c(l1,out);
+ l0=l1=ll[0]=ll[1]=0;
+ return(0);
+}
+
+int des_encrypt(u_int32_t *input, u_int32_t *output, struct des_ks_struct *ks, int encrypt)
+{
+ register u_int32_t l,r,t,u;
+#ifdef ALT_ECB
+ register unsigned char *des_SP=(unsigned char *)des_SPtrans;
+#endif
+#ifdef MSDOS
+ union fudge {
+ u_int32_t l;
+ unsigned short s[2];
+ unsigned char c[4];
+ } U,T;
+#endif
+ register int i;
+ register u_int32_t *s;
+
+ l=input[0];
+ r=input[1];
+
+ /* do IP */
+ PERM_OP(r,l,t, 4,0x0f0f0f0f);
+ PERM_OP(l,r,t,16,0x0000ffff);
+ PERM_OP(r,l,t, 2,0x33333333);
+ PERM_OP(l,r,t, 8,0x00ff00ff);
+ PERM_OP(r,l,t, 1,0x55555555);
+ /* r and l are reversed - remember that :-) - fix
+ * it in the next step */
+
+ /* Things have been modified so that the initial rotate is
+ * done outside the loop. This required the
+ * des_SPtrans values in sp.h to be rotated 1 bit to the right.
+ * One perl script later and things have a 5% speed up on a sparc2.
+ * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
+ * for pointing this out. */
+ t=(r<<1)|(r>>31);
+ r=(l<<1)|(l>>31);
+ l=t;
+
+ /* clear the top bits on machines with 8byte longs */
+ l&=0xffffffff;
+ r&=0xffffffff;
+
+ s=(u_int32_t *)ks;
+ /* I don't know if it is worth the effort of loop unrolling the
+ * inner loop */
+ if (encrypt)
+ {
+ for (i=0; i<32; i+=4)
+ {
+ D_ENCRYPT(l,r,i+0); /* 1 */
+ D_ENCRYPT(r,l,i+2); /* 2 */
+ }
+ }
+ else
+ {
+ for (i=30; i>0; i-=4)
+ {
+ D_ENCRYPT(l,r,i-0); /* 16 */
+ D_ENCRYPT(r,l,i-2); /* 15 */
+ }
+ }
+ l=(l>>1)|(l<<31);
+ r=(r>>1)|(r<<31);
+ /* clear the top bits on machines with 8byte longs */
+ l&=0xffffffff;
+ r&=0xffffffff;
+
+ /* swap l and r
+ * we will not do the swap so just remember they are
+ * reversed for the rest of the subroutine
+ * luckily FP fixes this problem :-) */
+
+ PERM_OP(r,l,t, 1,0x55555555);
+ PERM_OP(l,r,t, 8,0x00ff00ff);
+ PERM_OP(r,l,t, 2,0x33333333);
+ PERM_OP(l,r,t,16,0x0000ffff);
+ PERM_OP(r,l,t, 4,0x0f0f0f0f);
+
+ output[0]=l;
+ output[1]=r;
+ l=r=t=u=0;
+ return(0);
+}
+
--- /dev/null
+/* $Id: enc_read.c,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+
+#include "des_locl.h"
+#include <unistd.h>
+#include <errno.h>
+
+/* This has some uglies in it but it works - even over sockets. */
+extern int errno;
+int des_rw_mode=DES_PCBC_MODE;
+
+int des_enc_read(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock (*iv))
+{
+ /* data to be unencrypted */
+ int net_num=0;
+ unsigned char net[BSIZE];
+ /* extra unencrypted data
+ * for when a block of 100 comes in but is des_read one byte at
+ * a time. */
+ static char unnet[BSIZE];
+ static int unnet_start=0;
+ static int unnet_left=0;
+ int i;
+ long num=0,rnum;
+ unsigned char *p;
+
+ /* left over data from last decrypt */
+ if (unnet_left != 0)
+ {
+ if (unnet_left < len)
+ {
+ /* we still still need more data but will return
+ * with the number of bytes we have - should always
+ * check the return value */
+ memcpy(buf,&(unnet[unnet_start]),unnet_left);
+ /* eay 26/08/92 I had the next 2 lines
+ * reversed :-( */
+ i=unnet_left;
+ unnet_start=unnet_left=0;
+ }
+ else
+ {
+ memcpy(buf,&(unnet[unnet_start]),len);
+ unnet_start+=len;
+ unnet_left-=len;
+ i=len;
+ }
+ return(i);
+ }
+
+ /* We need to get more data. */
+ if (len > MAXWRITE) len=MAXWRITE;
+
+ /* first - get the length */
+ net_num=0;
+ while (net_num < HDRSIZE)
+ {
+ i=read(fd,&(net[net_num]),HDRSIZE-net_num);
+ if ((i == -1) && (errno == EINTR)) continue;
+ if (i <= 0) return(0);
+ net_num+=i;
+ }
+
+ /* we now have at net_num bytes in net */
+ p=net;
+ num=0;
+ n2l(p,num);
+ /* num should be rounded up to the next group of eight
+ * we make sure that we have read a multiple of 8 bytes from the net.
+ */
+ if ((num > MAXWRITE) || (num < 0)) /* error */
+ return(-1);
+ rnum=(num < 8)?8:((num+7)/8*8);
+
+ net_num=0;
+ while (net_num < rnum)
+ {
+ i=read(fd,&(net[net_num]),rnum-net_num);
+ if ((i == -1) && (errno == EINTR)) continue;
+ if (i <= 0) return(0);
+ net_num+=i;
+ }
+
+ /* Check if there will be data left over. */
+ if (len < num)
+ {
+ if (des_rw_mode & DES_PCBC_MODE)
+ des_pcbc_encrypt((des_cblock *)net,(des_cblock *)unnet,
+ num,sched,iv,DES_DECRYPT);
+ else
+ des_cbc_encrypt((des_cblock *)net,(des_cblock *)unnet,
+ num,sched,iv,DES_DECRYPT);
+ memcpy(buf,unnet,len);
+ unnet_start=len;
+ unnet_left=num-len;
+
+ /* The following line is done because we return num
+ * as the number of bytes read. */
+ num=len;
+ }
+ else
+ {
+ /* >output is a multiple of 8 byes, if len < rnum
+ * >we must be careful. The user must be aware that this
+ * >routine will write more bytes than he asked for.
+ * >The length of the buffer must be correct.
+ * FIXED - Should be ok now 18-9-90 - eay */
+ if (len < rnum)
+ {
+ char tmpbuf[BSIZE];
+
+ if (des_rw_mode & DES_PCBC_MODE)
+ des_pcbc_encrypt((des_cblock *)net,
+ (des_cblock *)tmpbuf,
+ num,sched,iv,DES_DECRYPT);
+ else
+ des_cbc_encrypt((des_cblock *)net,
+ (des_cblock *)tmpbuf,
+ num,sched,iv,DES_DECRYPT);
+
+ /* eay 26/08/92 fix a bug that returned more
+ * bytes than you asked for (returned len bytes :-( */
+ memcpy(buf,tmpbuf,num);
+ }
+ else if (num >= 8)
+ {
+ if (des_rw_mode & DES_PCBC_MODE)
+ des_pcbc_encrypt((des_cblock *)net,
+ (des_cblock *)buf,num,sched,iv,
+ DES_DECRYPT);
+ else
+ des_cbc_encrypt((des_cblock *)net,
+ (des_cblock *)buf,num,sched,iv,
+ DES_DECRYPT);
+ }
+ else
+ {
+ if (des_rw_mode & DES_PCBC_MODE)
+ des_pcbc_encrypt((des_cblock *)net,
+ (des_cblock *)buf,8,sched,iv,
+ DES_DECRYPT);
+ else
+ des_cbc_encrypt((des_cblock *)net,
+ (des_cblock *)buf,8,sched,iv,
+ DES_DECRYPT);
+#ifdef LEFT_JUSTIFIED
+ memcpy(buf, buf, num);
+#else
+ memcpy(buf, buf+(8-num), num);
+#endif
+ }
+ }
+ return(num);
+}
+
--- /dev/null
+/* $Id: enc_writ.c,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+
+#include "des_locl.h"
+#include <unistd.h>
+#include <errno.h>
+
+int des_enc_write(int fd, char *buf, int len, struct des_ks_struct *sched, des_cblock (*iv))
+{
+ long rnum;
+ int i,j,k,outnum;
+ char outbuf[BSIZE+HDRSIZE];
+ char shortbuf[8];
+ char *p;
+ static int start=1;
+
+ /* If we are sending less than 8 bytes, the same char will look
+ * the same if we don't pad it out with random bytes */
+ if (start)
+ {
+ start=0;
+ srand(time(NULL));
+ }
+
+ /* lets recurse if we want to send the data in small chunks */
+ if (len > MAXWRITE)
+ {
+ j=0;
+ for (i=0; i<len; i+=k)
+ {
+ k=des_enc_write(fd,&(buf[i]),
+ ((len-i) > MAXWRITE)?MAXWRITE:(len-i),sched,iv);
+ if (k < 0)
+ return(k);
+ else
+ j+=k;
+ }
+ return(j);
+ }
+
+ /* write length first */
+ p=outbuf;
+ l2n(len,p);
+
+ /* pad short strings */
+ if (len < 8)
+ {
+#ifdef LEFT_JUSTIFIED
+ p=shortbuf;
+ memcpy(shortbuf,buf,len);
+ for (i=len; i<8; i++)
+ shortbuf[i]=rand();
+ rnum=8;
+#else
+ p=shortbuf;
+ for (i=0; i<8-len; i++)
+ shortbuf[i]=rand();
+ memcpy(shortbuf + 8 - len, buf, len);
+ rnum=8;
+#endif
+ }
+ else
+ {
+ p=buf;
+ rnum=((len+7)/8*8); /* round up to nearest eight */
+ }
+
+ if (des_rw_mode & DES_PCBC_MODE)
+ des_pcbc_encrypt((des_cblock *)p,(des_cblock *)&(outbuf[HDRSIZE]),
+ (long)((len<8)?8:len),sched,iv,DES_ENCRYPT);
+ else
+ des_cbc_encrypt((des_cblock *)p,(des_cblock *)&(outbuf[HDRSIZE]),
+ (long)((len<8)?8:len),sched,iv,DES_ENCRYPT);
+
+ /* output */
+ outnum=rnum+HDRSIZE;
+
+ for (j=0; j<outnum; j+=i)
+ {
+ /* eay 26/08/92 I was not doing writing from where we
+ * got upto. */
+ i=write(fd,&(outbuf[j]),(int)(outnum-j));
+ if (i == -1)
+ {
+ if (errno == EINTR)
+ i=0;
+ else /* This is really a bad error - very bad
+ * It will stuff-up both ends. */
+ return(-1);
+ }
+ }
+
+ return(len);
+}
--- /dev/null
+/* $Id: key_par.c,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $ */
+
+#include "des_locl.h"
+
+/* MIT Link and source compatibility */
+
+#ifdef des_fixup_key_parity
+#undef des_fixup_key_parity
+#endif /* des_fixup_key_parity */
+
+void
+des_fixup_key_parity(des_cblock *key)
+{
+ des_set_odd_parity(key);
+}
--- /dev/null
+/* $Id: ofb_enc.c,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+#include "des_locl.h"
+
+/* The input and output are loaded in multiples of 8 bits.
+ * What this means is that if you hame numbits=12 and length=2
+ * the first 12 bits will be retrieved from the first byte and half
+ * the second. The second 12 bits will come from the 3rd and half the 4th
+ * byte.
+ */
+int des_ofb_encrypt(unsigned char *in, unsigned char *out, int numbits, long int length, struct des_ks_struct *schedule, des_cblock (*ivec))
+{
+ register u_int32_t d0,d1,v0,v1,n=(numbits+7)/8;
+ register u_int32_t mask0,mask1;
+ register long l=length;
+ register int num=numbits;
+ u_int32_t ti[2];
+ unsigned char *iv;
+
+ if (num > 64) return(0);
+ if (num > 32)
+ {
+ mask0=0xffffffff;
+ if (num >= 64)
+ mask1=mask0;
+ else
+ mask1=(1L<<(num-32))-1;
+ }
+ else
+ {
+ if (num == 32)
+ mask0=0xffffffff;
+ else
+ mask0=(1L<<num)-1;
+ mask1=0x00000000;
+ }
+
+ iv=(unsigned char *)ivec;
+ c2l(iv,v0);
+ c2l(iv,v1);
+ ti[0]=v0;
+ ti[1]=v1;
+ while (l-- > 0)
+ {
+ des_encrypt(ti,ti,
+ schedule,DES_ENCRYPT);
+ c2ln(in,d0,d1,n);
+ in+=n;
+ d0=(d0^ti[0])&mask0;
+ d1=(d1^ti[1])&mask1;
+ l2cn(d0,d1,out,n);
+ out+=n;
+ }
+ v0=ti[0];
+ v1=ti[1];
+ iv=(unsigned char *)ivec;
+ l2c(v0,iv);
+ l2c(v1,iv);
+ v0=v1=d0=d1=ti[0]=ti[1]=0;
+ return(0);
+}
+
--- /dev/null
+/* $Id: pcbc_enc.c,v 1.1.1.1 1995/12/14 06:52:44 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+#include "des_locl.h"
+
+int des_pcbc_encrypt(des_cblock (*input), des_cblock (*output), long int length, struct des_ks_struct *schedule, des_cblock (*ivec), int encrypt)
+{
+ register u_int32_t sin0,sin1,xor0,xor1,tout0,tout1;
+ u_int32_t tin[2],tout[2];
+ unsigned char *in,*out,*iv;
+
+ in=(unsigned char *)input;
+ out=(unsigned char *)output;
+ iv=(unsigned char *)ivec;
+
+ if (encrypt)
+ {
+ c2l(iv,xor0);
+ c2l(iv,xor1);
+ for (; length>0; length-=8)
+ {
+ if (length >= 8)
+ {
+ c2l(in,sin0);
+ c2l(in,sin1);
+ }
+ else
+ c2ln(in,sin0,sin1,length);
+ tin[0]=sin0^xor0;
+ tin[1]=sin1^xor1;
+ des_encrypt(tin,tout,
+ schedule,encrypt);
+ tout0=tout[0];
+ tout1=tout[1];
+ xor0=sin0^tout[0];
+ xor1=sin1^tout[1];
+ l2c(tout0,out);
+ l2c(tout1,out);
+ }
+ }
+ else
+ {
+ c2l(iv,xor0); c2l(iv,xor1);
+ for (; length>0; length-=8)
+ {
+ c2l(in,sin0);
+ c2l(in,sin1);
+ tin[0]=sin0;
+ tin[1]=sin1;
+ des_encrypt(tin,tout,
+ schedule,encrypt);
+ tout0=tout[0]^xor0;
+ tout1=tout[1]^xor1;
+ if (length >= 8)
+ {
+ l2c(tout0,out);
+ l2c(tout1,out);
+ }
+ else
+ l2cn(tout0,tout1,out,length);
+ xor0=tout0^sin0;
+ xor1=tout1^sin1;
+ }
+ }
+ tin[0]=tin[1]=tout[0]=tout[1]=0;
+ sin0=sin1=xor0=xor1=tout0=tout1=0;
+ return(0);
+}
--- /dev/null
+/* $Id: podd.h,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+static unsigned char odd_parity[256]={
+ 1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
+ 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
+ 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
+ 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
+ 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
+ 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
+ 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
+112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
+128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
+145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
+161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
+176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
+193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
+208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
+224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
+241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254};
--- /dev/null
+/* Copyright (C) 1993 Eric Young - see README for more details */
+/* From "Message Authentication" R.R. Jueneman, S.M. Matyas, C.H. Meyer
+ * IEEE Communications Magazine Sept 1985 Vol. 23 No. 9 p 29-40
+ * This module in only based on the code in this paper and is
+ * almost definitely not the same as the MIT implementation.
+ *
+ * $Id: qud_cksm.c,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $
+ */
+#include "des_locl.h"
+
+/* bug fix for dos - 7/6/91 - Larry hughes@logos.ucs.indiana.edu */
+#define B0(a) (((u_int32_t)(a)))
+#define B1(a) (((u_int32_t)(a))<<8)
+#define B2(a) (((u_int32_t)(a))<<16)
+#define B3(a) (((u_int32_t)(a))<<24)
+
+/* used to scramble things a bit */
+/* Got the value MIT uses via brute force :-) 2/10/90 eay */
+#define NOISE ((u_int32_t)83653421)
+
+u_int32_t des_quad_cksum(des_cblock (*input), des_cblock (*output), long int length, int out_count, des_cblock (*seed))
+{
+ u_int32_t z0,z1,t0,t1;
+ int i;
+ long l=0;
+ unsigned char *cp;
+ unsigned char *lp;
+
+ if (out_count < 1) out_count=1;
+ lp=(unsigned char *)output;
+
+ z0=B0((*seed)[0])|B1((*seed)[1])|B2((*seed)[2])|B3((*seed)[3]);
+ z1=B0((*seed)[4])|B1((*seed)[5])|B2((*seed)[6])|B3((*seed)[7]);
+
+ for (i=0; ((i<4)&&(i<out_count)); i++)
+ {
+ cp=(unsigned char *)input;
+ l=length;
+ while (l > 0)
+ {
+ if (l > 1)
+ {
+ t0= (u_int32_t)(*(cp++));
+ t0|=(u_int32_t)B1(*(cp++));
+ l--;
+ }
+ else
+ t0= (u_int32_t)(*(cp++));
+ l--;
+ /* add */
+ t0+=z0;
+ t0&=0xffffffff;
+ t1=z1;
+ /* square, well sort of square */
+ z0=((((t0*t0)&0xffffffff)+((t1*t1)&0xffffffff))
+ &0xffffffff)%0x7fffffff;
+ z1=((t0*((t1+NOISE)&0xffffffff))&0xffffffff)%0x7fffffff;
+ }
+ if (lp != NULL)
+ {
+ /* I believe I finally have things worked out.
+ * The MIT library assumes that the checksum
+ * is one huge number and it is returned in a
+ * host dependant byte order.
+ */
+ static u_int32_t l=1;
+ static unsigned char *c=(unsigned char *)&l;
+
+ if (c[0])
+ {
+ l2c(z0,lp);
+ l2c(z1,lp);
+ }
+ else
+ {
+ lp=output[out_count-i-1];
+ l2n(z1,lp);
+ l2n(z0,lp);
+ }
+ }
+ }
+ return(z0);
+}
+
--- /dev/null
+/* $Id: random_key.c,v 1.1.1.1 1995/12/14 06:52:45 tholo Exp $ */
+
+/* Copyright (C) 1992 Eric Young - see COPYING for more details */
+#include "des_locl.h"
+
+void des_random_key(ret)
+des_cblock ret;
+ {
+ des_key_schedule ks;
+ static u_int32_t c=0;
+ static pid_t pid=0;
+ static des_cblock data={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
+ des_cblock key;
+
+#ifdef MSDOS
+ pid=1;
+#else
+ if (!pid) pid=getpid();
+#endif
+ ((u_int32_t *)key)[0]=(u_int32_t)time(NULL);
+ ((u_int32_t *)key)[1]=(u_int32_t)((pid)|((c++)<<16));
+
+ des_set_odd_parity((des_cblock *)data);
+ des_set_key((des_cblock *)data,ks);
+ des_cbc_cksum((des_cblock *)key,(des_cblock *)key,
+ (int32_t)sizeof(key),ks,(des_cblock *)data);
+ des_set_odd_parity((des_cblock *)key);
+ des_cbc_cksum((des_cblock *)key,(des_cblock *)key,
+ (int32_t)sizeof(key),ks,(des_cblock *)data);
+
+ bcopy(key,ret,sizeof(key));
+ bzero(key,sizeof(key));
+ bzero(ks,sizeof(ks));
+ }
--- /dev/null
+/* $Id: read_pwd.c,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+/* 06-Apr-92 Luke Brennan Support for VMS */
+#include "des_locl.h"
+#include <string.h>
+#include <signal.h>
+#include <setjmp.h>
+
+/* Ick! */
+#if defined(__svr4__) || defined(__sgi) || defined(linux)
+#define TERMIO
+#endif
+
+#ifndef VMS
+#ifndef MSDOS
+#ifdef TERMIO
+#include <termio.h>
+#define sgttyb termio
+#define sg_flags c_lflag
+#define TIOCGETP TCGETA
+#define TIOCSETP TCSETA
+#else /* !TERMIO */
+#include <sgtty.h>
+#endif
+#include <sys/ioctl.h>
+#else /* MSDOS */
+#define fgets(a,b,c) noecho_fgets(a,b,c)
+#endif
+#else /* VMS */
+#include <ssdef.h>
+#include <iodef.h>
+#include <ttdef.h>
+#include <descrip.h>
+struct IOSB {
+ short iosb$w_value;
+ short iosb$w_count;
+ long iosb$l_info;
+ };
+#endif
+#ifndef NSIG
+#define NSIG 32
+#endif
+
+static void read_till_nl();
+static int read_pw();
+static void recsig();
+static void pushsig();
+static void popsig();
+#ifdef MSDOS
+static int noecho_fgets();
+#endif
+
+static void (*savsig[NSIG])();
+static jmp_buf save;
+
+int des_read_password(key,prompt,verify)
+des_cblock *key;
+char *prompt;
+int verify;
+ {
+ int ok;
+ char buf[BUFSIZ],buff[BUFSIZ];
+
+ if ((ok=read_pw(buf,buff,BUFSIZ,prompt,verify)) == 0)
+ des_string_to_key(buf,key);
+ bzero(buf,BUFSIZ);
+ bzero(buff,BUFSIZ);
+ return(ok);
+ }
+
+int des_read_2passwords(key1,key2,prompt,verify)
+des_cblock *key1;
+des_cblock *key2;
+char *prompt;
+int verify;
+ {
+ int ok;
+ char buf[BUFSIZ],buff[BUFSIZ];
+
+ if ((ok=read_pw(buf,buff,BUFSIZ,prompt,verify)) == 0)
+ des_string_to_2keys(buf,key1,key2);
+ bzero(buf,BUFSIZ);
+ bzero(buff,BUFSIZ);
+ return(ok);
+ }
+
+int des_read_pw_string(buf,length,prompt,verify)
+char *buf;
+int length;
+char *prompt;
+int verify;
+ {
+ char buff[BUFSIZ];
+ int ret;
+
+ ret=read_pw(buf,buff,(length>BUFSIZ)?BUFSIZ:length,prompt,verify);
+ bzero(buff,BUFSIZ);
+ return(ret);
+ }
+
+static void read_till_nl(in)
+FILE *in;
+ {
+#define SIZE 4
+ char buf[SIZE+1];
+
+ do {
+ fgets(buf,SIZE,in);
+ } while (strchr(buf,'\n') == NULL);
+ }
+
+/* return 0 if ok, 1 (or -1) otherwise */
+static int read_pw(buf,buff,size,prompt,verify)
+char *buf,*buff;
+int size;
+char *prompt;
+int verify;
+ {
+#ifndef VMS
+#ifndef MSDOS
+ struct sgttyb tty_orig,tty_new;
+#endif /* !MSDOS */
+#else
+ struct IOSB iosb;
+ $DESCRIPTOR(terminal,"TT");
+ long tty_orig[3], tty_new[3];
+ long status;
+ unsigned short channel = 0;
+#endif
+ int ok=0;
+ char *p;
+ int ps=0;
+ FILE *tty;
+
+#ifndef MSDOS
+ if ((tty=fopen("/dev/tty","r")) == NULL)
+ tty=stdin;
+#else /* MSDOS */
+ if ((tty=fopen("con","r")) == NULL)
+ tty=stdin;
+#endif /* MSDOS */
+#ifndef VMS
+#ifdef TIOCGETP
+ if (ioctl(fileno(tty),TIOCGETP,(char *)&tty_orig) == -1)
+ return(-1);
+ bcopy(&(tty_orig),&(tty_new),sizeof(tty_orig));
+#endif
+#else /* VMS */
+ status = SYS$ASSIGN(&terminal,&channel,0,0);
+ if (status != SS$_NORMAL)
+ return(-1);
+ status=SYS$QIOW(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0);
+ if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
+ return(-1);
+#endif
+
+ if (setjmp(save))
+ {
+ ok=0;
+ goto error;
+ }
+ pushsig();
+ ps=1;
+#ifndef VMS
+#ifndef MSDOS
+ tty_new.sg_flags &= ~ECHO;
+#endif /* !MSDOS */
+#ifdef TIOCSETP
+ if (ioctl(fileno(tty),TIOCSETP,(char *)&tty_new) == -1)
+ return(-1);
+#endif
+#else /* VMS */
+ tty_new[0] = tty_orig[0];
+ tty_new[1] = tty_orig[1] | TT$M_NOECHO;
+ tty_new[2] = tty_orig[2];
+ status = SYS$QIOW(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
+ if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
+ return(-1);
+#endif /* VMS */
+ ps=2;
+
+ while (!ok)
+ {
+ fputs(prompt,stderr);
+ fflush(stderr);
+
+ buf[0]='\0';
+ fgets(buf,size,tty);
+ if (feof(tty)) goto error;
+ if ((p=(char *)strchr(buf,'\n')) != NULL)
+ *p='\0';
+ else read_till_nl(tty);
+ if (verify)
+ {
+ fprintf(stderr,"\nVerifying password %s",prompt);
+ fflush(stderr);
+ buff[0]='\0';
+ fgets(buff,size,tty);
+ if (feof(tty)) goto error;
+ if ((p=(char *)strchr(buff,'\n')) != NULL)
+ *p='\0';
+ else read_till_nl(tty);
+
+ if (strcmp(buf,buff) != 0)
+ {
+ fprintf(stderr,"\nVerify failure - try again\n");
+ fflush(stderr);
+ continue;
+ }
+ }
+ ok=1;
+ }
+
+error:
+ fprintf(stderr,"\n");
+ /* What can we do if there is an error? */
+#ifndef VMS
+#ifdef TIOCSETP
+ if (ps >= 2) ioctl(fileno(tty),TIOCSETP,(char *)&tty_orig);
+#endif
+#else /* VMS */
+ if (ps >= 2)
+ status = SYS$QIOW(0,channel,IO$_SETMODE,&iosb,0,0
+ ,tty_orig,12,0,0,0,0);
+#endif /* VMS */
+
+ if (ps >= 1) popsig();
+ if (stdin != tty) fclose(tty);
+#ifdef VMS
+ status = SYS$DASSGN(channel);
+#endif
+ return(!ok);
+ }
+
+static void pushsig()
+ {
+ int i;
+
+ for (i=0; i<NSIG; i++)
+ savsig[i]=signal(i,recsig);
+ }
+
+static void popsig()
+ {
+ int i;
+
+ for (i=0; i<NSIG; i++)
+ signal(i,savsig[i]);
+ }
+
+static void recsig()
+ {
+ longjmp(save,1);
+ }
+
+#ifdef MSDOS
+static int noecho_fgets(buf,size,tty)
+char *buf;
+int size;
+FILE *tty;
+ {
+ int i;
+ char *p;
+
+ p=buf;
+ for (;;)
+ {
+ if (size == 0)
+ {
+ *p='\0';
+ break;
+ }
+ size--;
+ i=getch();
+ if (i == '\r') i='\n';
+ *(p++)=i;
+ if (i == '\n')
+ {
+ *p='\0';
+ break;
+ }
+ }
+ }
+#endif
--- /dev/null
+/* $Id: rnd_keys.c,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see COPYING for more details */
+#include "des_locl.h"
+#include <sys/time.h>
+
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+/*
+ * Create a sequence of random 64 bit blocks.
+ * The sequence is indexed with a long long and
+ * based on an initial des key used as a seed.
+ */
+static des_key_schedule sequence_seed;
+static u_int32_t sequence_index[2];
+
+/*
+ * In case the generator does not get inited use this for backup.
+ */
+static int initialized;
+static des_cblock default_seed = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
+static void
+do_initialize()
+{
+ des_set_odd_parity(&default_seed);
+ des_set_random_generator_seed(&default_seed);
+}
+
+#define zero_long_long(ll) do { ll[0] = ll[1] = 0; } while (0)
+
+#define incr_long_long(ll) do { if (++ll[0] == 0) ++ll[1]; } while (0)
+
+#define des_set_sequence_number(ll) \
+do { \
+ memcpy((char *)sequence_index, (ll), sizeof(sequence_index)); \
+ } while (0)
+
+#define des_generate_random_block(ret) \
+do { \
+ des_ecb_encrypt((des_cblock *) sequence_index, (ret), sequence_seed, DES_ENCRYPT); \
+ incr_long_long(sequence_index); \
+ } while (0)
+
+void
+des_set_random_generator_seed(des_cblock *seed)
+{
+ des_key_sched(seed, sequence_seed);
+ zero_long_long(sequence_index);
+ initialized = 1;
+}
+
+/*
+ * Generate a sequence of random des keys
+ * using the random block sequence, fixup
+ * parity and skip weak keys.
+ */
+int
+des_new_random_key(des_cblock *key)
+{
+ if (!initialized)
+ do_initialize();
+
+ try_again:
+ des_generate_random_block(key);
+ /* random key must have odd parity and not be weak */
+ des_set_odd_parity(key);
+ if (des_is_weak_key(key))
+ goto try_again;
+ return(0);
+}
+
+/*
+ * des_init_random_number_generator:
+ *
+ * This routine takes a secret key possibly shared by a number
+ * of servers and uses it to generate a random number stream that is
+ * not shared by any of the other servers. It does this by using the current
+ * process id, host id, and the current time to the nearest second. The
+ * resulting stream seed is not useful information for cracking the secret
+ * key. Moreover, this routine keeps no copy of the secret key.
+ *
+ */
+void
+des_init_random_number_generator(des_cblock *seed)
+{
+ struct timeval now;
+ static long uniq[2];
+ des_cblock new_key;
+ long gethostid(void);
+
+ gettimeofday(&now, (struct timezone *)0);
+ if (!uniq[0])
+ {
+ struct hostent *hent;
+ char hostname[100];
+ gethostname(hostname, sizeof(hostname));
+ hent = gethostbyname(hostname);
+ if (hent != NULL)
+ bcopy(hent->h_addr_list[0], &uniq[0], sizeof(uniq[0]));
+ else
+ uniq[0] = gethostid();
+#ifdef MSDOS
+ uniq[1] = 1;
+#else
+ uniq[1] = getpid();
+#endif
+ }
+
+ /* Pick a unique random key from the shared sequence. */
+ des_set_random_generator_seed(seed);
+ des_set_sequence_number((unsigned char *)uniq);
+ des_new_random_key(&new_key);
+
+ /* Select a new nonshared sequence, */
+ des_set_random_generator_seed(&new_key);
+
+ /* and use the current time to pick a key for the new sequence. */
+ des_set_sequence_number((unsigned char *)&now);
+ des_new_random_key(&new_key);
+ des_set_random_generator_seed(&new_key);
+}
--- /dev/null
+/* $Id: set_key.c,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+/* set_key.c v 1.4 eay 24/9/91
+ * 1.4 Speed up by 400% :-)
+ * 1.3 added register declarations.
+ * 1.2 unrolled make_key_sched a bit more
+ * 1.1 added norm_expand_bits
+ * 1.0 First working version
+ */
+#include "des_locl.h"
+#include "podd.h"
+#include "sk.h"
+
+static int check_parity(des_cblock (*key));
+
+int des_check_key=0;
+
+void des_set_odd_parity(des_cblock (*key))
+{
+ int i;
+
+ for (i=0; i<DES_KEY_SZ; i++)
+ (*key)[i]=odd_parity[(*key)[i]];
+}
+
+static int check_parity(des_cblock (*key))
+{
+ int i;
+
+ for (i=0; i<DES_KEY_SZ; i++)
+ {
+ if ((*key)[i] != odd_parity[(*key)[i]])
+ return(0);
+ }
+ return(1);
+}
+
+/* Weak and semi week keys as take from
+ * %A D.W. Davies
+ * %A W.L. Price
+ * %T Security for Computer Networks
+ * %I John Wiley & Sons
+ * %D 1984
+ * Many thanks to smb@ulysses.att.com (Steven Bellovin) for the reference
+ * (and actual cblock values).
+ */
+#define NUM_WEAK_KEY 16
+static des_cblock weak_keys[NUM_WEAK_KEY]={
+ /* weak keys */
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+ 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,
+ 0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
+ 0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
+ /* semi-weak keys */
+ 0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,
+ 0xFE,0x01,0xFE,0x01,0xFE,0x01,0xFE,0x01,
+ 0x1F,0xE0,0x1F,0xE0,0x0E,0xF1,0x0E,0xF1,
+ 0xE0,0x1F,0xE0,0x1F,0xF1,0x0E,0xF1,0x0E,
+ 0x01,0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,
+ 0xE0,0x01,0xE0,0x01,0xF1,0x01,0xF1,0x01,
+ 0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,0xFE,
+ 0xFE,0x1F,0xFE,0x1F,0xFE,0x0E,0xFE,0x0E,
+ 0x01,0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,
+ 0x1F,0x01,0x1F,0x01,0x0E,0x01,0x0E,0x01,
+ 0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE,
+ 0xFE,0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1};
+
+int des_is_weak_key(des_cblock (*key))
+{
+ int i;
+
+ for (i=0; i<NUM_WEAK_KEY; i++)
+ /* Added == 0 to comparision, I obviously don't run
+ * this section very often :-(, thanks to
+ * engineering@MorningStar.Com for the fix
+ * eay 93/06/29 */
+ if (memcmp(weak_keys[i],key,sizeof(key)) == 0) return(1);
+ return(0);
+}
+
+/* NOW DEFINED IN des_local.h
+ * See ecb_encrypt.c for a pseudo description of these macros.
+ * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
+ * (b)^=(t),\
+ * (a)=((a)^((t)<<(n))))
+ */
+
+#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
+ (a)=(a)^(t)^(t>>(16-(n))))
+
+static char shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0};
+
+/* return 0 if key parity is odd (correct),
+ * return -1 if key parity error,
+ * return -2 if illegal weak key.
+ */
+int des_set_key(des_cblock (*key), struct des_ks_struct *schedule)
+{
+ register u_int32_t c,d,t,s;
+ register unsigned char *in;
+ register u_int32_t *k;
+ register int i;
+
+ if (des_check_key)
+ {
+ if (!check_parity(key))
+ return(-1);
+
+ if (des_is_weak_key(key))
+ return(-2);
+ }
+
+ k=(u_int32_t *)schedule;
+ in=(unsigned char *)key;
+
+ c2l(in,c);
+ c2l(in,d);
+
+ /* do PC1 in 60 simple operations */
+ /* PERM_OP(d,c,t,4,0x0f0f0f0f);
+ HPERM_OP(c,t,-2, 0xcccc0000);
+ HPERM_OP(c,t,-1, 0xaaaa0000);
+ HPERM_OP(c,t, 8, 0x00ff0000);
+ HPERM_OP(c,t,-1, 0xaaaa0000);
+ HPERM_OP(d,t,-8, 0xff000000);
+ HPERM_OP(d,t, 8, 0x00ff0000);
+ HPERM_OP(d,t, 2, 0x33330000);
+ d=((d&0x00aa00aa)<<7)|((d&0x55005500)>>7)|(d&0xaa55aa55);
+ d=(d>>8)|((c&0xf0000000)>>4);
+ c&=0x0fffffff; */
+
+ /* I now do it in 47 simple operations :-)
+ * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)
+ * for the inspiration. :-) */
+ PERM_OP (d,c,t,4,0x0f0f0f0f);
+ HPERM_OP(c,t,-2,0xcccc0000);
+ HPERM_OP(d,t,-2,0xcccc0000);
+ PERM_OP (d,c,t,1,0x55555555);
+ PERM_OP (c,d,t,8,0x00ff00ff);
+ PERM_OP (d,c,t,1,0x55555555);
+ d= (((d&0x000000ff)<<16)| (d&0x0000ff00) |
+ ((d&0x00ff0000)>>16)|((c&0xf0000000)>>4));
+ c&=0x0fffffff;
+
+ for (i=0; i<ITERATIONS; i++)
+ {
+ if (shifts2[i])
+ { c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); }
+ else
+ { c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); }
+ c&=0x0fffffff;
+ d&=0x0fffffff;
+ /* could be a few less shifts but I am to lazy at this
+ * point in time to investigate */
+ s= des_skb[0][ (c )&0x3f ]|
+ des_skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)]|
+ des_skb[2][((c>>13)&0x0f)|((c>>14)&0x30)]|
+ des_skb[3][((c>>20)&0x01)|((c>>21)&0x06) |
+ ((c>>22)&0x38)];
+ t= des_skb[4][ (d )&0x3f ]|
+ des_skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)]|
+ des_skb[6][ (d>>15)&0x3f ]|
+ des_skb[7][((d>>21)&0x0f)|((d>>22)&0x30)];
+
+ /* table contained 0213 4657 */
+ *(k++)=((t<<16)|(s&0x0000ffff))&0xffffffff;
+ s= ((s>>16)|(t&0xffff0000));
+
+ s=(s<<4)|(s>>28);
+ *(k++)=s&0xffffffff;
+ }
+ return(0);
+}
+
+int des_key_sched(des_cblock *key, des_key_schedule schedule)
+{
+ return(des_set_key(key, (struct des_ks_struct *)schedule));
+}
--- /dev/null
+major=4
+minor=0
--- /dev/null
+/* $Id: sk.h,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+static u_int32_t des_skb[8][64]={
+/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
+0x00000000,0x00000010,0x20000000,0x20000010,
+0x00010000,0x00010010,0x20010000,0x20010010,
+0x00000800,0x00000810,0x20000800,0x20000810,
+0x00010800,0x00010810,0x20010800,0x20010810,
+0x00000020,0x00000030,0x20000020,0x20000030,
+0x00010020,0x00010030,0x20010020,0x20010030,
+0x00000820,0x00000830,0x20000820,0x20000830,
+0x00010820,0x00010830,0x20010820,0x20010830,
+0x00080000,0x00080010,0x20080000,0x20080010,
+0x00090000,0x00090010,0x20090000,0x20090010,
+0x00080800,0x00080810,0x20080800,0x20080810,
+0x00090800,0x00090810,0x20090800,0x20090810,
+0x00080020,0x00080030,0x20080020,0x20080030,
+0x00090020,0x00090030,0x20090020,0x20090030,
+0x00080820,0x00080830,0x20080820,0x20080830,
+0x00090820,0x00090830,0x20090820,0x20090830,
+/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
+0x00000000,0x02000000,0x00002000,0x02002000,
+0x00200000,0x02200000,0x00202000,0x02202000,
+0x00000004,0x02000004,0x00002004,0x02002004,
+0x00200004,0x02200004,0x00202004,0x02202004,
+0x00000400,0x02000400,0x00002400,0x02002400,
+0x00200400,0x02200400,0x00202400,0x02202400,
+0x00000404,0x02000404,0x00002404,0x02002404,
+0x00200404,0x02200404,0x00202404,0x02202404,
+0x10000000,0x12000000,0x10002000,0x12002000,
+0x10200000,0x12200000,0x10202000,0x12202000,
+0x10000004,0x12000004,0x10002004,0x12002004,
+0x10200004,0x12200004,0x10202004,0x12202004,
+0x10000400,0x12000400,0x10002400,0x12002400,
+0x10200400,0x12200400,0x10202400,0x12202400,
+0x10000404,0x12000404,0x10002404,0x12002404,
+0x10200404,0x12200404,0x10202404,0x12202404,
+/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
+0x00000000,0x00000001,0x00040000,0x00040001,
+0x01000000,0x01000001,0x01040000,0x01040001,
+0x00000002,0x00000003,0x00040002,0x00040003,
+0x01000002,0x01000003,0x01040002,0x01040003,
+0x00000200,0x00000201,0x00040200,0x00040201,
+0x01000200,0x01000201,0x01040200,0x01040201,
+0x00000202,0x00000203,0x00040202,0x00040203,
+0x01000202,0x01000203,0x01040202,0x01040203,
+0x08000000,0x08000001,0x08040000,0x08040001,
+0x09000000,0x09000001,0x09040000,0x09040001,
+0x08000002,0x08000003,0x08040002,0x08040003,
+0x09000002,0x09000003,0x09040002,0x09040003,
+0x08000200,0x08000201,0x08040200,0x08040201,
+0x09000200,0x09000201,0x09040200,0x09040201,
+0x08000202,0x08000203,0x08040202,0x08040203,
+0x09000202,0x09000203,0x09040202,0x09040203,
+/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
+0x00000000,0x00100000,0x00000100,0x00100100,
+0x00000008,0x00100008,0x00000108,0x00100108,
+0x00001000,0x00101000,0x00001100,0x00101100,
+0x00001008,0x00101008,0x00001108,0x00101108,
+0x04000000,0x04100000,0x04000100,0x04100100,
+0x04000008,0x04100008,0x04000108,0x04100108,
+0x04001000,0x04101000,0x04001100,0x04101100,
+0x04001008,0x04101008,0x04001108,0x04101108,
+0x00020000,0x00120000,0x00020100,0x00120100,
+0x00020008,0x00120008,0x00020108,0x00120108,
+0x00021000,0x00121000,0x00021100,0x00121100,
+0x00021008,0x00121008,0x00021108,0x00121108,
+0x04020000,0x04120000,0x04020100,0x04120100,
+0x04020008,0x04120008,0x04020108,0x04120108,
+0x04021000,0x04121000,0x04021100,0x04121100,
+0x04021008,0x04121008,0x04021108,0x04121108,
+/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
+0x00000000,0x10000000,0x00010000,0x10010000,
+0x00000004,0x10000004,0x00010004,0x10010004,
+0x20000000,0x30000000,0x20010000,0x30010000,
+0x20000004,0x30000004,0x20010004,0x30010004,
+0x00100000,0x10100000,0x00110000,0x10110000,
+0x00100004,0x10100004,0x00110004,0x10110004,
+0x20100000,0x30100000,0x20110000,0x30110000,
+0x20100004,0x30100004,0x20110004,0x30110004,
+0x00001000,0x10001000,0x00011000,0x10011000,
+0x00001004,0x10001004,0x00011004,0x10011004,
+0x20001000,0x30001000,0x20011000,0x30011000,
+0x20001004,0x30001004,0x20011004,0x30011004,
+0x00101000,0x10101000,0x00111000,0x10111000,
+0x00101004,0x10101004,0x00111004,0x10111004,
+0x20101000,0x30101000,0x20111000,0x30111000,
+0x20101004,0x30101004,0x20111004,0x30111004,
+/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
+0x00000000,0x08000000,0x00000008,0x08000008,
+0x00000400,0x08000400,0x00000408,0x08000408,
+0x00020000,0x08020000,0x00020008,0x08020008,
+0x00020400,0x08020400,0x00020408,0x08020408,
+0x00000001,0x08000001,0x00000009,0x08000009,
+0x00000401,0x08000401,0x00000409,0x08000409,
+0x00020001,0x08020001,0x00020009,0x08020009,
+0x00020401,0x08020401,0x00020409,0x08020409,
+0x02000000,0x0A000000,0x02000008,0x0A000008,
+0x02000400,0x0A000400,0x02000408,0x0A000408,
+0x02020000,0x0A020000,0x02020008,0x0A020008,
+0x02020400,0x0A020400,0x02020408,0x0A020408,
+0x02000001,0x0A000001,0x02000009,0x0A000009,
+0x02000401,0x0A000401,0x02000409,0x0A000409,
+0x02020001,0x0A020001,0x02020009,0x0A020009,
+0x02020401,0x0A020401,0x02020409,0x0A020409,
+/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
+0x00000000,0x00000100,0x00080000,0x00080100,
+0x01000000,0x01000100,0x01080000,0x01080100,
+0x00000010,0x00000110,0x00080010,0x00080110,
+0x01000010,0x01000110,0x01080010,0x01080110,
+0x00200000,0x00200100,0x00280000,0x00280100,
+0x01200000,0x01200100,0x01280000,0x01280100,
+0x00200010,0x00200110,0x00280010,0x00280110,
+0x01200010,0x01200110,0x01280010,0x01280110,
+0x00000200,0x00000300,0x00080200,0x00080300,
+0x01000200,0x01000300,0x01080200,0x01080300,
+0x00000210,0x00000310,0x00080210,0x00080310,
+0x01000210,0x01000310,0x01080210,0x01080310,
+0x00200200,0x00200300,0x00280200,0x00280300,
+0x01200200,0x01200300,0x01280200,0x01280300,
+0x00200210,0x00200310,0x00280210,0x00280310,
+0x01200210,0x01200310,0x01280210,0x01280310,
+/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
+0x00000000,0x04000000,0x00040000,0x04040000,
+0x00000002,0x04000002,0x00040002,0x04040002,
+0x00002000,0x04002000,0x00042000,0x04042000,
+0x00002002,0x04002002,0x00042002,0x04042002,
+0x00000020,0x04000020,0x00040020,0x04040020,
+0x00000022,0x04000022,0x00040022,0x04040022,
+0x00002020,0x04002020,0x00042020,0x04042020,
+0x00002022,0x04002022,0x00042022,0x04042022,
+0x00000800,0x04000800,0x00040800,0x04040800,
+0x00000802,0x04000802,0x00040802,0x04040802,
+0x00002800,0x04002800,0x00042800,0x04042800,
+0x00002802,0x04002802,0x00042802,0x04042802,
+0x00000820,0x04000820,0x00040820,0x04040820,
+0x00000822,0x04000822,0x00040822,0x04040822,
+0x00002820,0x04002820,0x00042820,0x04042820,
+0x00002822,0x04002822,0x00042822,0x04042822,
+};
--- /dev/null
+/* $Id: spr.h,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+static u_int32_t des_SPtrans[8][64]={
+/* nibble 0 */
+0x00820200, 0x00020000, 0x80800000, 0x80820200,
+0x00800000, 0x80020200, 0x80020000, 0x80800000,
+0x80020200, 0x00820200, 0x00820000, 0x80000200,
+0x80800200, 0x00800000, 0x00000000, 0x80020000,
+0x00020000, 0x80000000, 0x00800200, 0x00020200,
+0x80820200, 0x00820000, 0x80000200, 0x00800200,
+0x80000000, 0x00000200, 0x00020200, 0x80820000,
+0x00000200, 0x80800200, 0x80820000, 0x00000000,
+0x00000000, 0x80820200, 0x00800200, 0x80020000,
+0x00820200, 0x00020000, 0x80000200, 0x00800200,
+0x80820000, 0x00000200, 0x00020200, 0x80800000,
+0x80020200, 0x80000000, 0x80800000, 0x00820000,
+0x80820200, 0x00020200, 0x00820000, 0x80800200,
+0x00800000, 0x80000200, 0x80020000, 0x00000000,
+0x00020000, 0x00800000, 0x80800200, 0x00820200,
+0x80000000, 0x80820000, 0x00000200, 0x80020200,
+
+/* nibble 1 */
+0x10042004, 0x00000000, 0x00042000, 0x10040000,
+0x10000004, 0x00002004, 0x10002000, 0x00042000,
+0x00002000, 0x10040004, 0x00000004, 0x10002000,
+0x00040004, 0x10042000, 0x10040000, 0x00000004,
+0x00040000, 0x10002004, 0x10040004, 0x00002000,
+0x00042004, 0x10000000, 0x00000000, 0x00040004,
+0x10002004, 0x00042004, 0x10042000, 0x10000004,
+0x10000000, 0x00040000, 0x00002004, 0x10042004,
+0x00040004, 0x10042000, 0x10002000, 0x00042004,
+0x10042004, 0x00040004, 0x10000004, 0x00000000,
+0x10000000, 0x00002004, 0x00040000, 0x10040004,
+0x00002000, 0x10000000, 0x00042004, 0x10002004,
+0x10042000, 0x00002000, 0x00000000, 0x10000004,
+0x00000004, 0x10042004, 0x00042000, 0x10040000,
+0x10040004, 0x00040000, 0x00002004, 0x10002000,
+0x10002004, 0x00000004, 0x10040000, 0x00042000,
+
+/* nibble 2 */
+0x41000000, 0x01010040, 0x00000040, 0x41000040,
+0x40010000, 0x01000000, 0x41000040, 0x00010040,
+0x01000040, 0x00010000, 0x01010000, 0x40000000,
+0x41010040, 0x40000040, 0x40000000, 0x41010000,
+0x00000000, 0x40010000, 0x01010040, 0x00000040,
+0x40000040, 0x41010040, 0x00010000, 0x41000000,
+0x41010000, 0x01000040, 0x40010040, 0x01010000,
+0x00010040, 0x00000000, 0x01000000, 0x40010040,
+0x01010040, 0x00000040, 0x40000000, 0x00010000,
+0x40000040, 0x40010000, 0x01010000, 0x41000040,
+0x00000000, 0x01010040, 0x00010040, 0x41010000,
+0x40010000, 0x01000000, 0x41010040, 0x40000000,
+0x40010040, 0x41000000, 0x01000000, 0x41010040,
+0x00010000, 0x01000040, 0x41000040, 0x00010040,
+0x01000040, 0x00000000, 0x41010000, 0x40000040,
+0x41000000, 0x40010040, 0x00000040, 0x01010000,
+
+/* nibble 3 */
+0x00100402, 0x04000400, 0x00000002, 0x04100402,
+0x00000000, 0x04100000, 0x04000402, 0x00100002,
+0x04100400, 0x04000002, 0x04000000, 0x00000402,
+0x04000002, 0x00100402, 0x00100000, 0x04000000,
+0x04100002, 0x00100400, 0x00000400, 0x00000002,
+0x00100400, 0x04000402, 0x04100000, 0x00000400,
+0x00000402, 0x00000000, 0x00100002, 0x04100400,
+0x04000400, 0x04100002, 0x04100402, 0x00100000,
+0x04100002, 0x00000402, 0x00100000, 0x04000002,
+0x00100400, 0x04000400, 0x00000002, 0x04100000,
+0x04000402, 0x00000000, 0x00000400, 0x00100002,
+0x00000000, 0x04100002, 0x04100400, 0x00000400,
+0x04000000, 0x04100402, 0x00100402, 0x00100000,
+0x04100402, 0x00000002, 0x04000400, 0x00100402,
+0x00100002, 0x00100400, 0x04100000, 0x04000402,
+0x00000402, 0x04000000, 0x04000002, 0x04100400,
+
+/* nibble 4 */
+0x02000000, 0x00004000, 0x00000100, 0x02004108,
+0x02004008, 0x02000100, 0x00004108, 0x02004000,
+0x00004000, 0x00000008, 0x02000008, 0x00004100,
+0x02000108, 0x02004008, 0x02004100, 0x00000000,
+0x00004100, 0x02000000, 0x00004008, 0x00000108,
+0x02000100, 0x00004108, 0x00000000, 0x02000008,
+0x00000008, 0x02000108, 0x02004108, 0x00004008,
+0x02004000, 0x00000100, 0x00000108, 0x02004100,
+0x02004100, 0x02000108, 0x00004008, 0x02004000,
+0x00004000, 0x00000008, 0x02000008, 0x02000100,
+0x02000000, 0x00004100, 0x02004108, 0x00000000,
+0x00004108, 0x02000000, 0x00000100, 0x00004008,
+0x02000108, 0x00000100, 0x00000000, 0x02004108,
+0x02004008, 0x02004100, 0x00000108, 0x00004000,
+0x00004100, 0x02004008, 0x02000100, 0x00000108,
+0x00000008, 0x00004108, 0x02004000, 0x02000008,
+
+/* nibble 5 */
+0x20000010, 0x00080010, 0x00000000, 0x20080800,
+0x00080010, 0x00000800, 0x20000810, 0x00080000,
+0x00000810, 0x20080810, 0x00080800, 0x20000000,
+0x20000800, 0x20000010, 0x20080000, 0x00080810,
+0x00080000, 0x20000810, 0x20080010, 0x00000000,
+0x00000800, 0x00000010, 0x20080800, 0x20080010,
+0x20080810, 0x20080000, 0x20000000, 0x00000810,
+0x00000010, 0x00080800, 0x00080810, 0x20000800,
+0x00000810, 0x20000000, 0x20000800, 0x00080810,
+0x20080800, 0x00080010, 0x00000000, 0x20000800,
+0x20000000, 0x00000800, 0x20080010, 0x00080000,
+0x00080010, 0x20080810, 0x00080800, 0x00000010,
+0x20080810, 0x00080800, 0x00080000, 0x20000810,
+0x20000010, 0x20080000, 0x00080810, 0x00000000,
+0x00000800, 0x20000010, 0x20000810, 0x20080800,
+0x20080000, 0x00000810, 0x00000010, 0x20080010,
+
+/* nibble 6 */
+0x00001000, 0x00000080, 0x00400080, 0x00400001,
+0x00401081, 0x00001001, 0x00001080, 0x00000000,
+0x00400000, 0x00400081, 0x00000081, 0x00401000,
+0x00000001, 0x00401080, 0x00401000, 0x00000081,
+0x00400081, 0x00001000, 0x00001001, 0x00401081,
+0x00000000, 0x00400080, 0x00400001, 0x00001080,
+0x00401001, 0x00001081, 0x00401080, 0x00000001,
+0x00001081, 0x00401001, 0x00000080, 0x00400000,
+0x00001081, 0x00401000, 0x00401001, 0x00000081,
+0x00001000, 0x00000080, 0x00400000, 0x00401001,
+0x00400081, 0x00001081, 0x00001080, 0x00000000,
+0x00000080, 0x00400001, 0x00000001, 0x00400080,
+0x00000000, 0x00400081, 0x00400080, 0x00001080,
+0x00000081, 0x00001000, 0x00401081, 0x00400000,
+0x00401080, 0x00000001, 0x00001001, 0x00401081,
+0x00400001, 0x00401080, 0x00401000, 0x00001001,
+
+/* nibble 7 */
+0x08200020, 0x08208000, 0x00008020, 0x00000000,
+0x08008000, 0x00200020, 0x08200000, 0x08208020,
+0x00000020, 0x08000000, 0x00208000, 0x00008020,
+0x00208020, 0x08008020, 0x08000020, 0x08200000,
+0x00008000, 0x00208020, 0x00200020, 0x08008000,
+0x08208020, 0x08000020, 0x00000000, 0x00208000,
+0x08000000, 0x00200000, 0x08008020, 0x08200020,
+0x00200000, 0x00008000, 0x08208000, 0x00000020,
+0x00200000, 0x00008000, 0x08000020, 0x08208020,
+0x00008020, 0x08000000, 0x00000000, 0x00208000,
+0x08200020, 0x08008020, 0x08008000, 0x00200020,
+0x08208000, 0x00000020, 0x00200020, 0x08008000,
+0x08208020, 0x00200000, 0x08200000, 0x08000020,
+0x00208000, 0x00008020, 0x08008020, 0x08200000,
+0x00000020, 0x08208000, 0x00208020, 0x00000000,
+0x08000000, 0x08200020, 0x00008000, 0x00208020};
--- /dev/null
+/* $Id: str2key.c,v 1.1.1.1 1995/12/14 06:52:45 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+#include "des_locl.h"
+
+extern int des_check_key;
+
+int des_string_to_key(char *str, des_cblock (*key))
+{
+ des_key_schedule ks;
+ int i,length;
+ register unsigned char j;
+
+ memset(key,0,8);
+ length=strlen(str);
+#ifdef OLD_STR_TO_KEY
+ for (i=0; i<length; i++)
+ (*key)[i%8]^=(str[i]<<1);
+#else /* MIT COMPATIBLE */
+ for (i=0; i<length; i++)
+ {
+ j=str[i];
+ if ((i%16) < 8)
+ (*key)[i%8]^=(j<<1);
+ else
+ {
+ /* Reverse the bit order 05/05/92 eay */
+ j=((j<<4)&0xf0)|((j>>4)&0x0f);
+ j=((j<<2)&0xcc)|((j>>2)&0x33);
+ j=((j<<1)&0xaa)|((j>>1)&0x55);
+ (*key)[7-(i%8)]^=j;
+ }
+ }
+#endif
+ des_set_odd_parity((des_cblock *)key);
+ i=des_check_key;
+ des_check_key=0;
+ des_set_key((des_cblock *)key,ks);
+ des_check_key=i;
+ des_cbc_cksum((des_cblock *)str,(des_cblock *)key,(long)length,ks,
+ (des_cblock *)key);
+ memset(ks,0,sizeof(ks));
+ des_set_odd_parity((des_cblock *)key);
+ return(0);
+}
+
+int des_string_to_2keys(char *str, des_cblock (*key1), des_cblock (*key2))
+{
+ des_key_schedule ks;
+ int i,length;
+ register unsigned char j;
+
+ memset(key1,0,8);
+ memset(key2,0,8);
+ length=strlen(str);
+#ifdef OLD_STR_TO_KEY
+ if (length <= 8)
+ {
+ for (i=0; i<length; i++)
+ {
+ (*key2)[i]=(*key1)[i]=(str[i]<<1);
+ }
+ }
+ else
+ {
+ for (i=0; i<length; i++)
+ {
+ if ((i/8)&1)
+ (*key2)[i%8]^=(str[i]<<1);
+ else
+ (*key1)[i%8]^=(str[i]<<1);
+ }
+ }
+#else /* MIT COMPATIBLE */
+ for (i=0; i<length; i++)
+ {
+ j=str[i];
+ if ((i%32) < 16)
+ {
+ if ((i%16) < 8)
+ (*key1)[i%8]^=(j<<1);
+ else
+ (*key2)[i%8]^=(j<<1);
+ }
+ else
+ {
+ j=((j<<4)&0xf0)|((j>>4)&0x0f);
+ j=((j<<2)&0xcc)|((j>>2)&0x33);
+ j=((j<<1)&0xaa)|((j>>1)&0x55);
+ if ((i%16) < 8)
+ (*key1)[7-(i%8)]^=j;
+ else
+ (*key2)[7-(i%8)]^=j;
+ }
+ }
+ if (length <= 8) memcpy(key2,key1,8);
+#endif
+ des_set_odd_parity((des_cblock *)key1);
+ des_set_odd_parity((des_cblock *)key2);
+ i=des_check_key;
+ des_check_key=0;
+ des_set_key((des_cblock *)key1,ks);
+ des_cbc_cksum((des_cblock *)str,(des_cblock *)key1,(long)length,ks,
+ (des_cblock *)key1);
+ des_set_key((des_cblock *)key2,ks);
+ des_cbc_cksum((des_cblock *)str,(des_cblock *)key2,(long)length,ks,
+ (des_cblock *)key2);
+ des_check_key=i;
+ memset(ks,0,sizeof(ks));
+ des_set_odd_parity(key1);
+ des_set_odd_parity(key2);
+ return(0);
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:41 tholo Exp $
+
+PROG= ext_srvtab
+DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES}
+LDADD= -lkdb -lkrb -ldes
+MAN= ext_srvtab.8
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: ext_srvtab.8,v 1.1.1.1 1995/12/14 06:52:41 tholo Exp $
+.TH EXT_SRVTAB 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+ext_srvtab \- extract service key files from Kerberos key distribution center database
+.SH SYNOPSIS
+ext_srvtab [
+.B \-n
+] [
+.B \-r realm
+] [
+.B hostname ...
+]
+.SH DESCRIPTION
+.I ext_srvtab
+extracts service key files from the Kerberos key distribution center
+(KDC) database.
+.PP
+Upon execution, it prompts the user to enter the master key string for
+the database. If the
+.B \-n
+option is specified, the master key is instead fetched from the master
+key cache file.
+.PP
+For each
+.I hostname
+specified on the command line,
+.I ext_srvtab
+creates the service key file
+.IR hostname -new-srvtab,
+containing all the entries in the database with an instance field of
+.I hostname.
+This new file contains all the keys registered for Kerberos-mediated
+service providing programs which use the
+.IR krb_get_phost (3)
+principal and instance conventions to run on the host
+.IR hostname .
+If the
+.B \-r
+option is specified, the realm fields in the extracted file will
+match the given realm rather than the local realm.
+.SH DIAGNOSTICS
+.TP 20n
+"verify_master_key: Invalid master key, does not match database."
+The master key string entered was incorrect.
+.SH FILES
+.TP 20n
+.IR hostname -new-srvtab
+Service key file generated for
+.I hostname
+.TP
+/kerberos/principal.pag, /kerberos/principal.dir
+DBM files containing database
+.TP
+/.k
+Master key cache file.
+.SH SEE ALSO
+read_service_key(3), krb_get_phost(3)
--- /dev/null
+/* $Id: ext_srvtab.c,v 1.1.1.1 1995/12/14 06:52:41 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <adm_locl.h>
+
+static des_cblock master_key;
+static des_cblock session_key;
+static des_key_schedule master_key_schedule;
+char progname[] = "ext_srvtab";
+static char realm[REALM_SZ];
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "Usage: %s [-n] [-r realm] instance [instance ...]\n", progname);
+ exit(1);
+}
+
+static void
+StampOutSecrets(void)
+{
+ bzero(master_key, sizeof master_key);
+ bzero(session_key, sizeof session_key);
+ bzero(master_key_schedule, sizeof master_key_schedule);
+}
+
+static void
+Die(void)
+{
+ StampOutSecrets();
+ exit(1);
+}
+
+static void
+FWrite(char *p, int size, int n, FILE *f)
+{
+ if (fwrite(p, size, n, f) != n) {
+ printf("Error writing output file. Terminating.\n");
+ Die();
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE *fout;
+ char fname[1024];
+ int fopen_errs = 0;
+ int arg;
+ Principal princs[40];
+ int more;
+ int prompt = TRUE;
+ register int n, i;
+
+ bzero(realm, sizeof(realm));
+
+ /* Parse commandline arguments */
+ if (argc < 2)
+ usage();
+ else {
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-n") == 0)
+ prompt = FALSE;
+ else if (strcmp(argv[i], "-r") == 0) {
+ if (++i >= argc)
+ usage();
+ else {
+ strcpy(realm, argv[i]);
+ /*
+ * This is to humor the broken way commandline
+ * argument parsing is done. Later, this
+ * program ignores everything that starts with -.
+ */
+ argv[i][0] = '-';
+ }
+ }
+ else if (argv[i][0] == '-')
+ usage();
+ else
+ if (!k_isinst(argv[i])) {
+ fprintf(stderr, "%s: bad instance name: %s\n",
+ progname, argv[i]);
+ usage();
+ }
+ }
+ }
+
+ if (kdb_get_master_key (prompt, &master_key, master_key_schedule) != 0) {
+ fprintf (stderr, "Couldn't read master key.\n");
+ fflush (stderr);
+ exit(1);
+ }
+
+ if (kdb_verify_master_key (&master_key, master_key_schedule, stderr) < 0) {
+ exit(1);
+ }
+
+ /* For each arg, search for instances of arg, and produce */
+ /* srvtab file */
+ if (!realm[0])
+ if (krb_get_lrealm(realm, 1) != KSUCCESS) {
+ fprintf(stderr, "%s: couldn't get local realm\n", progname);
+ exit(1);
+ }
+ (void) umask(077);
+
+ for (arg = 1; arg < argc; arg++) {
+ if (argv[arg][0] == '-')
+ continue;
+ sprintf(fname, "%s-new-srvtab", argv[arg]);
+ if ((fout = fopen(fname, "w")) == NULL) {
+ fprintf(stderr, "Couldn't create file '%s'.\n", fname);
+ fopen_errs++;
+ continue;
+ }
+ printf("Generating '%s'....\n", fname);
+ n = kerb_get_principal("*", argv[arg], &princs[0], 40, &more);
+ if (more)
+ fprintf(stderr, "More than 40 found...\n");
+ for (i = 0; i < n; i++) {
+ FWrite(princs[i].name, strlen(princs[i].name) + 1, 1, fout);
+ FWrite(princs[i].instance, strlen(princs[i].instance) + 1,
+ 1, fout);
+ FWrite(realm, strlen(realm) + 1, 1, fout);
+ FWrite((char*)&princs[i].key_version,
+ sizeof(princs[i].key_version), 1, fout);
+ bcopy(&princs[i].key_low, session_key, sizeof(long));
+ bcopy(&princs[i].key_high, session_key + sizeof(long),
+ sizeof(long));
+ kdb_encrypt_key (&session_key, &session_key,
+ &master_key, master_key_schedule, DES_DECRYPT);
+ FWrite((char*)session_key, sizeof session_key, 1, fout);
+ }
+ fclose(fout);
+ }
+
+ StampOutSecrets();
+
+ exit(fopen_errs); /* 0 errors if successful */
+
+}
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $
+
+SUBDIR= kerberosIV ss
+
+.include <bsd.subdir.mk>
--- /dev/null
+/* $Id: adm_locl.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#ifndef __adm_locl_h
+#define __adm_locl_h
+
+#define TRUE 1
+#define FALSE 0
+
+#include <sys/cdefs.h>
+#include <kerberosIV/site.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <netinet/in.h>
+
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include <kerberosIV/krb_db.h>
+#include "kdc.h"
+
+/* Utils */
+long maketime __P((struct tm *, int));
+
+#endif /* __adm_locl_h */
--- /dev/null
+/* $Id: kadm_locl.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <sys/cdefs.h>
+#include "kerberosIV/site.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <sys/wait.h>
+#include <pwd.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <syslog.h>
+
+#include "kerberosIV/com_err.h"
+#include <ss/ss.h>
+
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include "krb_err.h"
+#include <kerberosIV/krb_db.h>
+#include <kerberosIV/kadm.h>
+#include "kadm_err.h"
+#include "kerberosIV/acl.h"
+
+#include "kadm_server.h"
+
+/* GLOBALS */
+extern char *acldir;
+extern Kadm_Server server_parm;
+
+/* Utils */
+int kadm_change __P((char *, char *, char *, des_cblock));
+int kadm_add_entry __P((char *, char *, char *, Kadm_vals *, Kadm_vals *));
+int kadm_mod_entry __P((char *, char *, char *, Kadm_vals *, Kadm_vals *, Kadm_vals *));
+int kadm_get_entry __P((char *, char *, char *, Kadm_vals *, u_char *, Kadm_vals *));
+int kadm_ser_cpw __P((u_char *, int, AUTH_DAT *, u_char **, int *));
+int kadm_ser_add __P((u_char *, int, AUTH_DAT *, u_char **, int *));
+int kadm_ser_mod __P((u_char *, int, AUTH_DAT *, u_char **, int *));
+int kadm_ser_get __P((u_char *, int, AUTH_DAT *, u_char **, int *));
+int kadm_ser_init __P((int inter, char realm[]));
+int kadm_ser_in __P((u_char **, int *));
+
+long maketime __P((struct tm *, int));
+
+void change_password __P((int argc, char *argv[]));
+void change_admin_password __P((int argc, char *argv[]));
+void add_new_key __P((int argc, char *argv[]));
+void get_entry __P((int argc, char *argv[]));
+void mod_entry __P((int argc, char *argv[]));
+void help __P((int argc, char *argv[]));
+void clean_up __P((void));
+void quit __P((void));
--- /dev/null
+/* $Id: kadm_server.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * Definitions for Kerberos administration server & client
+ */
+
+#ifndef KADM_SERVER_DEFS
+#define KADM_SERVER_DEFS
+
+/*
+ * kadm_server.h
+ * Header file for the fourth attempt at an admin server
+ * Doug Church, December 28, 1989, MIT Project Athena
+ * ps. Yes that means this code belongs to athena etc...
+ * as part of our ongoing attempt to copyright all greek names
+ */
+
+#include <sys/types.h>
+#include <kerberosIV/krb.h>
+#include <kerberosIV/des.h>
+
+typedef struct {
+ struct sockaddr_in admin_addr;
+ struct sockaddr_in recv_addr;
+ int recv_addr_len;
+ int admin_fd; /* our link to clients */
+ char sname[ANAME_SZ];
+ char sinst[INST_SZ];
+ char krbrlm[REALM_SZ];
+ des_cblock master_key;
+ des_cblock session_key;
+ des_key_schedule master_key_schedule;
+ long master_key_version;
+} Kadm_Server;
+
+#endif /* KADM_SERVER_DEFS */
--- /dev/null
+/* $Id: kdc.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Include file for the Kerberos Key Distribution Center.
+ */
+
+#ifndef KDC_DEFS
+#define KDC_DEFS
+
+#define S_AD_SZ sizeof(struct sockaddr_in)
+
+#define max(a,b) (a>b ? a : b)
+#define min(a,b) (a<b ? a : b)
+
+#define TRUE 1
+#define FALSE 0
+
+#define KRB_PROG "./kerberos"
+
+#define ONE_MINUTE 60
+#define FIVE_MINUTES (5 * ONE_MINUTE)
+#define ONE_HOUR (60 * ONE_MINUTE)
+#define ONE_DAY (24 * ONE_HOUR)
+#define THREE_DAYS (3 * ONE_DAY)
+
+#endif /* KDC_DEFS */
+
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:35 tholo Exp $
+
+FILES= acl.h com_err.h des.h kadm.h kafs.h kparse.h krb.h krb_db.h site.h
+NOOBJ= noobj
+
+all include clean cleandir depend lint tags:
+
+realinstall:
+ @echo installing ${FILES}
+ @-for i in ${FILES}; do \
+ cmp -s $$i ${DESTDIR}/usr/include/kerberosIV/$$i || \
+ install -c -m 444 $$i ${DESTDIR}/usr/include/kerberosIV/$$i; \
+ done
+
+beforeinstall:
+ install -d -o ${BINOWN} -g ${BINGRP} -m 755 ${DESTDIR}/usr/include/kerberosIV
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $Id: acl.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+#ifndef __ACL_H
+#define __ACL_H
+
+#include <sys/cdefs.h>
+
+void acl_canonicalize_principal __P((char *principal, char *canon));
+int acl_initialize __P((char *acl_file, int perm));
+int acl_exact_match __P((char *acl, char *principal));
+int acl_check __P((char *acl, char *principal));
+int acl_add __P((char *acl, char *principal));
+int acl_delete __P((char *acl, char *principal));
+
+#endif /* __ACL_H */
--- /dev/null
+/* $Id: com_err.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+/*-
+ * Header file for common error description library.
+ *
+ * Copyright 1988, Student Information Processing Board of the
+ * Massachusetts Institute of Technology.
+ *
+ * For copyright and distribution info, see the documentation supplied
+ * with this package.
+ */
+
+#ifndef __COM_ERR_H
+#define __COM_ERR_H
+
+#include <stdarg.h>
+
+/* ANSI C -- use prototypes etc */
+void com_err __P((const char *, long, const char *, ...));
+char const *error_message __P((long));
+void (*com_err_hook) __P((const char *, long, const char *, va_list));
+void (*set_com_err_hook __P((void (*) (const char *, long, const char *, va_list))))
+ __P((const char *, long, const char *, va_list));
+void (*reset_com_err_hook __P((void)))
+ __P((const char *, long, const char *, va_list));
+
+#endif /* ! defined(__COM_ERR_H) */
--- /dev/null
+/* $Id: des.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+/* Copyright (C) 1993 Eric Young - see README for more details */
+#ifndef DES_DEFS
+#define DES_DEFS
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+typedef unsigned char des_cblock[8];
+typedef struct des_ks_struct {
+ union {
+ des_cblock _;
+ /* make sure things are correct size on machines with
+ * 8 byte longs */
+ u_int32_t pad[2];
+ } ks;
+#define _ ks._
+} des_key_schedule[16];
+
+#define DES_KEY_SZ (sizeof(des_cblock))
+#define DES_ENCRYPT 1
+#define DES_DECRYPT 0
+
+#define DES_CBC_MODE 0
+#define DES_PCBC_MODE 1
+
+#if !defined(NCOMPAT)
+#define C_Block des_cblock
+#define Key_schedule des_key_schedule
+#define ENCRYPT DES_ENCRYPT
+#define DECRYPT DES_DECRYPT
+#define KEY_SZ DES_KEY_SZ
+#define string_to_key des_string_to_key
+#define read_pw_string des_read_pw_string
+#define random_key des_random_key
+#define pcbc_encrypt des_pcbc_encrypt
+#define set_key des_set_key
+#define key_sched des_key_sched
+#define ecb_encrypt des_ecb_encrypt
+#define cbc_encrypt des_cbc_encrypt
+#define cbc_cksum des_cbc_cksum
+#define quad_cksum des_quad_cksum
+
+/* For compatibility with the MIT lib - eay 20/05/92 */
+typedef struct des_ks_struct bit_64;
+#endif
+
+extern int des_check_key; /* defaults to false */
+extern int des_rw_mode; /* defaults to DES_PCBC_MODE */
+
+int des_3ecb_encrypt __P((des_cblock *input,des_cblock *output,des_key_schedule ks1,des_key_schedule ks2,int encrypt));
+int des_3cbc_encrypt __P((des_cblock *input,des_cblock *output,long length,des_key_schedule sk1,des_key_schedule sk2,des_cblock *ivec1,des_cblock *ivec2,int encrypt));
+u_int32_t des_cbc_cksum __P((des_cblock *input,des_cblock *output,long length,des_key_schedule schedule,des_cblock *ivec));
+int des_cbc_encrypt __P((des_cblock *input,des_cblock *output,long length,des_key_schedule schedule,des_cblock *ivec,int encrypt));
+int des_cfb_encrypt __P((unsigned char *in,unsigned char *out,int numbits,long length,des_key_schedule schedule,des_cblock *ivec,int encrypt));
+int des_ecb_encrypt __P((des_cblock *input,des_cblock *output,des_key_schedule ks,int encrypt));
+int des_encrypt __P((u_int32_t *input,u_int32_t *output,des_key_schedule ks, int encrypt));
+int des_enc_read __P((int fd,char *buf,int len,des_key_schedule sched,des_cblock *iv));
+int des_enc_write __P((int fd,char *buf,int len,des_key_schedule sched,des_cblock *iv));
+int des_ofb_encrypt __P((unsigned char *in,unsigned char *out,int numbits,long length,des_key_schedule schedule,des_cblock *ivec));
+int des_pcbc_encrypt __P((des_cblock *input,des_cblock *output,long length,des_key_schedule schedule,des_cblock *ivec,int encrypt));
+
+void des_set_odd_parity __P((des_cblock *key));
+int des_is_weak_key __P((des_cblock *key));
+int des_set_key __P((des_cblock *key,des_key_schedule schedule));
+int des_key_sched __P((des_cblock *key,des_key_schedule schedule));
+
+int des_string_to_key __P((char *str,des_cblock *key));
+int des_string_to_2keys __P((char *str,des_cblock *key1,des_cblock *key2));
+
+void des_set_random_generator_seed __P((des_cblock *seed));
+int des_new_random_key __P((des_cblock *key));
+void des_init_random_number_generator __P((des_cblock *seed));
+void des_random_key __P((des_cblock ret));
+int des_read_password __P((des_cblock *key,char *prompt,int verify));
+int des_read_2passwords __P((des_cblock *key1,des_cblock *key2,char *prompt,int verify));
+int des_read_pw_string __P((char *buf,int length,char *prompt,int verify));
+
+u_int32_t des_quad_cksum __P((des_cblock *input,des_cblock *output,long length,int out_count,des_cblock *seed));
+
+/* MIT Link and source compatibility */
+void des_fixup_key_parity __P((des_cblock *key));
+#define des_fixup_key_parity des_set_odd_parity
+
+#endif /* DES_DEFS */
--- /dev/null
+/* $Id: kadm.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Definitions for Kerberos administration server & client
+ */
+
+#ifndef KADM_DEFS
+#define KADM_DEFS
+
+/*
+ * kadm.h
+ * Header file for the fourth attempt at an admin server
+ * Doug Church, December 28, 1989, MIT Project Athena
+ */
+
+/* The global structures for the client and server */
+typedef struct {
+ struct sockaddr_in admin_addr;
+ struct sockaddr_in my_addr;
+ int my_addr_len;
+ int admin_fd; /* file descriptor for link to admin server */
+ char sname[ANAME_SZ]; /* the service name */
+ char sinst[INST_SZ]; /* the services instance */
+ char krbrlm[REALM_SZ];
+} Kadm_Client;
+
+typedef struct { /* status of the server, i.e the parameters */
+ int inter; /* Space for command line flags */
+ char *sysfile; /* filename of server */
+} admin_params; /* Well... it's the admin's parameters */
+
+/* Largest password length to be supported */
+#define MAX_KPW_LEN 128
+
+/* Largest packet the admin server will ever allow itself to return */
+#define KADM_RET_MAX 2048
+
+/* That's right, versions are 8 byte strings */
+#define KADM_VERSTR "KADM0.0A"
+#define KADM_ULOSE "KYOULOSE" /* sent back when server can't
+ decrypt client's msg */
+#define KADM_VERSIZE strlen(KADM_VERSTR)
+
+/* the lookups for the server instances */
+#define PWSERV_NAME "changepw"
+#define KADM_SNAME "kerberos_master"
+#define KADM_SINST "kerberos"
+
+/* Attributes fields constants and macros */
+#define ALLOC 2
+#define RESERVED 3
+#define DEALLOC 4
+#define DEACTIVATED 5
+#define ACTIVE 6
+
+/* Kadm_vals structure for passing db fields into the server routines */
+#define FLDSZ 4
+
+typedef struct {
+ u_int8_t fields[FLDSZ]; /* The active fields in this struct */
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+ u_int32_t key_low;
+ u_int32_t key_high;
+ u_int32_t exp_date;
+ u_int16_t attributes;
+ u_int8_t max_life;
+} Kadm_vals; /* The basic values structure in Kadm */
+
+/* Kadm_vals structure for passing db fields into the server routines */
+#define FLDSZ 4
+
+/* Need to define fields types here */
+#define KADM_NAME 31
+#define KADM_INST 30
+#define KADM_EXPDATE 29
+#define KADM_ATTR 28
+#define KADM_MAXLIFE 27
+#define KADM_DESKEY 26
+
+/* To set a field entry f in a fields structure d */
+#define SET_FIELD(f,d) (d[3-(f/8)]|=(1<<(f%8)))
+
+/* To set a field entry f in a fields structure d */
+#define CLEAR_FIELD(f,d) (d[3-(f/8)]&=(~(1<<(f%8))))
+
+/* Is field f in fields structure d */
+#define IS_FIELD(f,d) (d[3-(f/8)]&(1<<(f%8)))
+
+/* Various return codes */
+#define KADM_SUCCESS 0
+
+#define WILDCARD_STR "*"
+
+enum acl_types {
+ADDACL,
+GETACL,
+MODACL
+};
+
+/* Various opcodes for the admin server's functions */
+#define CHANGE_PW 2
+#define ADD_ENT 3
+#define MOD_ENT 4
+#define GET_ENT 5
+
+void prin_vals __P((Kadm_vals *));
+int stv_long __P((u_char *, u_int32_t *, int, int));
+
+int stream_to_vals __P((u_char *, Kadm_vals *, int));
+int vals_to_stream __P((Kadm_vals *, u_char **));
+
+int kadm_init_link __P((char *, char *, char *));
+int kadm_change_pw __P((unsigned char *));
+int kadm_mod __P((Kadm_vals *, Kadm_vals *));
+int kadm_get __P((Kadm_vals *, u_char *));
+int kadm_add __P((Kadm_vals *));
+void kadm_vals_to_prin __P((u_char *, Principal *, Kadm_vals *));
+void kadm_prin_to_vals __P((u_char *, Kadm_vals *, Principal *));
+
+#endif /* KADM_DEFS */
--- /dev/null
+/* $Id: kafs.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+#ifndef __KAFS_H
+#define __KAFS_H
+
+#define AFSCALL_PIOCTL 20
+#define AFSCALL_SETPAG 21
+
+#ifndef _VICEIOCTL
+#if defined(__STDC__) || defined(sgi)
+#define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
+#else
+#define _VICEIOCTL(id) ((unsigned int ) _IOW(V, id, struct ViceIoctl))
+#endif
+#endif /* _VICEIOCTL */
+
+#define VIOCSETTOK _VICEIOCTL(3)
+#define VIOCUNLOG _VICEIOCTL(9)
+
+struct ViceIoctl {
+ caddr_t in, out;
+ short in_size;
+ short out_size;
+};
+
+struct ClearToken {
+ int32_t AuthHandle;
+ char HandShakeKey[8];
+ int32_t ViceId;
+ int32_t BeginTimestamp;
+ int32_t EndTimestamp;
+};
+
+/* Use k_hasafs() to probe if the machine supports AFS syscalls.
+ The other functions will generate a SIGSYS if AFS is not supported */
+
+int k_hasafs __P((void));
+
+int k_afsklog __P((char *realm));
+int k_pioctl __P((char *a_path,
+ int o_opcode,
+ struct ViceIoctl *a_paramsP,
+ int a_followSymlinks));
+int k_unlog __P((void));
+int k_setpag __P((void));
+
+#endif /* __KAFS_H */
--- /dev/null
+/* $Id: kparse.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Include file for kparse routines.
+ */
+
+#ifndef KPARSE_DEFS
+#define KPARSE_DEFS
+
+/*
+ * values returned by fGetParameterSet()
+ */
+
+#define PS_BAD_KEYWORD -2 /* unknown or duplicate keyword */
+#define PS_SYNTAX -1 /* syntax error */
+#define PS_OKAY 0 /* got a complete parameter set */
+#define PS_EOF 1 /* nothing more in the file */
+
+/*
+ * values returned by fGetKeywordValue()
+ */
+
+#define KV_SYNTAX -2 /* syntax error */
+#define KV_EOF -1 /* nothing more in the file */
+#define KV_OKAY 0 /* got a keyword/value pair */
+#define KV_EOL 1 /* nothing more on this line */
+
+/*
+ * values returned by fGetToken()
+ */
+
+#define GTOK_BAD_QSTRING -1 /* newline found in quoted string */
+#define GTOK_EOF 0 /* end of file encountered */
+#define GTOK_QSTRING 1 /* quoted string */
+#define GTOK_STRING 2 /* unquoted string */
+#define GTOK_NUMBER 3 /* one or more digits */
+#define GTOK_PUNK 4 /* punks are punctuation, newline,
+ * etc. */
+#define GTOK_WHITE 5 /* one or more whitespace chars */
+
+/*
+ * extended character classification macros
+ */
+
+#define ISOCTAL(CH) ( (CH>='0') && (CH<='7') )
+#define ISQUOTE(CH) ( (CH=='\"') || (CH=='\'') || (CH=='`') )
+#define ISWHITESPACE(C) ( (C==' ') || (C=='\t') )
+#define ISLINEFEED(C) ( (C=='\n') || (C=='\r') || (C=='\f') )
+
+/*
+ * tokens consist of any printable charcacter except comma, equal, or
+ * whitespace
+ */
+
+#define ISTOKENCHAR(C) ((C>040) && (C<0177) && (C != ',') && (C != '='))
+
+/*
+ * the parameter table defines the keywords that will be recognized by
+ * fGetParameterSet, and their default values if not specified.
+ */
+
+typedef struct {
+ char *keyword;
+ char *defvalue;
+ char *value;
+} parmtable;
+
+#define PARMCOUNT(P) (sizeof(P)/sizeof(P[0]))
+
+extern int LineNbr; /* current line # in parameter file */
+
+extern char ErrorMsg[]; /*
+ * meaningful only when KV_SYNTAX,
+ * PS_SYNTAX, or PS_BAD_KEYWORD is
+ * returned by fGetKeywordValue or
+ * fGetParameterSet
+ */
+
+#include <stdio.h>
+
+int fGetParameterSet __P((FILE *fp, parmtable *parm, int parmcount));
+int ParmCompare __P((parmtable *parm, int parmcount, char *keyword, char *value));
+void FreeParameterSet __P((parmtable *parm, int parmcount));
+int fGetKeywordValue __P((FILE *fp, char *keyword, int klen, char *value, int vlen));
+int fGetToken __P((FILE *fp, char *dest, int maxlen));
+int fGetLiteral __P((FILE *fp));
+int fUngetChar __P((int ch, FILE *fp));
+int fGetChar __P((FILE *fp));
+char * strsave __P((char *p));
+char * strutol __P((char *start));
+
+#endif /* KPARSE_DEFS */
--- /dev/null
+/* $Id: krb.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Include file for the Kerberos library.
+ */
+
+/* Only one time, please */
+#ifndef KRB_DEFS
+#define KRB_DEFS
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/* Include site.h file to define paths */
+#include <kerberosIV/site.h>
+
+/* Need some defs from des.h */
+#include <kerberosIV/des.h>
+
+/* Global library variables. */
+extern int krbONE;
+#define HOST_BYTE_ORDER (* (char *) &krbONE)
+extern int private_msg_ver; /* in rd_priv.c */
+extern int req_act_vno; /* this is defined in the kerberos server code */
+
+
+/* Text describing error codes */
+#define MAX_KRB_ERRORS 256
+extern const char *krb_err_txt[MAX_KRB_ERRORS];
+
+/* General definitions */
+#define KSUCCESS 0
+#define KFAILURE 255
+
+/*
+ * Kerberos specific definitions
+ *
+ * KRBLOG is the log file for the kerberos master server. KRB_CONF is
+ * the configuration file where different host machines running master
+ * and slave servers can be found. KRB_MASTER is the name of the
+ * machine with the master database. The admin_server runs on this
+ * machine, and all changes to the db (as opposed to read-only
+ * requests, which can go to slaves) must go to it. KRB_HOST is the
+ * default machine * when looking for a kerberos slave server. Other
+ * possibilities are * in the KRB_CONF file. KRB_REALM is the name of
+ * the realm.
+ */
+
+/* The maximum sizes for aname, realm, sname, and instance +1 */
+#define ANAME_SZ 40
+#define REALM_SZ 40
+#define SNAME_SZ 40
+#define INST_SZ 40
+/* include space for '.' and '@' */
+#define MAX_K_NAME_SZ (ANAME_SZ + INST_SZ + REALM_SZ + 2)
+#define KKEY_SZ 100
+#define VERSION_SZ 1
+#define MSG_TYPE_SZ 1
+#define DATE_SZ 26 /* RTI date output */
+
+#define MAX_HSTNM 100
+
+#ifndef DEFAULT_TKT_LIFE /* allow compile-time override */
+/* default lifetime for krb_mk_req & co., 10 hrs */
+#define DEFAULT_TKT_LIFE 120
+#endif
+
+/* Definition of text structure used to pass text around */
+#define MAX_KTXT_LEN 1250
+
+struct ktext {
+ int length; /* Length of the text */
+ unsigned char dat[MAX_KTXT_LEN]; /* The data itself */
+ u_int32_t mbz; /* zero to catch runaway strings */
+};
+
+typedef struct ktext *KTEXT;
+typedef struct ktext KTEXT_ST;
+
+
+/* Definitions for send_to_kdc */
+#define CLIENT_KRB_TIMEOUT 4 /* time between retries */
+#define CLIENT_KRB_RETRY 5 /* retry this many times */
+#define CLIENT_KRB_BUFLEN 512 /* max unfragmented packet */
+
+/* Definitions for ticket file utilities */
+#define R_TKT_FIL 0
+#define W_TKT_FIL 1
+
+/* Parameters for rd_ap_req */
+/* Maximum alloable clock skew in seconds */
+#define CLOCK_SKEW 5*60
+
+/* Structure definition for rd_ap_req */
+
+struct auth_dat {
+ unsigned char k_flags; /* Flags from ticket */
+ char pname[ANAME_SZ]; /* Principal's name */
+ char pinst[INST_SZ]; /* His Instance */
+ char prealm[REALM_SZ]; /* His Realm */
+ u_int32_t checksum; /* Data checksum (opt) */
+ des_cblock session; /* Session Key */
+ int life; /* Life of ticket */
+ u_int32_t time_sec; /* Time ticket issued */
+ u_int32_t address; /* Address in ticket */
+ KTEXT_ST reply; /* Auth reply (opt) */
+};
+
+typedef struct auth_dat AUTH_DAT;
+
+/* Structure definition for credentials returned by get_cred */
+
+struct credentials {
+ char service[ANAME_SZ]; /* Service name */
+ char instance[INST_SZ]; /* Instance */
+ char realm[REALM_SZ]; /* Auth domain */
+ des_cblock session; /* Session key */
+ int lifetime; /* Lifetime */
+ int kvno; /* Key version number */
+ KTEXT_ST ticket_st; /* The ticket itself */
+ int32_t issue_date; /* The issue time */
+ char pname[ANAME_SZ]; /* Principal's name */
+ char pinst[INST_SZ]; /* Principal's instance */
+};
+
+typedef struct credentials CREDENTIALS;
+
+/* Structure definition for rd_private_msg and rd_safe_msg */
+
+struct msg_dat {
+ unsigned char *app_data; /* pointer to appl data */
+ u_int32_t app_length; /* length of appl data */
+ u_int32_t hash; /* hash to lookup replay */
+ int swap; /* swap bytes? */
+ int32_t time_sec; /* msg timestamp seconds */
+ unsigned char time_5ms; /* msg timestamp 5ms units */
+};
+
+typedef struct msg_dat MSG_DAT;
+
+
+/* Location of ticket file for save_cred and get_cred */
+#define TKT_FILE tkt_string()
+#define TKT_ROOT "/tmp/tkt"
+
+/* Error codes returned from the KDC */
+#define KDC_OK 0 /* Request OK */
+#define KDC_NAME_EXP 1 /* Principal expired */
+#define KDC_SERVICE_EXP 2 /* Service expired */
+#define KDC_AUTH_EXP 3 /* Auth expired */
+#define KDC_PKT_VER 4 /* Protocol version unknown */
+#define KDC_P_MKEY_VER 5 /* Wrong master key version */
+#define KDC_S_MKEY_VER 6 /* Wrong master key version */
+#define KDC_BYTE_ORDER 7 /* Byte order unknown */
+#define KDC_PR_UNKNOWN 8 /* Principal unknown */
+#define KDC_PR_N_UNIQUE 9 /* Principal not unique */
+#define KDC_NULL_KEY 10 /* Principal has null key */
+#define KDC_GEN_ERR 20 /* Generic error from KDC */
+
+
+/* Values returned by get_credentials */
+#define GC_OK 0 /* Retrieve OK */
+#define RET_OK 0 /* Retrieve OK */
+#define GC_TKFIL 21 /* Can't read ticket file */
+#define RET_TKFIL 21 /* Can't read ticket file */
+#define GC_NOTKT 22 /* Can't find ticket or TGT */
+#define RET_NOTKT 22 /* Can't find ticket or TGT */
+
+
+/* Values returned by mk_ap_req */
+#define MK_AP_OK 0 /* Success */
+#define MK_AP_TGTEXP 26 /* TGT Expired */
+
+/* Values returned by rd_ap_req */
+#define RD_AP_OK 0 /* Request authentic */
+#define RD_AP_UNDEC 31 /* Can't decode authenticator */
+#define RD_AP_EXP 32 /* Ticket expired */
+#define RD_AP_NYV 33 /* Ticket not yet valid */
+#define RD_AP_REPEAT 34 /* Repeated request */
+#define RD_AP_NOT_US 35 /* The ticket isn't for us */
+#define RD_AP_INCON 36 /* Request is inconsistent */
+#define RD_AP_TIME 37 /* delta_t too big */
+#define RD_AP_BADD 38 /* Incorrect net address */
+#define RD_AP_VERSION 39 /* protocol version mismatch */
+#define RD_AP_MSG_TYPE 40 /* invalid msg type */
+#define RD_AP_MODIFIED 41 /* message stream modified */
+#define RD_AP_ORDER 42 /* message out of order */
+#define RD_AP_UNAUTHOR 43 /* unauthorized request */
+
+/* Values returned by get_pw_tkt */
+#define GT_PW_OK 0 /* Got password changing tkt */
+#define GT_PW_NULL 51 /* Current PW is null */
+#define GT_PW_BADPW 52 /* Incorrect current password */
+#define GT_PW_PROT 53 /* Protocol Error */
+#define GT_PW_KDCERR 54 /* Error returned by KDC */
+#define GT_PW_NULLTKT 55 /* Null tkt returned by KDC */
+
+
+/* Values returned by send_to_kdc */
+#define SKDC_OK 0 /* Response received */
+#define SKDC_RETRY 56 /* Retry count exceeded */
+#define SKDC_CANT 57 /* Can't send request */
+
+/*
+ * Values returned by get_intkt
+ * (can also return SKDC_* and KDC errors)
+ */
+
+#define INTK_OK 0 /* Ticket obtained */
+#define INTK_W_NOTALL 61 /* Not ALL tickets returned */
+#define INTK_BADPW 62 /* Incorrect password */
+#define INTK_PROT 63 /* Protocol Error */
+#define INTK_ERR 70 /* Other error */
+
+/* Values returned by get_adtkt */
+#define AD_OK 0 /* Ticket Obtained */
+#define AD_NOTGT 71 /* Don't have tgt */
+
+/* Error codes returned by ticket file utilities */
+#define NO_TKT_FIL 76 /* No ticket file found */
+#define TKT_FIL_ACC 77 /* Couldn't access tkt file */
+#define TKT_FIL_LCK 78 /* Couldn't lock ticket file */
+#define TKT_FIL_FMT 79 /* Bad ticket file format */
+#define TKT_FIL_INI 80 /* tf_init not called first */
+
+/* Error code returned by kparse_name */
+#define KNAME_FMT 81 /* Bad Kerberos name format */
+
+/* Error code returned by krb_mk_safe */
+#define SAFE_PRIV_ERROR -1 /* syscall error */
+
+/*
+ * macros for byte swapping; also scratch space
+ * u_quad 0-->7, 1-->6, 2-->5, 3-->4, 4-->3, 5-->2, 6-->1, 7-->0
+ * u_int32_t 0-->3, 1-->2, 2-->1, 3-->0
+ * u_int16_t 0-->1, 1-->0
+ */
+
+#define swap_u_16(x) {\
+ u_int32_t _krb_swap_tmp[4];\
+ swab(((char *) x) +0, ((char *) _krb_swap_tmp) +14 ,2); \
+ swab(((char *) x) +2, ((char *) _krb_swap_tmp) +12 ,2); \
+ swab(((char *) x) +4, ((char *) _krb_swap_tmp) +10 ,2); \
+ swab(((char *) x) +6, ((char *) _krb_swap_tmp) +8 ,2); \
+ swab(((char *) x) +8, ((char *) _krb_swap_tmp) +6 ,2); \
+ swab(((char *) x) +10,((char *) _krb_swap_tmp) +4 ,2); \
+ swab(((char *) x) +12,((char *) _krb_swap_tmp) +2 ,2); \
+ swab(((char *) x) +14,((char *) _krb_swap_tmp) +0 ,2); \
+ bcopy((char *)_krb_swap_tmp,(char *)x,16);\
+ }
+
+#define swap_u_12(x) {\
+ u_int32_t _krb_swap_tmp[4];\
+ swab(( char *) x, ((char *) _krb_swap_tmp) +10 ,2); \
+ swab(((char *) x) +2, ((char *) _krb_swap_tmp) +8 ,2); \
+ swab(((char *) x) +4, ((char *) _krb_swap_tmp) +6 ,2); \
+ swab(((char *) x) +6, ((char *) _krb_swap_tmp) +4 ,2); \
+ swab(((char *) x) +8, ((char *) _krb_swap_tmp) +2 ,2); \
+ swab(((char *) x) +10,((char *) _krb_swap_tmp) +0 ,2); \
+ bcopy((char *)_krb_swap_tmp,(char *)x,12);\
+ }
+
+#define swap_C_Block(x) {\
+ u_int32_t _krb_swap_tmp[4];\
+ swab(( char *) x, ((char *) _krb_swap_tmp) +6 ,2); \
+ swab(((char *) x) +2,((char *) _krb_swap_tmp) +4 ,2); \
+ swab(((char *) x) +4,((char *) _krb_swap_tmp) +2 ,2); \
+ swab(((char *) x) +6,((char *) _krb_swap_tmp) ,2); \
+ bcopy((char *)_krb_swap_tmp,(char *)x,8);\
+ }
+#define swap_u_quad(x) {\
+ u_int32_t _krb_swap_tmp[4];\
+ swab(( char *) &x, ((char *) _krb_swap_tmp) +6 ,2); \
+ swab(((char *) &x) +2,((char *) _krb_swap_tmp) +4 ,2); \
+ swab(((char *) &x) +4,((char *) _krb_swap_tmp) +2 ,2); \
+ swab(((char *) &x) +6,((char *) _krb_swap_tmp) ,2); \
+ bcopy((char *)_krb_swap_tmp,(char *)&x,8);\
+ }
+
+#define swap_u_long(x) {\
+ u_int32_t _krb_swap_tmp[4];\
+ swab((char *) &x, ((char *) _krb_swap_tmp) +2 ,2); \
+ swab(((char *) &x) +2,((char *) _krb_swap_tmp),2); \
+ x = _krb_swap_tmp[0]; \
+ }
+
+#define swap_u_short(x) {\
+ u_int16_t _krb_swap_sh_tmp; \
+ swab((char *) &x, ( &_krb_swap_sh_tmp) ,2); \
+ x = (u_int16_t) _krb_swap_sh_tmp; \
+ }
+/* Kerberos ticket flag field bit definitions */
+#define K_FLAG_ORDER 0 /* bit 0 --> lsb */
+#define K_FLAG_1 /* reserved */
+#define K_FLAG_2 /* reserved */
+#define K_FLAG_3 /* reserved */
+#define K_FLAG_4 /* reserved */
+#define K_FLAG_5 /* reserved */
+#define K_FLAG_6 /* reserved */
+#define K_FLAG_7 /* reserved, bit 7 --> msb */
+
+/* Defines for krb_sendauth and krb_recvauth */
+
+#define KOPT_DONT_MK_REQ 0x00000001 /* don't call krb_mk_req */
+#define KOPT_DO_MUTUAL 0x00000002 /* do mutual auth */
+
+#define KOPT_DONT_CANON 0x00000004 /*
+ * don't canonicalize inst as
+ * a hostname
+ */
+
+#define KRB_SENDAUTH_VLEN 8 /* length for version strings */
+
+#ifdef ATHENA_COMPAT
+#define KOPT_DO_OLDSTYLE 0x00000008 /* use the old-style protocol */
+#endif /* ATHENA_COMPAT */
+
+struct tm;
+struct tm *k_localtime __P((u_int32_t *));
+
+/* --- Random prototypes */
+#include <sys/types.h> /* to get u_char */
+
+/* Host address comparison */
+int krb_equiv __P((u_int32_t, u_int32_t));
+
+/* Password conversion */
+void mit_string_to_key __P((char *str, char *cell, des_cblock *key));
+void afs_string_to_key __P((char *str, char *cell, des_cblock *key));
+
+/* Lifetime conversion */
+u_int32_t krb_life_to_time __P((u_int32_t start, int life));
+int krb_time_to_life __P((u_int32_t start, u_int32_t end));
+char *krb_life_to_atime __P((int life));
+int krb_atime_to_life __P((char *atime));
+
+/* Ticket manipulation */
+int tf_get_cred __P((CREDENTIALS *));
+int tf_get_pinst __P((char *));
+int tf_get_pname __P((char *));
+int tf_init __P((char *, int));
+int tf_save_cred __P((char *, char *, char *, unsigned char *, int , int , KTEXT ticket, u_int32_t));
+void tf_close __P((void));
+
+/* Private communication */
+struct sockaddr_in;
+int32_t krb_mk_priv __P((u_char *, u_char *, u_int32_t , struct des_ks_struct *, des_cblock *, struct sockaddr_in *, struct sockaddr_in *));
+int32_t krb_rd_priv __P((u_char *, u_int32_t, struct des_ks_struct *, des_cblock *, struct sockaddr_in *, struct sockaddr_in *, MSG_DAT *));
+
+/* Misc */
+KTEXT create_auth_reply __P((char *, char *, char *, int32_t, int, u_int32_t, int, KTEXT));
+
+char *krb_get_phost __P((char *));
+char *krb_realmofhost __P((char *));
+char *tkt_string __P((void));
+
+int create_ciph __P((KTEXT, unsigned char *, char *, char *, char *, u_int32_t, int, KTEXT, u_int32_t, des_cblock *));
+int decomp_ticket __P((KTEXT, unsigned char *, char *, char *, char *, u_int32_t *, unsigned char *, int *, u_int32_t *, char *, char *, des_cblock *, struct des_ks_struct *));
+int dest_tkt __P((void));
+int get_ad_tkt __P((char *, char *, char *, int));
+int get_pw_tkt __P((char *, char *, char *, char *));
+int get_request __P((KTEXT, int, char **, char **));
+int get_request __P((KTEXT, int, char **, char **));
+int in_tkt __P((char *, char *));
+int k_isinst __P((char *));
+int k_isname __P((char *));
+int k_isrealm __P((char *));
+int kname_parse __P((char *, char *, char *, char *));
+int krb_create_ticket __P((KTEXT, unsigned char, char *, char *, char *, int32_t, char *, int16_t, int32_t, char *, char *, des_cblock *));
+int krb_get_admhst __P((char *, char *, int));
+int krb_get_admhst __P((char *, char *, int));
+int krb_get_cred __P((char *, char *, char *, CREDENTIALS *));
+int krb_get_in_tkt __P((char *, char *, char *, char *, char *, int , int (*key_proc) (/* ??? */), int (*decrypt_proc) (/* ??? */), char *));
+int krb_get_krbhst __P((char *, char *, int));
+int krb_get_krbhst __P((char *, char *, int));
+int krb_get_krbhst __P((char *, char *, int));
+int krb_get_lrealm __P((char *, int));
+int krb_get_pw_in_tkt __P((char *, char *, char *, char *, char *, int, char *));
+int krb_get_svc_in_tkt __P((char *, char *, char *, char *, char *, int, char *));
+int krb_get_tf_fullname __P((char *, char *, char *, char *));
+int krb_get_tf_realm __P((char *, char *));
+int krb_kntoln __P((AUTH_DAT *, char *));
+int krb_mk_req __P((KTEXT , char *, char *, char *, int32_t));
+int krb_net_read __P((int , char *, int));
+int krb_net_write __P((int , char *, int));
+int krb_rd_err __P((u_char *, u_int32_t, int32_t *, MSG_DAT *));
+int krb_rd_req __P((KTEXT , char *, char *, int32_t, AUTH_DAT *, char *));
+int krb_recvauth __P((int32_t, int, KTEXT, char *, char *, struct sockaddr_in *, struct sockaddr_in *, AUTH_DAT *, char *, struct des_ks_struct *, char *));
+int krb_sendauth __P((int32_t, int, KTEXT, char *, char *, char *, u_int32_t, MSG_DAT *, CREDENTIALS *, struct des_ks_struct *, struct sockaddr_in *, struct sockaddr_in *, char *));
+int krb_set_key __P((char *, int));
+int krb_set_lifetime __P((int));
+int kuserok __P((AUTH_DAT *, char *));
+int read_service_key __P((char *, char *, char *, int , char *, char *));
+int save_credentials __P((char *, char *, char *, unsigned char *, int , int , KTEXT , int32_t));
+int send_to_kdc __P((KTEXT , KTEXT , char *));
+
+int32_t krb_mk_err __P((u_char *, int32_t, char *));
+int32_t krb_mk_safe __P((u_char *, u_char *, u_int32_t, des_cblock *, struct sockaddr_in *, struct sockaddr_in *));
+int32_t krb_rd_safe __P((u_char *, u_int32_t, des_cblock *, struct sockaddr_in *, struct sockaddr_in *, MSG_DAT *));
+
+void ad_print __P((AUTH_DAT *));
+void cr_err_reply __P((KTEXT, char *, char *, char *, u_int32_t, u_int32_t, char *));
+void extract_ticket __P((KTEXT, int, char *, int *, int *, char *, KTEXT));
+void krb_set_tkt_string __P((char *));
+
+void kset_logfile __P((char *));
+void set_logfile __P((char *));
+
+void log ();
+char *klog ();
+
+int getst __P((int, char *, int));
+
+
+#endif /* KRB_DEFS */
--- /dev/null
+/* $Id: krb_db.h,v 1.1.1.1 1995/12/14 06:52:35 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/* spm Project Athena 8/85
+ *
+ * This file defines data structures for the kerberos
+ * authentication/authorization database.
+ *
+ * They MUST correspond to those defined in *.rel
+ */
+
+#ifndef KRB_DB_DEFS
+#define KRB_DB_DEFS
+
+#define KERB_M_NAME "K" /* Kerberos */
+#define KERB_M_INST "M" /* Master */
+#define KERB_DEFAULT_NAME "default"
+#define KERB_DEFAULT_INST ""
+
+/* this also defines the number of queue headers */
+#define KERB_DB_HASH_MODULO 64
+
+
+/* Arguments to kerb_dbl_lock() */
+
+#define KERB_DBL_EXCLUSIVE 1
+#define KERB_DBL_SHARED 0
+
+/* arguments to kerb_db_set_lockmode() */
+
+#define KERB_DBL_BLOCKING 0
+#define KERB_DBL_NONBLOCKING 1
+
+/* Principal defines the structure of a principal's name */
+
+typedef struct {
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+
+ u_int32_t key_low;
+ u_int32_t key_high;
+ u_int32_t exp_date;
+ char exp_date_txt[DATE_SZ];
+ u_int32_t mod_date;
+ char mod_date_txt[DATE_SZ];
+ u_int16_t attributes;
+ u_int8_t max_life;
+ u_int8_t kdc_key_ver;
+ u_int8_t key_version;
+
+ char mod_name[ANAME_SZ];
+ char mod_instance[INST_SZ];
+ char *old; /* cast to (Principal *); not in db,
+ * ptr to old vals */
+}
+ Principal;
+
+typedef struct {
+ int32_t cpu;
+ int32_t elapsed;
+ int32_t dio;
+ int32_t pfault;
+ int32_t t_stamp;
+ int32_t n_retrieve;
+ int32_t n_replace;
+ int32_t n_append;
+ int32_t n_get_stat;
+ int32_t n_put_stat;
+}
+ DB_stat;
+
+/* Dba defines the structure of a database administrator */
+
+typedef struct {
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+ u_int16_t attributes;
+ u_int32_t exp_date;
+ char exp_date_txt[DATE_SZ];
+ char *old; /*
+ * cast to (Dba *); not in db, ptr to
+ * old vals
+ */
+}
+ Dba;
+
+int kerb_get_principal __P((char *, char *, Principal *, unsigned int, int *));
+int kerb_put_principal __P((Principal *, unsigned int));
+void kerb_db_get_stat __P((DB_stat *));
+void kerb_db_put_stat __P((DB_stat *));
+int kerb_get_dba __P((char *, char *, Dba *, unsigned int, int *));
+int kerb_db_get_dba __P(());
+int kerb_init __P((void));
+void kerb_fini __P((void));
+time_t kerb_get_db_age __P((void));
+
+void kdb_encrypt_key __P((des_cblock *, des_cblock *, des_cblock *, des_key_schedule, int));
+int kerb_db_set_name __P((char *));
+
+long kdb_get_master_key __P((int, des_cblock *, des_key_schedule));
+
+#include <stdio.h>
+long kdb_verify_master_key __P((des_cblock *, des_key_schedule, FILE *));
+
+int kerb_db_create __P((char *db_name));
+int kerb_db_put_principal __P((Principal *, unsigned int));
+int kerb_db_iterate __P((int (*)(char *, Principal *), char *));
+int kerb_db_rename __P((char *, char *));
+int kerb_db_set_lockmode __P((int));
+
+#endif /* KRB_DB_DEFS */
--- /dev/null
+/* $Id: site.h,v 1.1.1.1 1995/12/14 06:52:35 tholo Exp $ */
+
+/*
+ * Site-specific definitions.
+ */
+
+#ifndef SITE_H
+#define SITE_H
+
+/*
+ * Location of common files.
+ */
+#define KRB_CONF "/etc/kerberosIV/krb.conf"
+#define KRB_RLM_TRANS "/etc/kerberosIV/krb.realms"
+#define KRB_EQUIV "/etc/kerberosIV/krb.equiv"
+#define KRB_ACL "/etc/kerberosIV/kerberos.acl"
+#define MKEYFILE "/etc/kerberosIV/master_key"
+#define KEYFILE "/etc/kerberosIV/srvtab"
+#define DBM_FILE "/etc/kerberosIV/principal"
+
+#define K_LOGFIL "/var/log/kpropd.log"
+#define KS_LOGFIL "/var/log/kerberos_slave.log"
+#define KRBLOG "/var/log/kerberos.log" /* master server */
+#define KRBSLAVELOG "/var/log/kerberos_slave.log" /* master (?) server */
+
+#define KRB_MASTER "kerberos"
+#define KRB_HOST "kowande.bu.oz.au"
+#define KRB_REALM "KOWANDE.BU.OZ.AU"
+
+/* from: kadm_server.h */
+/* the default syslog file */
+#define KADM_SYSLOG "/var/log/admin_server.log"
+
+#define DEFAULT_ACL_DIR "/etc/kerberosIV/"
+/* These get appended to DEFAULT_ACL_DIR */
+#define ADD_ACL_FILE "admin_acl.add"
+#define GET_ACL_FILE "admin_acl.get"
+#define MOD_ACL_FILE "admin_acl.mod"
+
+/*
+ * Set ORGANIZATION to be the desired organization string printed
+ * by the 'kinit' program. It may have spaces.
+ */
+#define ORGANIZATION "The OpenBSD Project"
+
+#endif
--- /dev/null
+/* $Id: klog.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+/*-
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * This file defines the types of log messages logged by klog. Each
+ * type of message may be selectively turned on or off.
+ */
+
+#ifndef KLOG_DEFS
+#define KLOG_DEFS
+
+#define NLOGTYPE 100 /* Maximum number of log msg types */
+
+#define L_NET_ERR 1 /* Error in network code */
+#define L_NET_INFO 2 /* Info on network activity */
+#define L_KRB_PERR 3 /* Kerberos protocol errors */
+#define L_KRB_PINFO 4 /* Kerberos protocol info */
+#define L_INI_REQ 5 /* Request for initial ticket */
+#define L_NTGT_INTK 6 /* Initial request not for TGT */
+#define L_DEATH_REQ 7 /* Request for server death */
+#define L_TKT_REQ 8 /* All ticket requests using a tgt */
+#define L_ERR_SEXP 9 /* Service expired */
+#define L_ERR_MKV 10 /* Master key version incorrect */
+#define L_ERR_NKY 11 /* User's key is null */
+#define L_ERR_NUN 12 /* Principal not unique */
+#define L_ERR_UNK 13 /* Principal Unknown */
+#define L_ALL_REQ 14 /* All requests */
+#define L_APPL_REQ 15 /* Application requests (using tgt) */
+#define L_KRB_PWARN 16 /* Protocol warning messages */
+
+char *klog();
+
+#endif /* KLOG_DEFS */
--- /dev/null
+/* $Id: kprop.h,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $ */
+
+/*-
+ * Copyright 1987 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information,
+ * please see the file <mit-copyright.h>.
+ */
+
+#define KPROP_SERVICE_NAME "rcmd"
+#define KPROP_SRVTAB "/etc/srvtab"
+#define TGT_SERVICE_NAME "krbtgt"
+#define KPROP_PROT_VERSION_LEN 8
+#define KPROP_PROT_VERSION "kprop01"
+#define KPROP_TRANSFER_PRIVATE 1
+#define KPROP_TRANSFER_SAFE 2
+#define KPROP_TRANSFER_CLEAR 3
+#define KPROP_BUFSIZ 32768
--- /dev/null
+/* $Id: kuser_locl.h,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $ */
+
+#include "kerberosIV/site.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/file.h>
+
+#include <pwd.h>
+
+#include <kerberosIV/krb.h>
+#include <prot.h>
--- /dev/null
+/* $Id: prot.h,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $ */
+
+/*-
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Include file with authentication protocol information.
+ */
+
+#ifndef PROT_DEFS
+#define PROT_DEFS
+
+#define KRB_PORT 750 /* PC's don't have
+ * /etc/services */
+#define KRB_PROT_VERSION 4
+#define MAX_PKT_LEN 1000
+#define MAX_TXT_LEN 1000
+#define TICKET_GRANTING_TICKET "krbtgt"
+
+/* Macro's to obtain various fields from a packet */
+
+#define pkt_version(packet) (unsigned int) *(packet->dat)
+#define pkt_msg_type(packet) (unsigned int) *(packet->dat+1)
+#define pkt_a_name(packet) (packet->dat+2)
+#define pkt_a_inst(packet) \
+ (packet->dat+3+strlen((char *)pkt_a_name(packet)))
+#define pkt_a_realm(packet) \
+ (pkt_a_inst(packet)+1+strlen((char *)pkt_a_inst(packet)))
+
+/* Macro to obtain realm from application request */
+#define apreq_realm(auth) (auth->dat + 3)
+
+#define pkt_time_ws(packet) (char *) \
+ (packet->dat+5+strlen((char *)pkt_a_name(packet)) + \
+ strlen((char *)pkt_a_inst(packet)) + \
+ strlen((char *)pkt_a_realm(packet)))
+
+#define pkt_no_req(packet) (unsigned short) \
+ *(packet->dat+9+strlen((char *)pkt_a_name(packet)) + \
+ strlen((char *)pkt_a_inst(packet)) + \
+ strlen((char *)pkt_a_realm(packet)))
+#define pkt_x_date(packet) (char *) \
+ (packet->dat+10+strlen((char *)pkt_a_name(packet)) + \
+ strlen((char *)pkt_a_inst(packet)) + \
+ strlen((char *)pkt_a_realm(packet)))
+#define pkt_err_code(packet) ( (char *) \
+ (packet->dat+9+strlen((char *)pkt_a_name(packet)) + \
+ strlen((char *)pkt_a_inst(packet)) + \
+ strlen((char *)pkt_a_realm(packet))))
+#define pkt_err_text(packet) \
+ (packet->dat+13+strlen((char *)pkt_a_name(packet)) + \
+ strlen((char *)pkt_a_inst(packet)) + \
+ strlen((char *)pkt_a_realm(packet)))
+
+/* Routines to create and read packets may be found in prot.c */
+
+KTEXT create_auth_reply();
+KTEXT create_death_packet();
+
+/* Message types , always leave lsb for byte order */
+
+#define AUTH_MSG_KDC_REQUEST 1<<1
+#define AUTH_MSG_KDC_REPLY 2<<1
+#define AUTH_MSG_APPL_REQUEST 3<<1
+#define AUTH_MSG_APPL_REQUEST_MUTUAL 4<<1
+#define AUTH_MSG_ERR_REPLY 5<<1
+#define AUTH_MSG_PRIVATE 6<<1
+#define AUTH_MSG_SAFE 7<<1
+#define AUTH_MSG_APPL_ERR 8<<1
+#define AUTH_MSG_DIE 63<<1
+
+/* values for kerb error codes */
+
+#define KERB_ERR_OK 0
+#define KERB_ERR_NAME_EXP 1
+#define KERB_ERR_SERVICE_EXP 2
+#define KERB_ERR_AUTH_EXP 3
+#define KERB_ERR_PKT_VER 4
+#define KERB_ERR_NAME_MAST_KEY_VER 5
+#define KERB_ERR_SERV_MAST_KEY_VER 6
+#define KERB_ERR_BYTE_ORDER 7
+#define KERB_ERR_PRINCIPAL_UNKNOWN 8
+#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9
+#define KERB_ERR_NULL_KEY 10
+
+#endif /* PROT_DEFS */
--- /dev/null
+/* $Id: slav_locl.h,v 1.1.1.1 1995/12/14 06:52:34 tholo Exp $ */
+
+#ifndef __slav_locl_h
+#define __slav_locl_h
+
+#include "kerberosIV/site.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/file.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include <netdb.h>
+
+#include <kerberosIV/krb.h>
+#include <kerberosIV/krb_db.h>
+#include "klog.h"
+#include "prot.h"
+#include "kdc.h"
+
+#endif /* __slav_locl_h */
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:35 tholo Exp $
+
+FILES= ss.h
+NOOBJ= noobj
+
+all include clean cleandir depend lint tags:
+
+realinstall:
+ @echo installing ${FILES}
+ @-for i in ${FILES}; do \
+ cmp -s $$i ${DESTDIR}/usr/include/ss/$$i || \
+ install -c -m 444 $$i ${DESTDIR}/usr/include/ss/$$i; \
+ done
+
+beforeinstall:
+ install -d -o ${BINOWN} -g ${BINGRP} -m 755 ${DESTDIR}/usr/include/ss
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $Id: ss.h,v 1.1.1.1 1995/12/14 06:52:35 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#ifndef _SS_H
+#define _SS_H
+
+#include <sys/cdefs.h>
+
+#ifndef NO_SS_ERR_H
+#include <ss/ss_err.h>
+#endif
+
+typedef const struct _ss_request_entry {
+ const char * const *command_names; /* whatever */
+ void (* const function) __P((int, const char * const *, int, void *));
+ const char * const info_string; /* NULL */
+ int flags; /* 0 */
+} ss_request_entry;
+
+typedef const struct _ss_request_table {
+ int version;
+ ss_request_entry *requests;
+} ss_request_table;
+
+#define SS_RQT_TBL_V2 2
+
+typedef struct _ss_rp_options { /* DEFAULT VALUES */
+ int version; /* SS_RP_V1 */
+ void (*unknown) __P((int, const char * const *, int, void *)); /* call for unknown command */
+ int allow_suspend;
+ int catch_int;
+} ss_rp_options;
+
+#define SS_RP_V1 1
+
+#define SS_OPT_DONT_LIST 0x0001
+#define SS_OPT_DONT_SUMMARIZE 0x0002
+
+void ss_help __P((int, const char * const *, int, void *));
+char *ss_current_request();
+char *ss_name();
+void ss_error __P((int, long, char const *, ...));
+void ss_perror __P((int, long, char const *));
+int ss_create_invocation __P((char *, char *, char *, ss_request_table *, int *));
+int ss_listen(int);
+void ss_abort_subsystem();
+
+extern ss_request_table ss_std_requests;
+#endif /* _SS_H */
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:45 tholo Exp $
+
+LIB= kadm
+SRCS= kadm_err.c kadm_cli_wrap.c kadm_stream.c kadm_supp.c
+CFLAGS+=-I. -I${.CURDIR}
+.if exists(${.CURDIR}/../krb/obj)
+CFLAGS+=-I${.CURDIR}/../krb/obj
+.else
+CFLAGS+=-I${.CURDIR}/../krb
+.endif
+LDADD+= ${COM_ERR}
+CLEANFILES+= kadm_err.c kadm_err.h
+
+kadm_err.c kadm_err.h: kadm_err.et
+ test -e kadm_err.et || ln -s ${.CURDIR}/kadm_err.et .
+ ${COMPILE_ET} kadm_err.et
+ -test -h kadm_err.et && rm kadm_err.et
+
+beforeinstall:
+ -cd ${.OBJDIR}; cmp -s kadm_err.h ${DESTDIR}/usr/include/kerberosIV/kadm_err.h || \
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 kadm_err.h ${DESTDIR}/usr/include/kerberosIV
+
+.include <bsd.lib.mk>
--- /dev/null
+/* $Id: kadm_cli_wrap.c,v 1.1.1.1 1995/12/14 06:52:45 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * Kerberos administration server client-side routines
+ */
+
+/*
+ * kadm_cli_wrap.c the client side wrapping of the calls to the admin server
+ */
+
+#include "kadm_local.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+static Kadm_Client client_parm;
+
+/* Macros for use in returning data... used in kadm_cli_send */
+#define RET_N_FREE(r) {clear_secrets(); free((char *)act_st); free((char *)priv_pak); return r;}
+
+/* Keys for use in the transactions */
+static des_cblock sess_key; /* to be filled in by kadm_cli_keyd */
+static des_key_schedule sess_sched;
+
+static void
+clear_secrets()
+{
+ bzero((char *)sess_key, sizeof(sess_key));
+ bzero((char *)sess_sched, sizeof(sess_sched));
+ return;
+}
+
+static void (*opipe)();
+
+static void
+kadm_cli_disconn()
+{
+ (void) close(client_parm.admin_fd);
+ (void) signal(SIGPIPE, opipe);
+ return;
+}
+
+/*
+ * kadm_init_link
+ * receives : name, inst, realm
+ *
+ * initializes client parm, the Kadm_Client structure which holds the
+ * data about the connection between the server and client, the services
+ * used, the locations and other fun things
+ */
+int
+kadm_init_link(n, i, r)
+ char *n;
+ char *i;
+ char *r;
+{
+ struct servent *sep; /* service we will talk to */
+ struct hostent *hop; /* host we will talk to */
+ char adm_hostname[MAXHOSTNAMELEN];
+
+ (void) init_kadm_err_tbl();
+ (void) init_krb_err_tbl();
+ (void) strcpy(client_parm.sname, n);
+ (void) strcpy(client_parm.sinst, i);
+ (void) strcpy(client_parm.krbrlm, r);
+ client_parm.admin_fd = -1;
+
+ /* set up the admin_addr - fetch name of admin host */
+ if (krb_get_admhst(adm_hostname, client_parm.krbrlm, 1) != KSUCCESS)
+ return KADM_NO_HOST;
+ if ((hop = gethostbyname(adm_hostname)) == NULL)
+ return KADM_UNK_HOST; /* couldnt find the admin servers
+ * address */
+ if ((sep = getservbyname(KADM_SNAME, "tcp")) == NULL)
+ return KADM_NO_SERV; /* couldnt find the admin service */
+ bzero((char *) &client_parm.admin_addr,
+ sizeof(client_parm.admin_addr));
+ client_parm.admin_addr.sin_family = hop->h_addrtype;
+ bcopy((char *) hop->h_addr, (char *) &client_parm.admin_addr.sin_addr,
+ hop->h_length);
+ client_parm.admin_addr.sin_port = sep->s_port;
+
+ return KADM_SUCCESS;
+} /* procedure kadm_init_link */
+
+static int
+kadm_cli_conn()
+{ /* this connects and sets my_addr */
+ int on = 1;
+
+ if ((client_parm.admin_fd =
+ socket(client_parm.admin_addr.sin_family, SOCK_STREAM,0)) < 0)
+ return KADM_NO_SOCK; /* couldnt create the socket */
+ if (connect(client_parm.admin_fd,
+ (struct sockaddr *) & client_parm.admin_addr,
+ sizeof(client_parm.admin_addr))) {
+ (void) close(client_parm.admin_fd);
+ client_parm.admin_fd = -1;
+ return KADM_NO_CONN; /* couldnt get the connect */
+ }
+ opipe = signal(SIGPIPE, SIG_IGN);
+ client_parm.my_addr_len = sizeof(client_parm.my_addr);
+ if (getsockname(client_parm.admin_fd,
+ (struct sockaddr *) & client_parm.my_addr,
+ &client_parm.my_addr_len) < 0) {
+ (void) close(client_parm.admin_fd);
+ client_parm.admin_fd = -1;
+ (void) signal(SIGPIPE, opipe);
+ return KADM_NO_HERE; /* couldnt find out who we are */
+ }
+ if (setsockopt(client_parm.admin_fd, SOL_SOCKET, SO_KEEPALIVE, &on,
+ sizeof(on)) < 0) {
+ (void) close(client_parm.admin_fd);
+ client_parm.admin_fd = -1;
+ (void) signal(SIGPIPE, opipe);
+ return KADM_NO_CONN; /* XXX */
+ }
+ return KADM_SUCCESS;
+}
+
+/* takes in the sess_key and key_schedule and sets them appropriately */
+static int
+kadm_cli_keyd(s_k, s_s)
+ des_cblock *s_k; /* session key */
+ struct des_ks_struct *s_s; /* session key schedule */
+{
+ CREDENTIALS cred; /* to get key data */
+ int stat;
+
+ /* want .sname and .sinst here.... */
+ if ((stat = krb_get_cred(client_parm.sname, client_parm.sinst,
+ client_parm.krbrlm, &cred)))
+ return stat + krb_err_base;
+ bcopy((char *) cred.session, (char *) s_k, sizeof(des_cblock));
+ bzero((char *) cred.session, sizeof(des_cblock));
+#ifdef NOENCRYPTION
+ bzero(s_s, sizeof(des_key_schedule));
+#else
+ if ((stat = des_key_sched(s_k,s_s)))
+ return(stat+krb_err_base);
+#endif
+ return KADM_SUCCESS;
+} /* This code "works" */
+
+static int
+kadm_cli_out(dat, dat_len, ret_dat, ret_siz)
+ u_char *dat;
+ int dat_len;
+ u_char **ret_dat;
+ int *ret_siz;
+{
+ u_short dlen;
+ int retval;
+
+ dlen = (u_short) dat_len;
+
+ if (dat_len != (int)dlen)
+ return (KADM_NO_ROOM);
+
+ dlen = htons(dlen);
+ if (krb_net_write(client_parm.admin_fd, (char *) &dlen,
+ sizeof(u_short)) < 0)
+ return (errno); /* XXX */
+
+ if (krb_net_write(client_parm.admin_fd, (char *) dat, dat_len) < 0)
+ return (errno); /* XXX */
+
+ if ((retval = krb_net_read(client_parm.admin_fd, (char *) &dlen,
+ sizeof(u_short)) != sizeof(u_short))) {
+ if (retval < 0)
+ return(errno); /* XXX */
+ else
+ return(EPIPE); /* short read ! */
+ }
+
+ dlen = ntohs(dlen);
+ *ret_dat = (u_char *)malloc((unsigned)dlen);
+ if (!*ret_dat)
+ return(KADM_NOMEM);
+
+ if ((retval = krb_net_read(client_parm.admin_fd, (char *) *ret_dat,
+ (int) dlen) != dlen)) {
+ if (retval < 0)
+ return(errno); /* XXX */
+ else
+ return(EPIPE); /* short read ! */
+ }
+ *ret_siz = (int) dlen;
+ return KADM_SUCCESS;
+}
+
+/*
+ * kadm_cli_send
+ * recieves : opcode, packet, packet length, serv_name, serv_inst
+ * returns : return code from the packet build, the server, or
+ * something else
+ *
+ * It assembles a packet as follows:
+ * 8 bytes : VERSION STRING
+ * 4 bytes : LENGTH OF MESSAGE DATA and OPCODE
+ * : KTEXT
+ * : OPCODE \
+ * : DATA > Encrypted (with make priv)
+ * : ...... /
+ *
+ * If it builds the packet and it is small enough, then it attempts to open the
+ * connection to the admin server. If the connection is succesfully open
+ * then it sends the data and waits for a reply.
+ */
+static int
+kadm_cli_send(st_dat, st_siz, ret_dat, ret_siz)
+ u_char *st_dat; /* the actual data */
+ int st_siz; /* length of said data */
+ u_char **ret_dat; /* to give return info */
+ int *ret_siz; /* length of returned info */
+{
+ int act_len, retdat; /* current offset into packet, return
+ * data */
+ KTEXT_ST authent; /* the authenticator we will build */
+ u_char *act_st; /* the pointer to the complete packet */
+ u_char *priv_pak; /* private version of the packet */
+ int priv_len; /* length of private packet */
+ u_int32_t cksum; /* checksum of the packet */
+ MSG_DAT mdat;
+ u_char *return_dat;
+
+ act_st = (u_char *) malloc(KADM_VERSIZE); /* verstr stored first */
+ (void) strncpy((char *)act_st, KADM_VERSTR, KADM_VERSIZE);
+ act_len = KADM_VERSIZE;
+
+ if ((retdat = kadm_cli_keyd(&sess_key, sess_sched)) != KADM_SUCCESS) {
+ free((char *)act_st);
+ return retdat; /* couldnt get key working */
+ }
+ priv_pak = (u_char *) malloc((unsigned)(st_siz + 200));
+ /* 200 bytes for extra info case */
+ if ((priv_len = krb_mk_priv(st_dat, priv_pak, (u_int32_t)st_siz,
+ sess_sched, &sess_key, &client_parm.my_addr,
+ &client_parm.admin_addr)) < 0)
+ RET_N_FREE(KADM_NO_ENCRYPT); /* whoops... we got a lose
+ * here */
+ /* here is the length of priv data. receiver calcs
+ size of authenticator by subtracting vno size, priv size, and
+ sizeof(u_int32_t) (for the size indication) from total size */
+
+ act_len += vts_long((u_int32_t) priv_len, &act_st, act_len);
+#ifdef NOENCRYPTION
+ cksum = 0;
+#else
+ cksum = des_quad_cksum((des_cblock *)priv_pak, (des_cblock *)0, (long)priv_len, 0,
+ &sess_key);
+#endif
+ if ((retdat = krb_mk_req(&authent, client_parm.sname, client_parm.sinst,
+ client_parm.krbrlm, (long)cksum))) {
+ /* authenticator? */
+ RET_N_FREE(retdat + krb_err_base);
+ }
+
+ act_st = (u_char *) realloc((char *) act_st,
+ (unsigned) (act_len + authent.length
+ + priv_len));
+ if (!act_st) {
+ clear_secrets();
+ free((char *)priv_pak);
+ return(KADM_NOMEM);
+ }
+ bcopy((char *) authent.dat, (char *) act_st + act_len, authent.length);
+ bcopy((char *) priv_pak, (char *) act_st + act_len + authent.length,
+ priv_len);
+ free((char *)priv_pak);
+ if ((retdat = kadm_cli_out(act_st,
+ act_len + authent.length + priv_len,
+ ret_dat, ret_siz)) != KADM_SUCCESS)
+ RET_N_FREE(retdat);
+ free((char *)act_st);
+#define RET_N_FREE2(r) {free((char *)*ret_dat); clear_secrets(); return(r);}
+
+ /* first see if it's a YOULOUSE */
+ if ((*ret_siz >= KADM_VERSIZE) &&
+ !strncmp(KADM_ULOSE, (char *)*ret_dat, KADM_VERSIZE)) {
+ u_int32_t errcode;
+ /* it's a youlose packet */
+ if (*ret_siz < KADM_VERSIZE + sizeof(u_int32_t))
+ RET_N_FREE2(KADM_BAD_VER);
+ bcopy((char *)(*ret_dat) + KADM_VERSIZE, (char *)&errcode,
+ sizeof(u_int32_t));
+ retdat = (int) ntohl(errcode);
+ RET_N_FREE2(retdat);
+ }
+ /* need to decode the ret_dat */
+ if ((retdat = krb_rd_priv(*ret_dat, (u_int32_t)*ret_siz, sess_sched,
+ &sess_key, &client_parm.admin_addr,
+ &client_parm.my_addr, &mdat)))
+ RET_N_FREE2(retdat+krb_err_base);
+ if (mdat.app_length < KADM_VERSIZE + 4)
+ /* too short! */
+ RET_N_FREE2(KADM_BAD_VER);
+ if (strncmp((char *)mdat.app_data, KADM_VERSTR, KADM_VERSIZE))
+ /* bad version */
+ RET_N_FREE2(KADM_BAD_VER);
+ bcopy((char *)mdat.app_data+KADM_VERSIZE,
+ (char *)&retdat, sizeof(u_int32_t));
+ retdat = ntohl((u_int32_t)retdat);
+ if (!(return_dat = (u_char *)malloc((unsigned)(mdat.app_length -
+ KADM_VERSIZE - sizeof(u_int32_t)))))
+ RET_N_FREE2(KADM_NOMEM);
+ bcopy((char *) mdat.app_data + KADM_VERSIZE + sizeof(u_int32_t),
+ (char *)return_dat,
+ (int)mdat.app_length - KADM_VERSIZE - sizeof(u_int32_t));
+ free((char *)*ret_dat);
+ clear_secrets();
+ *ret_dat = return_dat;
+ *ret_siz = mdat.app_length - KADM_VERSIZE - sizeof(u_int32_t);
+ return retdat;
+}
+
+/*
+ * kadm_change_pw
+ * recieves : key
+ *
+ * Replaces the password (i.e. des key) of the caller with that specified in
+ * key. Returns no actual data from the master server, since this is called
+ * by a user
+ */
+int
+kadm_change_pw(newkey)
+ unsigned char *newkey; /* The DES form of the users key */
+{
+ int stsize, retc; /* stream size and return code */
+ u_char *send_st; /* send stream */
+ u_char *ret_st;
+ int ret_sz;
+ u_int32_t keytmp;
+
+ if ((retc = kadm_cli_conn()) != KADM_SUCCESS)
+ return(retc);
+ /* possible problem with vts_long on a non-multiple of four boundary */
+
+ stsize = 0; /* start of our output packet */
+ send_st = (u_char *) malloc(1);/* to make it reallocable */
+ send_st[stsize++] = (u_char) CHANGE_PW;
+
+ /* change key to stream */
+
+ bcopy((char *) (((long *) newkey) + 1), (char *) &keytmp, 4);
+ keytmp = htonl(keytmp);
+ stsize += vts_long(keytmp, &send_st, stsize);
+
+ bcopy((char *) newkey, (char *) &keytmp, 4);
+ keytmp = htonl(keytmp);
+ stsize += vts_long(keytmp, &send_st, stsize);
+
+ retc = kadm_cli_send(send_st, stsize, &ret_st, &ret_sz);
+ free((char *)send_st);
+ if (retc == KADM_SUCCESS) {
+ free((char *)ret_st);
+ }
+ kadm_cli_disconn();
+ return(retc);
+}
+
+/*
+ * kadm_add
+ * receives : vals
+ * returns : vals
+ *
+ * Adds and entry containing values to the database returns the values of the
+ * entry, so if you leave certain fields blank you will be able to determine
+ * the default values they are set to
+ */
+int
+kadm_add(vals)
+ Kadm_vals *vals;
+{
+ u_char *st, *st2; /* st will hold the stream of values */
+ int st_len; /* st2 the final stream with opcode */
+ int retc; /* return code from call */
+ u_char *ret_st;
+ int ret_sz;
+
+ if ((retc = kadm_cli_conn()) != KADM_SUCCESS)
+ return(retc);
+ st_len = vals_to_stream(vals, &st);
+ st2 = (u_char *) malloc((unsigned)(1 + st_len));
+ *st2 = (u_char) ADD_ENT; /* here's the opcode */
+ bcopy((char *) st, (char *) st2 + 1, st_len); /* append st on */
+ retc = kadm_cli_send(st2, st_len + 1, &ret_st, &ret_sz);
+ free((char *)st);
+ free((char *)st2);
+ if (retc == KADM_SUCCESS) {
+ /* ret_st has vals */
+ if (stream_to_vals(ret_st, vals, ret_sz) < 0)
+ retc = KADM_LENGTH_ERROR;
+ free((char *)ret_st);
+ }
+ kadm_cli_disconn();
+ return(retc);
+}
+
+/*
+ * kadm_mod
+ * receives : KTEXT, {values, values}
+ * returns : CKSUM, RETCODE, {values}
+ * acl : su, sms (as register or dealloc)
+ *
+ * Modifies all entries corresponding to the first values so they match the
+ * second values. returns the values for the changed entries in vals2
+ */
+int
+kadm_mod(vals1, vals2)
+ Kadm_vals *vals1;
+ Kadm_vals *vals2;
+{
+ u_char *st, *st2; /* st will hold the stream of values */
+ int st_len, nlen; /* st2 the final stream with opcode */
+ u_char *ret_st;
+ int ret_sz;
+
+ /* nlen is the length of second vals */
+ int retc; /* return code from call */
+
+ if ((retc = kadm_cli_conn()) != KADM_SUCCESS)
+ return(retc);
+
+ st_len = vals_to_stream(vals1, &st);
+ st2 = (u_char *) malloc((unsigned)(1 + st_len));
+ *st2 = (u_char) MOD_ENT; /* here's the opcode */
+ bcopy((char *) st, (char *) st2 + 1, st_len++); /* append st on */
+ free((char *)st);
+ nlen = vals_to_stream(vals2, &st);
+ st2 = (u_char *) realloc((char *) st2, (unsigned)(st_len + nlen));
+ bcopy((char *) st, (char *) st2 + st_len, nlen); /* append st on */
+ retc = kadm_cli_send(st2, st_len + nlen, &ret_st, &ret_sz);
+ free((char *)st);
+ free((char *)st2);
+ if (retc == KADM_SUCCESS) {
+ /* ret_st has vals */
+ if (stream_to_vals(ret_st, vals2, ret_sz) < 0)
+ retc = KADM_LENGTH_ERROR;
+ free((char *)ret_st);
+ }
+ kadm_cli_disconn();
+ return(retc);
+}
+
+/*
+ * kadm_get
+ * receives : KTEXT, {values, flags}
+ * returns : CKSUM, RETCODE, {count, values, values, values}
+ * acl : su
+ *
+ * gets the fields requested by flags from all entries matching values returns
+ * this data for each matching recipient, after a count of how many such
+ * matches there were
+ */
+int
+kadm_get(vals, fl)
+ Kadm_vals *vals;
+ u_char *fl;
+{
+ int loop; /* for copying the fields data */
+ u_char *st, *st2; /* st will hold the stream of values */
+ int st_len; /* st2 the final stream with opcode */
+ int retc; /* return code from call */
+ u_char *ret_st;
+ int ret_sz;
+
+ if ((retc = kadm_cli_conn()) != KADM_SUCCESS)
+ return(retc);
+ st_len = vals_to_stream(vals, &st);
+ st2 = (u_char *) malloc((unsigned)(1 + st_len + FLDSZ));
+ *st2 = (u_char) GET_ENT; /* here's the opcode */
+ bcopy((char *) st, (char *) st2 + 1, st_len); /* append st on */
+ for (loop = FLDSZ - 1; loop >= 0; loop--)
+ *(st2 + st_len + FLDSZ - loop) = fl[loop]; /* append the flags */
+ retc = kadm_cli_send(st2, st_len + 1 + FLDSZ, &ret_st, &ret_sz);
+ free((char *)st);
+ free((char *)st2);
+ if (retc == KADM_SUCCESS) {
+ /* ret_st has vals */
+ if (stream_to_vals(ret_st, vals, ret_sz) < 0)
+ retc = KADM_LENGTH_ERROR;
+ free((char *)ret_st);
+ }
+ kadm_cli_disconn();
+ return(retc);
+}
--- /dev/null
+# $Id: kadm_err.et,v 1.1.1.1 1995/12/14 06:52:45 tholo Exp $
+
+# Copyright 1988 by the Massachusetts Institute of Technology.
+#
+# For copying and distribution information, please see the file
+# <mit-copyright.h>.
+#
+# Kerberos administration server error table
+#
+ et kadm
+
+# KADM_SUCCESS, as all success codes should be, is zero
+
+ec KADM_RCSID, "$Header: /home/cvs/src/kerberosIV/kadm/Attic/kadm_err.et,v 1.1.1.1 1995/12/14 06:52:45 tholo Exp $"
+# /* Building and unbuilding the packet errors */
+ec KADM_NO_REALM, "Cannot fetch local realm"
+ec KADM_NO_CRED, "Unable to fetch credentials"
+ec KADM_BAD_KEY, "Bad key supplied"
+ec KADM_NO_ENCRYPT, "Can't encrypt data"
+ec KADM_NO_AUTH, "Cannot encode/decode authentication info"
+ec KADM_WRONG_REALM, "Principal attemping change is in wrong realm"
+ec KADM_NO_ROOM, "Packet is too large"
+ec KADM_BAD_VER, "Version number is incorrect"
+ec KADM_BAD_CHK, "Checksum does not match"
+ec KADM_NO_READ, "Unsealing private data failed"
+ec KADM_NO_OPCODE, "Unsupported operation"
+ec KADM_NO_HOST, "Could not find administrating host"
+ec KADM_UNK_HOST, "Administrating host name is unknown"
+ec KADM_NO_SERV, "Could not find service name in services database"
+ec KADM_NO_SOCK, "Could not create socket"
+ec KADM_NO_CONN, "Could not connect to server"
+ec KADM_NO_HERE, "Could not fetch local socket address"
+ec KADM_NO_MAST, "Could not fetch master key"
+ec KADM_NO_VERI, "Could not verify master key"
+
+# /* From the server side routines */
+ec KADM_INUSE, "Entry already exists in database"
+ec KADM_UK_SERROR, "Database store error"
+ec KADM_UK_RERROR, "Database read error"
+ec KADM_UNAUTH, "Insufficient access to perform requested operation"
+# KADM_DATA isn't really an error, but...
+ec KADM_DATA, "Data is available for return to client"
+ec KADM_NOENTRY, "No such entry in the database"
+
+ec KADM_NOMEM, "Memory exhausted"
+ec KADM_NO_HOSTNAME, "Could not fetch system hostname"
+ec KADM_NO_BIND, "Could not bind port"
+ec KADM_LENGTH_ERROR, "Length mismatch problem"
+ec KADM_ILL_WILDCARD, "Illegal use of wildcard"
+
+ec KADM_DB_INUSE, "Database is locked or in use--try again later"
+end
--- /dev/null
+/* $Id: kadm_local.h,v 1.1.1.1 1995/12/14 06:52:45 tholo Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include "krb_err.h"
+#include <kerberosIV/krb_db.h>
+#include <kerberosIV/kadm.h>
+#include "kadm_err.h"
+
+int vts_long __P((u_int32_t, u_char **, int));
+int vals_to_stream __P((Kadm_vals *, u_char **));
+int stream_to_vals __P((u_char *, Kadm_vals *, int));
+
+int kadm_init_link __P((char n[], char i[], char r[]));
+int kadm_change_pw __P((des_cblock));
+int kadm_add __P((Kadm_vals *));
+int kadm_mod __P((Kadm_vals *, Kadm_vals *));
+int kadm_get __P((Kadm_vals *, u_char fl[4]));
--- /dev/null
+/* $Id: kadm_stream.c,v 1.1.1.1 1995/12/14 06:52:45 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Stream conversion functions for Kerberos administration server
+ */
+
+/*
+ kadm_stream.c
+ this holds the stream support routines for the kerberos administration server
+
+ vals_to_stream: converts a vals struct to a stream for transmission
+ internals build_field_header, vts_[string, char, long, short]
+ stream_to_vals: converts a stream to a vals struct
+ internals check_field_header, stv_[string, char, long, short]
+ error: prints out a kadm error message, returns
+ fatal: prints out a kadm fatal error message, exits
+*/
+
+#include "kadm_local.h"
+
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+
+static int
+build_field_header(cont, st)
+ u_char *cont; /* container for fields data */
+ u_char **st; /* stream */
+{
+ *st = (u_char *) malloc (4);
+ bcopy((char *) cont, (char *) *st, 4);
+ return 4; /* return pointer to current stream location */
+}
+
+static int
+check_field_header(st, cont, maxlen)
+ u_char *st; /* stream */
+ u_char *cont; /* container for fields data */
+ int maxlen;
+{
+ if (4 > maxlen)
+ return(-1);
+ bcopy((char *) st, (char *) cont, 4);
+ return 4; /* return pointer to current stream location */
+}
+
+static int
+vts_string(dat, st, loc)
+ char *dat; /* a string to put on the stream */
+ u_char **st; /* base pointer to the stream */
+ int loc; /* offset into the stream for current data */
+{
+ *st = (u_char *) realloc ((char *)*st, (unsigned) (loc + strlen(dat) + 1));
+ bcopy(dat, (char *)(*st + loc), strlen(dat)+1);
+ return strlen(dat)+1;
+}
+
+
+static int
+vts_short(dat, st, loc)
+ u_int16_t dat; /* the attributes field */
+ u_char **st; /* a base pointer to the stream */
+ int loc; /* offset into the stream for current data */
+{
+ u_int16_t temp; /* to hold the net order short */
+
+ temp = htons(dat); /* convert to network order */
+ *st = (u_char *) realloc ((char *)*st, (unsigned)(loc + sizeof(u_int16_t)));
+ bcopy((char *) &temp, (char *)(*st + loc), sizeof(u_int16_t));
+ return sizeof(u_int16_t);
+}
+
+static int
+vts_char(dat, st, loc)
+ u_char dat; /* the attributes field */
+ u_char **st; /* a base pointer to the stream */
+ int loc; /* offset into the stream for current data */
+{
+ *st = (u_char *) realloc ((char *)*st, (unsigned)(loc + sizeof(u_char)));
+ (*st)[loc] = (u_char) dat;
+ return 1;
+}
+
+int
+vts_long(dat, st, loc)
+ u_int32_t dat; /* the attributes field */
+ u_char **st; /* a base pointer to the stream */
+ int loc; /* offset into the stream for current data */
+{
+ u_int32_t temp; /* to hold the net order short */
+
+ temp = htonl(dat); /* convert to network order */
+ *st = (u_char *) realloc ((char *)*st, (unsigned)(loc + sizeof(u_int32_t)));
+ bcopy((char *) &temp, (char *)(*st + loc), sizeof(u_int32_t));
+ return sizeof(u_int32_t);
+}
+
+static int
+stv_string(st, dat, loc, stlen, maxlen)
+ register u_char *st; /* base pointer to the stream */
+ char *dat; /* a string to read from the stream */
+ register int loc; /* offset into the stream for current data */
+ int stlen; /* max length of string to copy in */
+ int maxlen; /* max length of input stream */
+{
+ int maxcount; /* max count of chars to copy */
+
+ maxcount = min(maxlen - loc, stlen);
+
+ (void) strncpy(dat, (char *)st + loc, maxcount);
+
+ if (dat[maxcount-1]) /* not null-term --> not enuf room */
+ return(-1);
+ return strlen(dat)+1;
+}
+
+static int
+stv_short(st, dat, loc, maxlen)
+ u_char *st; /* a base pointer to the stream */
+ u_int16_t *dat; /* the attributes field */
+ int loc; /* offset into the stream for current data */
+ int maxlen;
+{
+ u_int16_t temp; /* to hold the net order short */
+
+ if (loc + sizeof(temp) > maxlen)
+ return(-1);
+ /*bcopy((char *)((u_long)st+(u_long)loc), (char *) &temp, sizeof(u_short));*/
+ bcopy(st + loc, (char *) &temp, sizeof(temp));
+ *dat = ntohs(temp); /* convert to network order */
+ return sizeof(temp);
+}
+
+int
+stv_long(st, dat, loc, maxlen)
+ u_char *st; /* a base pointer to the stream */
+ u_int32_t *dat; /* the attributes field */
+ int loc; /* offset into the stream for current data */
+ int maxlen; /* maximum length of st */
+{
+ u_int32_t temp; /* to hold the net order short */
+
+ if (loc + sizeof(temp) > maxlen)
+ return(-1);
+ /*bcopy((char *)((u_long)st+(u_long)loc), (char *) &temp, sizeof(u_long));*/
+ bcopy(st + loc, (char *) &temp, sizeof(temp));
+ *dat = ntohl(temp); /* convert to network order */
+ return sizeof(temp);
+}
+
+static int
+stv_char(st, dat, loc, maxlen)
+ u_char *st; /* a base pointer to the stream */
+ u_char *dat; /* the attributes field */
+ int loc; /* offset into the stream for current data */
+ int maxlen;
+{
+ if (loc + 1 > maxlen)
+ return(-1);
+ *dat = *(st + loc);
+ return 1;
+}
+
+/*
+vals_to_stream
+ recieves : kadm_vals *, u_char *
+ returns : a realloced and filled in u_char *
+
+this function creates a byte-stream representation of the kadm_vals structure
+*/
+int
+vals_to_stream(dt_in, dt_out)
+ Kadm_vals *dt_in;
+ u_char **dt_out;
+{
+ int vsloop, stsize; /* loop counter, stream size */
+
+ stsize = build_field_header(dt_in->fields, dt_out);
+ for (vsloop=31; vsloop>=0; vsloop--)
+ if (IS_FIELD(vsloop,dt_in->fields)) {
+ switch (vsloop) {
+ case KADM_NAME:
+ stsize+=vts_string(dt_in->name, dt_out, stsize);
+ break;
+ case KADM_INST:
+ stsize+=vts_string(dt_in->instance, dt_out, stsize);
+ break;
+ case KADM_EXPDATE:
+ stsize+=vts_long(dt_in->exp_date, dt_out, stsize);
+ break;
+ case KADM_ATTR:
+ stsize+=vts_short(dt_in->attributes, dt_out, stsize);
+ break;
+ case KADM_MAXLIFE:
+ stsize+=vts_char(dt_in->max_life, dt_out, stsize);
+ break;
+ case KADM_DESKEY:
+ stsize+=vts_long(dt_in->key_high, dt_out, stsize);
+ stsize+=vts_long(dt_in->key_low, dt_out, stsize);
+ break;
+ default:
+ break;
+ }
+}
+ return(stsize);
+}
+
+/*
+stream_to_vals
+ recieves : u_char *, kadm_vals *
+ returns : a kadm_vals filled in according to u_char *
+
+this decodes a byte stream represntation of a vals struct into kadm_vals
+*/
+int
+stream_to_vals(dt_in, dt_out, maxlen)
+ u_char *dt_in;
+ Kadm_vals *dt_out;
+ int maxlen; /* max length to use */
+{
+ register int vsloop, stsize; /* loop counter, stream size */
+ register int status;
+
+ bzero((char *) dt_out, sizeof(*dt_out));
+
+ stsize = check_field_header(dt_in, dt_out->fields, maxlen);
+ if (stsize < 0)
+ return(-1);
+ for (vsloop=31; vsloop>=0; vsloop--)
+ if (IS_FIELD(vsloop,dt_out->fields))
+ switch (vsloop) {
+ case KADM_NAME:
+ if ((status = stv_string(dt_in, dt_out->name, stsize,
+ sizeof(dt_out->name), maxlen)) < 0)
+ return(-1);
+ stsize += status;
+ break;
+ case KADM_INST:
+ if ((status = stv_string(dt_in, dt_out->instance, stsize,
+ sizeof(dt_out->instance), maxlen)) < 0)
+ return(-1);
+ stsize += status;
+ break;
+ case KADM_EXPDATE:
+ if ((status = stv_long(dt_in, &dt_out->exp_date, stsize,
+ maxlen)) < 0)
+ return(-1);
+ stsize += status;
+ break;
+ case KADM_ATTR:
+ if ((status = stv_short(dt_in, &dt_out->attributes, stsize,
+ maxlen)) < 0)
+ return(-1);
+ stsize += status;
+ break;
+ case KADM_MAXLIFE:
+ if ((status = stv_char(dt_in, &dt_out->max_life, stsize,
+ maxlen)) < 0)
+ return(-1);
+ stsize += status;
+ break;
+ case KADM_DESKEY:
+ if ((status = stv_long(dt_in, &dt_out->key_high, stsize,
+ maxlen)) < 0)
+ return(-1);
+ stsize += status;
+ if ((status = stv_long(dt_in, &dt_out->key_low, stsize,
+ maxlen)) < 0)
+ return(-1);
+ stsize += status;
+ break;
+ default:
+ break;
+ }
+ return stsize;
+}
--- /dev/null
+/* $Id: kadm_supp.c,v 1.1.1.1 1995/12/14 06:52:46 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Support functions for Kerberos administration server & clients
+ */
+
+/*
+ kadm_supp.c
+ this holds the support routines for the kerberos administration server
+
+ error: prints out a kadm error message, returns
+ fatal: prints out a kadm fatal error message, exits
+ prin_vals: prints out data associated with a Principal in the vals
+ structure
+*/
+
+#include "kadm_local.h"
+
+/*
+prin_vals:
+ recieves : a vals structure
+*/
+void
+prin_vals(vals)
+ Kadm_vals *vals;
+{
+ printf("Info in Database for %s.%s:\n", vals->name, vals->instance);
+ printf(" Max Life: %d (%s) Exp Date: %s\n",
+ vals->max_life,
+ krb_life_to_atime(vals->max_life),
+ asctime(k_localtime(&vals->exp_date)));
+ printf(" Attribs: %.2x key: %lu %lu\n",
+ vals->attributes,
+ (long)vals->key_low, (long)vals->key_high);
+}
+
+#ifdef notdef
+nierror(s)
+int s;
+{
+ printf("Kerberos admin server loses..... %s\n",error_message(s));
+ return(s);
+}
+#endif
+
+/* kadm_prin_to_vals takes a fields arguments, a Kadm_vals and a Principal,
+ it copies the fields in Principal specified by fields into Kadm_vals,
+ i.e from old to new */
+
+void
+kadm_prin_to_vals(fields, new, old)
+ u_char *fields;
+ Kadm_vals *new;
+ Principal *old;
+{
+ bzero((char *)new, sizeof(*new));
+ if (IS_FIELD(KADM_NAME,fields)) {
+ (void) strncpy(new->name, old->name, ANAME_SZ);
+ SET_FIELD(KADM_NAME, new->fields);
+ }
+ if (IS_FIELD(KADM_INST,fields)) {
+ (void) strncpy(new->instance, old->instance, INST_SZ);
+ SET_FIELD(KADM_INST, new->fields);
+ }
+ if (IS_FIELD(KADM_EXPDATE,fields)) {
+ new->exp_date = old->exp_date;
+ SET_FIELD(KADM_EXPDATE, new->fields);
+ }
+ if (IS_FIELD(KADM_ATTR,fields)) {
+ new->attributes = old->attributes;
+ SET_FIELD(KADM_ATTR, new->fields);
+ }
+ if (IS_FIELD(KADM_MAXLIFE,fields)) {
+ new->max_life = old->max_life;
+ SET_FIELD(KADM_MAXLIFE, new->fields);
+ }
+ if (IS_FIELD(KADM_DESKEY,fields)) {
+ new->key_low = old->key_low;
+ new->key_high = old->key_high;
+ SET_FIELD(KADM_DESKEY, new->fields);
+ }
+}
+
+void
+kadm_vals_to_prin(fields, new, old)
+ u_char *fields;
+ Principal *new;
+ Kadm_vals *old;
+{
+
+ bzero((char *)new, sizeof(*new));
+ if (IS_FIELD(KADM_NAME,fields))
+ (void) strncpy(new->name, old->name, ANAME_SZ);
+ if (IS_FIELD(KADM_INST,fields))
+ (void) strncpy(new->instance, old->instance, INST_SZ);
+ if (IS_FIELD(KADM_EXPDATE,fields))
+ new->exp_date = old->exp_date;
+ if (IS_FIELD(KADM_ATTR,fields))
+ new->attributes = old->attributes;
+ if (IS_FIELD(KADM_MAXLIFE,fields))
+ new->max_life = old->max_life;
+ if (IS_FIELD(KADM_DESKEY,fields)) {
+ new->key_low = old->key_low;
+ new->key_high = old->key_high;
+ }
+}
--- /dev/null
+major=4
+minor=0
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $
+
+PROG= kadmin
+SRCS= kadmin.c kadmin_cmds.c maketime.c
+.PATH: ${.CURDIR}/../kdb_edit
+.if exists(${.CURDIR}/../kadm/obj)
+CFLAGS+=-I${.CURDIR}/../kadm/obj
+.else
+CFLAGS+=-I${.CURDIR}/../kadm
+.endif
+.if exists(${.CURDIR}/../krb/obj)
+CFLAGS+=-I${.CURDIR}/../krb/obj
+.else
+CFLAGS+=-I${.CURDIR}/../krb
+.endif
+.if exists(${.CURDIR}/../ss/obj)
+CFLAGS+=-I${.CURDIR}/../ss/obj
+.else
+CFLAGS+=-I${.CURDIR}/../ss
+.endif
+LDADD+= -lkadm -lkrb -ldes -lss -lcom_err
+DPADD+= ${LIBKADM} ${LIBKRB} ${LIBDES} ${LIBSS} ${LIBCOM_ERR}
+CLEANFILES+= kadmin_cmds.c
+MAN= kadmin.8
+
+kadmin_cmds.c: kadmin_cmds.ct
+ test -e kadmin_cmds.ct || ln -s ${.CURDIR}/kadmin_cmds.ct .
+ ${MK_CMDS} kadmin_cmds.ct
+ -test -h kadmin_cmds.ct && rm kadmin_cmds.ct
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: kadmin.8,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $
+.TH KADMIN 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kadmin \- network utility for Kerberos database administration
+.SH SYNOPSIS
+.B kadmin [-u user] [-r default_realm] [-m]
+.SH DESCRIPTION
+This utility provides a unified administration interface to
+the
+Kerberos
+master database.
+Kerberos
+administrators
+use
+.I kadmin
+to register new users and services to the master database,
+and to change information about existing database entries.
+For instance, an administrator can use
+.I kadmin
+to change a user's
+Kerberos
+password.
+A Kerberos administrator is a user with an ``admin'' instance
+whose name appears on one of the Kerberos administration access control
+lists. If the \-u option is used,
+.I user
+will be used as the administrator instead of the local user.
+If the \-r option is used,
+.I default_realm
+will be used as the default realm for transactions. Otherwise,
+the local realm will be used by default.
+If the \-m option is used, multiple requests will be permitted
+on only one entry of the admin password. Some sites won't
+support this option.
+
+The
+.I kadmin
+program communicates over the network with the
+.I kadmind
+program, which runs on the machine housing the Kerberos master
+database.
+The
+.I kadmind
+creates new entries and makes modifications to the database.
+
+When you enter the
+.I kadmin
+command,
+the program displays a message that welcomes you and explains
+how to ask for help.
+Then
+.I kadmin
+waits for you to enter commands (which are described below).
+It then asks you for your
+.I admin
+password before accessing the database.
+
+Use the
+.I add_new_key
+(or
+.I ank
+for short)
+command to register a new principal
+with the master database.
+The command requires one argument,
+the principal's name. The name
+given can be fully qualified using
+the standard
+.I name.instance@realm
+convention.
+You are asked to enter your
+.I admin
+password,
+then prompted twice to enter the principal's
+new password. If no realm is specified,
+the local realm is used unless another was
+given on the commandline with the \-r flag.
+If no instance is
+specified, a null instance is used. If
+a realm other than the default realm is specified,
+you will need to supply your admin password for
+the other realm.
+
+Use the
+.I change_password (cpw)
+to change a principal's
+Kerberos
+password.
+The command requires one argument,
+the principal's
+name.
+You are asked to enter your
+.I admin
+password,
+then prompted twice to enter the principal's new password.
+The name
+given can be fully qualified using
+the standard
+.I name.instance@realm
+convention.
+
+Use the
+.I change_admin_password (cap)
+to change your
+.I admin
+instance password.
+This command requires no arguments.
+It prompts you for your old
+.I admin
+password, then prompts you twice to enter the new
+.I admin
+password. If this is your first command,
+the default realm is used. Otherwise, the realm
+used in the last command is used.
+
+Use the
+.I destroy_tickets (dest)
+command to destroy your admin tickets explicitly.
+
+Use the
+.I list_requests (lr)
+command to get a list of possible commands.
+
+Use the
+.I help
+command to display
+.IR kadmin's
+various help messages.
+If entered without an argument,
+.I help
+displays a general help message.
+You can get detailed information on specific
+.I kadmin
+commands
+by entering
+.I help
+.IR command_name .
+
+To quit the program, type
+.IR quit .
+
+.SH BUGS
+The user interface is primitive, and the command names could be better.
+
+.SH "SEE ALSO"
+kerberos(1), kadmind(8), kpasswd(1), ksrvutil(8)
+.br
+``A Subsystem Utilities Package for UNIX'' by Ken Raeburn
+.SH AUTHORS
+Jeffrey I. Schiller, MIT Project Athena
+.br
+Emanuel Jay Berkenbilt, MIT Project Athena
--- /dev/null
+/* $Id: kadmin.c,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $ */
+
+/*
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Kerberos database administrator's tool.
+ *
+ * The default behavior of kadmin is if the -m option is given
+ * on the commandline, multiple requests are allowed to be given
+ * with one entry of the admin password (until the tickets expire).
+ * If you do not want this to be an available option, compile with
+ * NO_MULTIPLE defined.
+ */
+
+#include <kadm_locl.h>
+#include <sys/param.h>
+
+#define BAD_PW 1
+#define GOOD_PW 0
+#define FUDGE_VALUE 15 /* for ticket expiration time */
+#define PE_NO 0
+#define PE_YES 1
+#define PE_UNSURE 2
+
+/* for get_password, whether it should do the swapping...necessary for
+ using vals structure, unnecessary for change_pw requests */
+#define DONTSWAP 0
+#define SWAP 1
+
+extern ss_request_table admin_cmds;
+
+static char myname[ANAME_SZ];
+static char default_realm[REALM_SZ]; /* default kerberos realm */
+static char krbrlm[REALM_SZ]; /* current realm being administered */
+static int multiple = 0; /* Allow multiple requests per ticket */
+
+#ifdef NOENCRYPTION
+#define read_long_pw_string placebo_read_pw_string
+#else
+#define read_long_pw_string des_read_pw_string
+#endif
+
+static void
+get_maxlife(Kadm_vals *vals)
+{
+ char buff[BUFSIZ];
+ time_t life;
+ int l;
+
+ do {
+ printf("Maximum ticket lifetime? (%d) [%s] ",
+ vals->max_life, krb_life_to_atime(vals->max_life));
+ fflush(stdout);
+ if (fgets(buff, sizeof(buff), stdin) == NULL || *buff == '\n') {
+ clearerr(stdin);
+ return;
+ }
+ life = krb_atime_to_life(buff);
+ } while (life <= 0);
+
+ l = strlen(buff);
+ if (buff[l-2] == 'm')
+ life = krb_time_to_life(0L, life*60);
+ if (buff[l-2] == 'h')
+ life = krb_time_to_life(0L, life*60*60);
+
+ vals->max_life = life;
+ SET_FIELD(KADM_MAXLIFE,vals->fields);
+}
+
+static void
+get_attr(Kadm_vals *vals)
+{
+ char buff[BUFSIZ], *out;
+ int attr;
+
+ do {
+ printf("Attributes? [0x%.2x] ", vals->attributes);
+ fflush(stdout);
+ if (fgets(buff, sizeof(buff), stdin) == NULL || *buff == '\n') {
+ clearerr(stdin);
+ return;
+ }
+ attr = strtol(buff, &out, 0);
+ if (attr == 0 && out == buff)
+ attr = -1;
+ } while (attr < 0 || attr > 0xffff);
+
+ vals->attributes = attr;
+ SET_FIELD(KADM_ATTR,vals->fields);
+}
+
+static void
+get_expdate(Kadm_vals *vals)
+{
+ char buff[BUFSIZ];
+ time_t when;
+ struct tm edate;
+
+ bzero(&edate, sizeof(edate));
+ do {
+ printf("Expiration date (enter yyyy-mm-dd) ? [%.24s] ",
+ asctime(k_localtime(&vals->exp_date)));
+ fflush(stdout);
+ if (fgets(buff, sizeof(buff), stdin) == NULL || *buff == '\n') {
+ clearerr(stdin);
+ return;
+ }
+ if (sscanf(buff, "%d-%d-%d",
+ &edate.tm_year, &edate.tm_mon, &edate.tm_mday) == 3) {
+ edate.tm_mon--; /* January is 0, not 1 */
+ edate.tm_hour = 23; /* nearly midnight at the end of the */
+ edate.tm_min = 59; /* specified day */
+ when = maketime(&edate, 1);
+ }
+ } while (when <= 0);
+
+ vals->exp_date = when;
+ SET_FIELD(KADM_EXPDATE,vals->fields);
+}
+
+static int
+princ_exists(char *name, char *instance, char *realm)
+{
+ int status;
+
+ status = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm, 1, "");
+
+ if ((status == KSUCCESS) || (status == INTK_BADPW))
+ return(PE_YES);
+ else if (status == KDC_PR_UNKNOWN)
+ return(PE_NO);
+ else
+ return(PE_UNSURE);
+}
+
+static int
+get_password(u_int32_t *low, u_int32_t *high, char *prompt, int byteswap)
+{
+ char new_passwd[MAX_KPW_LEN]; /* new password */
+ des_cblock newkey;
+
+ if (read_long_pw_string(new_passwd, sizeof(new_passwd)-1, prompt, 1))
+ return(BAD_PW);
+ if (strlen(new_passwd) == 0) {
+ printf("Using random password.\n");
+#ifdef NOENCRYPTION
+ bzero((char *) newkey, sizeof(newkey));
+#else
+ des_new_random_key(&newkey);
+#endif
+ } else {
+#ifdef NOENCRYPTION
+ bzero((char *) newkey, sizeof(newkey));
+#else
+ des_string_to_key(new_passwd, &newkey);
+#endif
+ bzero(new_passwd, sizeof(new_passwd));
+ }
+
+ bcopy((char *) newkey,(char *)low,4);
+ bcopy((char *)(((int32_t *) newkey) + 1), (char *)high,4);
+
+ bzero((char *) newkey, sizeof(newkey));
+
+#ifdef NOENCRYPTION
+ *low = 1;
+#endif
+
+ if (byteswap != DONTSWAP) {
+ *low = htonl(*low);
+ *high = htonl(*high);
+ }
+ return(GOOD_PW);
+}
+
+static int
+get_admin_password(void)
+{
+ int status;
+ char admin_passwd[MAX_KPW_LEN]; /* Admin's password */
+ int ticket_life = 1; /* minimum ticket lifetime */
+ CREDENTIALS c;
+
+ if (multiple) {
+ /* If admin tickets exist and are valid, just exit. */
+ bzero(&c, sizeof(c));
+ if (krb_get_cred(PWSERV_NAME, KADM_SINST, krbrlm, &c) == KSUCCESS)
+ /*
+ * If time is less than lifetime - FUDGE_VALUE after issue date,
+ * tickets will probably last long enough for the next
+ * transaction.
+ */
+ if (time(0) < (c.issue_date + (5 * 60 * c.lifetime) - FUDGE_VALUE))
+ return(KADM_SUCCESS);
+ ticket_life = DEFAULT_TKT_LIFE;
+ }
+
+ if (princ_exists(myname, "admin", krbrlm) != PE_NO) {
+ if (read_long_pw_string(admin_passwd, sizeof(admin_passwd)-1,
+ "Admin password:", 0)) {
+ fprintf(stderr, "Error reading admin password.\n");
+ goto bad;
+ }
+ status = krb_get_pw_in_tkt(myname, "admin", krbrlm, PWSERV_NAME,
+ KADM_SINST, ticket_life, admin_passwd);
+ bzero(admin_passwd, sizeof(admin_passwd));
+
+ /* Initialize non shared random sequence from session key. */
+ bzero(&c, sizeof(c));
+ krb_get_cred(PWSERV_NAME, KADM_SINST, krbrlm, &c);
+ des_init_random_number_generator(&c.session);
+ }
+ else
+ status = KDC_PR_UNKNOWN;
+
+ switch(status) {
+ case GT_PW_OK:
+ return(GOOD_PW);
+ case KDC_PR_UNKNOWN:
+ printf("Principal %s.admin@%s does not exist.\n", myname, krbrlm);
+ goto bad;
+ case GT_PW_BADPW:
+ printf("Incorrect admin password.\n");
+ goto bad;
+ default:
+ com_err("kadmin", status+krb_err_base,
+ "while getting password tickets");
+ goto bad;
+ }
+
+ bad:
+ bzero(admin_passwd, sizeof(admin_passwd));
+ (void) dest_tkt();
+ return(BAD_PW);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: kadmin [-u admin_name] [-r default_realm]");
+ fprintf(stderr, " [-m]");
+ fprintf(stderr, "\n");
+ fprintf(stderr, " -m allows multiple admin requests to be ");
+ fprintf(stderr, "serviced with one entry of admin\n");
+ fprintf(stderr, " password.\n");
+ exit(1);
+}
+
+/* GLOBAL */
+void
+clean_up(void)
+{
+ (void) dest_tkt();
+ return;
+}
+
+/* GLOBAL */
+void
+quit(void)
+{
+ printf("Cleaning up and exiting.\n");
+ clean_up();
+ exit(0);
+}
+
+static int inited = 0;
+
+static void
+do_init(int argc, char **argv)
+{
+ struct passwd *pw;
+ int c;
+#define OPTION_STRING "u:r:m"
+
+ bzero(myname, sizeof(myname));
+
+ if (!inited) {
+ /*
+ * This is only as a default/initial realm; we don't care
+ * about failure.
+ */
+ if (krb_get_lrealm(default_realm, 1) != KSUCCESS)
+ strcpy(default_realm, KRB_REALM);
+
+ /*
+ * If we can reach the local realm, initialize to it. Otherwise,
+ * don't initialize.
+ */
+ if (kadm_init_link(PWSERV_NAME, KRB_MASTER, krbrlm) != KADM_SUCCESS)
+ bzero(krbrlm, sizeof(krbrlm));
+ else
+ strcpy(krbrlm, default_realm);
+
+ while ((c = getopt(argc, argv, OPTION_STRING)) != EOF)
+ switch (c) {
+ case 'u':
+ strncpy(myname, optarg, sizeof(myname) - 1);
+ break;
+ case 'r':
+ bzero(default_realm, sizeof(default_realm));
+ strncpy(default_realm, optarg, sizeof(default_realm) - 1);
+ break;
+ case 'm':
+ multiple++;
+ break;
+ default:
+ usage();
+ break;
+ }
+ if (optind < argc)
+ usage();
+ if (!myname[0]) {
+ pw = getpwuid((int) getuid());
+ if (!pw) {
+ fprintf(stderr,
+ "You aren't in the password file. Who are you?\n");
+ exit(1);
+ }
+ (void) strcpy(myname, pw->pw_name);
+ }
+ inited = 1;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ int sci_idx;
+ int code;
+ char tktstring[MAXPATHLEN];
+
+ sci_idx = ss_create_invocation("admin", "2.0", (char *) NULL,
+ &admin_cmds, &code);
+ if (code) {
+ ss_perror(sci_idx, code, "creating invocation");
+ exit(1);
+ }
+ (void) sprintf(tktstring, "/tmp/tkt_adm_%d",(int)getpid());
+ krb_set_tkt_string(tktstring);
+
+ do_init(argc, argv);
+
+ printf("Welcome to the Kerberos Administration Program, version 2\n");
+ printf("Type \"help\" if you need it.\n");
+ code = ss_listen(sci_idx);
+ printf("\n");
+ quit();
+ exit(0);
+}
+
+static int
+setvals(Kadm_vals *vals, char *string)
+{
+ char realm[REALM_SZ];
+ int status = KADM_SUCCESS;
+
+ bzero(vals, sizeof(*vals));
+ bzero(realm, sizeof(realm));
+
+ SET_FIELD(KADM_NAME,vals->fields);
+ SET_FIELD(KADM_INST,vals->fields);
+ if ((status = kname_parse(vals->name, vals->instance, realm, string))) {
+ printf("kerberos error: %s\n", krb_err_txt[status]);
+ return status;
+ }
+ if (!realm[0])
+ strcpy(realm, default_realm);
+ if (strcmp(realm, krbrlm)) {
+ strcpy(krbrlm, realm);
+ if ((status = kadm_init_link(PWSERV_NAME, KRB_MASTER, krbrlm))
+ != KADM_SUCCESS)
+ printf("kadm error for realm %s: %s\n",
+ krbrlm, error_message(status));
+ }
+ if (status)
+ return 1;
+ else
+ return KADM_SUCCESS;
+}
+
+void
+change_password(int argc, char **argv)
+{
+ Kadm_vals old, new;
+ int status;
+ char pw_prompt[BUFSIZ];
+
+ if (argc != 2) {
+ printf("Usage: change_password loginname\n");
+ return;
+ }
+
+ if (setvals(&old, argv[1]) != KADM_SUCCESS)
+ return;
+
+ new = old;
+
+ SET_FIELD(KADM_DESKEY,new.fields);
+
+ if (princ_exists(old.name, old.instance, krbrlm) != PE_NO) {
+ /* get the admin's password */
+ if (get_admin_password() != GOOD_PW)
+ return;
+
+ /* get the new password */
+ (void) sprintf(pw_prompt, "New password for %s:", argv[1]);
+
+ if (get_password(&new.key_low, &new.key_high,
+ pw_prompt, SWAP) == GOOD_PW) {
+ status = kadm_mod(&old, &new);
+ if (status == KADM_SUCCESS) {
+ printf("Password changed for %s.\n", argv[1]);
+ } else {
+ printf("kadmin: %s\nwhile changing password for %s",
+ error_message(status), argv[1]);
+ }
+ } else
+ printf("Error reading password; password unchanged\n");
+ bzero((char *)&new, sizeof(new));
+ if (!multiple)
+ clean_up();
+ }
+ else
+ printf("kadmin: Principal does not exist.\n");
+ return;
+}
+
+/*ARGSUSED*/
+void
+change_admin_password(int argc, char **argv)
+{
+ des_cblock newkey;
+ u_int32_t low, high;
+ int status;
+ char prompt_pw[BUFSIZ];
+
+ if (argc != 1) {
+ printf("Usage: change_admin_password\n");
+ return;
+ }
+ /* get the admin's password */
+ if (get_admin_password() != GOOD_PW)
+ return;
+
+ (void) sprintf(prompt_pw, "New password for %s.admin:",myname);
+ if (get_password(&low, &high, prompt_pw, DONTSWAP) == GOOD_PW) {
+ bcopy((char *)&low,(char *) newkey,4);
+ bcopy((char *)&high, (char *)(((int32_t *) newkey) + 1),4);
+ low = high = 0L;
+ if ((status = kadm_change_pw(newkey)) == KADM_SUCCESS)
+ printf("Admin password changed\n");
+ else
+ printf("kadm error: %s\n",error_message(status));
+ bzero((char *)newkey, sizeof(newkey));
+ } else
+ printf("Error reading password; password unchanged\n");
+ if (!multiple)
+ clean_up();
+ return;
+}
+
+void
+add_new_key(int argc, char **argv)
+{
+ Kadm_vals new;
+ char pw_prompt[BUFSIZ];
+ int status;
+
+ if (argc != 2) {
+ printf("Usage: add_new_key user_name.\n");
+ return;
+ }
+ if (setvals(&new, argv[1]) != KADM_SUCCESS)
+ return;
+
+ SET_FIELD(KADM_DESKEY,new.fields);
+
+ if (princ_exists(new.name, new.instance, krbrlm) != PE_YES) {
+ /* get the admin's password */
+ if (get_admin_password() != GOOD_PW)
+ return;
+
+ /* This is the default maximum lifetime for new principals. */
+ if (krb_life_to_time(0, 162) >= 24*60*60)
+ new.max_life = 162; /* ca 100 hours */
+ else
+ new.max_life = 255; /* ca 21 hours (maximum) */
+ new.exp_date = time(0) + 2*(365*24*60*60); /* + ca 2 years */
+ new.attributes = 0;
+ get_maxlife(&new);
+ get_attr(&new);
+ get_expdate(&new);
+
+ /* get the new password */
+ (void) sprintf(pw_prompt, "Password for %s:", argv[1]);
+
+ if (get_password(&new.key_low, &new.key_high,
+ pw_prompt, SWAP) == GOOD_PW) {
+ status = kadm_add(&new);
+ if (status == KADM_SUCCESS) {
+ printf("%s added to database.\n", argv[1]);
+ } else {
+ printf("kadm error: %s\n",error_message(status));
+ }
+ } else
+ printf("Error reading password; %s not added\n",argv[1]);
+ bzero((char *)&new, sizeof(new));
+ if (!multiple)
+ clean_up();
+ }
+ else
+ printf("kadmin: Principal already exists.\n");
+ return;
+}
+
+void
+get_entry(int argc, char **argv)
+{
+ int status;
+ u_char fields[4];
+ Kadm_vals vals;
+
+ if (argc != 2) {
+ printf("Usage: get_entry username\n");
+ return;
+ }
+
+ bzero(fields, sizeof(fields));
+
+ SET_FIELD(KADM_NAME,fields);
+ SET_FIELD(KADM_INST,fields);
+ SET_FIELD(KADM_EXPDATE,fields);
+ SET_FIELD(KADM_ATTR,fields);
+ SET_FIELD(KADM_MAXLIFE,fields);
+
+ if (setvals(&vals, argv[1]) != KADM_SUCCESS)
+ return;
+
+
+ if (princ_exists(vals.name, vals.instance, krbrlm) != PE_NO) {
+ /* get the admin's password */
+ if (get_admin_password() != GOOD_PW)
+ return;
+
+ if ((status = kadm_get(&vals, fields)) == KADM_SUCCESS)
+ prin_vals(&vals);
+ else
+ printf("kadm error: %s\n",error_message(status));
+
+ if (!multiple)
+ clean_up();
+ }
+ else
+ printf("kadmin: Principal does not exist.\n");
+ return;
+}
+
+void
+mod_entry(int argc, char **argv)
+{
+ int status;
+ u_char fields[4];
+ Kadm_vals ovals, nvals;
+
+ if (argc != 2) {
+ printf("Usage: mod_entry username\n");
+ return;
+ }
+
+ bzero(fields, sizeof(fields));
+
+ SET_FIELD(KADM_NAME,fields);
+ SET_FIELD(KADM_INST,fields);
+ SET_FIELD(KADM_EXPDATE,fields);
+ SET_FIELD(KADM_ATTR,fields);
+ SET_FIELD(KADM_MAXLIFE,fields);
+
+ if (setvals(&ovals, argv[1]) != KADM_SUCCESS)
+ return;
+
+ nvals = ovals;
+
+ if (princ_exists(ovals.name, ovals.instance, krbrlm) == PE_NO) {
+ printf("kadmin: Principal does not exist.\n");
+ return;
+ }
+
+ /* get the admin's password */
+ if (get_admin_password() != GOOD_PW)
+ return;
+
+ if ((status = kadm_get(&ovals, fields)) != KADM_SUCCESS) {
+ printf("[ unable to retrieve current settings: %s ]\n",
+ error_message(status));
+ nvals.max_life = DEFAULT_TKT_LIFE;
+ nvals.exp_date = 0;
+ nvals.attributes = 0;
+ } else {
+ nvals.max_life = ovals.max_life;
+ nvals.exp_date = ovals.exp_date;
+ nvals.attributes = ovals.attributes;
+ }
+
+ get_maxlife(&nvals);
+ get_attr(&nvals);
+ get_expdate(&nvals);
+
+ if (IS_FIELD(KADM_MAXLIFE, nvals.fields) || IS_FIELD(KADM_ATTR, nvals.fields) || IS_FIELD(KADM_EXPDATE, nvals.fields)) {
+ if ((status = kadm_mod(&ovals, &nvals)) != KADM_SUCCESS) {
+ printf("kadm error: %s\n",error_message(status));
+ goto out;
+ }
+ if ((status = kadm_get(&ovals, fields)) != KADM_SUCCESS) {
+ printf("kadm error: %s\n",error_message(status));
+ goto out;
+ }
+ }
+ prin_vals(&ovals);
+
+out:
+ if (!multiple)
+ clean_up();
+ return;
+}
+
+void
+help(int argc, char **argv)
+{
+ if (argc == 1) {
+ printf("Welcome to the Kerberos administration program.");
+ printf("Type \"?\" to get\n");
+ printf("a list of requests that are available. You can");
+ printf(" get help on each of\n");
+ printf("the commands by typing \"help command_name\".");
+ printf(" Some functions of this\n");
+ printf("program will require an \"admin\" password");
+ printf(" from you. This is a password\n");
+ printf("private to you, that is used to authenticate");
+ printf(" requests from this\n");
+ printf("program. You can change this password with");
+ printf(" the \"change_admin_password\"\n");
+ printf("(or short form \"cap\") command. Good Luck! \n");
+ } else if (!strcmp(argv[1], "change_password") ||
+ !strcmp(argv[1], "cpw")) {
+ printf("Usage: change_password user_name.\n");
+ printf("\n");
+ printf("user_name is the name of the user whose password");
+ printf(" you wish to change. \n");
+ printf("His/her password is changed in the kerberos database\n");
+ printf("When this command is issued, first the \"Admin\"");
+ printf(" password will be prompted\n");
+ printf("for and if correct the user's new password will");
+ printf(" be prompted for (twice with\n");
+ printf("appropriate comparison). Note: No minimum password");
+ printf(" length restrictions apply, but\n");
+ printf("longer passwords are more secure.\n");
+ } else if (!strcmp(argv[1], "change_admin_password") ||
+ !strcmp(argv[1], "cap")) {
+ printf("Usage: change_admin_password.\n");
+ printf("\n");
+ printf("This command takes no arguments and is used");
+ printf(" to change your private\n");
+ printf("\"Admin\" password. It will first prompt for");
+ printf(" the (current) \"Admin\"\n");
+ printf("password and then ask for the new password");
+ printf(" by prompting:\n");
+ printf("\n");
+ printf("New password for <Your User Name>.admin:\n");
+ printf("\n");
+ printf("Enter the new admin password that you desire");
+ printf(" (it will be asked for\n");
+ printf("twice to avoid errors).\n");
+ } else if (!strcmp(argv[1], "add_new_key") ||
+ !strcmp(argv[1], "ank")) {
+ printf("Usage: add_new_key user_name.\n");
+ printf("\n");
+ printf("user_name is the name of a new user to put");
+ printf(" in the kerberos database. Your\n");
+ printf("\"Admin\" password and the user's password");
+ printf(" are prompted for. The user's\n");
+ printf("password will be asked for");
+ printf(" twice to avoid errors.\n");
+ printf("You are also prompted for the default ticket");
+ printf(" lifetime, attributes\n");
+ printf("and expiration date (see the 'mod_entry' command).\n");
+ } else if (!strcmp(argv[1], "get_entry") ||
+ !strcmp(argv[1], "get")) {
+ printf("Usage: get_entry user_name.\n");
+ printf("\n");
+ printf("user_name is the name of a user whose");
+ printf(" entry you wish to review. Your\n");
+ printf("\"Admin\" password is prompted for. ");
+ printf(" The key field is not filled in, for\n");
+ printf("security reasons.\n");
+ } else if (!strcmp(argv[1], "mod_entry") ||
+ !strcmp(argv[1], "mod")) {
+ printf("Usage: mod_entry user_name.\n");
+ printf("\n");
+ printf("user_name is the name of a user whose");
+ printf(" entry you wish to modify. Your\n");
+ printf("\"Admin\" password is prompted for.");
+ printf(" You will also be prompted for the new\n");
+ printf("default ticket lifetime, attributes");
+ printf(" and expiration date. Attributes may\n");
+ printf("be entered in decimal by default,");
+ printf(" octal if begun with '0', or hexadecimal\n");
+ printf("if begun with '0x'. End the lifetime");
+ printf(" with 'm' to specify minutes, 'h'\n");
+ printf("to specify hours.\n");
+ } else if (!strcmp(argv[1], "destroy_tickets") ||
+ !strcmp(argv[1], "dest")) {
+ printf("Usage: destroy_tickets\n");
+ printf("\n");
+ printf("Destroy your admin tickets. This will");
+ printf(" cause you to be prompted for your\n");
+ printf("admin password on your next request.\n");
+ } else if (!strcmp(argv[1], "list_requests") ||
+ !strcmp(argv[1], "lr") ||
+ !strcmp(argv[1], "?")) {
+ printf("Usage: list_requests\n");
+ printf("\n");
+ printf("This command lists what other commands are");
+ printf(" currently available.\n");
+ } else if (!strcmp(argv[1], "exit") ||
+ !strcmp(argv[1], "quit") ||
+ !strcmp(argv[1], "q")) {
+ printf("Usage: quit\n");
+ printf("\n");
+ printf("This command exits this program.\n");
+ } else {
+ printf("Sorry there is no such command as %s.", argv[1]);
+ printf(" Type \"help\" for more information. \n");
+ }
+ return;
+}
+#if 0
+static void
+go_home(str,x)
+char *str;
+int x;
+{
+ fprintf(stderr, "%s: %s\n", str, error_message(x));
+ clean_up();
+ exit(1);
+}
+#endif
--- /dev/null
+# $Id: kadmin_cmds.ct,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $
+
+#-
+# Copyright 1988 by the Massachusetts Institute of Technology.
+#
+# Permission to use, copy, modify, and distribute this software
+# and its documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice
+# appear in all copies and that both that copyright notice and
+# this permission notice appear in supporting documentation,
+# and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+# used in advertising or publicity pertaining to distribution
+# of the software without specific, written prior permission.
+# M.I.T. and the M.I.T. S.I.P.B. make no representations about
+# the suitability of this software for any purpose. It is
+# provided "as is" without express or implied warranty.
+
+# Command table for Kerberos administration tool
+
+ command_table admin_cmds;
+
+ request change_password,
+ "Change a user's password",
+ change_password, cpw;
+
+ request change_admin_password, "Change your admin password",
+ change_admin_password, cap;
+
+ request add_new_key, "Add new user to kerberos database",
+ add_new_key, ank;
+
+ request get_entry, "Get entry from kerberos database",
+ get_entry, get;
+
+ request mod_entry, "Modify entry in kerberos database",
+ mod_entry, mod;
+
+ request clean_up, "Destroy admin tickets",
+ destroy_tickets, dest;
+
+ request help,"Request help with this program",
+ help;
+
+# list_requests is generic -- unrelated to Kerberos
+
+ request ss_list_requests, "List available requests.",
+ list_requests, lr, "?";
+
+ request quit, "Exit program.",
+ quit, exit, q;
+
+ end;
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $
+
+PROG= kadmind
+SRCS= admin_server.c kadm_funcs.c kadm_ser_wrap.c kadm_server.c
+.if exists(${.CURDIR}/../kadm/obj)
+CFLAGS+=-I${.CURDIR}/../kadm/obj
+.else
+CFLAGS+=-I${.CURDIR}/../kadm
+.endif
+.if exists(${.CURDIR}/../krb/obj)
+CFLAGS+=-I${.CURDIR}/../krb/obj
+.else
+CFLAGS+=-I${.CURDIR}/../krb
+.endif
+.if exists(${.CURDIR}/../ss/obj)
+CFLAGS+=-I${.CURDIR}/../ss/obj
+.else
+CFLAGS+=-I${.CURDIR}/../ss
+.endif
+LDADD+= -lkadm -lkdb -lkrb -ldes -lacl -lcom_err
+DPADD= ${LIBKADM} ${LIBKDB} ${LIBKRB} ${LIBDES} ${LIBACL} ${LIBCOM_ERR}
+MAN= kadmind.8
+BINDIR=/usr/libexec
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $Id: admin_server.c,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Top-level loop of the kerberos Administration server
+ */
+
+/*
+ admin_server.c
+ this holds the main loop and initialization and cleanup code for the server
+*/
+
+#include <kadm_locl.h>
+
+/* Almost all procs and such need this, so it is global */
+admin_params prm; /* The command line parameters struct */
+
+static char prog[32]; /* WHY IS THIS NEEDED??????? */
+char *progname = prog;
+/* GLOBAL */
+char *acldir = DEFAULT_ACL_DIR;
+static char krbrlm[REALM_SZ];
+
+static unsigned pidarraysize = 0;
+static int *pidarray = (int *)0;
+
+static exit_now = 0;
+
+static void
+doexit()
+{
+ exit_now = 1;
+#ifndef sgi /* Sigh -- sgi cc balks at this... */
+ return (void)(0);
+#endif
+}
+
+static void
+do_child()
+{
+ /* SIGCHLD brings us here */
+ int pid;
+ register int i, j;
+
+ int status;
+
+ pid = wait(&status);
+
+ for (i = 0; i < pidarraysize; i++)
+ if (pidarray[i] == pid) {
+ /* found it */
+ for (j = i; j < pidarraysize-1; j++)
+ /* copy others down */
+ pidarray[j] = pidarray[j+1];
+ pidarraysize--;
+ if (WIFEXITED(status) || WIFSIGNALED(status))
+ log("child %d: termsig %d, retcode %d", pid,
+ WTERMSIG(status), WEXITSTATUS(status));
+#ifndef sgi
+ return (void)(0);
+#endif
+ }
+ log("child %d not in list: termsig %d, retcode %d", pid,
+ WTERMSIG(status), WEXITSTATUS(status));
+#ifndef sgi
+ return (void)(0);
+#endif
+}
+
+static int nSIGCHLD = 0;
+
+static void
+count_SIGCHLD()
+{
+ nSIGCHLD++;
+#ifndef sgi
+ return (void)(0);
+#endif
+}
+
+static void
+kill_children(void)
+{
+ int i;
+ void (*ofunc)();
+
+ ofunc = signal(SIGCHLD, count_SIGCHLD);
+
+ for (i = 0; i < pidarraysize; i++) {
+ kill(pidarray[i], SIGINT);
+ log("killing child %d", pidarray[i]);
+ }
+
+ (void) signal(SIGCHLD, ofunc);
+
+ for (; nSIGCHLD != 0; nSIGCHLD--)
+ do_child();
+
+ return;
+}
+
+/* close the system log file */
+static void
+close_syslog(void)
+{
+ log("Shutting down admin server");
+}
+
+static void
+byebye(void) /* say goodnight gracie */
+{
+ printf("Admin Server (kadm server) has completed operation.\n");
+}
+
+static void
+clear_secrets(void)
+{
+ bzero((char *)server_parm.master_key, sizeof(server_parm.master_key));
+ bzero((char *)server_parm.master_key_schedule,
+ sizeof(server_parm.master_key_schedule));
+ server_parm.master_key_version = 0L;
+ return;
+}
+
+#ifdef DEBUG
+#define cleanexit(code) {kerb_fini(); return;}
+#endif
+
+#ifndef DEBUG
+static void
+cleanexit(int val)
+{
+ kerb_fini();
+ clear_secrets();
+ exit(val);
+}
+#endif
+
+static void
+process_client(int fd, struct sockaddr_in *who)
+{
+ u_char *dat;
+ int dat_len;
+ u_short dlen;
+ int retval;
+ int on = 1;
+ Principal service;
+ des_cblock skey;
+ int more;
+ int status;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
+ log("setsockopt keepalive: %d",errno);
+
+ server_parm.recv_addr = *who;
+
+ if (kerb_init()) { /* Open as client */
+ log("can't open krb db");
+ cleanexit(1);
+ }
+ /* need to set service key to changepw.KRB_MASTER */
+
+ status = kerb_get_principal(server_parm.sname, server_parm.sinst, &service,
+ 1, &more);
+ if (status == -1) {
+ /* db locked */
+ u_long retcode = KADM_DB_INUSE;
+ char *pdat;
+
+ dat_len = KADM_VERSIZE + sizeof(u_long);
+ dat = (u_char *) malloc((unsigned)dat_len);
+ pdat = (char *) dat;
+ retcode = htonl((u_long) KADM_DB_INUSE);
+ (void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE);
+ bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_long));
+ goto out;
+ } else if (!status) {
+ log("no service %s.%s",server_parm.sname, server_parm.sinst);
+ cleanexit(2);
+ }
+
+ bcopy((char *)&service.key_low, (char *)skey, 4);
+ bcopy((char *)&service.key_high, (char *)(((long *) skey) + 1), 4);
+ bzero((char *)&service, sizeof(service));
+ kdb_encrypt_key (&skey, &skey, &server_parm.master_key,
+ server_parm.master_key_schedule, DES_DECRYPT);
+ (void) krb_set_key((char *)skey, 0); /* if error, will show up when
+ rd_req fails */
+ bzero((char *)skey, sizeof(skey));
+
+ while (1) {
+ if ((retval = krb_net_read(fd, (char *)&dlen, sizeof(u_short))) !=
+ sizeof(u_short)) {
+ if (retval < 0)
+ log("dlen read: %s",error_message(errno));
+ else if (retval)
+ log("short dlen read: %d",retval);
+ (void) close(fd);
+ cleanexit(retval ? 3 : 0);
+ }
+ if (exit_now) {
+ cleanexit(0);
+ }
+ dat_len = (int) ntohs(dlen);
+ dat = (u_char *) malloc((unsigned)dat_len);
+ if (!dat) {
+ log("malloc: No memory");
+ (void) close(fd);
+ cleanexit(4);
+ }
+ if ((retval = krb_net_read(fd, (char *)dat, dat_len)) != dat_len) {
+ if (retval < 0)
+ log("data read: %s",error_message(errno));
+ else
+ log("short read: %d vs. %d", dat_len, retval);
+ (void) close(fd);
+ cleanexit(5);
+ }
+ if (exit_now) {
+ cleanexit(0);
+ }
+ if ((retval = kadm_ser_in(&dat,&dat_len)) != KADM_SUCCESS)
+ log("processing request: %s", error_message(retval));
+
+ /* kadm_ser_in did the processing and returned stuff in
+ dat & dat_len , return the appropriate data */
+
+ out:
+ dlen = (u_short) dat_len;
+
+ if (dat_len != (int)dlen) {
+ clear_secrets();
+ abort(); /* XXX */
+ }
+ dlen = htons(dlen);
+
+ if (krb_net_write(fd, (char *)&dlen, sizeof(u_short)) < 0) {
+ log("writing dlen to client: %s",error_message(errno));
+ (void) close(fd);
+ cleanexit(6);
+ }
+
+ if (krb_net_write(fd, (char *)dat, dat_len) < 0) {
+ log(LOG_ERR, "writing to client: %s",error_message(errno));
+ (void) close(fd);
+ cleanexit(7);
+ }
+ free((char *)dat);
+ }
+ /*NOTREACHED*/
+}
+
+/*
+kadm_listen
+listen on the admin servers port for a request
+*/
+static int
+kadm_listen(void)
+{
+ int found;
+ int admin_fd;
+ int peer_fd;
+ fd_set mask, readfds;
+ struct sockaddr_in peer;
+ int addrlen;
+ int pid;
+
+ (void) signal(SIGINT, doexit);
+ (void) signal(SIGTERM, doexit);
+ (void) signal(SIGHUP, doexit);
+ (void) signal(SIGQUIT, doexit);
+ (void) signal(SIGPIPE, SIG_IGN); /* get errors on write() */
+ (void) signal(SIGALRM, doexit);
+ (void) signal(SIGCHLD, do_child);
+
+ if ((admin_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ return KADM_NO_SOCK;
+ if (bind(admin_fd, (struct sockaddr *)&server_parm.admin_addr,
+ sizeof(struct sockaddr_in)) < 0)
+ return KADM_NO_BIND;
+ (void) listen(admin_fd, 1);
+ FD_ZERO(&mask);
+ FD_SET(admin_fd, &mask);
+
+ for (;;) { /* loop nearly forever */
+ if (exit_now) {
+ clear_secrets();
+ kill_children();
+ return(0);
+ }
+ readfds = mask;
+ if ((found = select(admin_fd+1,&readfds,(fd_set *)0,
+ (fd_set *)0, (struct timeval *)0)) == 0)
+ continue; /* no things read */
+ if (found < 0) {
+ if (errno != EINTR)
+ log("select: %s",error_message(errno));
+ continue;
+ }
+ if (FD_ISSET(admin_fd, &readfds)) {
+ /* accept the conn */
+ addrlen = sizeof(peer);
+ if ((peer_fd = accept(admin_fd, (struct sockaddr *)&peer,
+ &addrlen)) < 0) {
+ log("accept: %s",error_message(errno));
+ continue;
+ }
+#ifndef DEBUG
+ /* if you want a sep daemon for each server */
+ if ((pid = fork())) {
+ /* parent */
+ if (pid < 0) {
+ log("fork: %s",error_message(errno));
+ (void) close(peer_fd);
+ continue;
+ }
+ /* fork succeded: keep tabs on child */
+ (void) close(peer_fd);
+ if (pidarray) {
+ pidarray = (int *)realloc((char *)pidarray, ++pidarraysize);
+ pidarray[pidarraysize-1] = pid;
+ } else {
+ pidarray = (int *)malloc(pidarraysize = 1);
+ pidarray[0] = pid;
+ }
+ } else {
+ /* child */
+ (void) close(admin_fd);
+#endif /* DEBUG */
+ /* do stuff */
+ process_client (peer_fd, &peer);
+#ifndef DEBUG
+ }
+#endif
+ } else {
+ log("something else woke me up!");
+ return(0);
+ }
+ }
+ /*NOTREACHED*/
+}
+
+/*
+** Main does the logical thing, it sets up the database and RPC interface,
+** as well as handling the creation and maintenance of the syslog file...
+*/
+int
+main(int argc, char **argv) /* admin_server main routine */
+
+
+{
+ int errval;
+ int c;
+
+ prog[sizeof(prog)-1]='\0'; /* Terminate... */
+ (void) strncpy(prog, argv[0], sizeof(prog)-1);
+
+ /* initialize the admin_params structure */
+ prm.sysfile = KADM_SYSLOG; /* default file name */
+ prm.inter = 1;
+
+ bzero(krbrlm, sizeof(krbrlm));
+
+ while ((c = getopt(argc, argv, "f:hnd:a:r:")) != EOF)
+ switch(c) {
+ case 'f': /* Syslog file name change */
+ prm.sysfile = optarg;
+ break;
+ case 'n':
+ prm.inter = 0;
+ break;
+ case 'a': /* new acl directory */
+ acldir = optarg;
+ break;
+ case 'd':
+ /* put code to deal with alt database place */
+ if ((errval = kerb_db_set_name(optarg))) {
+ fprintf(stderr, "opening database %s: %s",
+ optarg, error_message(errval));
+ exit(1);
+ }
+ break;
+ case 'r':
+ (void) strncpy(krbrlm, optarg, sizeof(krbrlm) - 1);
+ break;
+ case 'h': /* get help on using admin_server */
+ default:
+ printf("Usage: admin_server [-h] [-n] [-r realm] [-d dbname] [-f filename] [-a acldir]\n");
+ exit(-1); /* failure */
+ }
+
+ if (krbrlm[0] == 0)
+ if (krb_get_lrealm(krbrlm, 0) != KSUCCESS) {
+ fprintf(stderr,
+ "Unable to get local realm. Fix krb.conf or use -r.\n");
+ exit(1);
+ }
+
+ printf("KADM Server %s initializing\n",KADM_VERSTR);
+ printf("Please do not use 'kill -9' to kill this job, use a\n");
+ printf("regular kill instead\n\n");
+
+ set_logfile(prm.sysfile);
+ log("Admin server starting");
+
+ (void) kerb_db_set_lockmode(KERB_DBL_NONBLOCKING);
+ errval = kerb_init(); /* Open the Kerberos database */
+ if (errval) {
+ fprintf(stderr, "error: kerb_init() failed");
+ close_syslog();
+ byebye();
+ }
+ /* set up the server_parm struct */
+ if ((errval = kadm_ser_init(prm.inter, krbrlm))==KADM_SUCCESS) {
+ kerb_fini(); /* Close the Kerberos database--
+ will re-open later */
+ errval = kadm_listen(); /* listen for calls to server from
+ clients */
+ }
+ if (errval != KADM_SUCCESS) {
+ fprintf(stderr,"error: %s\n",error_message(errval));
+ kerb_fini(); /* Close if error */
+ }
+ close_syslog(); /* Close syslog file, print
+ closing note */
+ byebye(); /* Say bye bye on the terminal
+ in use */
+ exit(1);
+} /* procedure main */
--- /dev/null
+/* $Id: kadm_funcs.c,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Kerberos administration server-side database manipulation routines
+ */
+
+/*
+kadm_funcs.c
+the actual database manipulation code
+*/
+
+#include <kadm_locl.h>
+#include <sys/param.h>
+
+static int
+check_access(char *pname, char *pinst, char *prealm, enum acl_types acltype)
+{
+ char checkname[MAX_K_NAME_SZ];
+ char filename[MAXPATHLEN];
+
+ (void) sprintf(checkname, "%s.%s@%s", pname, pinst, prealm);
+
+ switch (acltype) {
+ case ADDACL:
+ (void) sprintf(filename, "%s%s", acldir, ADD_ACL_FILE);
+ break;
+ case GETACL:
+ (void) sprintf(filename, "%s%s", acldir, GET_ACL_FILE);
+ break;
+ case MODACL:
+ (void) sprintf(filename, "%s%s", acldir, MOD_ACL_FILE);
+ break;
+ }
+ return(acl_check(filename, checkname));
+}
+
+static int
+wildcard(char *str)
+{
+ if (!strcmp(str, WILDCARD_STR))
+ return(1);
+ return(0);
+}
+
+#define failadd(code) { (void) log("FAILED addding '%s.%s' (%s)", valsin->name, valsin->instance, error_message(code)); return code; }
+
+int
+kadm_add_entry (char *rname, char *rinstance, char *rrealm, Kadm_vals *valsin, Kadm_vals *valsout)
+ /* requestors name */
+ /* requestors instance */
+ /* requestors realm */
+
+
+{
+ long numfound; /* check how many we get written */
+ int more; /* pointer to more grabbed records */
+ Principal data_i, data_o; /* temporary principal */
+ u_char flags[4];
+ des_cblock newpw;
+ Principal default_princ;
+
+ if (!check_access(rname, rinstance, rrealm, ADDACL)) {
+ (void) log("WARNING: '%s.%s@%s' tried to add an entry for '%s.%s'",
+ rname, rinstance, rrealm, valsin->name, valsin->instance);
+ return KADM_UNAUTH;
+ }
+
+ /* Need to check here for "legal" name and instance */
+ if (wildcard(valsin->name) || wildcard(valsin->instance)) {
+ failadd(KADM_ILL_WILDCARD);
+ }
+
+ (void) log("request to add an entry for '%s.%s' from '%s.%s@%s'",
+ valsin->name, valsin->instance, rname, rinstance, rrealm);
+
+ numfound = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
+ &default_princ, 1, &more);
+ if (numfound == -1) {
+ failadd(KADM_DB_INUSE);
+ } else if (numfound != 1) {
+ failadd(KADM_UK_RERROR);
+ }
+
+ kadm_vals_to_prin(valsin->fields, &data_i, valsin);
+ (void) strncpy(data_i.name, valsin->name, ANAME_SZ);
+ (void) strncpy(data_i.instance, valsin->instance, INST_SZ);
+
+ if (!IS_FIELD(KADM_EXPDATE,valsin->fields))
+ data_i.exp_date = default_princ.exp_date;
+ if (!IS_FIELD(KADM_ATTR,valsin->fields))
+ data_i.attributes = default_princ.attributes;
+ if (!IS_FIELD(KADM_MAXLIFE,valsin->fields))
+ data_i.max_life = default_princ.max_life;
+
+ bzero((char *)&default_princ, sizeof(default_princ));
+
+ /* convert to host order */
+ data_i.key_low = ntohl(data_i.key_low);
+ data_i.key_high = ntohl(data_i.key_high);
+
+
+ bcopy(&data_i.key_low,newpw,4);
+ bcopy(&data_i.key_high,(char *)(((long *) newpw) + 1),4);
+
+ /* encrypt new key in master key */
+ kdb_encrypt_key (&newpw, &newpw, &server_parm.master_key,
+ server_parm.master_key_schedule, DES_ENCRYPT);
+ bcopy(newpw,&data_i.key_low,4);
+ bcopy((char *)(((long *) newpw) + 1), &data_i.key_high,4);
+ bzero((char *)newpw, sizeof(newpw));
+
+ data_o = data_i;
+ numfound = kerb_get_principal(valsin->name, valsin->instance,
+ &data_o, 1, &more);
+ if (numfound == -1) {
+ failadd(KADM_DB_INUSE);
+ } else if (numfound) {
+ failadd(KADM_INUSE);
+ } else {
+ data_i.key_version++;
+ data_i.kdc_key_ver = server_parm.master_key_version;
+ (void) strncpy(data_i.mod_name, rname, sizeof(data_i.mod_name)-1);
+ (void) strncpy(data_i.mod_instance, rinstance,
+ sizeof(data_i.mod_instance)-1);
+
+ numfound = kerb_put_principal(&data_i, 1);
+ if (numfound == -1) {
+ failadd(KADM_DB_INUSE);
+ } else if (numfound) {
+ failadd(KADM_UK_SERROR);
+ } else {
+ numfound = kerb_get_principal(valsin->name, valsin->instance,
+ &data_o, 1, &more);
+ if ((numfound!=1) || (more!=0)) {
+ failadd(KADM_UK_RERROR);
+ }
+ bzero((char *)flags, sizeof(flags));
+ SET_FIELD(KADM_NAME,flags);
+ SET_FIELD(KADM_INST,flags);
+ SET_FIELD(KADM_EXPDATE,flags);
+ SET_FIELD(KADM_ATTR,flags);
+ SET_FIELD(KADM_MAXLIFE,flags);
+ kadm_prin_to_vals(flags, valsout, &data_o);
+ (void) log("'%s.%s' added.", valsin->name, valsin->instance);
+ return KADM_DATA; /* Set all the appropriate fields */
+ }
+ }
+}
+#undef failadd
+
+#define failget(code) { (void) log("FAILED retrieving '%s.%s' (%s)", valsin->name, valsin->instance, error_message(code)); return code; }
+
+int
+kadm_get_entry (char *rname, char *rinstance, char *rrealm, Kadm_vals *valsin, u_char *flags, Kadm_vals *valsout)
+ /* requestors name */
+ /* requestors instance */
+ /* requestors realm */
+ /* what they wannt to get */
+ /* which fields we want */
+ /* what data is there */
+{
+ long numfound; /* check how many were returned */
+ int more; /* To point to more name.instances */
+ Principal data_o; /* Data object to hold Principal */
+
+
+ if (!check_access(rname, rinstance, rrealm, GETACL)) {
+ (void) log("WARNING: '%s.%s@%s' tried to get '%s.%s's entry",
+ rname, rinstance, rrealm, valsin->name, valsin->instance);
+ return KADM_UNAUTH;
+ }
+
+ if (wildcard(valsin->name) || wildcard(valsin->instance)) {
+ failget(KADM_ILL_WILDCARD);
+ }
+
+ (void) log("retrieve '%s.%s's entry for '%s.%s@%s'",
+ valsin->name, valsin->instance, rname, rinstance, rrealm);
+
+ /* Look up the record in the database */
+ numfound = kerb_get_principal(valsin->name, valsin->instance,
+ &data_o, 1, &more);
+ if (numfound == -1) {
+ failget(KADM_DB_INUSE);
+ } else if (numfound) { /* We got the record, let's return it */
+ kadm_prin_to_vals(flags, valsout, &data_o);
+ (void) log("'%s.%s' retrieved.", valsin->name, valsin->instance);
+ return KADM_DATA; /* Set all the appropriate fields */
+ } else {
+ failget(KADM_NOENTRY); /* Else whimper and moan */
+ }
+}
+#undef failget
+
+#define failmod(code) { (void) log("FAILED modifying '%s.%s' (%s)", valsin1->name, valsin1->instance, error_message(code)); return code; }
+
+int
+kadm_mod_entry (char *rname, char *rinstance, char *rrealm, Kadm_vals *valsin1, Kadm_vals *valsin2, Kadm_vals *valsout)
+ /* requestors name */
+ /* requestors instance */
+ /* requestors realm */
+ /* holds the parameters being
+ passed in */
+ /* the actual record which is returned */
+{
+ long numfound;
+ int more;
+ Principal data_o, temp_key;
+ u_char fields[4];
+ des_cblock newpw;
+
+ if (wildcard(valsin1->name) || wildcard(valsin1->instance)) {
+ failmod(KADM_ILL_WILDCARD);
+ }
+
+ if (!check_access(rname, rinstance, rrealm, MODACL)) {
+ (void) log("WARNING: '%s.%s@%s' tried to change '%s.%s's entry",
+ rname, rinstance, rrealm, valsin1->name, valsin1->instance);
+ return KADM_UNAUTH;
+ }
+
+ (void) log("request to modify '%s.%s's entry from '%s.%s@%s' ",
+ valsin1->name, valsin1->instance, rname, rinstance, rrealm);
+
+ numfound = kerb_get_principal(valsin1->name, valsin1->instance,
+ &data_o, 1, &more);
+ if (numfound == -1) {
+ failmod(KADM_DB_INUSE);
+ } else if (numfound) {
+ kadm_vals_to_prin(valsin2->fields, &temp_key, valsin2);
+ (void) strncpy(data_o.name, valsin1->name, ANAME_SZ);
+ (void) strncpy(data_o.instance, valsin1->instance, INST_SZ);
+ if (IS_FIELD(KADM_EXPDATE,valsin2->fields))
+ data_o.exp_date = temp_key.exp_date;
+ if (IS_FIELD(KADM_ATTR,valsin2->fields))
+ data_o.attributes = temp_key.attributes;
+ if (IS_FIELD(KADM_MAXLIFE,valsin2->fields))
+ data_o.max_life = temp_key.max_life;
+ if (IS_FIELD(KADM_DESKEY,valsin2->fields)) {
+ data_o.key_version++;
+ data_o.kdc_key_ver = server_parm.master_key_version;
+
+
+ /* convert to host order */
+ temp_key.key_low = ntohl(temp_key.key_low);
+ temp_key.key_high = ntohl(temp_key.key_high);
+
+
+ bcopy(&temp_key.key_low,newpw,4);
+ bcopy(&temp_key.key_high,(char *)(((long *) newpw) + 1),4);
+
+ /* encrypt new key in master key */
+ kdb_encrypt_key (&newpw, &newpw, &server_parm.master_key,
+ server_parm.master_key_schedule, DES_ENCRYPT);
+ bcopy(newpw,&data_o.key_low,4);
+ bcopy((char *)(((long *) newpw) + 1), &data_o.key_high,4);
+ bzero((char *)newpw, sizeof(newpw));
+ }
+ bzero((char *)&temp_key, sizeof(temp_key));
+
+ (void) strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1);
+ (void) strncpy(data_o.mod_instance, rinstance,
+ sizeof(data_o.mod_instance)-1);
+ more = kerb_put_principal(&data_o, 1);
+
+ bzero((char *)&data_o, sizeof(data_o));
+
+ if (more == -1) {
+ failmod(KADM_DB_INUSE);
+ } else if (more) {
+ failmod(KADM_UK_SERROR);
+ } else {
+ numfound = kerb_get_principal(valsin1->name, valsin1->instance,
+ &data_o, 1, &more);
+ if ((more!=0)||(numfound!=1)) {
+ failmod(KADM_UK_RERROR);
+ }
+ bzero((char *) fields, sizeof(fields));
+ SET_FIELD(KADM_NAME,fields);
+ SET_FIELD(KADM_INST,fields);
+ SET_FIELD(KADM_EXPDATE,fields);
+ SET_FIELD(KADM_ATTR,fields);
+ SET_FIELD(KADM_MAXLIFE,fields);
+ kadm_prin_to_vals(fields, valsout, &data_o);
+ (void) log("'%s.%s' modified.", valsin1->name, valsin1->instance);
+ return KADM_DATA; /* Set all the appropriate fields */
+ }
+ }
+ else {
+ failmod(KADM_NOENTRY);
+ }
+}
+#undef failmod
+
+#define failchange(code) { (void) log("FAILED changing key for '%s.%s@%s' (%s)", rname, rinstance, rrealm, error_message(code)); return code; }
+
+int
+kadm_change (char *rname, char *rinstance, char *rrealm, unsigned char *newpw)
+{
+ long numfound;
+ int more;
+ Principal data_o;
+ des_cblock local_pw;
+
+ if (strcmp(server_parm.krbrlm, rrealm)) {
+ (void) log("change key request from wrong realm, '%s.%s@%s'!\n",
+ rname, rinstance, rrealm);
+ return(KADM_WRONG_REALM);
+ }
+
+ if (wildcard(rname) || wildcard(rinstance)) {
+ failchange(KADM_ILL_WILDCARD);
+ }
+ (void) log("'%s.%s@%s' wants to change its password",
+ rname, rinstance, rrealm);
+
+ bcopy(newpw, local_pw, sizeof(local_pw));
+
+ /* encrypt new key in master key */
+ kdb_encrypt_key (&local_pw, &local_pw, &server_parm.master_key,
+ server_parm.master_key_schedule, DES_ENCRYPT);
+
+ numfound = kerb_get_principal(rname, rinstance,
+ &data_o, 1, &more);
+ if (numfound == -1) {
+ failchange(KADM_DB_INUSE);
+ } else if (numfound) {
+ bcopy(local_pw,&data_o.key_low,4);
+ bcopy((char *)(((long *) local_pw) + 1), &data_o.key_high,4);
+ data_o.key_version++;
+ data_o.kdc_key_ver = server_parm.master_key_version;
+ (void) strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1);
+ (void) strncpy(data_o.mod_instance, rinstance,
+ sizeof(data_o.mod_instance)-1);
+ more = kerb_put_principal(&data_o, 1);
+ bzero((char *) local_pw, sizeof(local_pw));
+ bzero((char *) &data_o, sizeof(data_o));
+ if (more == -1) {
+ failchange(KADM_DB_INUSE);
+ } else if (more) {
+ failchange(KADM_UK_SERROR);
+ } else {
+ (void) log("'%s.%s@%s' password changed.", rname, rinstance, rrealm);
+ return KADM_SUCCESS;
+ }
+ }
+ else {
+ failchange(KADM_NOENTRY);
+ }
+}
+#undef failchange
--- /dev/null
+/* $Id: kadm_ser_wrap.c,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Kerberos administration server-side support functions
+ */
+
+/*
+kadm_ser_wrap.c
+unwraps wrapped packets and calls the appropriate server subroutine
+*/
+
+#include <kadm_locl.h>
+#include <sys/param.h>
+
+/* GLOBAL */
+Kadm_Server server_parm;
+
+/*
+kadm_ser_init
+set up the server_parm structure
+*/
+int
+kadm_ser_init(int inter, char *realm)
+ /* interactive or from file */
+
+{
+ struct servent *sep;
+ struct hostent *hp;
+ char hostname[MAXHOSTNAMELEN];
+
+ (void) init_kadm_err_tbl();
+ (void) init_krb_err_tbl();
+ if (gethostname(hostname, sizeof(hostname)))
+ return KADM_NO_HOSTNAME;
+
+ (void) strcpy(server_parm.sname, PWSERV_NAME);
+ (void) strcpy(server_parm.sinst, KRB_MASTER);
+ (void) strcpy(server_parm.krbrlm, realm);
+
+ server_parm.admin_fd = -1;
+ /* setting up the addrs */
+ if ((sep = getservbyname(KADM_SNAME, "tcp")) == NULL)
+ return KADM_NO_SERV;
+ bzero((char *)&server_parm.admin_addr,sizeof(server_parm.admin_addr));
+ server_parm.admin_addr.sin_family = AF_INET;
+ if ((hp = gethostbyname(hostname)) == NULL)
+ return KADM_NO_HOSTNAME;
+ bcopy(hp->h_addr, (char *) &server_parm.admin_addr.sin_addr.s_addr,
+ hp->h_length);
+ server_parm.admin_addr.sin_port = sep->s_port;
+ /* setting up the database */
+ if (kdb_get_master_key((inter==1), &server_parm.master_key,
+ server_parm.master_key_schedule) != 0)
+ return KADM_NO_MAST;
+ if ((server_parm.master_key_version =
+ kdb_verify_master_key(&server_parm.master_key,
+ server_parm.master_key_schedule,stderr))<0)
+ return KADM_NO_VERI;
+ return KADM_SUCCESS;
+}
+
+static void errpkt(u_char **dat, int *dat_len, int code)
+{
+ u_int32_t retcode;
+ char *pdat;
+
+ free((char *)*dat); /* free up req */
+ *dat_len = KADM_VERSIZE + sizeof(u_int32_t);
+ *dat = (u_char *) malloc((unsigned)*dat_len);
+ pdat = (char *) *dat;
+ retcode = htonl((u_int32_t) code);
+ (void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE);
+ bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_int32_t));
+ return;
+}
+
+/*
+kadm_ser_in
+unwrap the data stored in dat, process, and return it.
+*/
+int
+kadm_ser_in(u_char **dat, int *dat_len)
+{
+ u_char *in_st; /* pointer into the sent packet */
+ int in_len,retc; /* where in packet we are, for
+ returns */
+ u_int32_t r_len; /* length of the actual packet */
+ KTEXT_ST authent; /* the authenticator */
+ AUTH_DAT ad; /* who is this, klink */
+ u_int32_t ncksum; /* checksum of encrypted data */
+ des_key_schedule sess_sched; /* our schedule */
+ MSG_DAT msg_st;
+ u_char *retdat, *tmpdat;
+ int retval, retlen;
+
+ if (strncmp(KADM_VERSTR, (char *)*dat, KADM_VERSIZE)) {
+ errpkt(dat, dat_len, KADM_BAD_VER);
+ return KADM_BAD_VER;
+ }
+ in_len = KADM_VERSIZE;
+ /* get the length */
+ if ((retc = stv_long(*dat, &r_len, in_len, *dat_len)) < 0)
+ return KADM_LENGTH_ERROR;
+ in_len += retc;
+ authent.length = *dat_len - r_len - KADM_VERSIZE - sizeof(u_int32_t);
+ bcopy((char *)(*dat) + in_len, (char *)authent.dat, authent.length);
+ authent.mbz = 0;
+ /* service key should be set before here */
+ if ((retc = krb_rd_req(&authent, server_parm.sname, server_parm.sinst,
+ server_parm.recv_addr.sin_addr.s_addr, &ad, (char *)0)))
+ {
+ errpkt(dat, dat_len,retc + krb_err_base);
+ return retc + krb_err_base;
+ }
+
+#define clr_cli_secrets() {bzero((char *)sess_sched, sizeof(sess_sched)); bzero((char *)ad.session, sizeof(ad.session));}
+
+ in_st = *dat + *dat_len - r_len;
+#ifdef NOENCRYPTION
+ ncksum = 0;
+#else
+ ncksum = des_quad_cksum((des_cblock *)in_st, (des_cblock *)0, (long) r_len, 0, &ad.session);
+#endif
+ if (ncksum!=ad.checksum) { /* yow, are we correct yet */
+ clr_cli_secrets();
+ errpkt(dat, dat_len,KADM_BAD_CHK);
+ return KADM_BAD_CHK;
+ }
+#ifdef NOENCRYPTION
+ bzero(sess_sched, sizeof(sess_sched));
+#else
+ des_key_sched(&ad.session, sess_sched);
+#endif
+ if ((retc = (int) krb_rd_priv(in_st, r_len, sess_sched, &ad.session,
+ &server_parm.recv_addr,
+ &server_parm.admin_addr, &msg_st))) {
+ clr_cli_secrets();
+ errpkt(dat, dat_len,retc + krb_err_base);
+ return retc + krb_err_base;
+ }
+ switch (msg_st.app_data[0]) {
+ case CHANGE_PW:
+ retval = kadm_ser_cpw(msg_st.app_data+1,(int) msg_st.app_length,&ad,
+ &retdat, &retlen);
+ break;
+ case ADD_ENT:
+ retval = kadm_ser_add(msg_st.app_data+1,(int) msg_st.app_length,&ad,
+ &retdat, &retlen);
+ break;
+ case GET_ENT:
+ retval = kadm_ser_get(msg_st.app_data+1,(int) msg_st.app_length,&ad,
+ &retdat, &retlen);
+ break;
+ case MOD_ENT:
+ retval = kadm_ser_mod(msg_st.app_data+1,(int) msg_st.app_length,&ad,
+ &retdat, &retlen);
+ break;
+ default:
+ clr_cli_secrets();
+ errpkt(dat, dat_len, KADM_NO_OPCODE);
+ return KADM_NO_OPCODE;
+ }
+ /* Now seal the response back into a priv msg */
+ free((char *)*dat);
+ tmpdat = (u_char *) malloc((unsigned)(retlen + KADM_VERSIZE +
+ sizeof(u_int32_t)));
+ (void) strncpy((char *)tmpdat, KADM_VERSTR, KADM_VERSIZE);
+ retval = htonl((u_int32_t)retval);
+ bcopy((char *)&retval, (char *)tmpdat + KADM_VERSIZE, sizeof(u_int32_t));
+ if (retlen) {
+ bcopy((char *)retdat, (char *)tmpdat + KADM_VERSIZE + sizeof(u_int32_t),
+ retlen);
+ free((char *)retdat);
+ }
+ /* slop for mk_priv stuff */
+ *dat = (u_char *) malloc((unsigned) (retlen + KADM_VERSIZE +
+ sizeof(u_int32_t) + 200));
+ if ((*dat_len = krb_mk_priv(tmpdat, *dat,
+ (u_int32_t) (retlen + KADM_VERSIZE +
+ sizeof(u_int32_t)),
+ sess_sched,
+ &ad.session, &server_parm.admin_addr,
+ &server_parm.recv_addr)) < 0) {
+ clr_cli_secrets();
+ errpkt(dat, dat_len, KADM_NO_ENCRYPT);
+ return KADM_NO_ENCRYPT;
+ }
+ clr_cli_secrets();
+ return KADM_SUCCESS;
+}
--- /dev/null
+/* $Id: kadm_server.c,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Kerberos administration server-side subroutines
+ */
+
+#include <kadm_locl.h>
+
+/*
+kadm_ser_cpw - the server side of the change_password routine
+ recieves : KTEXT, {key}
+ returns : CKSUM, RETCODE
+ acl : caller can change only own password
+
+Replaces the password (i.e. des key) of the caller with that specified in key.
+Returns no actual data from the master server, since this is called by a user
+*/
+int
+kadm_ser_cpw(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, int *outlen)
+{
+ u_int32_t keylow, keyhigh;
+ des_cblock newkey;
+ int stvlen;
+
+ /* take key off the stream, and change the database */
+
+ if ((stvlen = stv_long(dat, &keyhigh, 0, len)) < 0)
+ return(KADM_LENGTH_ERROR);
+ if (stv_long(dat, &keylow, stvlen, len) < 0)
+ return(KADM_LENGTH_ERROR);
+
+ keylow = ntohl(keylow);
+ keyhigh = ntohl(keyhigh);
+ bcopy((char *)&keyhigh, (char *)(((int32_t *)newkey) + 1), 4);
+ bcopy((char *)&keylow, (char *)newkey, 4);
+ *datout = 0;
+ *outlen = 0;
+
+ return(kadm_change(ad->pname, ad->pinst, ad->prealm, newkey));
+}
+
+/*
+kadm_ser_add - the server side of the add_entry routine
+ recieves : KTEXT, {values}
+ returns : CKSUM, RETCODE, {values}
+ acl : su, sms (as alloc)
+
+Adds and entry containing values to the database
+returns the values of the entry, so if you leave certain fields blank you will
+ be able to determine the default values they are set to
+*/
+int
+kadm_ser_add(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, int *outlen)
+{
+ Kadm_vals values, retvals;
+ long status;
+
+ if ((status = stream_to_vals(dat, &values, len)) < 0)
+ return(KADM_LENGTH_ERROR);
+ if ((status = kadm_add_entry(ad->pname, ad->pinst, ad->prealm,
+ &values, &retvals)) == KADM_DATA) {
+ *outlen = vals_to_stream(&retvals,datout);
+ return KADM_SUCCESS;
+ } else {
+ *outlen = 0;
+ return status;
+ }
+}
+
+/*
+kadm_ser_mod - the server side of the mod_entry routine
+ recieves : KTEXT, {values, values}
+ returns : CKSUM, RETCODE, {values}
+ acl : su, sms (as register or dealloc)
+
+Modifies all entries corresponding to the first values so they match the
+ second values.
+returns the values for the changed entries
+*/
+int
+kadm_ser_mod(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, int *outlen)
+{
+ Kadm_vals vals1, vals2, retvals;
+ int wh;
+ long status;
+
+ if ((wh = stream_to_vals(dat, &vals1, len)) < 0)
+ return KADM_LENGTH_ERROR;
+ if ((status = stream_to_vals(dat+wh,&vals2, len-wh)) < 0)
+ return KADM_LENGTH_ERROR;
+ if ((status = kadm_mod_entry(ad->pname, ad->pinst, ad->prealm, &vals1,
+ &vals2, &retvals)) == KADM_DATA) {
+ *outlen = vals_to_stream(&retvals,datout);
+ return KADM_SUCCESS;
+ } else {
+ *outlen = 0;
+ return status;
+ }
+}
+
+/*
+kadm_ser_get
+ recieves : KTEXT, {values, flags}
+ returns : CKSUM, RETCODE, {count, values, values, values}
+ acl : su
+
+gets the fields requested by flags from all entries matching values
+returns this data for each matching recipient, after a count of how many such
+ matches there were
+*/
+int
+kadm_ser_get(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, int *outlen)
+{
+ Kadm_vals values, retvals;
+ u_char fl[FLDSZ];
+ int loop,wh;
+ long status;
+
+ if ((wh = stream_to_vals(dat, &values, len)) < 0)
+ return KADM_LENGTH_ERROR;
+ if (wh + FLDSZ > len)
+ return KADM_LENGTH_ERROR;
+ for (loop=FLDSZ-1; loop>=0; loop--)
+ fl[loop] = dat[wh++];
+ if ((status = kadm_get_entry(ad->pname, ad->pinst, ad->prealm,
+ &values, fl, &retvals)) == KADM_DATA) {
+ *outlen = vals_to_stream(&retvals,datout);
+ return KADM_SUCCESS;
+ } else {
+ *outlen = 0;
+ return status;
+ }
+}
+
--- /dev/null
+.\" Copyright 1987, 1988, 1989 by the Student Information Processing Board
+.\" of the Massachusetts Institute of Technology
+.\"
+.\" Permission to use, copy, modify, and distribute this software
+.\" and its documentation for any purpose and without fee is
+.\" hereby granted, provided that the above copyright notice
+.\" appear in all copies and that both that copyright notice and
+.\" this permission notice appear in supporting documentation,
+.\" and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+.\" used in advertising or publicity pertaining to distribution
+.\" of the software without specific, written prior permission.
+.\" M.I.T. and the M.I.T. S.I.P.B. make no representations about
+.\" the suitability of this software for any purpose. It is
+.\" provided "as is" without express or implied warranty.
+.\"
+.\" $Id: kadmind.8,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $
+.TH KADMIND 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kadmind \- Kerberos database administration daemon
+.SH SYNOPSIS
+.B kadmind
+[
+.B \-n
+] [
+.B \-h
+] [
+.B \-r realm
+] [
+.B \-f filename
+] [
+.B \-d dbname
+] [
+.B \-a acldir
+]
+.SH DESCRIPTION
+.I kadmind
+is the network database server for the Kerberos password-changing and
+administration tools.
+.PP
+Upon execution, it prompts the user to enter the master key string for
+the database.
+.PP
+If the
+.B \-n
+option is specified, the master key is instead fetched from the master
+key cache file.
+.PP
+If the
+.B \-r
+.I realm
+option is specified, the admin server will pretend that its
+local realm is
+.I realm
+instead of the actual local realm of the host it is running on.
+This makes it possible to run a server for a foreign kerberos
+realm.
+.PP
+If the
+.B \-f
+.I filename
+option is specified, then that file is used to hold the log information
+instead of the default.
+.PP
+If the
+.B \-d
+.I dbname
+option is specified, then that file is used as the database name instead
+of the default.
+.PP
+If the
+.B \-a
+.I acldir
+option is specified, then
+.I acldir
+is used as the directory in which to search for access control lists
+instead of the default.
+.PP
+If the
+.B \-h
+option is specified,
+.I kadmind
+prints out a short summary of the permissible control arguments, and
+then exits.
+.PP
+When performing requests on behalf of clients,
+.I kadmind
+checks access control lists (ACLs) to determine the authorization of the client
+to perform the requested action.
+Currently three distinct access types are supported:
+.TP 1i
+Addition
+(.add ACL file). If a principal is on this list, it may add new
+principals to the database.
+.TP
+Retrieval
+(.get ACL file). If a principal is on this list, it may retrieve
+database entries. NOTE: A principal's private key is never returned by
+the get functions.
+.TP
+Modification
+(.mod ACL file). If a principal is on this list, it may modify entries
+in the database.
+.PP
+A principal is always granted authorization to change its own password.
+.SH FILES
+.TP 20n
+/kerberos/admin_server.syslog
+Default log file.
+.TP
+/kerberos
+Default access control list directory.
+.TP
+admin_acl.{add,get,mod}
+Access control list files (within the directory)
+.TP
+/kerberos/principal.pag, /kerberos/principal.dir
+Default DBM files containing database
+.TP
+/.k
+Master key cache file.
+.SH "SEE ALSO"
+kerberos(1), kpasswd(1), kadmin(8), acl_check(3)
+.SH AUTHORS
+Douglas A. Church, MIT Project Athena
+.br
+John T. Kohl, Project Athena/Digital Equipment Corporation
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:46 tholo Exp $
+
+LIB= kafs
+SRCS= afssys.c
+
+.include <bsd.lib.mk>
--- /dev/null
+/* $Id: afssys.c,v 1.1.1.1 1995/12/14 06:52:46 tholo Exp $ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+
+#include <kerberosIV/krb.h>
+#include <kerberosIV/kafs.h>
+
+#include "afssysdefs.h"
+
+#define AUTH_SUPERUSER "afs"
+
+/*
+ * Here only ASCII characters are relevant.
+ */
+
+#define IsAsciiUpper(c) ('A' <= (c) && (c) <= 'Z')
+
+#define ToAsciiLower(c) ((c) - 'A' + 'a')
+
+static void
+folddown(a, b)
+ char *a, *b;
+{
+ for (; *b; a++, b++)
+ if (IsAsciiUpper(*b))
+ *a = ToAsciiLower(*b);
+ else
+ *a = *b;
+ *a = '\0';
+}
+
+#if !defined(linux) /* won't work there -- no SIGSYS, no syscall */
+
+int
+k_afsklog(realm)
+ char *realm;
+{
+ int k_errno;
+ CREDENTIALS c;
+ KTEXT_ST ticket;
+ char username[256];
+ char krealm[REALM_SZ];
+
+ if (!k_hasafs())
+ return KSUCCESS;
+
+ if (realm == 0 || realm[0] == 0)
+ {
+ k_errno = krb_get_lrealm(krealm, 0);
+ if (k_errno != KSUCCESS)
+ return k_errno;
+ realm = krealm;
+ }
+
+ k_errno = krb_get_cred(AUTH_SUPERUSER, "", realm, &c);
+ if (k_errno != KSUCCESS)
+ {
+ k_errno = krb_mk_req(&ticket, AUTH_SUPERUSER, "", realm, 0);
+ if (k_errno == KSUCCESS)
+ k_errno = krb_get_cred(AUTH_SUPERUSER, "", realm, &c);
+ }
+
+ if (k_errno == KSUCCESS)
+ {
+ char cell[256];
+ struct ViceIoctl parms;
+ struct ClearToken ct;
+ int32_t sizeof_x;
+ char buf[2048], *t;
+
+ folddown(cell, realm);
+
+ /*
+ * Build a struct ClearToken
+ */
+ ct.AuthHandle = c.kvno;
+ bcopy((char *)c.session, ct.HandShakeKey, sizeof(c.session));
+ ct.ViceId = getuid(); /* is this always valid? */
+ ct.BeginTimestamp = 1 + c.issue_date;
+ ct.EndTimestamp = krb_life_to_time(c.issue_date, c.lifetime);
+
+ t = buf;
+ /*
+ * length of secret token followed by secret token
+ */
+ sizeof_x = c.ticket_st.length;
+ bcopy((char *)&sizeof_x, t, sizeof(sizeof_x));
+ t += sizeof(sizeof_x);
+ bcopy((char *)c.ticket_st.dat, t, sizeof_x);
+ t += sizeof_x;
+ /*
+ * length of clear token followed by clear token
+ */
+ sizeof_x = sizeof(ct);
+ bcopy((char *)&sizeof_x, t, sizeof(sizeof_x));
+ t += sizeof(sizeof_x);
+ bcopy((char *)&ct, t, sizeof_x);
+ t += sizeof_x;
+
+ /*
+ * do *not* mark as primary cell
+ */
+ sizeof_x = 0;
+ bcopy((char *)&sizeof_x, t, sizeof(sizeof_x));
+ t += sizeof(sizeof_x);
+ /*
+ * follow with cell name
+ */
+ sizeof_x = strlen(cell) + 1;
+ bcopy(cell, t, sizeof_x);
+ t += sizeof_x;
+
+ /*
+ * Build argument block
+ */
+ parms.in = buf;
+ parms.in_size = t - buf;
+ parms.out = 0;
+ parms.out_size = 0;
+ (void) k_pioctl(0, VIOCSETTOK, &parms, 0);
+ }
+ return k_errno;
+}
+
+#define NO_ENTRY_POINT 0
+#define SINGLE_ENTRY_POINT 1
+#define MULTIPLE_ENTRY_POINT 2
+#define SINGLE_ENTRY_POINT2 3
+#define AIX_ENTRY_POINTS 4
+#define UNKNOWN_ENTRY_POINT 5
+static int afs_entry_point = UNKNOWN_ENTRY_POINT;
+
+int
+k_pioctl(a_path, o_opcode, a_paramsP, a_followSymlinks)
+ char *a_path;
+ int o_opcode;
+ struct ViceIoctl *a_paramsP;
+ int a_followSymlinks;
+{
+#ifdef AFS_SYSCALL
+ if (afs_entry_point == SINGLE_ENTRY_POINT)
+ return syscall(AFS_SYSCALL, AFSCALL_PIOCTL,
+ a_path, o_opcode, a_paramsP, a_followSymlinks);
+#endif
+
+#ifdef AFS_PIOCTL
+ if (afs_entry_point == MULTIPLE_ENTRY_POINT)
+ return syscall(AFS_PIOCTL,
+ a_path, o_opcode, a_paramsP, a_followSymlinks);
+#endif
+
+#ifdef AFS_SYSCALL2
+ if (afs_entry_point == SINGLE_ENTRY_POINT2)
+ return syscall(AFS_SYSCALL2, AFSCALL_PIOCTL,
+ a_path, o_opcode, a_paramsP, a_followSymlinks);
+#endif
+
+#ifdef _AIX
+ if (afs_entry_point == AIX_ENTRY_POINTS)
+ return lpioctl(a_path, o_opcode, a_paramsP, a_followSymlinks);
+#endif
+
+ errno = ENOSYS;
+ kill(getpid(), SIGSYS); /* You loose! */
+ return -1;
+}
+
+int
+k_unlog()
+{
+ struct ViceIoctl parms;
+ bzero((char *)&parms, sizeof(parms));
+ return k_pioctl(0, VIOCUNLOG, &parms, 0);
+}
+
+int
+k_setpag()
+{
+#ifdef AFS_SYSCALL
+ if (afs_entry_point == SINGLE_ENTRY_POINT)
+ return syscall(AFS_SYSCALL, AFSCALL_SETPAG);
+#endif
+
+#ifdef AFS_SETPAG
+ if (afs_entry_point == MULTIPLE_ENTRY_POINT)
+ return syscall(AFS_SETPAG);
+#endif
+
+#ifdef AFS_SYSCALL2
+ if (afs_entry_point == SINGLE_ENTRY_POINT2)
+ return syscall(AFS_SYSCALL2, AFSCALL_SETPAG);
+#endif
+
+#ifdef _AIX
+ if (afs_entry_point == AIX_ENTRY_POINTS)
+ return lsetpag();
+#endif
+
+ errno = ENOSYS;
+ kill(getpid(), SIGSYS); /* You loose! */
+ return -1;
+}
+#endif /* defined(linux) */
+static jmp_buf catch_SIGSYS;
+
+static void
+SIGSYS_handler()
+{
+ errno = 0;
+ longjmp(catch_SIGSYS, 1);
+}
+
+int
+k_hasafs()
+{
+ int saved_errno;
+ void (*saved_func)();
+ struct ViceIoctl parms;
+
+#if defined(linux)
+ return 0;
+#else
+ /*
+ * Already checked presence of AFS syscalls?
+ */
+ if (afs_entry_point != UNKNOWN_ENTRY_POINT)
+ return afs_entry_point != NO_ENTRY_POINT;
+
+ /*
+ * Probe kernel for AFS specific syscalls,
+ * they (currently) come in two flavors.
+ * If the syscall is absent we recive a SIGSYS.
+ */
+ afs_entry_point = NO_ENTRY_POINT;
+ bzero(&parms, sizeof(parms));
+
+ saved_errno = errno;
+ saved_func = signal(SIGSYS, SIGSYS_handler);
+
+#ifdef AFS_SYSCALL
+ if (setjmp(catch_SIGSYS) == 0)
+ {
+ syscall(AFS_SYSCALL, AFSCALL_PIOCTL,
+ 0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ if (errno == EINVAL)
+ {
+ afs_entry_point = SINGLE_ENTRY_POINT;
+ goto done;
+ }
+ }
+#endif /* AFS_SYSCALL */
+
+#ifdef AFS_PIOCTL
+ if (setjmp(catch_SIGSYS) == 0)
+ {
+ syscall(AFS_PIOCTL,
+ 0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ if (errno == EINVAL)
+ {
+ afs_entry_point = MULTIPLE_ENTRY_POINT;
+ goto done;
+ }
+ }
+#endif /* AFS_PIOCTL */
+
+#ifdef AFS_SYSCALL2
+ if (setjmp(catch_SIGSYS) == 0)
+ {
+ syscall(AFS_SYSCALL2, AFSCALL_PIOCTL,
+ 0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ if (errno == EINVAL)
+ {
+ afs_entry_point = SINGLE_ENTRY_POINT2;
+ goto done;
+ }
+ }
+#endif /* AFS_SYSCALL */
+
+#ifdef _AIX
+ if (setjmp(catch_SIGSYS) == 0)
+ {
+ lpioctl(0, 0, 0, 0);
+ if (errno == EINVAL)
+ {
+ afs_entry_point = AIX_ENTRY_POINTS;
+ goto done;
+ }
+ }
+#endif
+
+ done:
+ (void) signal(SIGSYS, saved_func);
+ errno = saved_errno;
+ return afs_entry_point != NO_ENTRY_POINT;
+#endif /* linux */
+}
--- /dev/null
+/* $Id: afssysdefs.h,v 1.1.1.1 1995/12/14 06:52:46 tholo Exp $ */
+
+/*
+ * This section is for machines using single entry point AFS syscalls!
+ * or
+ * This section is for machines using multiple entry point AFS syscalls!
+ */
+
+#if defined(sun) && !defined(__svr4__)
+#define AFS_SYSCALL 31
+#endif
+
+#if defined(sun) && defined(__svr4__)
+#define AFS_SYSCALL 105
+#endif
+
+#if defined(hpux)
+#define AFS_SYSCALL 50
+#define AFS_SYSCALL2 49
+#endif
+
+#if defined(_AIX)
+/* _AIX is too weird */
+#endif
+
+#if defined(sgi)
+#define AFS_PIOCTL (64+1000)
+#define AFS_SETPAG (65+1000)
+#endif
+
+#if defined(__osf__)
+#define AFS_SYSCALL 232
+#define AFS_SYSCALL2 258
+#endif
--- /dev/null
+major=4
+minor=0
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $
+
+LIB= kdb
+CFLAGS+=-I${.CURDIR}
+SRCS= krb_cache.c krb_dbm.c krb_kdb_utils.c krb_lib.c print_princ.c
+
+.include <bsd.lib.mk>
--- /dev/null
+/* $Id: kdb_locl.h,v 1.1.1.1 1995/12/14 06:52:37 tholo Exp $ */
+
+#ifndef __kdb_locl_h
+#define __kdb_locl_h
+
+#include "kerberosIV/site.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/types.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <utime.h>
+#include <sys/file.h>
+
+#include <kerberosIV/krb.h>
+#include <kerberosIV/krb_db.h>
+
+/* --- */
+
+/* Globals! */
+
+/* Utils */
+
+int kerb_db_set_lockmode __P((int));
+void kerb_db_fini __P((void));
+int kerb_db_init __P((void));
+int kerb_db_set_name __P((char *name));
+time_t kerb_get_db_age __P((void));
+int kerb_db_create __P((char *db_name));
+int kerb_db_rename __P((char *from, char *to));
+
+int kerb_db_get_principal __P((char *name, char *, Principal *, unsigned int, int *));
+int kerb_db_put_principal __P((Principal *, unsigned int));
+int kerb_db_get_dba __P((char *, char *, Dba *, unsigned int, int *));
+
+void kerb_db_get_stat __P((DB_stat *));
+void kerb_db_put_stat __P((DB_stat *));
+void delta_stat __P((DB_stat *, DB_stat *, DB_stat *));
+
+int kerb_db_iterate __P((int (*func) (/* ??? */), char *arg));
+
+int kerb_cache_init __P((void));
+int kerb_cache_get_principal __P((char *name, char *, Principal *, unsigned int));
+int kerb_cache_put_principal __P((Principal *, unsigned int));
+int kerb_cache_get_dba __P((char *, char *, Dba *, unsigned int));
+int kerb_cache_put_dba __P((Dba *, unsigned int));
+
+void krb_print_principal __P((Principal *));
+
+#endif /* __kdb_locl_h */
--- /dev/null
+/* $Id: krb_cache.c,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * This is where a cache would be implemented, if it were necessary.
+ */
+
+#include "kdb_locl.h"
+
+#ifdef DEBUG
+extern int debug;
+extern long kerb_debug;
+#endif
+static init = 0;
+
+/*
+ * initialization routine for cache
+ */
+
+int
+kerb_cache_init()
+{
+ init = 1;
+ return (0);
+}
+
+/*
+ * look up a principal in the cache returns number of principals found
+ */
+
+int
+kerb_cache_get_principal(serv, inst, principal, max)
+ char *serv; /* could have wild card */
+ char *inst; /* could have wild card */
+ Principal *principal;
+ unsigned int max; /* max number of name structs to return */
+{
+ int found = 0;
+
+ if (!init)
+ kerb_cache_init();
+#ifdef DEBUG
+ if (kerb_debug & 2)
+ fprintf(stderr, "cache_get_principal for %s %s max = %d\n",
+ serv, inst, max);
+#endif /* DEBUG */
+
+#ifdef DEBUG
+ if (kerb_debug & 2) {
+ if (found) {
+ fprintf(stderr, "cache get %s %s found %s %s sid = %d\n",
+ serv, inst, principal->name, principal->instance);
+ } else {
+ fprintf(stderr, "cache %s %s not found\n", serv,
+ inst);
+ }
+ }
+#endif
+ return (found);
+}
+
+/*
+ * insert/replace a principal in the cache returns number of principals
+ * inserted
+ */
+
+int
+kerb_cache_put_principal(principal, max)
+ Principal *principal;
+ unsigned int max; /* max number of principal structs to
+ * insert */
+
+{
+ u_long i;
+ int count = 0;
+
+ if (!init)
+ kerb_cache_init();
+
+#ifdef DEBUG
+ if (kerb_debug & 2) {
+ fprintf(stderr, "kerb_cache_put_principal max = %d",
+ max);
+ }
+#endif
+
+ for (i = 0; i < max; i++) {
+#ifdef DEBUG
+ if (kerb_debug & 2)
+ fprintf(stderr, "\n %s %s",
+ principal->name, principal->instance);
+#endif
+ /* DO IT */
+ count++;
+ principal++;
+ }
+ return count;
+}
+
+/*
+ * look up a dba in the cache returns number of dbas found
+ */
+
+int
+kerb_cache_get_dba(serv, inst, dba, max)
+ char *serv; /* could have wild card */
+ char *inst; /* could have wild card */
+ Dba *dba;
+ unsigned int max; /* max number of name structs to return */
+{
+ int found = 0;
+
+ if (!init)
+ kerb_cache_init();
+
+#ifdef DEBUG
+ if (kerb_debug & 2)
+ fprintf(stderr, "cache_get_dba for %s %s max = %d\n",
+ serv, inst, max);
+#endif
+
+#ifdef DEBUG
+ if (kerb_debug & 2) {
+ if (found) {
+ fprintf(stderr, "cache get %s %s found %s %s sid = %d\n",
+ serv, inst, dba->name, dba->instance);
+ } else {
+ fprintf(stderr, "cache %s %s not found\n", serv, inst);
+ }
+ }
+#endif
+ return (found);
+}
+
+/*
+ * insert/replace a dba in the cache returns number of dbas inserted
+ */
+
+int
+kerb_cache_put_dba(dba, max)
+ Dba *dba;
+ unsigned int max; /* max number of dba structs to insert */
+
+{
+ u_long i;
+ int count = 0;
+
+ if (!init)
+ kerb_cache_init();
+#ifdef DEBUG
+ if (kerb_debug & 2) {
+ fprintf(stderr, "kerb_cache_put_dba max = %d", max);
+ }
+#endif
+ for (i = 0; i < max; i++) {
+#ifdef DEBUG
+ if (kerb_debug & 2)
+ fprintf(stderr, "\n %s %s",
+ dba->name, dba->instance);
+#endif
+ /* DO IT */
+ count++;
+ dba++;
+ }
+ return count;
+}
+
--- /dev/null
+/* $Id: krb_dbm.c,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "kdb_locl.h"
+
+#include <ndbm.h>
+
+#define KERB_DB_MAX_RETRY 5
+
+#ifdef DEBUG
+extern int debug;
+extern long kerb_debug;
+extern char *progname;
+#endif
+
+static init = 0;
+static char default_db_name[] = DBM_FILE;
+static char *current_db_name = default_db_name;
+
+static struct timeval timestamp;/* current time of request */
+static int non_blocking = 0;
+
+/*
+ * This module contains all of the code which directly interfaces to
+ * the underlying representation of the Kerberos database; this
+ * implementation uses a DBM or NDBM indexed "file" (actually
+ * implemented as two separate files) to store the relations, plus a
+ * third file as a semaphore to allow the database to be replaced out
+ * from underneath the KDC server.
+ */
+
+/*
+ * Locking:
+ *
+ * There are two distinct locking protocols used. One is designed to
+ * lock against processes (the admin_server, for one) which make
+ * incremental changes to the database; the other is designed to lock
+ * against utilities (kdb_util, kpropd) which replace the entire
+ * database in one fell swoop.
+ *
+ * The first locking protocol is implemented using flock() in the
+ * krb_dbl_lock() and krb_dbl_unlock routines.
+ *
+ * The second locking protocol is necessary because DBM "files" are
+ * actually implemented as two separate files, and it is impossible to
+ * atomically rename two files simultaneously. It assumes that the
+ * database is replaced only very infrequently in comparison to the time
+ * needed to do a database read operation.
+ *
+ * A third file is used as a "version" semaphore; the modification
+ * time of this file is the "version number" of the database.
+ * At the start of a read operation, the reader checks the version
+ * number; at the end of the read operation, it checks again. If the
+ * version number changed, or if the semaphore was nonexistant at
+ * either time, the reader sleeps for a second to let things
+ * stabilize, and then tries again; if it does not succeed after
+ * KERB_DB_MAX_RETRY attempts, it gives up.
+ *
+ * On update, the semaphore file is deleted (if it exists) before any
+ * update takes place; at the end of the update, it is replaced, with
+ * a version number strictly greater than the version number which
+ * existed at the start of the update.
+ *
+ * If the system crashes in the middle of an update, the semaphore
+ * file is not automatically created on reboot; this is a feature, not
+ * a bug, since the database may be inconsistant. Note that the
+ * absence of a semaphore file does not prevent another _update_ from
+ * taking place later. Database replacements take place automatically
+ * only on slave servers; a crash in the middle of an update will be
+ * fixed by the next slave propagation. A crash in the middle of an
+ * update on the master would be somewhat more serious, but this would
+ * likely be noticed by an administrator, who could fix the problem and
+ * retry the operation.
+ */
+
+/* Macros to convert ndbm names to dbm names.
+ * Note that dbm_nextkey() cannot be simply converted using a macro, since
+ * it is invoked giving the database, and nextkey() needs the previous key.
+ *
+ * Instead, all routines call "dbm_next" instead.
+ */
+
+#define dbm_next(db,key) dbm_nextkey(db)
+
+static char *gen_dbsuffix __P((char *db_name, char *sfx));
+static void decode_princ_key __P((datum *key, char *name, char *instance));
+static void encode_princ_contents __P((datum *contents, Principal *principal));
+static void decode_princ_contents __P((datum *contents, Principal *principal));
+static void encode_princ_key __P((datum *key, char *name, char *instance));
+static int kerb_dbl_init __P((void));
+static void kerb_dbl_fini __P((void));
+static int kerb_dbl_lock __P((int mode));
+static void kerb_dbl_unlock __P((void));
+static time_t kerb_start_update __P((char *db_name));
+static int kerb_end_update __P((char *db_name, time_t age));
+static time_t kerb_start_read __P((void));
+static int kerb_end_read __P((time_t age));
+
+/*
+ * Utility routine: generate name of database file.
+ */
+
+static char *
+gen_dbsuffix(db_name, sfx)
+ char *db_name;
+ char *sfx;
+{
+ char *dbsuffix;
+
+ if (sfx == NULL)
+ sfx = ".ok";
+
+ dbsuffix = malloc (strlen(db_name) + strlen(sfx) + 1);
+ strcpy(dbsuffix, db_name);
+ strcat(dbsuffix, sfx);
+ return dbsuffix;
+}
+
+static void
+decode_princ_key(key, name, instance)
+ datum *key;
+ char *name;
+ char *instance;
+{
+ strncpy(name, key->dptr, ANAME_SZ);
+ strncpy(instance, key->dptr + ANAME_SZ, INST_SZ);
+ name[ANAME_SZ - 1] = '\0';
+ instance[INST_SZ - 1] = '\0';
+}
+
+static void
+encode_princ_contents(contents, principal)
+ datum *contents;
+ Principal *principal;
+{
+ contents->dsize = sizeof(*principal);
+ contents->dptr = (char *) principal;
+}
+
+static void
+decode_princ_contents(contents, principal)
+ datum *contents;
+ Principal *principal;
+{
+ bcopy(contents->dptr, (char *) principal, sizeof(*principal));
+}
+
+static void
+encode_princ_key(key, name, instance)
+ datum *key;
+ char *name;
+ char *instance;
+{
+ static char keystring[ANAME_SZ + INST_SZ];
+
+ bzero(keystring, ANAME_SZ + INST_SZ);
+ strncpy(keystring, name, ANAME_SZ);
+ strncpy(&keystring[ANAME_SZ], instance, INST_SZ);
+ key->dptr = keystring;
+ key->dsize = ANAME_SZ + INST_SZ;
+}
+
+static int dblfd = -1; /* db LOCK fd */
+static int mylock = 0;
+static int inited = 0;
+
+static int
+kerb_dbl_init()
+{
+ if (!inited) {
+ char *filename = gen_dbsuffix (current_db_name, ".ok");
+ if ((dblfd = open(filename, O_RDWR)) < 0) {
+ fprintf(stderr, "kerb_dbl_init: couldn't open %s\n", filename);
+ fflush(stderr);
+ perror("open");
+ exit(1);
+ }
+ free(filename);
+ inited++;
+ }
+ return (0);
+}
+
+static void
+kerb_dbl_fini()
+{
+ close(dblfd);
+ dblfd = -1;
+ inited = 0;
+ mylock = 0;
+}
+
+static int
+kerb_dbl_lock(mode)
+ int mode;
+{
+ int flock_mode;
+
+ if (!inited)
+ kerb_dbl_init();
+ if (mylock) { /* Detect lock call when lock already
+ * locked */
+ fprintf(stderr, "Kerberos locking error (mylock)\n");
+ fflush(stderr);
+ exit(1);
+ }
+ switch (mode) {
+ case KERB_DBL_EXCLUSIVE:
+ flock_mode = LOCK_EX;
+ break;
+ case KERB_DBL_SHARED:
+ flock_mode = LOCK_SH;
+ break;
+ default:
+ fprintf(stderr, "invalid lock mode %d\n", mode);
+ abort();
+ }
+ if (non_blocking)
+ flock_mode |= LOCK_NB;
+
+ if (flock(dblfd, flock_mode) < 0)
+ return errno;
+ mylock++;
+ return 0;
+}
+
+static void
+kerb_dbl_unlock()
+{
+ if (!mylock) { /* lock already unlocked */
+ fprintf(stderr, "Kerberos database lock not locked when unlocking.\n");
+ fflush(stderr);
+ exit(1);
+ }
+ if (flock(dblfd, LOCK_UN) < 0) {
+ fprintf(stderr, "Kerberos database lock error. (unlocking)\n");
+ fflush(stderr);
+ perror("flock");
+ exit(1);
+ }
+ mylock = 0;
+}
+
+int
+kerb_db_set_lockmode(mode)
+ int mode;
+{
+ int old = non_blocking;
+ non_blocking = mode;
+ return old;
+}
+
+/*
+ * initialization for data base routines.
+ */
+
+int
+kerb_db_init()
+{
+ init = 1;
+ return (0);
+}
+
+/*
+ * gracefully shut down database--must be called by ANY program that does
+ * a kerb_db_init
+ */
+
+void
+kerb_db_fini()
+{
+}
+
+/*
+ * Set the "name" of the current database to some alternate value.
+ *
+ * Passing a null pointer as "name" will set back to the default.
+ * If the alternate database doesn't exist, nothing is changed.
+ */
+
+int
+kerb_db_set_name(name)
+ char *name;
+{
+ DBM *db;
+
+ if (name == NULL)
+ name = default_db_name;
+ db = dbm_open(name, 0, 0);
+ if (db == NULL)
+ return errno;
+ dbm_close(db);
+ kerb_dbl_fini();
+ current_db_name = name;
+ return 0;
+}
+
+/*
+ * Return the last modification time of the database.
+ */
+
+time_t
+kerb_get_db_age()
+{
+ struct stat st;
+ char *okname;
+ time_t age;
+
+ okname = gen_dbsuffix(current_db_name, ".ok");
+
+ if (stat (okname, &st) < 0)
+ age = 0;
+ else
+ age = st.st_mtime;
+
+ free (okname);
+ return age;
+}
+
+/*
+ * Remove the semaphore file; indicates that database is currently
+ * under renovation.
+ *
+ * This is only for use when moving the database out from underneath
+ * the server (for example, during slave updates).
+ */
+
+static time_t
+kerb_start_update(db_name)
+ char *db_name;
+{
+ char *okname = gen_dbsuffix(db_name, ".ok");
+ time_t age = kerb_get_db_age();
+
+ if (unlink(okname) < 0
+ && errno != ENOENT) {
+ age = -1;
+ }
+ free (okname);
+ return age;
+}
+
+static int
+kerb_end_update(db_name, age)
+ char *db_name;
+ time_t age;
+{
+ int fd;
+ int retval = 0;
+ char *new_okname = gen_dbsuffix(db_name, ".ok#");
+ char *okname = gen_dbsuffix(db_name, ".ok");
+
+ fd = open (new_okname, O_CREAT|O_RDWR|O_TRUNC, 0600);
+ if (fd < 0)
+ retval = errno;
+ else {
+ struct stat st;
+ struct utimbuf tv;
+ /* make sure that semaphore is "after" previous value. */
+ if (fstat (fd, &st) == 0
+ && st.st_mtime <= age) {
+ tv.actime = st.st_atime;
+ tv.modtime = age;
+ /* set times.. */
+ utime (new_okname, &tv);
+ fsync(fd);
+ }
+ close(fd);
+ if (rename (new_okname, okname) < 0)
+ retval = errno;
+ }
+
+ free (new_okname);
+ free (okname);
+
+ return retval;
+}
+
+static time_t
+kerb_start_read()
+{
+ return kerb_get_db_age();
+}
+
+static int
+kerb_end_read(age)
+ time_t age;
+{
+ if (kerb_get_db_age() != age || age == -1) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Create the database, assuming it's not there.
+ */
+
+int
+kerb_db_create(db_name)
+ char *db_name;
+{
+ char *okname = gen_dbsuffix(db_name, ".ok");
+ int fd;
+ register int ret = 0;
+ DBM *db;
+
+ db = dbm_open(db_name, O_RDWR|O_CREAT|O_EXCL, 0600);
+ if (db == NULL)
+ ret = errno;
+ else
+ dbm_close(db);
+ if (ret == 0) {
+ fd = open (okname, O_CREAT|O_RDWR|O_TRUNC, 0600);
+ if (fd < 0)
+ ret = errno;
+ close(fd);
+ }
+ return ret;
+}
+
+/*
+ * "Atomically" rename the database in a way that locks out read
+ * access in the middle of the rename.
+ *
+ * Not perfect; if we crash in the middle of an update, we don't
+ * necessarily know to complete the transaction the rename, but...
+ */
+
+int
+kerb_db_rename(from, to)
+ char *from;
+ char *to;
+{
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+ char *fromdb = gen_dbsuffix (from, ".db");
+ char *todb = gen_dbsuffix (from, ".db");
+#else
+ char *fromdir = gen_dbsuffix (from, ".dir");
+ char *todir = gen_dbsuffix (to, ".dir");
+ char *frompag = gen_dbsuffix (from , ".pag");
+ char *topag = gen_dbsuffix (to, ".pag");
+#endif
+ char *fromok = gen_dbsuffix(from, ".ok");
+ long trans = kerb_start_update(to);
+ int ok = 0;
+
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+ if (rename (fromdb, todb) == 0) {
+ (void) unlink (fromdb);
+ ok = 1;
+ }
+ free (fromdb);
+ free (todb);
+#else
+ if ((rename (fromdir, todir) == 0)
+ && (rename (frompag, topag) == 0)) {
+ (void) unlink (fromok);
+ ok = 1;
+ }
+ free (fromdir);
+ free (todir);
+ free (frompag);
+ free (topag);
+#endif
+ free (fromok);
+ if (ok)
+ return kerb_end_update(to, trans);
+ else
+ return -1;
+}
+
+/*
+ * look up a principal in the data base returns number of principals
+ * found , and whether there were more than requested.
+ */
+
+int
+kerb_db_get_principal(name, inst, principal, max, more)
+ char *name; /* could have wild card */
+ char *inst; /* could have wild card */
+ Principal *principal; /* max number of name structs to return */
+ unsigned int max; /* where there more than 'max' tuples? */
+ int *more;
+{
+ int found = 0, code;
+ extern int errorproc();
+ int wildp, wildi;
+ datum key, contents;
+ char testname[ANAME_SZ], testinst[INST_SZ];
+ u_long trans;
+ int try;
+ DBM *db;
+
+ if (!init)
+ kerb_db_init(); /* initialize database routines */
+
+ for (try = 0; try < KERB_DB_MAX_RETRY; try++) {
+ trans = kerb_start_read();
+
+ if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0)
+ return -1;
+
+ db = dbm_open(current_db_name, O_RDONLY, 0600);
+
+ *more = 0;
+
+#ifdef DEBUG
+ if (kerb_debug & 2)
+ fprintf(stderr,
+ "%s: db_get_principal for %s %s max = %d",
+ progname, name, inst, max);
+#endif
+
+ wildp = !strcmp(name, "*");
+ wildi = !strcmp(inst, "*");
+
+ if (!wildi && !wildp) { /* nothing's wild */
+ encode_princ_key(&key, name, inst);
+ contents = dbm_fetch(db, key);
+ if (contents.dptr == NULL) {
+ found = 0;
+ goto done;
+ }
+ decode_princ_contents(&contents, principal);
+#ifdef DEBUG
+ if (kerb_debug & 1) {
+ fprintf(stderr, "\t found %s %s p_n length %d t_n length %d\n",
+ principal->name, principal->instance,
+ strlen(principal->name),
+ strlen(principal->instance));
+ }
+#endif
+ found = 1;
+ goto done;
+ }
+ /* process wild cards by looping through entire database */
+
+ for (key = dbm_firstkey(db); key.dptr != NULL;
+ key = dbm_next(db, key)) {
+ decode_princ_key(&key, testname, testinst);
+ if ((wildp || !strcmp(testname, name)) &&
+ (wildi || !strcmp(testinst, inst))) { /* have a match */
+ if (found >= max) {
+ *more = 1;
+ goto done;
+ } else {
+ found++;
+ contents = dbm_fetch(db, key);
+ decode_princ_contents(&contents, principal);
+#ifdef DEBUG
+ if (kerb_debug & 1) {
+ fprintf(stderr,
+ "\tfound %s %s p_n length %d t_n length %d\n",
+ principal->name, principal->instance,
+ strlen(principal->name),
+ strlen(principal->instance));
+ }
+#endif
+ principal++; /* point to next */
+ }
+ }
+ }
+
+ done:
+ kerb_dbl_unlock(); /* unlock read lock */
+ dbm_close(db);
+ if (kerb_end_read(trans) == 0)
+ break;
+ found = -1;
+ if (!non_blocking)
+ sleep(1);
+ }
+ return (found);
+}
+
+/*
+ * Update a name in the data base. Returns number of names
+ * successfully updated.
+ */
+
+int
+kerb_db_put_principal(principal, max)
+ Principal *principal; /* number of principal structs to */
+ unsigned int max; /* update */
+
+{
+ int found = 0, code;
+ u_long i;
+ extern int errorproc();
+ datum key, contents;
+ DBM *db;
+
+ gettimeofday(×tamp, NULL);
+
+ if (!init)
+ kerb_db_init();
+
+ if ((code = kerb_dbl_lock(KERB_DBL_EXCLUSIVE)) != 0)
+ return -1;
+
+ db = dbm_open(current_db_name, O_RDWR, 0600);
+
+#ifdef DEBUG
+ if (kerb_debug & 2)
+ fprintf(stderr, "%s: kerb_db_put_principal max = %d",
+ progname, max);
+#endif
+
+ /* for each one, stuff temps, and do replace/append */
+ for (i = 0; i < max; i++) {
+ encode_princ_contents(&contents, principal);
+ encode_princ_key(&key, principal->name, principal->instance);
+ dbm_store(db, key, contents, DBM_REPLACE);
+#ifdef DEBUG
+ if (kerb_debug & 1) {
+ fprintf(stderr, "\n put %s %s\n",
+ principal->name, principal->instance);
+ }
+#endif
+ found++;
+ principal++; /* bump to next struct */
+ }
+
+ dbm_close(db);
+ kerb_dbl_unlock(); /* unlock database */
+ return (found);
+}
+
+void
+kerb_db_get_stat(s)
+ DB_stat *s;
+{
+ gettimeofday(×tamp, NULL);
+
+
+ s->cpu = 0;
+ s->elapsed = 0;
+ s->dio = 0;
+ s->pfault = 0;
+ s->t_stamp = timestamp.tv_sec;
+ s->n_retrieve = 0;
+ s->n_replace = 0;
+ s->n_append = 0;
+ s->n_get_stat = 0;
+ s->n_put_stat = 0;
+ /* update local copy too */
+}
+
+void
+kerb_db_put_stat(s)
+ DB_stat *s;
+{
+}
+
+void
+delta_stat(a, b, c)
+ DB_stat *a, *b, *c;
+{
+ /* c = a - b then b = a for the next time */
+
+ c->cpu = a->cpu - b->cpu;
+ c->elapsed = a->elapsed - b->elapsed;
+ c->dio = a->dio - b->dio;
+ c->pfault = a->pfault - b->pfault;
+ c->t_stamp = a->t_stamp - b->t_stamp;
+ c->n_retrieve = a->n_retrieve - b->n_retrieve;
+ c->n_replace = a->n_replace - b->n_replace;
+ c->n_append = a->n_append - b->n_append;
+ c->n_get_stat = a->n_get_stat - b->n_get_stat;
+ c->n_put_stat = a->n_put_stat - b->n_put_stat;
+
+ bcopy(a, b, sizeof(DB_stat));
+ return;
+}
+
+/*
+ * look up a dba in the data base returns number of dbas found , and
+ * whether there were more than requested.
+ */
+
+int
+kerb_db_get_dba(dba_name, dba_inst, dba, max, more)
+ char *dba_name; /* could have wild card */
+ char *dba_inst; /* could have wild card */
+ Dba *dba; /* max number of name structs to return */
+ unsigned int max; /* where there more than 'max' tuples? */
+ int *more;
+{
+ *more = 0;
+ return (0);
+}
+
+int
+kerb_db_iterate (func, arg)
+ int (*func)();
+ char *arg; /* void *, really */
+{
+ datum key, contents;
+ Principal *principal;
+ int code;
+ DBM *db;
+
+ kerb_db_init(); /* initialize and open the database */
+ if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0)
+ return code;
+
+ db = dbm_open(current_db_name, O_RDONLY, 0600);
+
+ for (key = dbm_firstkey (db); key.dptr != NULL; key = dbm_next(db, key)) {
+ contents = dbm_fetch (db, key);
+ /* XXX may not be properly aligned */
+ principal = (Principal *) contents.dptr;
+ if ((code = (*func)(arg, principal)) != 0)
+ return code;
+ }
+ dbm_close(db);
+ kerb_dbl_unlock();
+ return 0;
+}
--- /dev/null
+/* $Id: krb_kdb_utils.c,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * Utility routines for Kerberos programs which directly access
+ * the database. This code was duplicated in too many places
+ * before I gathered it here.
+ *
+ * Jon Rochlis, MIT Telecom, March 1988
+ */
+
+#include "kdb_locl.h"
+
+#include <kdc.h>
+
+long
+kdb_get_master_key(prompt, master_key, master_key_sched)
+ int prompt;
+ des_cblock *master_key;
+ struct des_ks_struct *master_key_sched;
+{
+ int kfile;
+
+ if (prompt) {
+#ifdef NOENCRYPTION
+ placebo_read_password(master_key,
+ "\nEnter Kerberos master key: ", 0);
+#else
+ des_read_password(master_key,
+ "\nEnter Kerberos master key: ", 0);
+#endif
+ printf ("\n");
+ }
+ else {
+ kfile = open(MKEYFILE, O_RDONLY, 0600);
+ if (kfile < 0) {
+ /* oh, for com_err_ */
+ return (-1);
+ }
+ if (read(kfile, (char *) master_key, 8) != 8) {
+ return (-1);
+ }
+ close(kfile);
+ }
+
+#ifndef NOENCRYPTION
+ des_key_sched(master_key,master_key_sched);
+#endif
+ return (0);
+}
+
+/* The old algorithm used the key schedule as the initial vector which
+ was byte order depedent ... */
+
+void
+kdb_encrypt_key (in, out, master_key, master_key_sched, e_d_flag)
+ des_cblock *in;
+ des_cblock *out;
+ des_cblock *master_key;
+ struct des_ks_struct *master_key_sched;
+ int e_d_flag;
+{
+
+#ifdef NOENCRYPTION
+ bcopy(in, out, sizeof(des_cblock));
+#else
+ des_pcbc_encrypt(in,out,(long)sizeof(des_cblock),master_key_sched,master_key,
+ e_d_flag);
+#endif
+}
+
+/* The caller is reasponsible for cleaning up the master key and sched,
+ even if we can't verify the master key */
+
+/* Returns master key version if successful, otherwise -1 */
+
+long
+kdb_verify_master_key (master_key, master_key_sched, out)
+ des_cblock *master_key;
+ struct des_ks_struct *master_key_sched;
+ FILE *out; /* setting this to non-null be do output */
+{
+ des_cblock key_from_db;
+ Principal principal_data[1];
+ int n, more = 0;
+ long master_key_version;
+
+ /* lookup the master key version */
+ n = kerb_get_principal(KERB_M_NAME, KERB_M_INST, principal_data,
+ 1 /* only one please */, &more);
+ if ((n != 1) || more) {
+ if (out != (FILE *) NULL)
+ fprintf(out,
+ "verify_master_key: %s, %d found.\n",
+ "Kerberos error on master key version lookup",
+ n);
+ return (-1);
+ }
+
+ master_key_version = (long) principal_data[0].key_version;
+
+ /* set up the master key */
+ if (out != (FILE *) NULL) /* should we punt this? */
+ fprintf(out, "Current Kerberos master key version is %d.\n",
+ principal_data[0].kdc_key_ver);
+
+ /*
+ * now use the master key to decrypt the key in the db, had better
+ * be the same!
+ */
+ bcopy(&principal_data[0].key_low, key_from_db, 4);
+ bcopy(&principal_data[0].key_high, ((long *) key_from_db) + 1, 4);
+ kdb_encrypt_key (&key_from_db, &key_from_db,
+ master_key, master_key_sched, DES_DECRYPT);
+
+ /* the decrypted database key had better equal the master key */
+ n = bcmp((char *) master_key, (char *) key_from_db,
+ sizeof(master_key));
+ /* this used to zero the master key here! */
+ bzero(key_from_db, sizeof(key_from_db));
+ bzero(principal_data, sizeof (principal_data));
+
+ if (n && (out != (FILE *) NULL)) {
+ fprintf(out, "\n\07\07verify_master_key: Invalid master key; ");
+ fprintf(out, "does not match database.\n");
+ return (-1);
+ }
+ if (out != (FILE *) NULL) {
+ fprintf(out, "\nMaster key entered. BEWARE!\07\07\n");
+ fflush(out);
+ }
+
+ return (master_key_version);
+}
--- /dev/null
+/* $Id: krb_lib.c,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "kdb_locl.h"
+
+#ifdef DEBUG
+extern int debug;
+extern char *progname;
+long kerb_debug;
+#endif
+
+static int init = 0;
+
+/*
+ * initialization routine for data base
+ */
+
+int
+kerb_init()
+{
+#ifdef DEBUG
+ if (!init) {
+ char *dbg = getenv("KERB_DBG");
+ if (dbg)
+ sscanf(dbg, "%d", &kerb_debug);
+ init = 1;
+ }
+#endif
+ kerb_db_init();
+
+#ifdef CACHE
+ kerb_cache_init();
+#endif
+
+ /* successful init, return 0, else errcode */
+ return (0);
+}
+
+/*
+ * finalization routine for database -- NOTE: MUST be called by any
+ * program using kerb_init. ALSO will have to be modified to finalize
+ * caches, if they're ever really implemented.
+ */
+
+void
+kerb_fini()
+{
+ kerb_db_fini();
+}
+
+/*
+ * look up a principal in the cache or data base returns number of
+ * principals found
+ */
+
+int
+kerb_get_principal(name, inst, principal, max, more)
+ char *name; /* could have wild card */
+ char *inst; /* could have wild card */
+ Principal *principal;
+ unsigned int max; /* max number of name structs to return */
+ int *more; /* more tuples than room for */
+
+{
+ int found = 0;
+#ifdef CACHE
+ static int wild = 0;
+#endif
+ if (!init)
+ kerb_init();
+
+#ifdef DEBUG
+ if (kerb_debug & 1)
+ fprintf(stderr, "\n%s: kerb_get_principal for %s %s max = %d\n",
+ progname, name, inst, max);
+#endif
+
+ /*
+ * if this is a request including a wild card, have to go to db
+ * since the cache may not be exhaustive.
+ */
+
+ /* clear the principal area */
+ bzero((char *) principal, max * sizeof(Principal));
+
+#ifdef CACHE
+ /*
+ * so check to see if the name contains a wildcard "*" or "?", not
+ * preceeded by a backslash.
+ */
+ wild = 0;
+ if (index(name, '*') || index(name, '?') ||
+ index(inst, '*') || index(inst, '?'))
+ wild = 1;
+
+ if (!wild) {
+ /* try the cache first */
+ found = kerb_cache_get_principal(name, inst, principal, max, more);
+ if (found)
+ return (found);
+ }
+#endif
+ /* If we didn't try cache, or it wasn't there, try db */
+ found = kerb_db_get_principal(name, inst, principal, max, more);
+ /* try to insert principal(s) into cache if it was found */
+#ifdef CACHE
+ if (found) {
+ kerb_cache_put_principal(principal, found);
+ }
+#endif
+ return (found);
+}
+
+/* principals */
+int
+kerb_put_principal(principal, n)
+ Principal *principal;
+ unsigned int n; /* number of principal structs to write */
+{
+ struct tm *tp;
+
+ /* set mod date */
+ principal->mod_date = time((time_t *)0);
+ /* and mod date string */
+
+ tp = k_localtime(&principal->mod_date);
+ (void) sprintf(principal->mod_date_txt, "%4d-%2d-%2d",
+ tp->tm_year > 1900 ? tp->tm_year : tp->tm_year + 1900,
+ tp->tm_mon + 1, tp->tm_mday); /* January is 0, not 1 */
+#ifdef DEBUG
+ if (kerb_debug & 1) {
+ int i;
+ fprintf(stderr, "\nkerb_put_principal...");
+ for (i = 0; i < n; i++) {
+ krb_print_principal(&principal[i]);
+ }
+ }
+#endif
+ /* write database */
+ if (kerb_db_put_principal(principal, n) < 0) {
+#ifdef DEBUG
+ if (kerb_debug & 1)
+ fprintf(stderr, "\n%s: kerb_db_put_principal err", progname);
+ /* watch out for cache */
+#endif
+ return -1;
+ }
+#ifdef CACHE
+ /* write cache */
+ if (!kerb_cache_put_principal(principal, n)) {
+#ifdef DEBUG
+ if (kerb_debug & 1)
+ fprintf(stderr, "\n%s: kerb_cache_put_principal err", progname);
+#endif
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+int
+kerb_get_dba(name, inst, dba, max, more)
+ char *name; /* could have wild card */
+ char *inst; /* could have wild card */
+ Dba *dba;
+ unsigned int max; /* max number of name structs to return */
+ int *more; /* more tuples than room for */
+
+{
+ int found = 0;
+#ifdef CACHE
+ static int wild = 0;
+#endif
+ if (!init)
+ kerb_init();
+
+#ifdef DEBUG
+ if (kerb_debug & 1)
+ fprintf(stderr, "\n%s: kerb_get_dba for %s %s max = %d\n",
+ progname, name, inst, max);
+#endif
+ /*
+ * if this is a request including a wild card, have to go to db
+ * since the cache may not be exhaustive.
+ */
+
+ /* clear the dba area */
+ bzero((char *) dba, max * sizeof(Dba));
+
+#ifdef CACHE
+ /*
+ * so check to see if the name contains a wildcard "*" or "?", not
+ * preceeded by a backslash.
+ */
+
+ wild = 0;
+ if (index(name, '*') || index(name, '?') ||
+ index(inst, '*') || index(inst, '?'))
+ wild = 1;
+
+ if (!wild) {
+ /* try the cache first */
+ found = kerb_cache_get_dba(name, inst, dba, max, more);
+ if (found)
+ return (found);
+ }
+#endif
+ /* If we didn't try cache, or it wasn't there, try db */
+ found = kerb_db_get_dba(name, inst, dba, max, more);
+#ifdef CACHE
+ /* try to insert dba(s) into cache if it was found */
+ if (found) {
+ kerb_cache_put_dba(dba, found);
+ }
+#endif
+ return (found);
+}
--- /dev/null
+/* $Id: print_princ.c,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "kdb_locl.h"
+
+void
+krb_print_principal(a_n)
+ Principal *a_n;
+{
+ struct tm *time_p;
+
+ /* run-time database does not contain string versions */
+ time_p = k_localtime(&(a_n->exp_date));
+
+ fprintf(stderr,
+ "\n%s %s expires %4d-%2d-%2d %2d:%2d, max_life %d*5 = %d min attr 0x%02x",
+ a_n->name, a_n->instance,
+ time_p->tm_year > 1900 ? time_p->tm_year : time_p->tm_year + 1900,
+ time_p->tm_mon + 1, time_p->tm_mday,
+ time_p->tm_hour, time_p->tm_min,
+ a_n->max_life, 5 * a_n->max_life, a_n->attributes);
+
+ fprintf(stderr,
+ "\n\tkey_ver %d k_low 0x%08lx k_high 0x%08lx akv %d exists %ld\n",
+ a_n->key_version, (long)a_n->key_low, (long)a_n->key_high,
+ a_n->kdc_key_ver, (long)a_n->old);
+
+ fflush(stderr);
+}
--- /dev/null
+major=4
+minor=0
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $
+
+PROG= kdb_destroy
+MAN= kdb_destroy.8
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: kdb_destroy.8,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $
+.TH KDB_DESTROY 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kdb_destroy \- destroy Kerberos key distribution center database
+.SH SYNOPSIS
+kdb_destroy
+.SH DESCRIPTION
+.I kdb_destroy
+deletes a Kerberos key distribution center database.
+.PP
+The user is prompted to verify that the database should be destroyed. A
+response beginning with `y' or `Y' confirms deletion.
+Any other response aborts deletion.
+.SH DIAGNOSTICS
+.TP 20n
+"Database cannot be deleted at /kerberos/principal"
+The attempt to delete the database failed (probably due to a system or
+access permission error).
+.TP
+"Database not deleted."
+The user aborted the deletion.
+.SH FILES
+.TP 20n
+/kerberos/principal.pag, /kerberos/principal.dir
+DBM files containing database
+.SH SEE ALSO
+kdb_init(8)
--- /dev/null
+/* $Id: kdb_destroy.c,v 1.1.1.1 1995/12/14 06:52:43 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <adm_locl.h>
+
+int
+main(void)
+{
+ char answer[10]; /* user input */
+ char dbm[256]; /* database path and name */
+ char dbm1[256]; /* database path and name */
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+ char *file; /* database file names */
+#else
+ char *file1, *file2; /* database file names */
+#endif
+
+ strcpy(dbm, DBM_FILE);
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+ file = strcat(dbm, ".db");
+#else
+ strcpy(dbm1, DBM_FILE);
+ file1 = strcat(dbm, ".dir");
+ file2 = strcat(dbm1, ".pag");
+#endif
+
+ printf("You are about to destroy the Kerberos database ");
+ printf("on this machine.\n");
+ printf("Are you sure you want to do this (y/n)? ");
+ fgets(answer, sizeof(answer), stdin);
+
+ if (answer[0] == 'y' || answer[0] == 'Y') {
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+ if (unlink(file) == 0)
+#else
+ if (unlink(file1) == 0 && unlink(file2) == 0)
+#endif
+ fprintf(stderr, "Database deleted at %s\n", DBM_FILE);
+ else
+ fprintf(stderr, "Database cannot be deleted at %s\n",
+ DBM_FILE);
+ } else
+ fprintf(stderr, "Database not deleted.\n");
+ exit(1);
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:42 tholo Exp $
+
+PROG= kdb_edit
+SRCS= kdb_edit.c maketime.c
+CFLAGS+=-I${.CURDIR}
+DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES}
+LDADD= -lkdb -lkrb -ldes
+MAN= kdb_edit.8
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: kdb_edit.8,v 1.1.1.1 1995/12/14 06:52:42 tholo Exp $
+.TH KDB_EDIT 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kdb_edit \- Kerberos key distribution center database editing utility
+.SH SYNOPSIS
+kdb_edit [
+.B \-n
+]
+.SH DESCRIPTION
+.I kdb_edit
+is used to create or change principals stored in the Kerberos key
+distribution center (KDC) database.
+.PP
+When executed,
+.I kdb_edit
+prompts for the master key string and verifies that it matches the
+master key stored in the database.
+If the
+.B \-n
+option is specified, the master key is instead fetched from the master
+key cache file.
+.PP
+Once the master key has been verified,
+.I kdb_edit
+begins a prompt loop. The user is prompted for the principal and
+instance to be modified. If the entry is not found the user may create
+it.
+Once an entry is found or created, the user may set the password,
+expiration date, maximum ticket lifetime, and attributes.
+Default expiration dates, maximum ticket lifetimes, and attributes are
+presented in brackets; if the user presses return the default is selected.
+There is no default password.
+The password RANDOM is interpreted specially, and if entered
+the user may have the program select a random DES key for the
+principal.
+.PP
+Upon successfully creating or changing the entry, ``Edit O.K.'' is
+printed.
+.SH DIAGNOSTICS
+.TP 20n
+"verify_master_key: Invalid master key, does not match database."
+The master key string entered was incorrect.
+.SH FILES
+.TP 20n
+/kerberos/principal.pag, /kerberos/principal.dir
+DBM files containing database
+.TP
+/.k
+Master key cache file.
--- /dev/null
+/* $Id: kdb_edit.c,v 1.1.1.1 1995/12/14 06:52:42 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * This routine changes the Kerberos encryption keys for principals,
+ * i.e., users or services.
+ */
+
+/*
+ * exit returns 0 ==> success -1 ==> error
+ */
+
+#include <adm_locl.h>
+
+#ifdef DEBUG
+extern kerb_debug;
+#endif
+
+#define zaptime(foo) bzero((char *)(foo), sizeof(*(foo)))
+
+static char prog[32];
+char *progname = prog;
+static int nflag = 0;
+static int debug;
+
+static des_cblock new_key;
+
+static int i, j;
+static int more;
+
+static char input_name[ANAME_SZ];
+static char input_instance[INST_SZ];
+
+#define MAX_PRINCIPAL 10
+static Principal principal_data[MAX_PRINCIPAL];
+
+static Principal old_principal;
+static Principal default_princ;
+
+static des_cblock master_key;
+static des_cblock session_key;
+static des_key_schedule master_key_schedule;
+static char pw_str[255];
+static long master_key_version;
+
+static void
+Usage(void)
+{
+ fprintf(stderr, "Usage: %s [-n]\n", progname);
+ exit(1);
+}
+
+/*
+ * "fgets" where the nl is zapped afterwards.
+ */
+static char*
+z_fgets(cp, count, fp)
+ char *cp;
+ int count;
+ FILE *fp;
+{
+ int ix;
+ char *p;
+
+ if (fgets(cp, count, fp) == 0) {
+ return 0;
+ }
+ cp[count-1] = 0;
+ if ((p = strchr(cp, '\n')) == 0) {
+ return 0;
+ }
+ *p = 0;
+ return cp;
+}
+
+
+static int
+change_principal(void)
+{
+ static char temp[255];
+ int creating = 0;
+ int editpw = 0;
+ int changed = 0;
+ long temp_long;
+ int n;
+ struct tm *tp, edate, *localtime(const time_t *);
+ long maketime(struct tm *tp, int local);
+
+ fprintf(stdout, "\nPrincipal name: ");
+ fflush(stdout);
+ if (!z_fgets(input_name, sizeof input_name, stdin) || *input_name == '\0')
+ return 0;
+ fprintf(stdout, "Instance: ");
+ fflush(stdout);
+ /* instance can be null */
+ z_fgets(input_instance, sizeof input_instance, stdin);
+ j = kerb_get_principal(input_name, input_instance, principal_data,
+ MAX_PRINCIPAL, &more);
+ if (!j) {
+ fprintf(stdout, "\n\07\07<Not found>, Create [y] ? ");
+ z_fgets(temp, sizeof temp, stdin); /* Default case should work, it didn't */
+ if (temp[0] != 'y' && temp[0] != 'Y' && temp[0] != '\0')
+ return -1;
+ /* make a new principal, fill in defaults */
+ j = 1;
+ creating = 1;
+ strcpy(principal_data[0].name, input_name);
+ strcpy(principal_data[0].instance, input_instance);
+ principal_data[0].old = NULL;
+ principal_data[0].exp_date = default_princ.exp_date;
+ principal_data[0].max_life = default_princ.max_life;
+ principal_data[0].attributes = default_princ.attributes;
+ principal_data[0].kdc_key_ver = (unsigned char) master_key_version;
+ principal_data[0].key_version = 0; /* bumped up later */
+ }
+ tp = k_localtime(&principal_data[0].exp_date);
+ (void) sprintf(principal_data[0].exp_date_txt, "%4d-%02d-%02d",
+ tp->tm_year > 1900 ? tp->tm_year : tp->tm_year + 1900,
+ tp->tm_mon + 1, tp->tm_mday); /* January is 0, not 1 */
+ for (i = 0; i < j; i++) {
+ for (;;) {
+ fprintf(stdout,
+ "\nPrincipal: %s, Instance: %s, kdc_key_ver: %d",
+ principal_data[i].name, principal_data[i].instance,
+ principal_data[i].kdc_key_ver);
+ editpw = 1;
+ changed = 0;
+ if (!creating) {
+ /*
+ * copy the existing data so we can use the old values
+ * for the qualifier clause of the replace
+ */
+ principal_data[i].old = (char *) &old_principal;
+ bcopy(&principal_data[i], &old_principal,
+ sizeof(old_principal));
+ printf("\nChange password [n] ? ");
+ z_fgets(temp, sizeof temp, stdin);
+ if (strcmp("y", temp) && strcmp("Y", temp))
+ editpw = 0;
+ }
+ fflush(stdout);
+ /* password */
+ if (editpw) {
+#ifdef NOENCRYPTION
+ placebo_read_pw_string(pw_str, sizeof pw_str,
+ "\nNew Password: ", TRUE);
+#else
+ des_read_pw_string(pw_str, sizeof pw_str,
+ "\nNew Password: ", TRUE);
+#endif
+ if ( strcmp(pw_str, "RANDOM") == 0
+ || strcmp(pw_str, "") == 0) {
+ printf("\nRandom password [y] ? ");
+ z_fgets(temp, sizeof temp, stdin);
+ if (!strcmp("n", temp) || !strcmp("N", temp)) {
+ /* no, use literal */
+#ifdef NOENCRYPTION
+ bzero(new_key, sizeof(des_cblock));
+ new_key[0] = 127;
+#else
+ des_string_to_key(pw_str, &new_key);
+#endif
+ bzero(pw_str, sizeof pw_str); /* "RANDOM" */
+ } else {
+#ifdef NOENCRYPTION
+ bzero(new_key, sizeof(des_cblock));
+ new_key[0] = 127;
+#else
+ des_new_random_key(&new_key);
+#endif
+ bzero(pw_str, sizeof pw_str);
+ }
+ } else if (!strcmp(pw_str, "NULL")) {
+ printf("\nNull Key [y] ? ");
+ z_fgets(temp, sizeof temp, stdin);
+ if (!strcmp("n", temp) || !strcmp("N", temp)) {
+ /* no, use literal */
+#ifdef NOENCRYPTION
+ bzero(new_key, sizeof(des_cblock));
+ new_key[0] = 127;
+#else
+ des_string_to_key(pw_str, &new_key);
+#endif
+ bzero(pw_str, sizeof pw_str); /* "NULL" */
+ } else {
+
+ principal_data[i].key_low = 0;
+ principal_data[i].key_high = 0;
+ goto null_key;
+ }
+ } else {
+#ifdef NOENCRYPTION
+ bzero(new_key, sizeof(des_cblock));
+ new_key[0] = 127;
+#else
+ des_string_to_key(pw_str, &new_key);
+#endif
+ bzero(pw_str, sizeof pw_str);
+ }
+
+ /* seal it under the kerberos master key */
+ kdb_encrypt_key (&new_key, &new_key,
+ &master_key, master_key_schedule,
+ DES_ENCRYPT);
+ bcopy(new_key, &principal_data[i].key_low, 4);
+ bcopy(((long *) new_key) + 1,
+ &principal_data[i].key_high, 4);
+ bzero(new_key, sizeof(new_key));
+ null_key:
+ /* set master key version */
+ principal_data[i].kdc_key_ver =
+ (unsigned char) master_key_version;
+ /* bump key version # */
+ principal_data[i].key_version++;
+ fprintf(stdout,
+ "\nPrincipal's new key version = %d\n",
+ principal_data[i].key_version);
+ fflush(stdout);
+ changed = 1;
+ }
+ /* expiration date */
+ fprintf(stdout, "Expiration date (enter yyyy-mm-dd) [ %s ] ? ",
+ principal_data[i].exp_date_txt);
+ zaptime(&edate);
+ while (z_fgets(temp, sizeof temp, stdin) &&
+ ((n = strlen(temp)) >
+ sizeof(principal_data[0].exp_date_txt))) {
+ bad_date:
+ fprintf(stdout, "\07\07Date Invalid\n");
+ fprintf(stdout,
+ "Expiration date (enter yyyy-mm-dd) [ %s ] ? ",
+ principal_data[i].exp_date_txt);
+ zaptime(&edate);
+ }
+
+ if (*temp) {
+ if (sscanf(temp, "%d-%d-%d", &edate.tm_year,
+ &edate.tm_mon, &edate.tm_mday) != 3)
+ goto bad_date;
+ (void) strcpy(principal_data[i].exp_date_txt, temp);
+ edate.tm_mon--; /* January is 0, not 1 */
+ edate.tm_hour = 23; /* nearly midnight at the end of the */
+ edate.tm_min = 59; /* specified day */
+ if (!(principal_data[i].exp_date = maketime(&edate, 1)))
+ goto bad_date;
+ changed = 1;
+ }
+
+ /* maximum lifetime */
+ fprintf(stdout, "Max ticket lifetime (*5 minutes) [ %d ] ? ",
+ principal_data[i].max_life);
+ while (z_fgets(temp, sizeof temp, stdin) && *temp) {
+ if (sscanf(temp, "%ld", &temp_long) != 1)
+ goto bad_life;
+ if (temp_long > 255 || (temp_long < 0)) {
+ bad_life:
+ fprintf(stdout, "\07\07Invalid, choose 0-255\n");
+ fprintf(stdout,
+ "Max ticket lifetime (*5 minutes) [ %d ] ? ",
+ principal_data[i].max_life);
+ continue;
+ }
+ changed = 1;
+ /* dont clobber */
+ principal_data[i].max_life = (unsigned short) temp_long;
+ break;
+ }
+
+ /* attributes */
+ fprintf(stdout, "Attributes [ %d ] ? ",
+ principal_data[i].attributes);
+ while (z_fgets(temp, sizeof temp, stdin) && *temp) {
+ if (sscanf(temp, "%ld", &temp_long) != 1)
+ goto bad_att;
+ if (temp_long > 65535 || (temp_long < 0)) {
+ bad_att:
+ fprintf(stdout, "\07\07Invalid, choose 0-65535\n");
+ fprintf(stdout, "Attributes [ %d ] ? ",
+ principal_data[i].attributes);
+ continue;
+ }
+ changed = 1;
+ /* dont clobber */
+ principal_data[i].attributes =
+ (unsigned short) temp_long;
+ break;
+ }
+
+ /*
+ * remaining fields -- key versions and mod info, should
+ * not be directly manipulated
+ */
+ if (changed) {
+ if (kerb_put_principal(&principal_data[i], 1)) {
+ fprintf(stdout,
+ "\nError updating Kerberos database");
+ } else {
+ fprintf(stdout, "Edit O.K.");
+ }
+ } else {
+ fprintf(stdout, "Unchanged");
+ }
+
+
+ bzero(&principal_data[i].key_low, 4);
+ bzero(&principal_data[i].key_high, 4);
+ fflush(stdout);
+ break;
+ }
+ }
+ if (more) {
+ fprintf(stdout, "\nThere were more tuples found ");
+ fprintf(stdout, "than there were space for");
+ }
+ return 1;
+}
+
+static void
+cleanup(void)
+{
+
+ bzero(master_key, sizeof(master_key));
+ bzero(session_key, sizeof(session_key));
+ bzero(master_key_schedule, sizeof(master_key_schedule));
+ bzero(principal_data, sizeof(principal_data));
+ bzero(new_key, sizeof(new_key));
+ bzero(pw_str, sizeof(pw_str));
+}
+
+int
+main(int argc, char **argv)
+{
+ /* Local Declarations */
+
+ long n;
+
+ prog[sizeof prog - 1] = '\0'; /* make sure terminated */
+ strncpy(prog, argv[0], sizeof prog - 1); /* salt away invoking
+ * program */
+
+ /* Assume a long is four bytes */
+ if (sizeof(long) != 4) {
+ fprintf(stdout, "%s: size of long is %d.\n", prog, (int)sizeof(long));
+ exit(-1);
+ }
+ /* Assume <=32 signals */
+ if (NSIG > 32) {
+ fprintf(stderr, "%s: more than 32 signals defined.\n", prog);
+ exit(-1);
+ }
+ while (--argc > 0 && (*++argv)[0] == '-')
+ for (i = 1; argv[0][i] != '\0'; i++) {
+ switch (argv[0][i]) {
+
+ /* debug flag */
+ case 'd':
+ debug = 1;
+ continue;
+
+ /* debug flag */
+#ifdef DEBUG
+ case 'l':
+ kerb_debug |= 1;
+ continue;
+#endif
+ case 'n': /* read MKEYFILE for master key */
+ nflag = 1;
+ continue;
+
+ default:
+ fprintf(stderr, "%s: illegal flag \"%c\"\n",
+ progname, argv[0][i]);
+ Usage(); /* Give message and die */
+ }
+ };
+
+ fprintf(stdout, "Opening database...\n");
+ fflush(stdout);
+ kerb_init();
+ if (argc > 0) {
+ if (kerb_db_set_name(*argv) != 0) {
+ fprintf(stderr, "Could not open altername database name\n");
+ exit(1);
+ }
+ }
+
+#ifdef notdef
+ no_core_dumps(); /* diddle signals to avoid core dumps! */
+
+ /* ignore whatever is reasonable */
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+
+#endif
+
+ if (kdb_get_master_key ((nflag == 0),
+ &master_key, master_key_schedule) != 0) {
+ fprintf (stdout, "Couldn't read master key.\n");
+ fflush (stdout);
+ exit (-1);
+ }
+
+ if ((master_key_version = kdb_verify_master_key(&master_key,
+ master_key_schedule,
+ stdout)) < 0)
+ exit (-1);
+
+ /* Initialize non shared random sequence */
+ des_init_random_number_generator(&master_key);
+
+ /* lookup the default values */
+ n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
+ &default_princ, 1, &more);
+ if (n != 1) {
+ fprintf(stderr,
+ "%s: Kerberos error on default value lookup, %ld found.\n",
+ progname, n);
+ exit(-1);
+ }
+ fprintf(stdout, "Previous or default values are in [brackets] ,\n");
+ fprintf(stdout, "enter return to leave the same, or new value.\n");
+
+ while (change_principal()) {
+ }
+
+ cleanup();
+ exit(0);
+}
+
+#if 0
+static void
+sig_exit(sig, code, scp)
+ int sig, code;
+ struct sigcontext *scp;
+{
+ cleanup();
+ fprintf(stderr,
+ "\nSignal caught, sig = %d code = %d old pc = 0x%X \nexiting",
+ sig, code, scp->sc_pc);
+ exit(-1);
+}
+
+static void
+no_core_dumps()
+{
+ signal(SIGQUIT, sig_exit);
+ signal(SIGILL, sig_exit);
+ signal(SIGTRAP, sig_exit);
+ signal(SIGIOT, sig_exit);
+ signal(SIGEMT, sig_exit);
+ signal(SIGFPE, sig_exit);
+ signal(SIGBUS, sig_exit);
+ signal(SIGSEGV, sig_exit);
+ signal(SIGSYS, sig_exit);
+}
+#endif
--- /dev/null
+/* $Id: maketime.c,v 1.1.1.1 1995/12/14 06:52:42 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Convert a struct tm * to a UNIX time.
+ */
+
+#include <adm_locl.h>
+
+#define daysinyear(y) (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
+
+#define SECSPERDAY 24*60*60
+#define SECSPERHOUR 60*60
+#define SECSPERMIN 60
+
+static int cumdays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
+ 365};
+
+static int leapyear[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+static int nonleapyear[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+long
+maketime(struct tm *tp, int local)
+{
+ register long retval;
+ int foo;
+ int *marray;
+
+ if (tp->tm_mon < 0 || tp->tm_mon > 11 ||
+ tp->tm_hour < 0 || tp->tm_hour > 23 ||
+ tp->tm_min < 0 || tp->tm_min > 59 ||
+ tp->tm_sec < 0 || tp->tm_sec > 59) /* out of range */
+ return 0;
+
+ retval = 0;
+ if (tp->tm_year < 1900)
+ foo = tp->tm_year + 1900;
+ else
+ foo = tp->tm_year;
+
+ if (foo < 1901 || foo > 2038) /* year is too small/large */
+ return 0;
+
+ if (daysinyear(foo) == 366) {
+ if (tp->tm_mon > 1)
+ retval+= SECSPERDAY; /* add leap day */
+ marray = leapyear;
+ } else
+ marray = nonleapyear;
+
+ if (tp->tm_mday < 0 || tp->tm_mday > marray[tp->tm_mon])
+ return 0; /* out of range */
+
+ while (--foo >= 1970)
+ retval += daysinyear(foo) * SECSPERDAY;
+
+ retval += cumdays[tp->tm_mon] * SECSPERDAY;
+ retval += (tp->tm_mday-1) * SECSPERDAY;
+ retval += tp->tm_hour * SECSPERHOUR + tp->tm_min * SECSPERMIN + tp->tm_sec;
+
+ if (local) {
+ /* need to use local time, so we retrieve timezone info */
+ struct timezone tz;
+ struct timeval tv;
+ if (gettimeofday(&tv, &tz) < 0) {
+ /* some error--give up? */
+ return(retval);
+ }
+ retval += tz.tz_minuteswest * SECSPERMIN;
+ }
+ return(retval);
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:42 tholo Exp $
+
+PROG= kdb_init
+DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES}
+LDADD= -lkdb -lkrb -ldes
+MAN= kdb_init.8
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: kdb_init.8,v 1.1.1.1 1995/12/14 06:52:42 tholo Exp $
+.TH KDB_INIT 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kdb_init \- Initialize Kerberos key distribution center database
+.SH SYNOPSIS
+kdb_init [
+.B realm
+]
+.SH DESCRIPTION
+.I kdb_init
+initializes a Kerberos key distribution center database, creating the
+necessary principals.
+.PP
+If the optional
+.I realm
+argument is not present,
+.I kdb_init
+prompts for a realm name (defaulting to the definition in /usr/include/krb.h).
+After determining the realm to be created, it prompts for
+a master key password. The master key password is used to encrypt
+every encryption key stored in the database.
+.SH DIAGNOSTICS
+.TP 20n
+"/kerberos/principal: File exists"
+An attempt was made to create a database on a machine which already had
+an existing database.
+.SH FILES
+.TP 20n
+/kerberos/principal.pag, /kerberos/principal.dir
+DBM files containing database
+.TP
+/usr/include/krb.h
+Include file defining default realm
+.SH SEE ALSO
+kdb_destroy(8)
--- /dev/null
+/* $Id: kdb_init.c,v 1.1.1.1 1995/12/14 06:52:42 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * program to initialize the database, reports error if database file
+ * already exists.
+ */
+
+#include <adm_locl.h>
+
+enum ap_op {
+ NULL_KEY, /* setup null keys */
+ MASTER_KEY, /* use master key as new key */
+ RANDOM_KEY /* choose a random key */
+};
+
+char *progname;
+static des_cblock master_key;
+static des_key_schedule master_key_schedule;
+
+/* use a return code to indicate success or failure. check the return */
+/* values of the routines called by this routine. */
+
+static int
+add_principal(char *name, char *instance, enum ap_op aap_op)
+{
+ Principal principal;
+ struct tm *tm;
+ des_cblock new_key;
+
+ bzero(&principal, sizeof(principal));
+ strncpy(principal.name, name, ANAME_SZ);
+ strncpy(principal.instance, instance, INST_SZ);
+ switch (aap_op) {
+ case NULL_KEY:
+ principal.key_low = 0;
+ principal.key_high = 0;
+ break;
+ case RANDOM_KEY:
+#ifdef NOENCRYPTION
+ bzero(new_key, sizeof(des_cblock));
+ new_key[0] = 127;
+#else
+ des_new_random_key(&new_key);
+#endif
+ kdb_encrypt_key (&new_key, &new_key, &master_key, master_key_schedule,
+ DES_ENCRYPT);
+ bcopy(new_key, &principal.key_low, 4);
+ bcopy(((long *) new_key) + 1, &principal.key_high, 4);
+ break;
+ case MASTER_KEY:
+ bcopy (master_key, new_key, sizeof (des_cblock));
+ kdb_encrypt_key (&new_key, &new_key, &master_key, master_key_schedule,
+ DES_ENCRYPT);
+ bcopy(new_key, &principal.key_low, 4);
+ bcopy(((long *) new_key) + 1, &principal.key_high, 4);
+ break;
+ }
+ principal.exp_date = 946702799; /* Happy new century */
+ strncpy(principal.exp_date_txt, "12/31/99", DATE_SZ);
+ principal.mod_date = time(0);
+
+ tm = k_localtime(&principal.mod_date);
+ principal.attributes = 0;
+ principal.max_life = 255;
+
+ principal.kdc_key_ver = 1;
+ principal.key_version = 1;
+
+ strncpy(principal.mod_name, "db_creation", ANAME_SZ);
+ strncpy(principal.mod_instance, "", INST_SZ);
+ principal.old = 0;
+
+ if (kerb_db_put_principal(&principal, 1) != 1)
+ return -1; /* FAIL */
+
+ /* let's play it safe */
+ bzero (new_key, sizeof (des_cblock));
+ bzero (&principal.key_low, 4);
+ bzero (&principal.key_high, 4);
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ char realm[REALM_SZ];
+ char *cp;
+ int code;
+ char *database;
+
+ progname = (cp = strrchr(*argv, '/')) ? cp + 1 : *argv;
+
+ if (argc > 3) {
+ fprintf(stderr, "Usage: %s [realm-name] [database-name]\n", argv[0]);
+ exit(1);
+ }
+ if (argc == 3) {
+ database = argv[2];
+ --argc;
+ } else
+ database = DBM_FILE;
+
+ /* Do this first, it'll fail if the database exists */
+ if ((code = kerb_db_create(database)) != 0) {
+ fprintf(stderr, "Couldn't create database: %s\n",
+ strerror(code));
+ exit(1);
+ }
+ kerb_db_set_name(database);
+
+ if (argc == 2)
+ strncpy(realm, argv[1], REALM_SZ);
+ else {
+ fprintf(stderr, "Realm name [default %s ]: ", KRB_REALM);
+ if (fgets(realm, sizeof(realm), stdin) == NULL) {
+ fprintf(stderr, "\nEOF reading realm\n");
+ exit(1);
+ }
+ if ((cp = strchr(realm, '\n')))
+ *cp = '\0';
+ if (!*realm) /* no realm given */
+ strcpy(realm, KRB_REALM);
+ }
+ if (!k_isrealm(realm)) {
+ fprintf(stderr, "%s: Bad kerberos realm name \"%s\"\n",
+ progname, realm);
+ exit(1);
+ }
+ printf("You will be prompted for the database Master Password.\n");
+ printf("It is important that you NOT FORGET this password.\n");
+ fflush(stdout);
+
+ if (kdb_get_master_key (TRUE, &master_key, master_key_schedule) != 0) {
+ fprintf (stderr, "Couldn't read master key.\n");
+ exit (-1);
+ }
+
+ /* Initialize non shared random sequence */
+ des_init_random_number_generator(&master_key);
+
+ if (
+ add_principal(KERB_M_NAME, KERB_M_INST, MASTER_KEY) ||
+ add_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST, NULL_KEY) ||
+ add_principal("krbtgt", realm, RANDOM_KEY) ||
+ add_principal("changepw", KRB_MASTER, RANDOM_KEY)
+ ) {
+ fprintf(stderr, "\n%s: couldn't initialize database.\n",
+ progname);
+ exit(1);
+ }
+
+ /* play it safe */
+ bzero (master_key, sizeof (des_cblock));
+ bzero (master_key_schedule, sizeof (des_key_schedule));
+ exit(0);
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:42 tholo Exp $
+
+PROG= kdb_util
+SRCS= kdb_util.c maketime.c
+.PATH: ${.CURDIR}/../kdb_edit
+DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES}
+LDADD= -lkdb -lkrb -ldes
+MAN= kdb_util.8
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: kdb_util.8,v 1.1.1.1 1995/12/14 06:52:42 tholo Exp $
+.TH KDB_UTIL 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kdb_util \- Kerberos key distribution center database utility
+.SH SYNOPSIS
+kdb_util
+.B operation filename
+.SH DESCRIPTION
+.I kdb_util
+allows the Kerberos key distribution center (KDC) database administrator to
+perform utility functions on the database.
+.PP
+.I Operation
+must be one of the following:
+.TP 10n
+.I load
+initializes the KDC database with the records described by the
+text contained in the file
+.IR filename .
+Any existing database is overwritten.
+.TP
+.I dump
+dumps the KDC database into a text representation in the file
+.IR filename .
+.TP
+.I slave_dump
+performs a database dump like the
+.I dump
+operation, and additionally creates a semaphore file signalling the
+propagation software that an update is available for distribution to
+slave KDC databases.
+.TP
+.I new_master_key
+prompts for the old and new master key strings, and then dumps the KDC
+database into a text representation in the file
+.IR filename .
+The keys in the text representation are encrypted in the new master key.
+.TP
+.I convert_old_db
+prompts for the master key string, and then dumps the KDC database into
+a text representation in the file
+.IR filename .
+The existing database is assumed to be encrypted using the old format
+(encrypted by the key schedule of the master key); the dumped database
+is encrypted using the new format (encrypted directly with master key).
+.PP
+.SH DIAGNOSTICS
+.TP 20n
+"verify_master_key: Invalid master key, does not match database."
+The master key string entered was incorrect.
+.SH FILES
+.TP 20n
+/kerberos/principal.pag, /kerberos/principal.dir
+DBM files containing database
+.TP
+.IR filename .ok
+semaphore file created by
+.IR slave_dump.
--- /dev/null
+/* $Id: kdb_util.c,v 1.1.1.1 1995/12/14 06:52:42 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Kerberos database manipulation utility. This program allows you to
+ * dump a kerberos database to an ascii readable file and load this
+ * file into the database. Read locking of the database is done during a
+ * dump operation. NO LOCKING is done during a load operation. Loads
+ * should happen with other processes shutdown.
+ *
+ * Written July 9, 1987 by Jeffrey I. Schiller
+ */
+
+#include <adm_locl.h>
+
+static char *prog;
+
+Principal aprinc;
+
+static des_cblock master_key, new_master_key;
+static des_key_schedule master_key_schedule, new_master_key_schedule;
+
+#define zaptime(foo) bzero((char *)(foo), sizeof(*(foo)))
+
+/* cv_key is a procedure which takes a principle and changes its key,
+ either for a new method of encrypting the keys, or a new master key.
+ if cv_key is null no transformation of key is done (other than net byte
+ order). */
+
+struct callback_args {
+ void (*cv_key)();
+ FILE *output_file;
+};
+
+static void
+print_time(FILE *file, time_t timeval)
+{
+ struct tm *tm;
+ tm = gmtime(&timeval);
+ fprintf(file, " %04d%02d%02d%02d%02d",
+ tm->tm_year < 1900 ? tm->tm_year + 1900: tm->tm_year,
+ tm->tm_mon + 1,
+ tm->tm_mday,
+ tm->tm_hour,
+ tm->tm_min);
+}
+
+static long
+time_explode(char *cp)
+{
+ char wbuf[5];
+ struct tm tp;
+ long maketime(struct tm *tp, int local);
+ int local;
+
+ zaptime(&tp); /* clear out the struct */
+
+ if (strlen(cp) > 10) { /* new format */
+ (void) strncpy(wbuf, cp, 4);
+ wbuf[4] = 0;
+ tp.tm_year = atoi(wbuf);
+ cp += 4; /* step over the year */
+ local = 0; /* GMT */
+ } else { /* old format: local time,
+ year is 2 digits, assuming 19xx */
+ wbuf[0] = *cp++;
+ wbuf[1] = *cp++;
+ wbuf[2] = 0;
+ tp.tm_year = 1900 + atoi(wbuf);
+ local = 1; /* local */
+ }
+
+ wbuf[0] = *cp++;
+ wbuf[1] = *cp++;
+ wbuf[2] = 0;
+ tp.tm_mon = atoi(wbuf)-1;
+
+ wbuf[0] = *cp++;
+ wbuf[1] = *cp++;
+ tp.tm_mday = atoi(wbuf);
+
+ wbuf[0] = *cp++;
+ wbuf[1] = *cp++;
+ tp.tm_hour = atoi(wbuf);
+
+ wbuf[0] = *cp++;
+ wbuf[1] = *cp++;
+ tp.tm_min = atoi(wbuf);
+
+
+ return(maketime(&tp, local));
+}
+
+static int
+dump_db_1(char *arg, Principal *principal)
+{ /* replace null strings with "*" */
+ struct callback_args *a = (struct callback_args *)arg;
+
+ if (principal->instance[0] == '\0') {
+ principal->instance[0] = '*';
+ principal->instance[1] = '\0';
+ }
+ if (principal->mod_name[0] == '\0') {
+ principal->mod_name[0] = '*';
+ principal->mod_name[1] = '\0';
+ }
+ if (principal->mod_instance[0] == '\0') {
+ principal->mod_instance[0] = '*';
+ principal->mod_instance[1] = '\0';
+ }
+ if (a->cv_key != NULL) {
+ (*a->cv_key) (principal);
+ }
+ fprintf(a->output_file, "%s %s %d %d %d %d %x %x",
+ principal->name,
+ principal->instance,
+ principal->max_life,
+ principal->kdc_key_ver,
+ principal->key_version,
+ principal->attributes,
+ (int)htonl (principal->key_low),
+ (int)htonl (principal->key_high));
+ print_time(a->output_file, principal->exp_date);
+ print_time(a->output_file, principal->mod_date);
+ fprintf(a->output_file, " %s %s\n",
+ principal->mod_name,
+ principal->mod_instance);
+ return 0;
+}
+
+static int
+dump_db (char *db_file, FILE *output_file, void (*cv_key) (Principal *))
+{
+ struct callback_args a;
+
+ a.cv_key = cv_key;
+ a.output_file = output_file;
+
+ kerb_db_iterate (dump_db_1, (char *)&a);
+ return fflush(output_file);
+}
+
+static void
+load_db (char *db_file, FILE *input_file)
+{
+ char exp_date_str[50];
+ char mod_date_str[50];
+ int temp1, temp2, temp3;
+ int code;
+ char *temp_db_file;
+ temp1 = strlen(db_file)+2;
+ temp_db_file = malloc (temp1);
+ strcpy(temp_db_file, db_file);
+ strcat(temp_db_file, "~");
+
+ /* Create the database */
+ if ((code = kerb_db_create(temp_db_file)) != 0) {
+ fprintf(stderr, "Couldn't create temp database %s: %s\n",
+ temp_db_file, strerror(code));
+ exit(1);
+ }
+ kerb_db_set_name(temp_db_file);
+ for (;;) { /* explicit break on eof from fscanf */
+ u_long key_lo, key_hi; /* Must match format string */
+ bzero((char *)&aprinc, sizeof(aprinc));
+ if (fscanf(input_file,
+ "%s %s %d %d %d %hd %lx %lx %s %s %s %s\n",
+ aprinc.name,
+ aprinc.instance,
+ &temp1,
+ &temp2,
+ &temp3,
+ &aprinc.attributes,
+ &key_lo,
+ &key_hi,
+ exp_date_str,
+ mod_date_str,
+ aprinc.mod_name,
+ aprinc.mod_instance) == EOF)
+ break;
+ aprinc.key_low = ntohl (key_lo);
+ aprinc.key_high = ntohl (key_hi);
+ aprinc.max_life = (unsigned char) temp1;
+ aprinc.kdc_key_ver = (unsigned char) temp2;
+ aprinc.key_version = (unsigned char) temp3;
+ aprinc.exp_date = time_explode(exp_date_str);
+ aprinc.mod_date = time_explode(mod_date_str);
+ if (aprinc.instance[0] == '*')
+ aprinc.instance[0] = '\0';
+ if (aprinc.mod_name[0] == '*')
+ aprinc.mod_name[0] = '\0';
+ if (aprinc.mod_instance[0] == '*')
+ aprinc.mod_instance[0] = '\0';
+ if (kerb_db_put_principal(&aprinc, 1) != 1) {
+ fprintf(stderr, "Couldn't store %s.%s: %s; load aborted\n",
+ aprinc.name, aprinc.instance,
+ strerror(errno));
+ exit(1);
+ };
+ }
+ if ((code = kerb_db_rename(temp_db_file, db_file)) != 0)
+ perror("database rename failed");
+ (void) fclose(input_file);
+ free(temp_db_file);
+}
+
+/*ARGSUSED*/
+static void
+update_ok_file (char *file_name)
+{
+ /* handle slave locking/failure stuff */
+ char *file_ok;
+ int fd;
+ static char ok[]=".dump_ok";
+
+ if ((file_ok = (char *)malloc(strlen(file_name) + strlen(ok) + 1))
+ == NULL) {
+ fprintf(stderr, "kdb_util: out of memory.\n");
+ (void) fflush (stderr);
+ perror ("malloc");
+ exit (1);
+ }
+ strcpy(file_ok, file_name);
+ strcat(file_ok, ok);
+ if ((fd = open(file_ok, O_WRONLY|O_CREAT|O_TRUNC, 0400)) < 0) {
+ fprintf(stderr, "Error creating 'ok' file, '%s'", file_ok);
+ perror("");
+ (void) fflush (stderr);
+ exit (1);
+ }
+ free(file_ok);
+ close(fd);
+}
+
+static void
+convert_key_new_master (Principal *p)
+{
+ des_cblock key;
+
+ /* leave null keys alone */
+ if ((p->key_low == 0) && (p->key_high == 0)) return;
+
+ /* move current key to des_cblock for encryption, special case master key
+ since that's changing */
+ if ((strncmp (p->name, KERB_M_NAME, ANAME_SZ) == 0) &&
+ (strncmp (p->instance, KERB_M_INST, INST_SZ) == 0)) {
+ bcopy((char *)new_master_key, (char *) key, sizeof (des_cblock));
+ (p->key_version)++;
+ } else {
+ bcopy((char *)&(p->key_low), (char *)key, 4);
+ bcopy((char *)&(p->key_high), (char *) (((long *) key) + 1), 4);
+ kdb_encrypt_key (&key, &key, &master_key, master_key_schedule, DES_DECRYPT);
+ }
+
+ kdb_encrypt_key (&key, &key, &new_master_key, new_master_key_schedule, DES_ENCRYPT);
+
+ bcopy((char *)key, (char *)&(p->key_low), 4);
+ bcopy((char *)(((long *) key) + 1), (char *)&(p->key_high), 4);
+ bzero((char *)key, sizeof (key)); /* a little paranoia ... */
+
+ (p->kdc_key_ver)++;
+}
+
+static void
+clear_secrets (void)
+{
+ bzero((char *)master_key, sizeof (des_cblock));
+ bzero((char *)master_key_schedule, sizeof (des_key_schedule));
+ bzero((char *)new_master_key, sizeof (des_cblock));
+ bzero((char *)new_master_key_schedule, sizeof (des_key_schedule));
+}
+
+static void
+convert_new_master_key (char *db_file, FILE *out)
+{
+
+ printf ("\n\nEnter the CURRENT master key.");
+ if (kdb_get_master_key (TRUE, &master_key, master_key_schedule) != 0) {
+ fprintf (stderr, "%s: Couldn't get master key.\n", prog);
+ clear_secrets ();
+ exit (-1);
+ }
+
+ if (kdb_verify_master_key (&master_key, master_key_schedule, stderr) < 0) {
+ clear_secrets ();
+ exit (-1);
+ }
+
+ printf ("\n\nNow enter the NEW master key. Do not forget it!!");
+ if (kdb_get_master_key (TRUE, &new_master_key, new_master_key_schedule) != 0) {
+ fprintf (stderr, "%s: Couldn't get new master key.\n", prog);
+ clear_secrets ();
+ exit (-1);
+ }
+
+ dump_db (db_file, out, convert_key_new_master);
+}
+
+static void
+convert_key_old_db (Principal *p)
+{
+ des_cblock key;
+
+ /* leave null keys alone */
+ if ((p->key_low == 0) && (p->key_high == 0)) return;
+
+ bcopy((char *)&(p->key_low), (char *)key, 4);
+ bcopy((char *)&(p->key_high), (char *)(((long *) key) + 1), 4);
+
+#ifndef NOENCRYPTION
+ des_pcbc_encrypt((des_cblock *)key,(des_cblock *)key,
+ (long)sizeof(des_cblock),master_key_schedule,
+ (des_cblock *)master_key_schedule, DES_DECRYPT);
+#endif
+
+ /* make new key, new style */
+ kdb_encrypt_key (&key, &key, &master_key, master_key_schedule, DES_ENCRYPT);
+
+ bcopy((char *)key, (char *)&(p->key_low), 4);
+ bcopy((char *)(((long *) key) + 1), (char *)&(p->key_high), 4);
+ bzero((char *)key, sizeof (key)); /* a little paranoia ... */
+}
+
+static void
+convert_old_format_db (char *db_file, FILE *out)
+{
+ des_cblock key_from_db;
+ Principal principal_data[1];
+ int n, more;
+
+ if (kdb_get_master_key (TRUE, &master_key, master_key_schedule) != 0L) {
+ fprintf (stderr, "%s: Couldn't get master key.\n", prog);
+ clear_secrets();
+ exit (-1);
+ }
+
+ /* can't call kdb_verify_master_key because this is an old style db */
+ /* lookup the master key version */
+ n = kerb_get_principal(KERB_M_NAME, KERB_M_INST, principal_data,
+ 1 /* only one please */, &more);
+ if ((n != 1) || more) {
+ fprintf(stderr, "verify_master_key: Kerberos error on master key lookup, %d found.\n", n);
+ exit (-1);
+ }
+
+ /* set up the master key */
+ fprintf(stderr, "Current Kerberos master key version is %d.\n",
+ principal_data[0].kdc_key_ver);
+
+ /*
+ * now use the master key to decrypt (old style) the key in the db, had better
+ * be the same!
+ */
+ bcopy((char *)&principal_data[0].key_low, (char *)key_from_db, 4);
+ bcopy((char *)&principal_data[0].key_high,
+ (char *)(((long *) key_from_db) + 1), 4);
+#ifndef NOENCRYPTION
+ des_pcbc_encrypt(&key_from_db,&key_from_db,(long)sizeof(key_from_db),
+ master_key_schedule,(des_cblock *)master_key_schedule, DES_DECRYPT);
+#endif
+ /* the decrypted database key had better equal the master key */
+ n = bcmp((char *) master_key, (char *) key_from_db,
+ sizeof(master_key));
+ bzero((char *)key_from_db, sizeof(key_from_db));
+
+ if (n) {
+ fprintf(stderr, "\n\07\07verify_master_key: Invalid master key, ");
+ fprintf(stderr, "does not match database.\n");
+ exit (-1);
+ }
+
+ fprintf(stderr, "Master key verified.\n");
+ (void) fflush(stderr);
+
+ dump_db (db_file, out, convert_key_old_db);
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE *file;
+ enum {
+ OP_LOAD,
+ OP_DUMP,
+ OP_SLAVE_DUMP,
+ OP_NEW_MASTER,
+ OP_CONVERT_OLD_DB
+ } op;
+ char *file_name;
+ char *db_name;
+ prog = argv[0];
+
+ if (argc != 3 && argc != 4) {
+ fprintf(stderr, "Usage: %s operation file-name [database name].\n",
+ argv[0]);
+ exit(1);
+ }
+ if (argc == 3)
+ db_name = DBM_FILE;
+ else
+ db_name = argv[3];
+
+ if (kerb_db_set_name (db_name) != 0) {
+ perror("Can't open database");
+ exit(1);
+ }
+
+ if (!strcmp(argv[1], "load"))
+ op = OP_LOAD;
+ else if (!strcmp(argv[1], "dump"))
+ op = OP_DUMP;
+ else if (!strcmp(argv[1], "slave_dump"))
+ op = OP_SLAVE_DUMP;
+ else if (!strcmp(argv[1], "new_master_key"))
+ op = OP_NEW_MASTER;
+ else if (!strcmp(argv[1], "convert_old_db"))
+ op = OP_CONVERT_OLD_DB;
+ else {
+ fprintf(stderr,
+ "%s: %s is an invalid operation.\n", prog, argv[1]);
+ fprintf(stderr,
+ "%s: Valid operations are \"dump\", \"slave_dump\",", argv[0]);
+ fprintf(stderr,
+ "\"load\", \"new_master_key\", and \"convert_old_db\".\n");
+ exit(1);
+ }
+
+ file_name = argv[2];
+ file = fopen(file_name, op == OP_LOAD ? "r" : "w");
+ if (file == NULL) {
+ fprintf(stderr, "%s: Unable to open %s\n", prog, argv[2]);
+ (void) fflush(stderr);
+ perror("open");
+ exit(1);
+ }
+
+ switch (op) {
+ case OP_DUMP:
+ if ((dump_db (db_name, file, (void (*)()) 0) == EOF) ||
+ (fclose(file) == EOF)) {
+ fprintf(stderr, "error on file %s:", file_name);
+ perror("");
+ exit(1);
+ }
+ break;
+ case OP_SLAVE_DUMP:
+ if ((dump_db (db_name, file, (void (*)()) 0) == EOF) ||
+ (fclose(file) == EOF)) {
+ fprintf(stderr, "error on file %s:", file_name);
+ perror("");
+ exit(1);
+ }
+ update_ok_file (file_name);
+ break;
+ case OP_LOAD:
+ load_db (db_name, file);
+ break;
+ case OP_NEW_MASTER:
+ convert_new_master_key (db_name, file);
+ printf("Don't forget to do a `kdb_util load %s' to reload the database!\n", file_name);
+ break;
+ case OP_CONVERT_OLD_DB:
+ convert_old_format_db (db_name, file);
+ printf("Don't forget to do a `kdb_util load %s' to reload the database!\n", file_name);
+ break;
+ }
+ exit(0);
+ }
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+
+PROG= kdestroy
+DPADD= ${LIBKRB} ${LIBDES}
+LDADD= -lkrb -ldes
+BINDIR= /usr/bin
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: kdestroy.1,v 1.1.1.1 1995/12/14 06:52:50 tholo Exp $
+.TH KDESTROY 1 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kdestroy \- destroy Kerberos tickets
+.SH SYNOPSIS
+.B kdestroy
+[
+.B \-f
+]
+[
+.B \-q
+]
+.SH DESCRIPTION
+The
+.I kdestroy
+utility destroys the user's active
+Kerberos
+authorization tickets by writing zeros to the file that contains them.
+If the ticket file does not exist,
+.I kdestroy
+displays a message to that effect.
+.PP
+After overwriting the file,
+.I kdestroy
+removes the file from the system.
+The utility
+displays a message indicating the success or failure of the
+operation.
+If
+.I kdestroy
+is unable to destroy the ticket file,
+the utility will warn you by making your terminal beep.
+.PP
+In the Athena workstation environment,
+the
+.I toehold
+service automatically destroys your tickets when you
+end a workstation session.
+If your site does not provide a similar ticket-destroying mechanism,
+you can place the
+.I kdestroy
+command in your
+.I .logout
+file so that your tickets are destroyed automatically
+when you logout.
+.PP
+The options to
+.I kdestroy
+are as follows:
+.TP 7
+.B \-f
+.I kdestroy
+runs without displaying the status message.
+.TP
+.B \-q
+.I kdestroy
+will not make your terminal beep if it fails to destroy the tickets.
+.SH FILES
+KRBTKFILE environment variable if set, otherwise
+.br
+/tmp/tkt[uid]
+.SH SEE ALSO
+kerberos(1), kinit(1), klist(1)
+.SH BUGS
+.PP
+Only the tickets in the user's current ticket file are destroyed.
+Separate ticket files are used to hold root instance and password
+changing tickets. These files should probably be destroyed too, or
+all of a user's tickets kept in a single ticket file.
+.SH AUTHORS
+Steve Miller, MIT Project Athena/Digital Equipment Corporation
+.br
+Clifford Neuman, MIT Project Athena
+.br
+Bill Sommerfeld, MIT Project Athena
--- /dev/null
+/* $Id: kdestroy.c,v 1.1.1.1 1995/12/14 06:52:50 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * This program causes Kerberos tickets to be destroyed.
+ * Options are:
+ *
+ * -q[uiet] - no bell even if tickets not destroyed
+ * -f[orce] - no message printed at all
+ */
+
+#include <kuser_locl.h>
+
+static char *pname;
+
+static void
+usage()
+{
+ fprintf(stderr, "Usage: %s [-f] [-q]\n", pname);
+ exit(1);
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int fflag=0, qflag=0, k_errno;
+ register char *cp;
+
+ cp = strrchr (argv[0], '/');
+ if (cp == NULL)
+ pname = argv[0];
+ else
+ pname = cp+1;
+
+ if (argc > 2)
+ usage();
+ else if (argc == 2) {
+ if (!strcmp(argv[1], "-f"))
+ ++fflag;
+ else if (!strcmp(argv[1], "-q"))
+ ++qflag;
+ else usage();
+ }
+
+ k_errno = dest_tkt();
+
+ if (fflag) {
+ if (k_errno != 0 && k_errno != RET_TKFIL)
+ exit(1);
+ else
+ exit(0);
+ } else {
+ if (k_errno == 0)
+ printf("Tickets destroyed.\n");
+ else if (k_errno == RET_TKFIL)
+ fprintf(stderr, "No tickets to destroy.\n");
+ else {
+ fprintf(stderr, "Tickets NOT destroyed.\n");
+ if (!qflag)
+ fprintf(stderr, "\007");
+ exit(1);
+ }
+ }
+ exit(0);
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:52 tholo Exp $
+
+PROG= kerberos
+DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES}
+LDADD= -lkdb -lkrb -ldes
+MAN= kerberos.8
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: kerberos.8,v 1.1.1.1 1995/12/14 06:52:52 tholo Exp $
+.TH KERBEROS 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kerberos \- introduction to the Kerberos system
+
+.SH DESCRIPTION
+The
+Kerberos
+system authenticates
+individual users in a network environment.
+After authenticating yourself to
+Kerberos,
+you can use network utilities such as
+.IR rlogin ,
+.IR rcp ,
+and
+.IR rsh
+without
+having to present passwords to remote hosts and without having to bother
+with
+.I \.rhosts
+files.
+Note that these utilities will work without passwords only if
+the remote machines you deal with
+support the
+Kerberos
+system.
+All Athena timesharing machines and public workstations support
+Kerberos.
+.PP
+Before you can use
+Kerberos,
+you must register as an Athena user,
+and you must make sure you have been added to
+the
+Kerberos
+database.
+You can use the
+.I kinit
+command to find out.
+This command
+tries to log you into the
+Kerberos
+system.
+.I kinit
+will prompt you for a username and password.
+Enter your username and password.
+If the utility lets you login without giving you a message,
+you have already been registered.
+.PP
+If you enter your username and
+.I kinit
+responds with this message:
+.nf
+
+Principal unknown (kerberos)
+
+.fi
+you haven't been registered as a
+Kerberos
+user.
+See your system administrator.
+.PP
+A Kerberos name contains three parts.
+The first is the
+.I principal name,
+which is usually a user's or service's name.
+The second is the
+.I instance,
+which in the case of a user is usually null.
+Some users may have privileged instances, however,
+such as ``root'' or ``admin''.
+In the case of a service, the instance is the
+name of the machine on which it runs; i.e. there
+can be an
+.I rlogin
+service running on the machine ABC, which
+is different from the rlogin service running on
+the machine XYZ.
+The third part of a Kerberos name
+is the
+.I realm.
+The realm corresponds to the Kerberos service providing
+authentication for the principal.
+For example, at MIT there is a Kerberos running at the
+Laboratory for Computer Science and one running at
+Project Athena.
+.PP
+When writing a Kerberos name, the principal name is
+separated from the instance (if not null) by a period,
+and the realm (if not the local realm) follows, preceded by
+an ``@'' sign.
+The following are examples of valid Kerberos names:
+.sp
+.nf
+.in +8
+billb
+jis.admin
+srz@lcs.mit.edu
+treese.root@athena.mit.edu
+.in -8
+.fi
+.PP
+When you authenticate yourself with
+Kerberos,
+through either the workstation
+.I toehold
+system or the
+.I kinit
+command,
+Kerberos
+gives you an initial
+Kerberos
+.IR ticket .
+(A
+Kerberos
+ticket
+is an encrypted protocol message that provides authentication.)
+Kerberos
+uses this ticket for network utilities
+such as
+.I rlogin
+and
+.IR rcp .
+The ticket transactions are done transparently,
+so you don't have to worry about their management.
+.PP
+Note, however, that tickets expire.
+Privileged tickets, such as root instance tickets,
+expire in a few minutes, while tickets that carry more ordinary
+privileges may be good for several hours or a day, depending on the
+installation's policy.
+If your login session extends beyond the time limit,
+you will have to re-authenticate yourself to
+Kerberos
+to get new tickets.
+Use the
+.IR kinit
+command to re-authenticate yourself.
+.PP
+If you use the
+.I kinit
+command to get your tickets,
+make sure you use the
+.I kdestroy
+command
+to destroy your tickets before you end your login session.
+You should probably put the
+.I kdestroy
+command in your
+.I \.logout
+file so that your tickets will be destroyed automatically when you logout.
+For more information about the
+.I kinit
+and
+.I kdestroy
+commands,
+see the
+.I kinit(1)
+and
+.I kdestroy(1)
+manual pages.
+.PP
+Currently,
+Kerberos
+supports the following network services:
+.IR rlogin ,
+.IR rsh ,
+and
+.IR rcp .
+Other services are being worked on,
+such as the
+.IR pop
+mail system and NFS (network file system),
+but are not yet available.
+
+.SH "SEE ALSO"
+kdestroy(1), kinit(1), klist(1), kpasswd(1), des_crypt(3), kerberos(3),
+kadmin(8)
+.SH BUGS
+Kerberos
+will not do authentication forwarding.
+In other words,
+if you use
+.I rlogin
+to login to a remote host,
+you cannot use
+Kerberos
+services from that host
+until you authenticate yourself explicitly on that host.
+Although you may need to authenticate yourself on the remote
+host,
+be aware that when you do so,
+.I rlogin
+sends your password across the network in clear text.
+
+.SH AUTHORS
+Steve Miller, MIT Project Athena/Digital Equipment Corporation
+.br
+Clifford Neuman, MIT Project Athena
+
+The following people helped out on various aspects of the system:
+
+Jeff Schiller designed and wrote the administration server and its
+user interface, kadmin.
+He also wrote the dbm version of the database management system.
+
+Mark Colan developed the
+Kerberos
+versions of
+.IR rlogin ,
+.IR rsh ,
+and
+.IR rcp ,
+as well as contributing work on the servers.
+
+John Ostlund developed the
+Kerberos
+versions of
+.I passwd
+and
+.IR userreg .
+
+Stan Zanarotti pioneered Kerberos in a foreign realm (LCS),
+and made many contributions based on that experience.
+
+Many people contributed code and/or useful ideas, including
+Jim Aspnes,
+Bob Baldwin,
+John Barba,
+Richard Basch,
+Jim Bloom,
+Bill Bryant,
+Rob French,
+Dan Geer,
+David Jedlinsky,
+John Kohl,
+John Kubiatowicz,
+Bob McKie,
+Brian Murphy,
+Ken Raeburn,
+Chris Reed,
+Jon Rochlis,
+Mike Shanzer,
+Bill Sommerfeld,
+Jennifer Steiner,
+Ted Ts'o,
+and
+Win Treese.
+
+.SH RESTRICTIONS
+
+COPYRIGHT 1985,1986 Massachusetts Institute of Technology
--- /dev/null
+/* $Id: kerberos.c,v 1.1.1.1 1995/12/14 06:52:52 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include "kerberosIV/site.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <sys/types.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include <netdb.h>
+
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include <kerberosIV/krb_db.h>
+
+#include <prot.h>
+#include <klog.h>
+#include <kdc.h>
+
+static struct sockaddr_in sina = {AF_INET};
+int f;
+
+/* XXX several files in libkdb know about this */
+char *progname;
+
+static des_key_schedule master_key_schedule;
+static des_cblock master_key;
+
+static struct timeval kerb_time;
+static Principal a_name_data; /* for requesting user */
+static Principal s_name_data; /* for services requested */
+static des_cblock session_key;
+static u_char master_key_version;
+static char k_instance[INST_SZ];
+static char *lt;
+static int more;
+
+static int mflag; /* Are we invoked manually? */
+static int lflag; /* Have we set an alterate log file? */
+static char *log_file; /* name of alt. log file */
+static int nflag; /* don't check max age */
+static int rflag; /* alternate realm specified */
+
+/* fields within the received request packet */
+static u_char req_msg_type;
+static u_char req_version;
+static char *req_name_ptr;
+static char *req_inst_ptr;
+static char *req_realm_ptr;
+static u_long req_time_ws;
+
+int req_act_vno = KRB_PROT_VERSION; /* Temporary for version skew */
+
+static char local_realm[REALM_SZ];
+
+/* statistics */
+static int q_bytes; /* current bytes remaining in queue */
+static int q_n; /* how many consecutive non-zero
+ * q_bytes */
+static int max_q_bytes;
+static int max_q_n;
+static int n_auth_req;
+static int n_appl_req;
+static int n_packets;
+
+static int max_age = -1;
+static int pause_int = -1;
+
+/*
+ * Print usage message and exit.
+ */
+static void
+usage(void)
+{
+ fprintf(stderr, "Usage: %s [-s] [-m] [-n] [-p pause_seconds]%s%s\n", progname,
+ " [-a max_age] [-l log_file] [-r realm]"
+ ," [database_pathname]"
+ );
+ exit(1);
+}
+
+/*
+ * kerb_er_reply creates an error reply packet and sends it to the
+ * client.
+ */
+
+static void
+kerb_err_reply(struct sockaddr_in *client, KTEXT pkt, long int err, char *string)
+{
+ static KTEXT_ST e_pkt_st;
+ KTEXT e_pkt = &e_pkt_st;
+ static char e_msg[128];
+
+ strcpy(e_msg, "\nKerberos error -- ");
+ strcat(e_msg, string);
+ cr_err_reply(e_pkt, req_name_ptr, req_inst_ptr, req_realm_ptr,
+ req_time_ws, err, e_msg);
+ sendto(f, e_pkt->dat, e_pkt->length, 0, (struct sockaddr*)client, S_AD_SZ);
+}
+
+static void
+hang(void)
+{
+ if (pause_int == -1) {
+ klog(L_KRB_PERR, "Kerberos will pause so as not to loop init");
+ for (;;)
+ pause();
+ } else {
+ char buf[256];
+ sprintf(buf, "Kerberos will wait %d seconds before dying so as not to loop init", pause_int);
+ klog(L_KRB_PERR, buf);
+ sleep(pause_int);
+ klog(L_KRB_PERR, "Do svedania....\n");
+ exit(1);
+ }
+}
+
+/*
+ * Given a pointer to a long containing the number of seconds
+ * since the beginning of time (midnight 1 Jan 1970 GMT), return
+ * a string containing the local time in the form:
+ *
+ * "25-Jan-88 10:17:56"
+ */
+
+static char *
+strtime(time_t *t)
+{
+ static char st_data[40];
+ static char *st = st_data;
+ struct tm *tm;
+ char *month_sname(int n);
+
+ tm = localtime(t);
+ (void) sprintf(st,"%2d-%s-%02d %02d:%02d:%02d",tm->tm_mday,
+ month_sname(tm->tm_mon + 1),tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ return st;
+}
+
+static int
+check_princ(char *p_name, char *instance, unsigned int lifetime, Principal *p)
+{
+ static int n;
+ static int more;
+
+ n = kerb_get_principal(p_name, instance, p, 1, &more);
+ klog(L_ALL_REQ,
+ "Principal: \"%s\", Instance: \"%s\" Lifetime = %d n = %d",
+ p_name, instance, lifetime, n, 0);
+
+ if (n < 0) {
+ lt = klog(L_KRB_PERR, "Database unavailable!");
+ hang();
+ }
+
+ /*
+ * if more than one p_name, pick one, randomly create a session key,
+ * compute maximum lifetime, lookup authorizations if applicable,
+ * and stuff into cipher.
+ */
+ if (n == 0) {
+ /* service unknown, log error, skip to next request */
+ lt = klog(L_ERR_UNK, "UNKNOWN \"%s\" \"%s\"", p_name,
+ instance, 0);
+ return KERB_ERR_PRINCIPAL_UNKNOWN;
+ }
+ if (more) {
+ /* not unique, log error */
+ lt = klog(L_ERR_NUN, "Principal NOT UNIQUE \"%s\" \"%s\"",
+ p_name, instance, 0);
+ return KERB_ERR_PRINCIPAL_NOT_UNIQUE;
+ }
+ /* If the user's key is null, we want to return an error */
+ if ((p->key_low == 0) && (p->key_high == 0)) {
+ /* User has a null key */
+ lt = klog(L_ERR_NKY, "Null key \"%s\" \"%s\"", p_name,
+ instance, 0);
+ return KERB_ERR_NULL_KEY;
+ }
+ if (master_key_version != p->kdc_key_ver) {
+ /* log error reply */
+ lt = klog(L_ERR_MKV,
+ "Key vers incorrect, KRB = %d, \"%s\" \"%s\" = %d",
+ master_key_version, p->name, p->instance, p->kdc_key_ver,
+ 0);
+ return KERB_ERR_NAME_MAST_KEY_VER;
+ }
+ /* make sure the service hasn't expired */
+ if ((u_long) p->exp_date < (u_long) kerb_time.tv_sec) {
+ /* service did expire, log it */
+ lt = klog(L_ERR_SEXP,
+ "EXPIRED \"%s\" \"%s\" %s", p->name, p->instance,
+ strtime((time_t*)&(p->exp_date)), 0);
+ return KERB_ERR_NAME_EXP;
+ }
+ /* ok is zero */
+ return 0;
+}
+
+/* Set the key for krb_rd_req so we can check tgt */
+static int
+set_tgtkey(char *r)
+ /* Realm for desired key */
+{
+ int n;
+ static char lastrealm[REALM_SZ];
+ Principal p_st;
+ Principal *p = &p_st;
+ des_cblock key;
+
+ if (!strcmp(lastrealm, r))
+ return (KSUCCESS);
+
+ log("Getting key for %s", r);
+
+ n = kerb_get_principal("krbtgt", r, p, 1, &more);
+ if (n == 0)
+ return (KFAILURE);
+
+ /* unseal tgt key from master key */
+ bcopy(&p->key_low, key, 4);
+ bcopy(&p->key_high, ((long *) key) + 1, 4);
+ kdb_encrypt_key(&key, &key, &master_key,
+ master_key_schedule, DES_DECRYPT);
+ krb_set_key(key, 0);
+ strcpy(lastrealm, r);
+ return (KSUCCESS);
+}
+
+static void
+kerberos(struct sockaddr_in *client, KTEXT pkt)
+{
+ static KTEXT_ST rpkt_st;
+ KTEXT rpkt = &rpkt_st;
+ static KTEXT_ST ciph_st;
+ KTEXT ciph = &ciph_st;
+ static KTEXT_ST tk_st;
+ KTEXT tk = &tk_st;
+ static KTEXT_ST auth_st;
+ KTEXT auth = &auth_st;
+ AUTH_DAT ad_st;
+ AUTH_DAT *ad = &ad_st;
+
+
+ static struct in_addr client_host;
+ static int msg_byte_order;
+ static int swap_bytes;
+ static u_char k_flags;
+ u_long lifetime;
+ int i;
+ des_cblock key;
+ des_key_schedule key_s;
+ char *ptr;
+
+
+
+ ciph->length = 0;
+
+ client_host = client->sin_addr;
+
+ /* eval macros and correct the byte order and alignment as needed */
+ req_version = pkt_version(pkt); /* 1 byte, version */
+ req_msg_type = pkt_msg_type(pkt); /* 1 byte, Kerberos msg type */
+
+ req_act_vno = req_version;
+
+ /* check packet version */
+ if (req_version != KRB_PROT_VERSION) {
+ lt = klog(L_KRB_PERR,
+ "KRB prot version mismatch: KRB =%d request = %d",
+ KRB_PROT_VERSION, req_version, 0);
+ /* send an error reply */
+ kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
+ return;
+ }
+ msg_byte_order = req_msg_type & 1;
+
+ swap_bytes = 0;
+ if (msg_byte_order != HOST_BYTE_ORDER) {
+ swap_bytes++;
+ }
+ klog(L_KRB_PINFO,
+ "Prot version: %d, Byte order: %d, Message type: %d",
+ req_version, msg_byte_order, req_msg_type);
+
+ switch (req_msg_type & ~1) {
+
+ case AUTH_MSG_KDC_REQUEST:
+ {
+ u_long req_life; /* Requested liftime */
+ char *service; /* Service name */
+ char *instance; /* Service instance */
+
+ n_auth_req++;
+ tk->length = 0;
+ k_flags = 0; /* various kerberos flags */
+
+
+ /* set up and correct for byte order and alignment */
+ req_name_ptr = (char *) pkt_a_name(pkt);
+ req_inst_ptr = (char *) pkt_a_inst(pkt);
+ req_realm_ptr = (char *) pkt_a_realm(pkt);
+ bcopy(pkt_time_ws(pkt), &req_time_ws, sizeof(req_time_ws));
+ /* time has to be diddled */
+ if (swap_bytes) {
+ swap_u_long(req_time_ws);
+ }
+ ptr = (char *) pkt_time_ws(pkt) + 4;
+
+ req_life = (unsigned char) (*ptr++);
+
+ service = ptr;
+ instance = ptr + strlen(service) + 1;
+
+ rpkt = &rpkt_st;
+ klog(L_INI_REQ,
+ "Initial ticket request Host: %s User: \"%s\" \"%s\"",
+ inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0);
+
+ if ((i = check_princ(req_name_ptr, req_inst_ptr, 0,
+ &a_name_data))) {
+ kerb_err_reply(client, pkt, i, lt);
+ return;
+ }
+ tk->length = 0; /* init */
+ if (strcmp(service, "krbtgt"))
+ klog(L_NTGT_INTK,
+ "INITIAL request from %s.%s for %s.%s",
+ req_name_ptr, req_inst_ptr, service, instance, 0);
+ /* this does all the checking */
+ if ((i = check_princ(service, instance, 0,
+ &s_name_data))) {
+ kerb_err_reply(client, pkt, i, lt);
+ return;
+ }
+ /* Bound requested lifetime with service and user */
+ lifetime = min(req_life, ((u_long) s_name_data.max_life));
+ lifetime = min(lifetime, ((u_long) a_name_data.max_life));
+
+#ifdef NOENCRYPTION
+ bzero(session_key, sizeof(des_cblock));
+#else
+ des_new_random_key(&session_key);
+#endif
+ /* unseal server's key from master key */
+ bcopy(&s_name_data.key_low, key, 4);
+ bcopy(&s_name_data.key_high, ((long *) key) + 1, 4);
+ kdb_encrypt_key(&key, &key, &master_key,
+ master_key_schedule, DES_DECRYPT);
+ /* construct and seal the ticket */
+ krb_create_ticket(tk, k_flags, a_name_data.name,
+ a_name_data.instance, local_realm,
+ client_host.s_addr, session_key, lifetime, kerb_time.tv_sec,
+ s_name_data.name, s_name_data.instance, &key);
+ bzero(key, sizeof(key));
+ bzero(key_s, sizeof(key_s));
+
+ /*
+ * get the user's key, unseal it from the server's key, and
+ * use it to seal the cipher
+ */
+
+ /* a_name_data.key_low a_name_data.key_high */
+ bcopy(&a_name_data.key_low, key, 4);
+ bcopy(&a_name_data.key_high, ((long *) key) + 1, 4);
+
+ /* unseal the a_name key from the master key */
+ kdb_encrypt_key(&key, &key, &master_key,
+ master_key_schedule, DES_DECRYPT);
+
+ create_ciph(ciph, session_key, s_name_data.name,
+ s_name_data.instance, local_realm, lifetime,
+ s_name_data.key_version, tk, kerb_time.tv_sec, &key);
+
+ /* clear session key */
+ bzero(session_key, sizeof(session_key));
+
+ bzero(key, sizeof(key));
+
+
+
+ /* always send a reply packet */
+ rpkt = create_auth_reply(req_name_ptr, req_inst_ptr,
+ req_realm_ptr, req_time_ws, 0, a_name_data.exp_date,
+ a_name_data.key_version, ciph);
+ sendto(f, rpkt->dat, rpkt->length, 0, (struct sockaddr*)client, S_AD_SZ);
+ bzero(&a_name_data, sizeof(a_name_data));
+ bzero(&s_name_data, sizeof(s_name_data));
+ break;
+ }
+ case AUTH_MSG_APPL_REQUEST:
+ {
+ u_long time_ws; /* Workstation time */
+ u_long req_life; /* Requested liftime */
+ char *service; /* Service name */
+ char *instance; /* Service instance */
+ int kerno; /* Kerberos error number */
+ char tktrlm[REALM_SZ];
+
+ n_appl_req++;
+ tk->length = 0;
+ k_flags = 0; /* various kerberos flags */
+
+ auth->length = 4 + strlen((char*)pkt->dat + 3);
+ auth->length += (int) *(pkt->dat + auth->length) +
+ (int) *(pkt->dat + auth->length + 1) + 2;
+
+ bcopy(pkt->dat, auth->dat, auth->length);
+
+ strncpy(tktrlm, (char*)(auth->dat + 3), REALM_SZ);
+ if (set_tgtkey(tktrlm)) {
+ lt = klog(L_ERR_UNK,
+ "FAILED realm %s unknown. Host: %s ",
+ tktrlm, inet_ntoa(client_host));
+ kerb_err_reply(client, pkt, kerno, lt);
+ return;
+ }
+ kerno = krb_rd_req(auth, "ktbtgt", tktrlm, client_host.s_addr,
+ ad, 0);
+
+ if (kerno) {
+ klog(L_ERR_UNK, "FAILED krb_rd_req from %s: %s",
+ inet_ntoa(client_host), krb_err_txt[kerno]);
+ kerb_err_reply(client, pkt, kerno, "krb_rd_req failed");
+ return;
+ }
+ ptr = (char *) pkt->dat + auth->length;
+
+ bcopy(ptr, &time_ws, 4);
+ ptr += 4;
+
+ req_life = (unsigned char) (*ptr++);
+
+ service = ptr;
+ instance = ptr + strlen(service) + 1;
+
+ klog(L_APPL_REQ, "APPL Request %s.%s@%s on %s for %s.%s",
+ ad->pname, ad->pinst, ad->prealm, inet_ntoa(client_host),
+ service, instance, 0);
+
+ if (strcmp(ad->prealm, tktrlm)) {
+ kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
+ "Can't hop realms");
+ return;
+ }
+ if (!strcmp(service, "changepw")) {
+ kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
+ "Can't authorize password changed based on TGT");
+ return;
+ }
+ kerno = check_princ(service, instance, req_life,
+ &s_name_data);
+ if (kerno) {
+ kerb_err_reply(client, pkt, kerno, lt);
+ return;
+ }
+ /* Bound requested lifetime with service and user */
+ lifetime = min(req_life,
+ krb_time_to_life(kerb_time.tv_sec,krb_life_to_time(ad->time_sec,ad->life)));
+ lifetime = min(lifetime, ((u_long) s_name_data.max_life));
+
+ /* unseal server's key from master key */
+ bcopy(&s_name_data.key_low, key, 4);
+ bcopy(&s_name_data.key_high, ((long *) key) + 1, 4);
+ kdb_encrypt_key(&key, &key, &master_key,
+ master_key_schedule, DES_DECRYPT);
+ /* construct and seal the ticket */
+
+#ifdef NOENCRYPTION
+ bzero(session_key, sizeof(des_cblock));
+#else
+ des_new_random_key(&session_key);
+#endif
+
+ krb_create_ticket(tk, k_flags, ad->pname, ad->pinst,
+ ad->prealm, client_host.s_addr,
+ session_key, lifetime, kerb_time.tv_sec,
+ s_name_data.name, s_name_data.instance,
+ &key);
+ bzero(key, sizeof(key));
+ bzero(key_s, sizeof(key_s));
+
+ create_ciph(ciph, session_key, service, instance,
+ local_realm,
+ lifetime, s_name_data.key_version, tk,
+ kerb_time.tv_sec, &ad->session);
+
+ /* clear session key */
+ bzero(session_key, sizeof(session_key));
+
+ bzero(ad->session, sizeof(ad->session));
+
+ rpkt = create_auth_reply(ad->pname, ad->pinst,
+ ad->prealm, time_ws,
+ 0, 0, 0, ciph);
+ sendto(f, rpkt->dat, rpkt->length, 0, (struct sockaddr*)client, S_AD_SZ);
+ bzero(&s_name_data, sizeof(s_name_data));
+ break;
+ }
+
+
+#ifdef notdef_DIE
+ case AUTH_MSG_DIE:
+ {
+ lt = klog(L_DEATH_REQ,
+ "Host: %s User: \"%s\" \"%s\" Kerberos killed",
+ inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0);
+ exit(0);
+ }
+#endif /* notdef_DIE */
+
+ default:
+ {
+ lt = klog(L_KRB_PERR,
+ "Unknown message type: %d from %s port %u",
+ req_msg_type, inet_ntoa(client_host),
+ ntohs(client->sin_port));
+ break;
+ }
+ }
+}
+
+/*
+ * setup_disc
+ *
+ * disconnect all descriptors, remove ourself from the process
+ * group that spawned us.
+ */
+
+static void
+setup_disc(void)
+{
+ int s;
+
+ for (s = 0; s < 3; s++) {
+ (void) close(s);
+ }
+
+ (void) open("/dev/null", 0);
+ (void) dup2(0, 1);
+ (void) dup2(0, 2);
+
+ setsid();
+
+ (void) chdir("/tmp");
+ return;
+}
+
+/*
+ * Make sure that database isn't stale.
+ *
+ * Exit if it is; we don't want to tell lies.
+ */
+
+static void check_db_age(void)
+{
+ long age;
+
+ if (max_age != -1) {
+ /* Requires existance of kerb_get_db_age() */
+ gettimeofday(&kerb_time, 0);
+ age = kerb_get_db_age();
+ if (age == 0) {
+ klog(L_KRB_PERR, "Database currently being updated!");
+ hang();
+ }
+ if ((age + max_age) < kerb_time.tv_sec) {
+ klog(L_KRB_PERR, "Database out of date!");
+ hang();
+ /* NOTREACHED */
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ struct sockaddr_in from;
+ register int n;
+ int on = 1;
+ int child;
+ struct servent *sp;
+ int fromlen;
+ static KTEXT_ST pkt_st;
+ KTEXT pkt = &pkt_st;
+ int kerror;
+ int c;
+ extern char *optarg;
+ extern int optind;
+
+ progname = argv[0];
+
+ while ((c = getopt(argc, argv, "snmp:a:l:r:")) != EOF) {
+ switch(c) {
+ case 's':
+ /*
+ * Set parameters to slave server defaults.
+ */
+ if (max_age == -1 && !nflag)
+ max_age = ONE_DAY; /* 24 hours */
+ if (pause_int == -1)
+ pause_int = FIVE_MINUTES; /* 5 minutes */
+ if (lflag == 0) {
+ log_file = KRBSLAVELOG;
+ lflag++;
+ }
+ break;
+ case 'n':
+ max_age = -1; /* don't check max age. */
+ nflag++;
+ break;
+ case 'm':
+ mflag++; /* running manually; prompt for master key */
+ break;
+ case 'p':
+ /* Set pause interval. */
+ if (!isdigit(optarg[0]))
+ usage();
+ pause_int = atoi(optarg);
+ if ((pause_int < 5) || (pause_int > ONE_HOUR)) {
+ fprintf(stderr, "pause_int must be between 5 and 3600 seconds.\n");
+ usage();
+ }
+ break;
+ case 'a':
+ /* Set max age. */
+ if (!isdigit(optarg[0]))
+ usage();
+ max_age = atoi(optarg);
+ if ((max_age < ONE_HOUR) || (max_age > THREE_DAYS)) {
+ fprintf(stderr, "max_age must be between one hour and three days, in seconds\n");
+ usage();
+ }
+ break;
+ case 'l':
+ /* Set alternate log file */
+ lflag++;
+ log_file = optarg;
+ break;
+ case 'r':
+ /* Set realm name */
+ rflag++;
+ strcpy(local_realm, optarg);
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (optind == (argc-1)) {
+ if (kerb_db_set_name(argv[optind]) != 0) {
+ fprintf(stderr, "Could not set alternate database name\n");
+ exit(1);
+ }
+ optind++;
+ }
+
+ if (optind != argc)
+ usage();
+
+ printf("Kerberos server starting\n");
+
+ if ((!nflag) && (max_age != -1))
+ printf("\tMaximum database age: %d seconds\n", max_age);
+ if (pause_int != -1)
+ printf("\tSleep for %d seconds on error\n", pause_int);
+ else
+ printf("\tSleep forever on error\n");
+ if (mflag)
+ printf("\tMaster key will be entered manually\n");
+
+ printf("\tLog file is %s\n", lflag ? log_file : KRBLOG);
+
+ if (lflag)
+ kset_logfile(log_file);
+
+ /* find our hostname, and use it as the instance */
+ if (gethostname(k_instance, INST_SZ)) {
+ fprintf(stderr, "%s: gethostname error\n", progname);
+ exit(1);
+ }
+
+ if ((sp = getservbyname("kerberos", "udp")) == 0) {
+ fprintf(stderr, "%s: udp/kerberos unknown service\n", progname);
+ exit(1);
+ }
+ sina.sin_port = sp->s_port;
+
+ if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ fprintf(stderr, "%s: Can't open socket\n", progname);
+ exit(1);
+ }
+ if (setsockopt(f, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
+ fprintf(stderr, "%s: setsockopt (SO_REUSEADDR)\n", progname);
+
+ if (bind(f, (struct sockaddr*)&sina, sizeof(sina)) < 0) {
+ fprintf(stderr, "%s: Can't bind socket\n", progname);
+ exit(1);
+ }
+ /* do all the database and cache inits */
+ if ((n = kerb_init())) {
+ if (mflag) {
+ printf("Kerberos db and cache init ");
+ printf("failed = %d ...exiting\n", n);
+ exit(-1);
+ } else {
+ klog(L_KRB_PERR,
+ "Kerberos db and cache init failed = %d ...exiting", n);
+ hang();
+ }
+ }
+
+ /* Make sure database isn't stale */
+ check_db_age();
+
+ /* setup master key */
+ if (kdb_get_master_key (mflag, &master_key, master_key_schedule) != 0) {
+ klog (L_KRB_PERR, "kerberos: couldn't get master key.\n");
+ exit (-1);
+ }
+ kerror = kdb_verify_master_key (&master_key, master_key_schedule, stdout);
+ if (kerror < 0) {
+ klog (L_KRB_PERR, "Can't verify master key.");
+ bzero (master_key, sizeof (master_key));
+ bzero (master_key_schedule, sizeof (master_key_schedule));
+ exit (-1);
+ }
+
+ master_key_version = (u_char) kerror;
+
+ fprintf(stdout, "\nCurrent Kerberos master key version is %d\n",
+ master_key_version);
+ des_init_random_number_generator(&master_key);
+
+ if (!rflag) {
+ /* Look up our local realm */
+ krb_get_lrealm(local_realm, 1);
+ }
+ fprintf(stdout, "Local realm: %s\n", local_realm);
+ fflush(stdout);
+
+ if (set_tgtkey(local_realm)) {
+ /* Ticket granting service unknown */
+ klog(L_KRB_PERR, "Ticket granting ticket service unknown");
+ fprintf(stderr, "Ticket granting ticket service unknown\n");
+ exit(1);
+ }
+ if (mflag) {
+ if ((child = fork()) != 0) {
+ printf("Kerberos started, PID=%d\n", child);
+ exit(0);
+ }
+ setup_disc();
+ }
+ /* receive loop */
+ for (;;) {
+ fromlen = S_AD_SZ;
+ n = recvfrom(f, pkt->dat, MAX_PKT_LEN, 0, (struct sockaddr*)&from, &fromlen);
+ if (n > 0) {
+ pkt->length = n;
+ pkt->mbz = 0; /* force zeros to catch runaway strings */
+ /* see what is left in the input queue */
+ ioctl(f, FIONREAD, &q_bytes);
+ gettimeofday(&kerb_time, NULL);
+ q_n++;
+ max_q_n = max(max_q_n, q_n);
+ n_packets++;
+ klog(L_NET_INFO,
+ "q_byt %d, q_n %d, rd_byt %d, mx_q_b %d, mx_q_n %d, n_pkt %d",
+ q_bytes, q_n, n, max_q_bytes, max_q_n, n_packets, 0);
+ max_q_bytes = max(max_q_bytes, q_bytes);
+ if (!q_bytes)
+ q_n = 0; /* reset consecutive packets */
+ kerberos(&from, pkt);
+ } else
+ klog(L_NET_ERR,
+ "%s: bad recvfrom n = %d errno = %d", progname, n, errno, 0);
+ }
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:51 tholo Exp $
+
+PROG= kinit
+DPADD= ${LIBKRB} ${LIBDES}
+LDADD= -lkrb -ldes
+BINDIR= /usr/bin
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: kinit.1,v 1.1.1.1 1995/12/14 06:52:52 tholo Exp $
+.TH KINIT 1 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kinit \- Kerberos login utility
+.SH SYNOPSIS
+.B kinit
+[
+.B \-irvl
+]
+.SH DESCRIPTION
+The
+.I kinit
+command is used to login to the
+Kerberos
+authentication and authorization system.
+Note that only registered
+Kerberos
+users can use the
+Kerberos
+system.
+For information about registering as a
+Kerberos
+user,
+see the
+.I kerberos(1)
+manual page.
+.PP
+If you are logged in to a workstation that is running the
+.I toehold
+service,
+you do not have to use
+.I kinit.
+The
+.I toehold
+login procedure will log you into
+Kerberos
+automatically.
+You will need to use
+.I kinit
+only in those situations in which
+your original tickets have expired.
+(Tickets expire in about a day.)
+Note as well that
+.I toehold
+will automatically destroy your tickets when you logout from the workstation.
+.PP
+When you use
+.I kinit
+without options,
+the utility
+prompts for your username and Kerberos password,
+and tries to authenticate your login with the local
+Kerberos
+server.
+.PP
+If
+Kerberos
+authenticates the login attempt,
+.I kinit
+retrieves your initial ticket and puts it in the ticket file specified by
+your KRBTKFILE environment variable.
+If this variable is undefined,
+your ticket will be stored in the
+.IR /tmp
+directory,
+in the file
+.I tktuid ,
+where
+.I uid
+specifies your user identification number.
+.PP
+If you have logged in to
+Kerberos
+without the benefit of the workstation
+.I toehold
+system,
+make sure you use the
+.I kdestroy
+command to destroy any active tickets before you end your login session.
+You may want to put the
+.I kdestroy
+command in your
+.I \.logout
+file so that your tickets will be destroyed automatically when you logout.
+.PP
+The options to
+.I kinit
+are as follows:
+.TP 7
+.B \-i
+.I kinit
+prompts you for a
+Kerberos
+instance.
+.TP
+.B \-r
+.I kinit
+prompts you for a
+Kerberos
+realm.
+This option lets you authenticate yourself with a remote
+Kerberos
+server.
+.TP
+.B \-v
+Verbose mode.
+.I kinit
+prints the name of the ticket file used, and
+a status message indicating the success or failure of
+your login attempt.
+.TP
+.B \-l
+.I kinit
+prompts you for a ticket lifetime in minutes. Due to protocol
+restrictions in Kerberos Version 4, this value must be between 5 and
+1275 minutes.
+.SH SEE ALSO
+.PP
+kerberos(1), kdestroy(1), klist(1), toehold(1)
+.SH BUGS
+The
+.B \-r
+option has not been fully implemented.
+.SH AUTHORS
+Steve Miller, MIT Project Athena/Digital Equipment Corporation
+.br
+Clifford Neuman, MIT Project Athena
--- /dev/null
+/* $Id: kinit.c,v 1.1.1.1 1995/12/14 06:52:51 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Routine to initialize user to Kerberos. Prompts optionally for
+ * user, instance and realm. Authenticates user and gets a ticket
+ * for the Kerberos ticket-granting service for future use.
+ *
+ * Options are:
+ *
+ * -i[instance]
+ * -r[realm]
+ * -v[erbose]
+ * -l[ifetime]
+ */
+
+#include <kuser_locl.h>
+#include <sys/param.h>
+
+#define LIFE DEFAULT_TKT_LIFE /* lifetime of ticket in 5-minute units */
+
+char *progname;
+
+static void
+get_input(s, size, stream)
+char *s;
+int size;
+FILE *stream;
+{
+ char *p;
+
+ if (fgets(s, size, stream) == NULL)
+ exit(1);
+ if ( (p = strchr(s, '\n')) != NULL)
+ *p = '\0';
+}
+
+
+static void
+usage()
+{
+ fprintf(stderr, "Usage: %s [-irvl] [name]\n", progname);
+ exit(1);
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char aname[ANAME_SZ];
+ char inst[INST_SZ];
+ char realm[REALM_SZ];
+ char buf[MAXHOSTNAMELEN];
+ char *username = NULL;
+ int iflag, rflag, vflag, lflag, lifetime, k_errno;
+ register char *cp;
+ register i;
+
+ *inst = *realm = '\0';
+ iflag = rflag = vflag = lflag = 0;
+ lifetime = LIFE;
+ progname = (cp = strrchr(*argv, '/')) ? cp + 1 : *argv;
+
+ while (--argc) {
+ if ((*++argv)[0] != '-') {
+ if (username)
+ usage();
+ username = *argv;
+ continue;
+ }
+ for (i = 1; (*argv)[i] != '\0'; i++)
+ switch ((*argv)[i]) {
+ case 'i': /* Instance */
+ ++iflag;
+ continue;
+ case 'r': /* Realm */
+ ++rflag;
+ continue;
+ case 'v': /* Verbose */
+ ++vflag;
+ continue;
+ case 'l':
+ ++lflag;
+ continue;
+ default:
+ usage();
+ exit(1);
+ }
+ }
+ if (username &&
+ (k_errno = kname_parse(aname, inst, realm, username))
+ != KSUCCESS) {
+ fprintf(stderr, "%s: %s\n", progname, krb_err_txt[k_errno]);
+ iflag = rflag = 1;
+ username = NULL;
+ }
+ if (gethostname(buf, MAXHOSTNAMELEN)) {
+ fprintf(stderr, "%s: gethostname failed\n", progname);
+ exit(1);
+ }
+ printf("%s (%s)\n", ORGANIZATION, buf);
+ if (username) {
+ printf("Kerberos Initialization for \"%s", aname);
+ if (*inst)
+ printf(".%s", inst);
+ if (*realm)
+ printf("@%s", realm);
+ printf("\"\n");
+ } else {
+ printf("Kerberos Initialization\n");
+ printf("Kerberos name: ");
+ get_input(aname, sizeof(aname), stdin);
+ if (!*aname)
+ exit(0);
+ if (!k_isname(aname)) {
+ fprintf(stderr, "%s: bad Kerberos name format\n",
+ progname);
+ exit(1);
+ }
+ }
+ /* optional instance */
+ if (iflag) {
+ printf("Kerberos instance: ");
+ get_input(inst, sizeof(inst), stdin);
+ if (!k_isinst(inst)) {
+ fprintf(stderr, "%s: bad Kerberos instance format\n",
+ progname);
+ exit(1);
+ }
+ }
+ if (rflag) {
+ printf("Kerberos realm: ");
+ get_input(realm, sizeof(realm), stdin);
+ if (!k_isrealm(realm)) {
+ fprintf(stderr, "%s: bad Kerberos realm format\n",
+ progname);
+ exit(1);
+ }
+ }
+ if (lflag) {
+ printf("Kerberos ticket lifetime (minutes): ");
+ get_input(buf, sizeof(buf), stdin);
+ lifetime = atoi(buf);
+ if (lifetime < 5)
+ lifetime = 1;
+ else
+ lifetime /= krb_time_to_life(0, lifetime*60);
+ /* This should be changed if the maximum ticket lifetime */
+ /* changes */
+ if (lifetime > 255)
+ lifetime = 255;
+ }
+ if (!*realm && krb_get_lrealm(realm, 1)) {
+ fprintf(stderr, "%s: krb_get_lrealm failed\n", progname);
+ exit(1);
+ }
+ k_errno = krb_get_pw_in_tkt(aname, inst, realm, "krbtgt", realm,
+ lifetime, 0);
+ if (vflag) {
+ printf("Kerberos realm %s:\n", realm);
+ printf("%s\n", krb_err_txt[k_errno]);
+ } else if (k_errno) {
+ fprintf(stderr, "%s: %s\n", progname, krb_err_txt[k_errno]);
+ exit(1);
+ }
+ exit(0);
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:50 tholo Exp $
+
+PROG= klist
+DPADD= ${LIBKRB} ${LIBDES}
+LDADD= -lkrb -ldes
+BINDIR= /usr/bin
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: klist.1,v 1.1.1.1 1995/12/14 06:52:50 tholo Exp $
+.TH KLIST 1 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+klist \- list currently held Kerberos tickets
+.SH SYNOPSIS
+.B klist
+[
+\fB\-s \fR|\fB \-t\fR
+] [
+.B \-file
+name ] [
+.B \-srvtab
+]
+.br
+.SH DESCRIPTION
+.I klist
+prints the name of the tickets file and the
+identity of the principal the tickets are for (as listed in the
+tickets file), and
+lists the principal names of all Kerberos tickets currently held by
+the user, along with the issue and expire time for each authenticator.
+Principal names are listed in the form
+.I name.instance@realm,
+with the '.' omitted if the instance is null,
+and the '@' omitted if the realm is null.
+
+If given the
+.B \-s
+option,
+.I klist
+does not print the issue and expire times, the name of the tickets file,
+or the identity of the principal.
+
+If given the
+.B \-t
+option,
+.B klist
+checks for the existence of a non-expired ticket-granting-ticket in the
+ticket file. If one is present, it exits with status 0, else it exits
+with status 1. No output is generated when this option is specified.
+
+If given the
+.B \-file
+option, the following argument is used as the ticket file.
+Otherwise, if the
+.B KRBTKFILE
+environment variable is set, it is used.
+If this environment variable
+is not set, the file
+.B /tmp/tkt[uid]
+is used, where
+.B uid
+is the current user-id of the user.
+
+If given the
+.B \-srvtab
+option, the file is treated as a service key file, and the names of the
+keys contained therein are printed. If no file is
+specified with a
+.B \-file
+option, the default is
+.IR /etc/srvtab .
+.SH FILES
+.TP 2i
+/etc/krb.conf
+to get the name of the local realm
+.TP
+/tmp/tkt[uid]
+as the default ticket file ([uid] is the decimal UID of the user).
+.TP
+/etc/srvtab
+as the default service key file
+.SH SEE ALSO
+.PP
+kerberos(1), kinit(1), kdestroy(1)
+.SH BUGS
+When reading a file as a service key file, very little sanity or error
+checking is performed.
--- /dev/null
+/* $Id: klist.c,v 1.1.1.1 1995/12/14 06:52:50 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Lists your current Kerberos tickets.
+ * Written by Bill Sommerfeld, MIT Project Athena.
+ */
+
+#include <kuser_locl.h>
+
+char *whoami; /* What was I invoked as?? */
+
+static char *
+short_date(dp)
+ time_t *dp;
+{
+ register char *cp;
+
+ if (*dp == (time_t)(-1L)) return "*** Never *** ";
+ cp = ctime(dp) + 4;
+ cp[15] = '\0';
+ return (cp);
+}
+
+static void
+display_tktfile(file, tgt_test, long_form)
+char *file;
+int tgt_test, long_form;
+{
+ char pname[ANAME_SZ];
+ char pinst[INST_SZ];
+ char prealm[REALM_SZ];
+ char buf1[20], buf2[20];
+ int k_errno;
+ CREDENTIALS c;
+ int header = 1;
+
+ if ((file == NULL) && ((file = getenv("KRBTKFILE")) == NULL))
+ file = TKT_FILE;
+
+ if (long_form)
+ printf("Ticket file: %s\n", file);
+
+ /*
+ * Since krb_get_tf_realm will return a ticket_file error,
+ * we will call tf_init and tf_close first to filter out
+ * things like no ticket file. Otherwise, the error that
+ * the user would see would be
+ * klist: can't find realm of ticket file: No ticket file (tf_util)
+ * instead of
+ * klist: No ticket file (tf_util)
+ */
+
+ /* Open ticket file */
+ if ((k_errno = tf_init(file, R_TKT_FIL))) {
+ if (!tgt_test)
+ fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
+ exit(1);
+ }
+ /* Close ticket file */
+ (void) tf_close();
+
+ /*
+ * We must find the realm of the ticket file here before calling
+ * tf_init because since the realm of the ticket file is not
+ * really stored in the principal section of the file, the
+ * routine we use must itself call tf_init and tf_close.
+ */
+ if ((k_errno = krb_get_tf_realm(file, prealm)) != KSUCCESS) {
+ if (!tgt_test)
+ fprintf(stderr, "%s: can't find realm of ticket file: %s\n",
+ whoami, krb_err_txt[k_errno]);
+ exit(1);
+ }
+
+ /* Open ticket file */
+ if ((k_errno = tf_init(file, R_TKT_FIL))) {
+ if (!tgt_test)
+ fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
+ exit(1);
+ }
+ /* Get principal name and instance */
+ if ((k_errno = tf_get_pname(pname)) ||
+ (k_errno = tf_get_pinst(pinst))) {
+ if (!tgt_test)
+ fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]);
+ exit(1);
+ }
+
+ /*
+ * You may think that this is the obvious place to get the
+ * realm of the ticket file, but it can't be done here as the
+ * routine to do this must open the ticket file. This is why
+ * it was done before tf_init.
+ */
+
+ if (!tgt_test && long_form)
+ printf("Principal:\t%s%s%s%s%s\n\n", pname,
+ (pinst[0] ? "." : ""), pinst,
+ (prealm[0] ? "@" : ""), prealm);
+ while ((k_errno = tf_get_cred(&c)) == KSUCCESS) {
+ if (!tgt_test && long_form && header) {
+ printf("%-15s %-15s %s\n",
+ " Issued", " Expires", " Principal");
+ header = 0;
+ }
+ if (tgt_test) {
+ c.issue_date = krb_life_to_time(c.issue_date, c.lifetime);
+ if (!strcmp(c.service, TICKET_GRANTING_TICKET) &&
+ !strcmp(c.instance, prealm)) {
+ if (time(0) < c.issue_date)
+ exit(0); /* tgt hasn't expired */
+ else
+ exit(1); /* has expired */
+ }
+ continue; /* not a tgt */
+ }
+ if (long_form) {
+ (void) strcpy(buf1, short_date(&c.issue_date));
+ c.issue_date = krb_life_to_time(c.issue_date, c.lifetime);
+ if (time(0) < (unsigned long) c.issue_date)
+ (void) strcpy(buf2, short_date(&c.issue_date));
+ else
+ (void) strcpy(buf2, ">>> Expired <<< ");
+ printf("%s %s ", buf1, buf2);
+ }
+ printf("%s%s%s%s%s\n",
+ c.service, (c.instance[0] ? "." : ""), c.instance,
+ (c.realm[0] ? "@" : ""), c.realm);
+ }
+ if (tgt_test)
+ exit(1); /* no tgt found */
+ if (header && long_form && k_errno == EOF) {
+ printf("No tickets in file.\n");
+ }
+}
+
+/* adapted from getst() in librkb */
+/*
+ * ok_getst() takes a file descriptor, a string and a count. It reads
+ * from the file until either it has read "count" characters, or until
+ * it reads a null byte. When finished, what has been read exists in
+ * the given string "s". If "count" characters were actually read, the
+ * last is changed to a null, so the returned string is always null-
+ * terminated. ok_getst() returns the number of characters read, including
+ * the null terminator.
+ *
+ * If there is a read error, it returns -1 (like the read(2) system call)
+ */
+
+static int
+ok_getst(fd, s, n)
+ int fd;
+ register char *s;
+ int n;
+{
+ register count = n;
+ int err;
+ while ((err = read(fd, s, 1)) > 0 && --count)
+ if (*s++ == '\0')
+ return (n - count);
+ if (err < 0)
+ return(-1);
+ *s = '\0';
+ return (n - count);
+}
+
+static void
+display_srvtab(file)
+char *file;
+{
+ int stab;
+ char serv[SNAME_SZ];
+ char inst[INST_SZ];
+ char rlm[REALM_SZ];
+ unsigned char key[8];
+ unsigned char vno;
+ int count;
+
+ printf("Server key file: %s\n", file);
+
+ if ((stab = open(file, O_RDONLY, 0400)) < 0) {
+ perror(file);
+ exit(1);
+ }
+ printf("%-15s %-15s %-10s %s\n","Service","Instance","Realm",
+ "Key Version");
+ printf("------------------------------------------------------\n");
+
+ /* argh. getst doesn't return error codes, it silently fails */
+ while (((count = ok_getst(stab, serv, SNAME_SZ)) > 0)
+ && ((count = ok_getst(stab, inst, INST_SZ)) > 0)
+ && ((count = ok_getst(stab, rlm, REALM_SZ)) > 0)) {
+ if (((count = read(stab,(char *) &vno,1)) != 1) ||
+ ((count = read(stab,(char *) key,8)) != 8)) {
+ if (count < 0)
+ perror("reading from key file");
+ else
+ fprintf(stderr, "key file truncated\n");
+ exit(1);
+ }
+ printf("%-15s %-15s %-15s %d\n",serv,inst,rlm,vno);
+ }
+ if (count < 0)
+ perror(file);
+ (void) close(stab);
+}
+
+static void
+usage()
+{
+ fprintf(stderr,
+ "Usage: %s [ -s | -t ] [ -file filename ] [ -srvtab ]\n", whoami);
+ exit(1);
+}
+
+/* ARGSUSED */
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int long_form = 1;
+ int tgt_test = 0;
+ int do_srvtab = 0;
+ char *tkt_file = NULL;
+ char *cp;
+
+ whoami = (cp = strrchr(*argv, '/')) ? cp + 1 : *argv;
+
+ while (*(++argv)) {
+ if (!strcmp(*argv, "-s")) {
+ long_form = 0;
+ continue;
+ }
+ if (!strcmp(*argv, "-t")) {
+ tgt_test = 1;
+ long_form = 0;
+ continue;
+ }
+ if (!strcmp(*argv, "-l")) { /* now default */
+ continue;
+ }
+ if (!strcmp(*argv, "-file")) {
+ if (*(++argv)) {
+ tkt_file = *argv;
+ continue;
+ } else
+ usage();
+ }
+ if (!strcmp(*argv, "-srvtab")) {
+ if (tkt_file == NULL) /* if no other file spec'ed,
+ set file to default srvtab */
+ tkt_file = KEYFILE;
+ do_srvtab = 1;
+ continue;
+ }
+ usage();
+ }
+
+ if (do_srvtab)
+ display_srvtab(tkt_file);
+ else
+ display_tktfile(tkt_file, tgt_test, long_form);
+ exit(0);
+}
--- /dev/null
+# from: @(#)Makefile 8.1 (Berkeley) 6/4/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:54 tholo Exp $
+
+PROG= kpasswdd
+SRCS= kpasswdd.c des_rw.c
+.PATH: ${.CURDIR}/../../usr.bin/rlogin
+CFLAGS+=-DKERBEROS -I${.CURDIR}/../../usr.bin/passwd
+DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES}
+LDADD= -lkdb -lkrb -ldes
+MAN= kpasswdd.8
+BINDIR=/usr/libexec
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from @(#)kpasswdd.8 8.1 (Berkeley) 6/9/93
+.\" $Id: kpasswdd.8,v 1.1.1.1 1995/12/14 06:52:53 tholo Exp $
+.\"
+.Dd June 9, 1993
+.Dt KPASSWDD 8
+.Os
+.Sh NAME
+.Nm kpasswdd
+.Nd Kerberos password changing daemon
+.Sh SYNOPSIS
+.Nm kpasswdd
+.Sh DESCRIPTION
+.Nm Kpasswdd
+is the server for the
+.Xr passwd 1
+program.
+The server provides a remote password changing facility
+with Kerberos authentication.
+A user must provide the old Kerberos password, encrypted
+in a random session key, to the server.
+.Nm Kpasswdd
+runs only on the Kerberos server, as it directly updates the
+Kerberos database.
+.Sh SEE ALSO
+.Xr kerberos 1 ,
+.Xr passwd 1
+.Sh HISTORY
+The
+.Nm kpasswdd
+utility first appeared in 4.4BSD.
--- /dev/null
+/* $Id: kpasswdd.c,v 1.1.1.1 1995/12/14 06:52:53 tholo Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)kpasswdd.c 8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * kpasswdd - update a principal's passwd field in the Kerberos
+ * database. Called from inetd.
+ * K. Fall
+ * 12-Dec-88
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/signal.h>
+#include <netinet/in.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include <kerberosIV/krb_db.h>
+#include <stdio.h>
+#include "kpasswd_proto.h"
+
+static struct kpasswd_data kpwd_data;
+static des_cblock master_key, key;
+static Key_schedule master_key_schedule,
+ key_schedule, random_sched;
+long mkeyversion;
+AUTH_DAT kdata;
+static Principal principal_data;
+static struct update_data ud_data;
+
+char inst[INST_SZ];
+char version[9];
+KTEXT_ST ticket;
+
+char *progname; /* for the library */
+
+main()
+{
+ struct sockaddr_in foreign;
+ int foreign_len = sizeof(foreign);
+ int rval, more;
+ static char name[] = "kpasswdd";
+
+ static struct rlimit rl = { 0, 0 };
+
+ progname = name;
+ openlog("kpasswdd", LOG_CONS | LOG_PID, LOG_AUTH);
+
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+ if (setrlimit(RLIMIT_CORE, &rl) < 0) {
+ syslog(LOG_ERR, "setrlimit: %m");
+ exit(1);
+ }
+
+ if (getpeername(0, &foreign, &foreign_len) < 0) {
+ syslog(LOG_ERR,"getpeername: %m");
+ exit(1);
+ }
+
+ strcpy(inst, "*");
+ rval = krb_recvauth(
+ 0L, /* options--!MUTUAL */
+ 0, /* file desc */
+ &ticket, /* client's ticket */
+ SERVICE, /* expected service */
+ inst, /* expected instance */
+ &foreign, /* foreign addr */
+ (struct sockaddr_in *) 0, /* local addr */
+ &kdata, /* returned krb data */
+ "", /* service keys file */
+ (bit_64 *) NULL, /* returned key schedule */
+ version
+ );
+
+
+ if (rval != KSUCCESS) {
+ syslog(LOG_NOTICE, "krb_recvauth: %s", krb_err_txt[rval]);
+ cleanup();
+ exit(1);
+ }
+
+ if (*version == '\0') {
+ /* indicates error on client's side (no tickets, etc.) */
+ cleanup();
+ exit(0);
+ } else if (strcmp(version, "KPWDV0.1") != 0) {
+ syslog(LOG_NOTICE,
+ "kpasswdd version conflict (recv'd %s)",
+ version);
+ cleanup();
+ exit(1);
+ }
+
+
+ /* get master key */
+ if (kdb_get_master_key(0, &master_key, master_key_schedule) != 0) {
+ syslog(LOG_ERR, "couldn't get master key");
+ cleanup();
+ exit(1);
+ }
+
+ mkeyversion = kdb_get_master_key(NULL, &master_key, master_key_schedule);
+
+ if (mkeyversion < 0) {
+ syslog(LOG_NOTICE, "couldn't verify master key");
+ cleanup();
+ exit(1);
+ }
+
+ /* get principal info */
+ rval = kerb_get_principal(
+ kdata.pname,
+ kdata.pinst,
+ &principal_data,
+ 1,
+ &more
+ );
+
+ if (rval < 0) {
+ syslog(LOG_NOTICE,
+ "error retrieving principal record for %s.%s",
+ kdata.pname, kdata.pinst);
+ cleanup();
+ exit(1);
+ }
+
+ if (rval != 1 || (more != 0)) {
+ syslog(LOG_NOTICE, "more than 1 dbase entry for %s.%s",
+ kdata.pname, kdata.pinst);
+ cleanup();
+ exit(1);
+ }
+
+ /* get the user's key */
+
+ bcopy(&principal_data.key_low, key, 4);
+ bcopy(&principal_data.key_high, ((long *) key) + 1, 4);
+ kdb_encrypt_key(&key, &key, &master_key, master_key_schedule,
+ DECRYPT);
+ key_sched(&key, key_schedule);
+ des_set_key(&key, key_schedule);
+
+
+ /* get random key and send it over {random} Kperson */
+
+ random_key(kpwd_data.random_key);
+ strcpy(kpwd_data.secure_msg, SECURE_STRING);
+ if (des_write(0, &kpwd_data, sizeof(kpwd_data)) != sizeof(kpwd_data)) {
+ syslog(LOG_NOTICE, "error writing initial data");
+ cleanup();
+ exit(1);
+ }
+
+ bzero(key, sizeof(key));
+ bzero(key_schedule, sizeof(key_schedule));
+
+ /* now read update info: { info }Krandom */
+
+ key_sched(&kpwd_data.random_key, random_sched);
+ des_set_key(&kpwd_data.random_key, random_sched);
+ if (des_read(0, &ud_data, sizeof(ud_data)) != sizeof(ud_data)) {
+ syslog(LOG_NOTICE, "update aborted");
+ cleanup();
+ exit(1);
+ }
+
+ /* validate info string by looking at the embedded string */
+
+ if (strcmp(ud_data.secure_msg, SECURE_STRING) != 0) {
+ syslog(LOG_NOTICE, "invalid update from %s",
+ inet_ntoa(foreign.sin_addr));
+ cleanup();
+ exit(1);
+ }
+
+ /* produce the new key entry in the database { key }Kmaster */
+ string_to_key(ud_data.pw, &key);
+ kdb_encrypt_key(&key, &key,
+ &master_key, master_key_schedule,
+ ENCRYPT);
+ bcopy(key, &principal_data.key_low, 4);
+ bcopy(((long *) key) + 1,
+ &principal_data.key_high, 4);
+ bzero(key, sizeof(key));
+ principal_data.key_version++;
+ if (kerb_put_principal(&principal_data, 1)) {
+ syslog(LOG_ERR, "couldn't write new record for %s.%s",
+ principal_data.name, principal_data.instance);
+ cleanup();
+ exit(1);
+ }
+
+ syslog(LOG_NOTICE,"wrote new password field for %s.%s from %s",
+ principal_data.name,
+ principal_data.instance,
+ inet_ntoa(foreign.sin_addr)
+ );
+
+ send_ack(0, "Update complete.\n");
+ cleanup();
+ exit(0);
+}
+
+cleanup()
+{
+ bzero(&kpwd_data, sizeof(kpwd_data));
+ bzero(&master_key, sizeof(master_key));
+ bzero(master_key_schedule, sizeof(master_key_schedule));
+ bzero(key, sizeof(key));
+ bzero(key_schedule, sizeof(key_schedule));
+ bzero(random_sched, sizeof(random_sched));
+ bzero(&principal_data, sizeof(principal_data));
+ bzero(&ud_data, sizeof(ud_data));
+}
+
+send_ack(remote, msg)
+ int remote;
+ char *msg;
+{
+ int cc;
+ cc = des_write(remote, msg, strlen(msg) + 1);
+ if (cc <= 0) {
+ syslog(LOG_NOTICE, "error writing ack");
+ cleanup();
+ exit(1);
+ }
+}
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $
+
+PROG= kprop
+LDADD+= -lkrb -ldes
+DPADD+= ${LIBKRB} ${LIBDES}
+NOMAN= noman
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $Id: kprop.c,v 1.1.1.1 1995/12/14 06:52:49 tholo Exp $ */
+
+/*-
+ * Copyright 1987 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information,
+ * please see the file <mit-copyright.h>.
+ */
+
+#include <slav_locl.h>
+#include <kprop.h>
+#include <sys/param.h>
+
+static char kprop_version[KPROP_PROT_VERSION_LEN] = KPROP_PROT_VERSION;
+
+int debug = 0;
+
+char my_realm[REALM_SZ];
+int princ_data_size = 3 * sizeof(long) + 3 * sizeof(unsigned char);
+short transfer_mode, net_transfer_mode;
+int force_flag;
+static char ok[] = ".dump_ok";
+
+struct slave_host {
+ u_long net_addr;
+ char *name;
+ char *instance;
+ char *realm;
+ int not_time_yet;
+ int succeeded;
+ struct slave_host *next;
+};
+
+static void
+Death(char *s)
+{
+ fprintf(stderr, "kprop: ");
+ perror(s);
+ exit(1);
+}
+
+static
+int get_slaves(struct slave_host **psl, char *file, time_t ok_mtime)
+{
+ FILE *fin;
+ char namebuf[128], *inst;
+ char *pc;
+ struct hostent *host;
+ struct slave_host **th;
+ char path[256];
+ char *ppath;
+ struct stat stbuf;
+
+ if ((fin = fopen(file, "r")) == NULL) {
+ fprintf(stderr, "Can't open slave host file, '%s'.\n", file);
+ exit(-1);
+ }
+ strcpy(path, file);
+ if ((ppath = strrchr(path, '/'))) {
+ ppath += 1;
+ } else {
+ ppath = path;
+ }
+ for (th = psl; fgets(namebuf, sizeof namebuf, fin); th = &(*th)->next) {
+ if ((pc = strchr(namebuf, '\n'))) {
+ *pc = '\0';
+ } else {
+ fprintf(stderr, "Host name too long (>= %d chars) in '%s'.\n",
+ (int)(sizeof(namebuf)), file);
+ exit(-1);
+ }
+ host = gethostbyname(namebuf);
+ if (host == NULL) {
+ fprintf(stderr, "Unknown host '%s' in '%s'.\n", namebuf, file);
+ exit(-1);
+ }
+ (*th) = (struct slave_host *) malloc(sizeof(struct slave_host));
+ if (!*th) {
+ fprintf(stderr, "No memory reading host list from '%s'.\n",
+ file);
+ exit(-1);
+ }
+ bzero( (*th) , (sizeof(struct slave_host)) );
+ (*th)->name = malloc(strlen(namebuf) + 1);
+ if (!(*th)->name) {
+ fprintf(stderr, "No memory reading host list from '%s'.\n",
+ file);
+ exit(-1);
+ }
+ /* get kerberos cannonical instance name */
+ strcpy((*th)->name, namebuf);
+ inst = krb_get_phost ((*th)->name);
+ (*th)->instance = malloc(strlen(inst) + 1);
+ if (!(*th)->instance) {
+ fprintf(stderr, "No memory reading host list from '%s'.\n",
+ file);
+ exit(-1);
+ }
+ strcpy((*th)->instance, inst);
+ /* what a concept, slave servers in different realms! */
+ (*th)->realm = my_realm;
+ bcopy(host->h_addr, (char *)&(*th)->net_addr, sizeof(host->h_addr));
+ (*th)->not_time_yet = 0;
+ (*th)->succeeded = 0;
+ (*th)->next = NULL;
+ strcat(strcpy(ppath, (*th)->name), "-last-prop");
+ if (!force_flag && !stat(path, &stbuf) && stbuf.st_mtime > ok_mtime) {
+ (*th)->not_time_yet = 1;
+ (*th)->succeeded = 1; /* no change since last success */
+ }
+ }
+ fclose(fin);
+ return (1);
+}
+
+/* The master -> slave protocol looks like this:
+ 1) 8 byte version string
+ 2) 2 bytes of "transfer mode" (net byte order of course)
+ 3) ticket/authentication send by sendauth
+ 4) 4 bytes of "block" length (u_long)
+ 5) data
+
+ 4 and 5 repeat til EOF ...
+*/
+
+static int
+prop_to_slaves(struct slave_host *sl, int fd, char *fslv)
+{
+ char buf[KPROP_BUFSIZ];
+ char obuf[KPROP_BUFSIZ + 64 /* leave room for private msg overhead */ ];
+ struct servent *sp;
+ struct sockaddr_in sin, my_sin;
+ int i, n, s;
+ struct slave_host *cs; /* current slave */
+ char path[256], my_host_name[MAXHOSTNAMELEN], *p_my_host_name;
+ char kprop_service_instance[INST_SZ];
+ char *pc;
+ u_long cksum;
+ u_long length, nlength;
+ long kerror;
+ KTEXT_ST ticket;
+ CREDENTIALS cred;
+ MSG_DAT msg_dat;
+ static char tkstring[] = "/tmp/kproptktXXXXXX";
+
+ des_key_schedule session_sched;
+
+ (void) mktemp(tkstring);
+ krb_set_tkt_string(tkstring);
+
+ if ((sp = getservbyname("krb_prop", "tcp")) == 0) {
+ fprintf(stderr, "tcp/krb_prop: service unknown.\n");
+ exit(1);
+ }
+
+ bzero(&sin, sizeof sin);
+ sin.sin_family = AF_INET;
+ sin.sin_port = sp->s_port;
+ sin.sin_addr.s_addr = INADDR_ANY;
+
+ strcpy(path, fslv);
+ if ((pc = strrchr(path, '/'))) {
+ pc += 1;
+ } else {
+ pc = path;
+ }
+
+ for (i = 0; i < 5; i++) { /* try each slave five times max */
+ for (cs = sl; cs; cs = cs->next) {
+ if (!cs->succeeded) {
+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("kprop: socket");
+ exit(1);
+ }
+ bcopy(&cs->net_addr, &sin.sin_addr,
+ sizeof cs->net_addr);
+
+ if (connect(s, (struct sockaddr *) &sin, sizeof sin) < 0) {
+ fprintf(stderr, "%s: ", cs->name);
+ perror("connect");
+ close(s);
+ continue; /*** NEXT SLAVE ***/
+ }
+
+ /* for krb_mk_{priv, safe} */
+ bzero (&my_sin, sizeof my_sin);
+ n = sizeof my_sin;
+ if (getsockname (s, (struct sockaddr *) &my_sin, &n) != 0) {
+ fprintf (stderr, "kprop: can't get socketname.");
+ perror ("getsockname");
+ close (s);
+ continue; /*** NEXT SLAVE ***/
+ }
+ if (n != sizeof (my_sin)) {
+ fprintf (stderr, "kprop: can't get socketname. len");
+ close (s);
+ continue; /*** NEXT SLAVE ***/
+ }
+
+ /* Get ticket */
+ kerror = krb_mk_req (&ticket, KPROP_SERVICE_NAME,
+ cs->instance, cs->realm, (u_long) 0);
+ /* if ticket has expired try to get a new one, but
+ * first get a TGT ...
+ */
+ if (kerror != MK_AP_OK) {
+ if (gethostname (my_host_name, sizeof(my_host_name)) != 0) {
+ fprintf (stderr, "%s:", cs->name);
+ perror ("getting my hostname");
+ close (s);
+ break; /* next one can't work either! */
+ }
+ /* get canonical kerberos service instance name */
+ p_my_host_name = krb_get_phost (my_host_name);
+ /* copy it to make sure gethostbyname static doesn't
+ * screw us. */
+ strcpy (kprop_service_instance, p_my_host_name);
+ kerror = krb_get_svc_in_tkt (KPROP_SERVICE_NAME,
+#if 0
+ kprop_service_instance,
+#else
+ KRB_MASTER,
+#endif
+ my_realm,
+ TGT_SERVICE_NAME,
+ my_realm,
+ 96,
+ KPROP_SRVTAB);
+ if (kerror != INTK_OK) {
+ fprintf (stderr,
+ "%s: %s. While getting initial ticket\n",
+ cs->name, krb_err_txt[kerror]);
+ close (s);
+ goto punt;
+ }
+ kerror = krb_mk_req (&ticket, KPROP_SERVICE_NAME,
+ cs->instance, cs->realm, (u_long) 0);
+ }
+ if (kerror != MK_AP_OK) {
+ fprintf (stderr, "%s: %s. Calling krb_mk_req.",
+ cs->name, krb_err_txt[kerror]);
+ close (s);
+ continue; /*** NEXT SLAVE ***/
+ }
+
+ if (write(s, kprop_version, sizeof(kprop_version))
+ != sizeof(kprop_version)) {
+ fprintf (stderr, "%s: ", cs->name);
+ perror ("write (version) error");
+ close (s);
+ continue; /*** NEXT SLAVE ***/
+ }
+
+ net_transfer_mode = htons (transfer_mode);
+ if (write(s, &net_transfer_mode, sizeof(net_transfer_mode))
+ != sizeof(net_transfer_mode)) {
+ fprintf (stderr, "%s: ", cs->name);
+ perror ("write (transfer_mode) error");
+ close (s);
+ continue; /*** NEXT SLAVE ***/
+ }
+
+ kerror = krb_get_cred (KPROP_SERVICE_NAME, cs->instance,
+ cs->realm, &cred);
+ if (kerror != KSUCCESS) {
+ fprintf (stderr, "%s: %s. Getting session key.",
+ cs->name, krb_err_txt[kerror]);
+ close (s);
+ continue; /*** NEXT SLAVE ***/
+ }
+#ifdef NOENCRYPTION
+ bzero((char *)session_sched, sizeof(session_sched));
+#else
+ if (des_key_sched (&cred.session, session_sched)) {
+ fprintf (stderr, "%s: can't make key schedule.",
+ cs->name);
+ close (s);
+ continue; /*** NEXT SLAVE ***/
+ }
+#endif
+ /* SAFE (quad_cksum) and CLEAR are just not good enough */
+ cksum = 0;
+#ifdef not_working_yet
+ if (transfer_mode != KPROP_TRANSFER_PRIVATE) {
+ cksum = get_data_checksum(fd, session_sched);
+ lseek(fd, 0L, 0);
+ }
+ else
+#endif
+ {
+ struct stat st;
+ fstat (fd, &st);
+ cksum = st.st_size;
+ }
+ kerror = krb_sendauth(KOPT_DO_MUTUAL,
+ s,
+ &ticket,
+ KPROP_SERVICE_NAME,
+ cs->instance,
+ cs->realm,
+ cksum,
+ &msg_dat,
+ &cred,
+ session_sched,
+ &my_sin,
+ &sin,
+ KPROP_PROT_VERSION);
+ if (kerror != KSUCCESS) {
+ fprintf (stderr, "%s: %s. Calling krb_sendauth.",
+ cs->name, krb_err_txt[kerror]);
+ close (s);
+ continue; /*** NEXT SLAVE ***/
+ }
+
+ lseek(fd, 0L, SEEK_SET); /* Rewind file before rereading it. */
+ while ((n = read(fd, buf, sizeof buf))) {
+ if (n < 0) {
+ perror("input file read error");
+ exit(1);
+ }
+ switch (transfer_mode) {
+ case KPROP_TRANSFER_PRIVATE:
+ case KPROP_TRANSFER_SAFE:
+ if (transfer_mode == KPROP_TRANSFER_PRIVATE)
+ length = krb_mk_priv (buf, obuf, n,
+ session_sched, &cred.session,
+ &my_sin, &sin);
+ else
+ length = krb_mk_safe (buf, obuf, n,
+ &cred.session,
+ &my_sin, &sin);
+ if (length == -1) {
+ fprintf (stderr, "%s: %s failed.",
+ cs->name,
+ (transfer_mode == KPROP_TRANSFER_PRIVATE)
+ ? "krb_rd_priv" : "krb_rd_safe");
+ close (s);
+ continue; /*** NEXT SLAVE ***/
+ }
+ nlength = htonl(length);
+ if (write(s, &nlength, sizeof nlength)
+ != sizeof nlength) {
+ fprintf (stderr, "%s: ", cs->name);
+ perror ("write error");
+ close (s);
+ continue; /*** NEXT SLAVE ***/
+ }
+ if (write(s, obuf, length) != length) {
+ fprintf(stderr, "%s: ", cs->name);
+ perror("write error");
+ close(s);
+ continue; /*** NEXT SLAVE ***/
+ }
+ break;
+ case KPROP_TRANSFER_CLEAR:
+ if (write(s, buf, n) != n) {
+ fprintf(stderr, "%s: ", cs->name);
+ perror("write error");
+ close(s);
+ continue; /*** NEXT SLAVE ***/
+ }
+ break;
+ }
+ }
+ close(s);
+ cs->succeeded = 1;
+ fprintf(stderr, "%s: success.\n", cs->name);
+ strcat(strcpy(pc, cs->name), "-last-prop");
+ unlink(path);
+ close(creat(path, 0600));
+ }
+ }
+ }
+punt:
+
+ dest_tkt();
+ for (cs = sl; cs; cs = cs->next) {
+ if (!cs->succeeded)
+ return (0); /* didn't get this slave */
+ }
+ return (1);
+}
+
+int
+main(int argc, char **argv)
+{
+ int fd, i;
+ char *floc, *floc_ok;
+ char *fslv;
+ struct stat stbuf, stbuf_ok;
+ time_t l_init, l_final;
+ char *pc;
+ int l_diff;
+ static struct slave_host *slave_host_list = NULL;
+ struct slave_host *sh;
+
+ transfer_mode = KPROP_TRANSFER_PRIVATE;
+
+ time(&l_init);
+ pc = ctime(&l_init);
+ pc[strlen(pc) - 1] = '\0';
+ printf("\nStart slave propagation: %s\n", pc);
+
+ floc = (char *) NULL;
+ fslv = (char *) NULL;
+
+ if (krb_get_lrealm(my_realm,1) != KSUCCESS)
+ Death ("Getting my kerberos realm. Check krb.conf");
+
+ for (i = 1; i < argc; i++)
+ switch (argv[i][0]) {
+ case '-':
+ if (strcmp (argv[i], "-private") == 0)
+ transfer_mode = KPROP_TRANSFER_PRIVATE;
+#ifdef not_safe_yet
+ else if (strcmp (argv[i], "-safe") == 0)
+ transfer_mode = KPROP_TRANSFER_SAFE;
+ else if (strcmp (argv[i], "-clear") == 0)
+ transfer_mode = KPROP_TRANSFER_CLEAR;
+#endif
+ else if (strcmp (argv[i], "-realm") == 0) {
+ i++;
+ if (i < argc)
+ strcpy(my_realm, argv[i]);
+ else
+ goto usage;
+ } else if (strcmp (argv[i], "-force") == 0)
+ force_flag++;
+ else {
+ fprintf (stderr, "kprop: unknown control argument %s.\n",
+ argv[i]);
+ exit (1);
+ }
+ break;
+ default:
+ /* positional arguments are marginal at best ... */
+ if (floc == (char *) NULL)
+ floc = argv[i];
+ else {
+ if (fslv == (char *) NULL)
+ fslv = argv[i];
+ else {
+ usage:
+ /* already got floc and fslv, what is this? */
+ fprintf(stderr,
+ "\nUsage: kprop [-force] [-realm realm] [-private|-safe|-clear] data_file slaves_file\n\n");
+ exit(1);
+ }
+ }
+ }
+ if ((floc == (char *)NULL) || (fslv == (char *)NULL))
+ goto usage;
+
+ if ((floc_ok = (char *) malloc(strlen(floc) + strlen(ok) + 1))
+ == NULL) {
+ Death(floc);
+ }
+ strcat(strcpy(floc_ok, floc), ok);
+
+ if ((fd = open(floc, O_RDONLY)) < 0) {
+ Death(floc);
+ }
+ if (flock(fd, LOCK_EX | LOCK_NB)) {
+ Death(floc);
+ }
+ if (stat(floc, &stbuf)) {
+ Death(floc);
+ }
+ if (stat(floc_ok, &stbuf_ok)) {
+ Death(floc_ok);
+ }
+ if (stbuf.st_mtime > stbuf_ok.st_mtime) {
+ fprintf(stderr, "kprop: '%s' more recent than '%s'.\n",
+ floc, floc_ok);
+ exit(1);
+ }
+ if (!get_slaves(&slave_host_list, fslv, stbuf_ok.st_mtime)) {
+ fprintf(stderr,
+ "kprop: can't read slave host file '%s'.\n", fslv);
+ exit(1);
+ }
+#ifdef KPROP_DBG
+ {
+ struct slave_host *sh;
+ int i;
+ fprintf(stderr, "\n\n");
+ fflush(stderr);
+ for (sh = slave_host_list; sh; sh = sh->next) {
+ fprintf(stderr, "slave %d: %s, %s", i++, sh->name,
+ inet_ntoa(sh->net_addr));
+ fflush(stderr);
+ }
+ }
+#endif /* KPROP_DBG */
+
+ if (!prop_to_slaves(slave_host_list, fd, fslv)) {
+ fprintf(stderr,
+ "kprop: propagation failed.\n");
+ exit(1);
+ }
+ if (flock(fd, LOCK_UN)) {
+ Death(floc);
+ }
+ fprintf(stderr, "\n\n");
+ for (sh = slave_host_list; sh; sh = sh->next) {
+ fprintf(stderr, "%s:\t\t%s\n", sh->name,
+ (sh->not_time_yet? "Not time yet" : (sh->succeeded ? "Succeeded" : "FAILED")));
+ }
+
+ time(&l_final);
+ l_diff = l_final - l_init;
+ printf("propagation finished, %d:%02d:%02d elapsed\n",
+ l_diff / 3600, (l_diff % 3600) / 60, l_diff % 60);
+
+ exit(0);
+}
+
+#ifdef doesnt_work_yet
+u_long get_data_checksum(fd, key_sched)
+ int fd;
+ des_key_schedule key_sched;
+{
+ unsigned long cksum = 0;
+ int n;
+ char buf[BUFSIZ];
+ long obuf[2];
+
+ while (n = read(fd, buf, sizeof buf)) {
+ if (n < 0) {
+ fprintf(stderr, "Input data file read error: ");
+ perror("read");
+ exit(1);
+ }
+ cksum = cbc_cksum(buf, obuf, n, key_sched, key_sched);
+ }
+ return cksum;
+}
+#endif
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:52 tholo Exp $
+
+PROG= kpropd
+LDADD+= -lkrb -ldes
+DPADD+= ${LIBKRB} ${LIBDES}
+NOMAN= noman
+BINDIR=/usr/libexec
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $Id: kpropd.c,v 1.1.1.1 1995/12/14 06:52:52 tholo Exp $ */
+
+/*-
+ * Copyright 1987 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information,
+ * please see the file <mit-copyright.h>.
+ */
+
+/*
+ * This program is run on slave servers, to catch updates "pushed"
+ * from the master kerberos server in a realm.
+ */
+
+#include <slav_locl.h>
+#include <kprop.h>
+
+static char *kdb_util_path = "kdb_util";
+
+static char kprop_version[KPROP_PROT_VERSION_LEN] = KPROP_PROT_VERSION;
+
+int debug = 0;
+
+char *logfile = K_LOGFIL;
+
+char errmsg[256];
+int pause_int = 300; /* 5 minutes in seconds */
+
+static char buf[KPROP_BUFSIZ+64 /* leave room for private msg overhead */];
+
+static void
+SlowDeath(void)
+{
+ klog(L_KRB_PERR, "kpropd will pause before dying so as not to loop init");
+ sleep(pause_int);
+ klog(L_KRB_PERR, "AAAAAHHHHhhhh....");
+ exit(1);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "\nUsage: kpropd [-r realm] [-s srvtab] [-l logfile] fname\n\n");
+ SlowDeath();
+}
+
+static void
+recv_auth (int in, int out, int private, struct sockaddr_in *remote, struct sockaddr_in *local, AUTH_DAT *ad)
+{
+ u_long length;
+ long kerror;
+ int n;
+ MSG_DAT msg_data;
+ des_key_schedule session_sched;
+
+ if (private)
+#ifdef NOENCRYPTION
+ bzero((char *)session_sched, sizeof(session_sched));
+#else
+ if (des_key_sched (&ad->session, session_sched)) {
+ klog (L_KRB_PERR, "kpropd: can't make key schedule");
+ SlowDeath();
+ }
+#endif
+
+ while (1) {
+ n = krb_net_read (in, (char *)&length, sizeof length);
+ if (n == 0) break;
+ if (n < 0) {
+ sprintf (errmsg, "kpropd: read: %s", strerror(errno));
+ klog (L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ length = ntohl (length);
+ if (length > sizeof buf) {
+ sprintf (errmsg, "kpropd: read length %ld, bigger than buf %d",
+ length, (int)(sizeof(buf)));
+ klog (L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ n = krb_net_read(in, buf, length);
+ if (n < 0) {
+ sprintf(errmsg, "kpropd: read: %s", strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ if (private)
+ kerror = krb_rd_priv (buf, n, session_sched, &ad->session,
+ remote, local, &msg_data);
+ else
+ kerror = krb_rd_safe (buf, n, &ad->session,
+ remote, local, &msg_data);
+ if (kerror != KSUCCESS) {
+ sprintf (errmsg, "kpropd: %s: %s",
+ private ? "krb_rd_priv" : "krb_rd_safe",
+ krb_err_txt[kerror]);
+ klog (L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ if (write(out, msg_data.app_data, msg_data.app_length) !=
+ msg_data.app_length) {
+ sprintf(errmsg, "kpropd: write: %s", strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ }
+}
+
+static void
+recv_clear (int in, int out)
+{
+ int n;
+
+ while (1) {
+ n = read (in, buf, sizeof buf);
+ if (n == 0) break;
+ if (n < 0) {
+ sprintf (errmsg, "kpropd: read: %s", strerror(errno));
+ klog (L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ if (write(out, buf, n) != n) {
+ sprintf(errmsg, "kpropd: write: %s", strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ struct sockaddr_in from;
+ struct sockaddr_in sin;
+ struct servent *sp;
+ int s, s2, fd, n, fdlock;
+ int from_len;
+ char local_file[256];
+ char local_temp[256];
+ struct hostent *hp;
+ char hostname[256];
+ char from_str[128];
+ long kerror;
+ AUTH_DAT auth_dat;
+ KTEXT_ST ticket;
+ char my_instance[INST_SZ];
+ char my_realm[REALM_SZ];
+ char cmd[1024];
+ short net_transfer_mode, transfer_mode;
+ des_key_schedule session_sched;
+ char version[9];
+ int c;
+ extern char *optarg;
+ extern int optind;
+ int rflag = 0;
+ char *srvtab = "";
+ char *local_db = DBM_FILE;
+
+ if (argv[argc - 1][0] == 'k' && isdigit(argv[argc - 1][1])) {
+ argc--; /* ttys file hack */
+ }
+ while ((c = getopt(argc, argv, "r:s:d:l:p:P:")) != EOF) {
+ switch(c) {
+ case 'r':
+ rflag++;
+ strcpy(my_realm, optarg);
+ break;
+ case 's':
+ srvtab = optarg;
+ break;
+ case 'd':
+ local_db = optarg;
+ break;
+ case 'l':
+ logfile = optarg;
+ break;
+ case 'p':
+ case 'P':
+ kdb_util_path = optarg;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+ if (optind != argc-1)
+ usage();
+
+ kset_logfile(logfile);
+
+ klog(L_KRB_PERR, "\n\n***** kpropd started *****");
+
+ strcpy(local_file, argv[optind]);
+ strcat(strcpy(local_temp, argv[optind]), ".tmp");
+
+ if ((sp = getservbyname("krb_prop", "tcp")) == NULL) {
+ klog(L_KRB_PERR, "kpropd: tcp/krb_prop: unknown service.");
+ SlowDeath();
+ }
+ bzero((char *)&sin, sizeof(sin));
+ sin.sin_port = sp->s_port;
+ sin.sin_family = AF_INET;
+
+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ sprintf(errmsg, "kpropd: socket: %s", strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ if (bind(s, (struct sockaddr*)&sin, sizeof sin) < 0) {
+ sprintf(errmsg, "kpropd: bind: %s", strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+
+ if (!rflag) {
+ kerror = krb_get_lrealm(my_realm,1);
+ if (kerror != KSUCCESS) {
+ sprintf (errmsg, "kpropd: Can't get local realm. %s",
+ krb_err_txt[kerror]);
+ klog (L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ }
+
+ /* Responder uses KPROP_SERVICE_NAME.'hostname' and requestor always
+ uses KPROP_SERVICE_NAME.KRB_MASTER (rcmd.kerberos) */
+ strcpy(my_instance, "*");
+
+ klog(L_KRB_PERR, "Established socket");
+
+ listen(s, 5);
+ for (;;) {
+ from_len = sizeof from;
+ if ((s2 = accept(s, (struct sockaddr *) &from, &from_len)) < 0) {
+ sprintf(errmsg, "kpropd: accept: %s", strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ continue;
+ }
+ strcpy(from_str, inet_ntoa(from.sin_addr));
+
+ if ((hp = gethostbyaddr((char*)&(from.sin_addr.s_addr), from_len, AF_INET)) == NULL) {
+ strcpy(hostname, "UNKNOWN");
+ } else {
+ strcpy(hostname, hp->h_name);
+ }
+
+ sprintf(errmsg, "Connection from %s, %s", hostname, from_str);
+ klog(L_KRB_PERR, errmsg);
+
+ /* for krb_rd_{priv, safe} */
+ n = sizeof sin;
+ if (getsockname (s2, (struct sockaddr *) &sin, &n) != 0) {
+ fprintf (stderr, "kpropd: can't get socketname.\n");
+ perror ("getsockname");
+ SlowDeath();
+ }
+ if (n != sizeof (sin)) {
+ fprintf (stderr, "kpropd: can't get socketname. len");
+ SlowDeath();
+ }
+
+ if ((fdlock = open(local_temp, O_WRONLY | O_CREAT, 0600)) < 0) {
+ sprintf(errmsg, "kpropd: open: %s", strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ if (flock(fdlock, LOCK_EX | LOCK_NB)) {
+ sprintf(errmsg, "kpropd: flock: %s", strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ if ((fd = creat(local_temp, 0600)) < 0) {
+ sprintf(errmsg, "kpropd: creat: %s", strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ if ((n = read (s2, buf, sizeof (kprop_version)))
+ != sizeof (kprop_version)) {
+ klog (L_KRB_PERR, "kpropd: can't read kprop protocol version str.");
+ SlowDeath();
+ }
+ if (strncmp (buf, kprop_version, sizeof (kprop_version))
+ != 0) {
+ sprintf (errmsg, "kpropd: unsupported version %s", buf);
+ klog (L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+
+ if ((n = read (s2, &net_transfer_mode, sizeof (net_transfer_mode)))
+ != sizeof (net_transfer_mode)) {
+ klog (L_KRB_PERR, "kpropd: can't read transfer mode.");
+ SlowDeath();
+ }
+ transfer_mode = ntohs (net_transfer_mode);
+ kerror = krb_recvauth(KOPT_DO_MUTUAL, s2, &ticket,
+ KPROP_SERVICE_NAME,
+ my_instance,
+ &from,
+ &sin,
+ &auth_dat,
+ srvtab,
+ session_sched,
+ version);
+ if (kerror != KSUCCESS) {
+ sprintf (errmsg, "kpropd: %s: Calling getkdata",
+ krb_err_txt[kerror]);
+ klog (L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+
+ sprintf (errmsg, "kpropd: Connection from %s.%s@%s",
+ auth_dat.pname, auth_dat.pinst, auth_dat.prealm);
+ klog (L_KRB_PERR, errmsg);
+
+ /* AUTHORIZATION is done here. We might want to expand this to
+ * read an acl file at some point, but allowing for now
+ * KPROP_SERVICE_NAME.KRB_MASTER@local-realm is fine ... */
+
+ if ((strcmp (KPROP_SERVICE_NAME, auth_dat.pname) != 0) ||
+ (strcmp (KRB_MASTER, auth_dat.pinst) != 0) ||
+ (strcmp (my_realm, auth_dat.prealm) != 0)) {
+ klog (L_KRB_PERR, "Authorization denied!");
+ SlowDeath();
+ }
+
+ switch (transfer_mode) {
+ case KPROP_TRANSFER_PRIVATE:
+ recv_auth (s2, fd, 1 /* private */, &from, &sin, &auth_dat);
+ break;
+ case KPROP_TRANSFER_SAFE:
+ recv_auth (s2, fd, 0 /* safe */, &from, &sin, &auth_dat);
+ break;
+ case KPROP_TRANSFER_CLEAR:
+ recv_clear (s2, fd);
+ break;
+ default:
+ sprintf (errmsg, "kpropd: bad transfer mode %d", transfer_mode);
+ klog (L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+
+ if (transfer_mode != KPROP_TRANSFER_PRIVATE) {
+ klog(L_KRB_PERR, "kpropd: non-private transfers not supported\n");
+ SlowDeath();
+#ifdef doesnt_work_yet
+ lseek(fd, (long) 0, L_SET);
+ if (auth_dat.checksum != get_data_checksum (fd, session_sched)) {
+ klog(L_KRB_PERR, "kpropd: checksum doesn't match");
+ SlowDeath();
+ }
+#endif
+ } else
+
+ {
+ struct stat st;
+ fstat(fd, &st);
+ if (st.st_size != auth_dat.checksum) {
+ klog(L_KRB_PERR, "kpropd: length doesn't match");
+ SlowDeath();
+ }
+ }
+ close(fd);
+ close(s2);
+ klog(L_KRB_PERR, "File received.");
+
+ if (rename(local_temp, local_file) < 0) {
+ sprintf(errmsg, "kpropd: rename: %s", strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ klog(L_KRB_PERR, "Temp file renamed to %s", local_file);
+
+ if (flock(fdlock, LOCK_UN)) {
+ sprintf(errmsg, "kpropd: flock (unlock): %s",
+ strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+ close(fdlock);
+ sprintf(cmd, "%s load %s %s\n", kdb_util_path, local_file, local_db);
+ if (system (cmd) != 0) {
+ klog (L_KRB_PERR, "Couldn't load database");
+ SlowDeath();
+ }
+ }
+}
+
+#ifdef doesnt_work_yet
+unsigned long get_data_checksum(fd, key_sched)
+ int fd;
+ des_key_schedule key_sched;
+{
+ unsigned long cksum = 0;
+ unsigned long cbc_cksum();
+ int n;
+ char buf[BUFSIZ];
+ char obuf[8];
+
+ while (n = read(fd, buf, sizeof buf)) {
+ if (n < 0) {
+ sprintf(errmsg, "kpropd: read (in checksum test): %s",
+ strerror(errno));
+ klog(L_KRB_PERR, errmsg);
+ SlowDeath();
+ }
+#ifndef NOENCRYPTION
+ cksum += des_cbc_cksum(buf, obuf, n, key_sched, key_sched);
+#endif
+ }
+ return cksum;
+}
+#endif
--- /dev/null
+# @(#)Makefile 8.1 (Berkeley) 6/1/93
+
+LIB= krb
+CFLAGS+=-I${.CURDIR}
+SRCS= cr_err_reply.c create_auth_reply.c create_ciph.c \
+ create_death_packet.c create_ticket.c debug_decl.c decomp_ticket.c \
+ dest_tkt.c extract_ticket.c fgetst.c get_ad_tkt.c get_admhst.c \
+ get_cred.c get_in_tkt.c get_krbhst.c get_krbrlm.c get_phost.c \
+ get_pw_tkt.c get_request.c get_svc_in_tkt.c get_tf_fullname.c \
+ get_tf_realm.c getrealm.c getst.c in_tkt.c k_localtime.c klog.c \
+ kname_parse.c kntoln.c kparse.c krb_equiv.c krb_err.c krb_err_txt.c \
+ krb_get_in_tkt.c kuserok.c lifetime.c log.c mk_err.c mk_priv.c \
+ mk_req.c mk_safe.c month_sname.c netread.c netwrite.c one.c \
+ pkt_cipher.c pkt_clen.c rd_err.c rd_priv.c rd_req.c rd_safe.c \
+ read_service_key.c recvauth.c save_credentials.c send_to_kdc.c \
+ sendauth.c str2key.c tf_util.c tkt_string.c
+MAN= kerberos.3 krb_realmofhost.3 krb_sendauth.3 krb_set_tkt_string.3 \
+ kuserok.3 tf_util.3
+MLINKS+=kerberos.3 krb_mk_req.3 kerberos.3 krb_rd_req.3 kerberos.3 krb_kntoln.3 \
+ kerberos.3 krb_set_key.3 kerberos.3 krb_get_cred.3 kerberos.3 krb_mk_priv.3 \
+ kerberos.3 krb_rd_priv.3 kerberos.3 krb_mk_safe.3 kerberos.3 krb_rd_safe.3 \
+ kerberos.3 krb_mk_err.3 kerberos.3 krb_rd_err.3 kerberos.3 krb_ck_repl.3
+MLINKS+=krb_realmofhost.3 krb_get_phost.3 krb_realmofhost.3 krb_get_krbhst.3 \
+ krb_realmofhost.3 krb_get_admhst.3 krb_realmofhost.3 krb_get_lrealm.3
+MLINKS+=krb_sendauth.3 krb_recvauth.3 krb_sendauth.3 krb_net_write.3 \
+ krb_sendauth.3 krb_net_read.3
+MLINKS+=tf_util.3 tf_init.3 tf_util.3 tf_get_pname.3 tf_util.3 tf_get_pinst.3 \
+ tf_util.3 tf_get_cred.3 tf_util.3 tf_close.3
+
+LDADD+= ${COM_ERR}
+CLEANFILES+= krb_err.c krb_err.h
+
+krb_err.c krb_err.h: krb_err.et
+ test -e krb_err.et || ln -s ${.CURDIR}/krb_err.et .
+ ${COMPILE_ET} krb_err.et
+ -test -h krb_err.et && rm krb_err.et
+
+beforeinstall:
+ -cd ${.OBJDIR}; cmp -s krb_err.h ${DESTDIR}/usr/include/kerberosIV/krb_err.h || \
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 krb_err.h ${DESTDIR}/usr/include/kerberosIV
+
+.include <bsd.lib.mk>
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/cr_err_reply.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * req_act_vno used to be defined as an extern ("defined in server").
+ * However, that does noone anything good, so we define our own so
+ * that the shared libraries do not turn up with an undefined variable!
+ */
+static int my_req_act_vno = KRB_PROT_VERSION;
+
+/*
+ * This routine is used by the Kerberos authentication server to
+ * create an error reply packet to send back to its client.
+ *
+ * It takes a pointer to the packet to be built, the name, instance,
+ * and realm of the principal, the client's timestamp, an error code
+ * and an error string as arguments. Its return value is undefined.
+ *
+ * The packet is built in the following format:
+ *
+ * type variable data
+ * or constant
+ * ---- ----------- ----
+ *
+ * unsigned char req_ack_vno protocol version number
+ *
+ * unsigned char AUTH_MSG_ERR_REPLY protocol message type
+ *
+ * [least significant HOST_BYTE_ORDER sender's (server's) byte
+ * bit of above field] order
+ *
+ * string pname principal's name
+ *
+ * string pinst principal's instance
+ *
+ * string prealm principal's realm
+ *
+ * unsigned long time_ws client's timestamp
+ *
+ * unsigned long e error code
+ *
+ * string e_string error text
+ */
+
+void
+cr_err_reply(pkt, pname, pinst, prealm, time_ws, e, e_string)
+ KTEXT pkt;
+ char *pname; /* Principal's name */
+ char *pinst; /* Principal's instance */
+ char *prealm; /* Principal's authentication domain */
+ u_int32_t time_ws; /* Workstation time */
+ u_int32_t e; /* Error code */
+ char *e_string; /* Text of error */
+{
+ u_char *v = (u_char *) pkt->dat; /* Prot vers number */
+ u_char *t = (u_char *)(pkt->dat+1); /* Prot message type */
+
+ /* Create fixed part of packet */
+ *v = (unsigned char) my_req_act_vno; /* KRB_PROT_VERSION; */
+ *t = (unsigned char) AUTH_MSG_ERR_REPLY;
+ *t |= HOST_BYTE_ORDER;
+
+ if (pname == 0)
+ pname = "";
+ if (pinst == 0)
+ pinst = "";
+ if (prealm == 0)
+ prealm = "";
+
+ /* Add the basic info */
+ (void) strcpy((char *) (pkt->dat+2),pname);
+ pkt->length = 3 + strlen(pname);
+ (void) strcpy((char *)(pkt->dat+pkt->length),pinst);
+ pkt->length += 1 + strlen(pinst);
+ (void) strcpy((char *)(pkt->dat+pkt->length),prealm);
+ pkt->length += 1 + strlen(prealm);
+ /* ws timestamp */
+ bcopy((char *) &time_ws,(char *)(pkt->dat+pkt->length),4);
+ pkt->length += 4;
+ /* err code */
+ bcopy((char *) &e,(char *)(pkt->dat+pkt->length),4);
+ pkt->length += 4;
+ /* err text */
+ (void) strcpy((char *)(pkt->dat+pkt->length),e_string);
+ pkt->length += 1 + strlen(e_string);
+
+ /* And return */
+ return;
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/create_auth_reply.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This routine is called by the Kerberos authentication server
+ * to create a reply to an authentication request. The routine
+ * takes the user's name, instance, and realm, the client's
+ * timestamp, the number of tickets, the user's key version
+ * number and the ciphertext containing the tickets themselves.
+ * It constructs a packet and returns a pointer to it.
+ *
+ * Notes: The packet returned by this routine is static. Thus, if you
+ * intend to keep the result beyond the next call to this routine, you
+ * must copy it elsewhere.
+ *
+ * The packet is built in the following format:
+ *
+ * variable
+ * type or constant data
+ * ---- ----------- ----
+ *
+ * unsigned char KRB_PROT_VERSION protocol version number
+ *
+ * unsigned char AUTH_MSG_KDC_REPLY protocol message type
+ *
+ * [least significant HOST_BYTE_ORDER sender's (server's) byte
+ * bit of above field] order
+ *
+ * string pname principal's name
+ *
+ * string pinst principal's instance
+ *
+ * string prealm principal's realm
+ *
+ * unsigned long time_ws client's timestamp
+ *
+ * unsigned char n number of tickets
+ *
+ * unsigned long x_date expiration date
+ *
+ * unsigned char kvno master key version
+ *
+ * short w_1 cipher length
+ *
+ * --- cipher->dat cipher data
+ */
+
+KTEXT
+create_auth_reply(pname, pinst, prealm, time_ws, n, x_date, kvno, cipher)
+ char *pname; /* Principal's name */
+ char *pinst; /* Principal's instance */
+ char *prealm; /* Principal's authentication domain */
+ int32_t time_ws; /* Workstation time */
+ int n; /* Number of tickets */
+ u_int32_t x_date; /* Principal's expiration date */
+ int kvno; /* Principal's key version number */
+ KTEXT cipher; /* Cipher text with tickets and
+ * session keys */
+{
+ static KTEXT_ST pkt_st;
+ KTEXT pkt = &pkt_st;
+ unsigned char *v = pkt->dat; /* Prot vers number */
+ unsigned char *t = (pkt->dat+1); /* Prot message type */
+ short w_l; /* Cipher length */
+
+ /* Create fixed part of packet */
+ *v = (unsigned char) KRB_PROT_VERSION;
+ *t = (unsigned char) AUTH_MSG_KDC_REPLY;
+ *t |= HOST_BYTE_ORDER;
+
+ if (n != 0)
+ *v = 3;
+
+ /* Add the basic info */
+ (void) strcpy((char *) (pkt->dat+2), pname);
+ pkt->length = 3 + strlen(pname);
+ (void) strcpy((char *) (pkt->dat+pkt->length),pinst);
+ pkt->length += 1 + strlen(pinst);
+ (void) strcpy((char *) (pkt->dat+pkt->length),prealm);
+ pkt->length += 1 + strlen(prealm);
+ /* Workstation timestamp */
+ bcopy((char *) &time_ws, (char *) (pkt->dat+pkt->length), 4);
+ pkt->length += 4;
+ *(pkt->dat+(pkt->length)++) = (unsigned char) n;
+ /* Expiration date */
+ bcopy((char *) &x_date, (char *) (pkt->dat+pkt->length),4);
+ pkt->length += 4;
+
+ /* Now send the ciphertext and info to help decode it */
+ *(pkt->dat+(pkt->length)++) = (unsigned char) kvno;
+ w_l = (short) cipher->length;
+ bcopy((char *) &w_l,(char *) (pkt->dat+pkt->length),2);
+ pkt->length += 2;
+ bcopy((char *) (cipher->dat), (char *) (pkt->dat+pkt->length),
+ cipher->length);
+ pkt->length += cipher->length;
+
+ /* And return the packet */
+ return pkt;
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/create_ciph.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This routine is used by the authentication server to create
+ * a packet for its client, containing a ticket for the requested
+ * service (given in "tkt"), and some information about the ticket,
+ *
+ * Returns KSUCCESS no matter what.
+ *
+ * The length of the cipher is stored in c->length; the format of
+ * c->dat is as follows:
+ *
+ * variable
+ * type or constant data
+ * ---- ----------- ----
+ *
+ *
+ * 8 bytes session session key for client, service
+ *
+ * string service service name
+ *
+ * string instance service instance
+ *
+ * string realm KDC realm
+ *
+ * unsigned char life ticket lifetime
+ *
+ * unsigned char kvno service key version number
+ *
+ * unsigned char tkt->length length of following ticket
+ *
+ * data tkt->dat ticket for service
+ *
+ * 4 bytes kdc_time KDC's timestamp
+ *
+ * <=7 bytes null null pad to 8 byte multiple
+ *
+ */
+
+int
+create_ciph(c, session, service, instance, realm,
+ life, kvno, tkt, kdc_time, key)
+ KTEXT c; /* Text block to hold ciphertext */
+ unsigned char *session; /* Session key to send to user */
+ char *service; /* Service name on ticket */
+ char *instance; /* Instance name on ticket */
+ char *realm; /* Realm of this KDC */
+ u_int32_t life; /* Lifetime of the ticket */
+ int kvno; /* Key version number for service */
+ KTEXT tkt; /* The ticket for the service */
+ u_int32_t kdc_time; /* KDC time */
+ des_cblock *key; /* Key to encrypt ciphertext with */
+{
+ char *ptr;
+ des_key_schedule key_s;
+
+ ptr = (char *) c->dat;
+
+ bcopy((char *) session, ptr, 8);
+ ptr += 8;
+
+ (void) strcpy(ptr,service);
+ ptr += strlen(service) + 1;
+
+ (void) strcpy(ptr,instance);
+ ptr += strlen(instance) + 1;
+
+ (void) strcpy(ptr,realm);
+ ptr += strlen(realm) + 1;
+
+ *(ptr++) = (unsigned char) life;
+ *(ptr++) = (unsigned char) kvno;
+ *(ptr++) = (unsigned char) tkt->length;
+
+ bcopy((char *)(tkt->dat),ptr,tkt->length);
+ ptr += tkt->length;
+
+ bcopy((char *) &kdc_time,ptr,4);
+ ptr += 4;
+
+ /* guarantee null padded encrypted data to multiple of 8 bytes */
+ bzero(ptr, 7);
+
+ c->length = (((ptr - (char *) c->dat) + 7) / 8) * 8;
+
+#ifndef NOENCRYPTION
+ des_key_sched(key,key_s);
+ des_pcbc_encrypt((des_cblock *)c->dat,(des_cblock *)c->dat,(long) c->length,key_s,
+ key, DES_ENCRYPT);
+#endif /* NOENCRYPTION */
+
+ return(KSUCCESS);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/create_death_packet.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This routine creates a packet to type AUTH_MSG_DIE which is sent to
+ * the Kerberos server to make it shut down. It is used only in the
+ * development environment.
+ *
+ * It takes a string "a_name" which is sent in the packet. A pointer
+ * to the packet is returned.
+ *
+ * The format of the killer packet is:
+ *
+ * type variable data
+ * or constant
+ * ---- ----------- ----
+ *
+ * unsigned char KRB_PROT_VERSION protocol version number
+ *
+ * unsigned char AUTH_MSG_DIE message type
+ *
+ * [least significant HOST_BYTE_ORDER byte order of sender
+ * bit of above field]
+ *
+ * string a_name presumably, name of
+ * principal sending killer
+ * packet
+ */
+
+#ifdef DEBUG
+KTEXT
+krb_create_death_packet(a_name)
+ char *a_name;
+{
+ static KTEXT_ST pkt_st;
+ KTEXT pkt = &pkt_st;
+
+ unsigned char *v = pkt->dat;
+ unsigned char *t = (pkt->dat+1);
+ *v = (unsigned char) KRB_PROT_VERSION;
+ *t = (unsigned char) AUTH_MSG_DIE;
+ *t |= HOST_BYTE_ORDER;
+ (void) strcpy((char *) (pkt->dat+2),a_name);
+ pkt->length = 3 + strlen(a_name);
+ return pkt;
+}
+#endif /* DEBUG */
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/create_ticket.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * Create ticket takes as arguments information that should be in a
+ * ticket, and the KTEXT object in which the ticket should be
+ * constructed. It then constructs a ticket and returns, leaving the
+ * newly created ticket in tkt.
+ * The length of the ticket is a multiple of
+ * eight bytes and is in tkt->length.
+ *
+ * If the ticket is too long, the ticket will contain nulls.
+ * The return value of the routine is undefined.
+ *
+ * The corresponding routine to extract information from a ticket it
+ * decomp_ticket. When changes are made to this routine, the
+ * corresponding changes should also be made to that file.
+ *
+ * The packet is built in the following format:
+ *
+ * variable
+ * type or constant data
+ * ---- ----------- ----
+ *
+ * tkt->length length of ticket (multiple of 8 bytes)
+ *
+ * tkt->dat:
+ *
+ * unsigned char flags namely, HOST_BYTE_ORDER
+ *
+ * string pname client's name
+ *
+ * string pinstance client's instance
+ *
+ * string prealm client's realm
+ *
+ * 4 bytes paddress client's address
+ *
+ * 8 bytes session session key
+ *
+ * 1 byte life ticket lifetime
+ *
+ * 4 bytes time_sec KDC timestamp
+ *
+ * string sname service's name
+ *
+ * string sinstance service's instance
+ *
+ * <=7 bytes null null pad to 8 byte multiple
+ *
+ */
+
+int
+krb_create_ticket(tkt, flags, pname, pinstance, prealm, paddress,
+ session, life, time_sec, sname, sinstance, key)
+ KTEXT tkt; /* Gets filled in by the ticket */
+ unsigned char flags; /* Various Kerberos flags */
+ char *pname; /* Principal's name */
+ char *pinstance; /* Principal's instance */
+ char *prealm; /* Principal's authentication domain */
+ int32_t paddress; /* Net address of requesting entity */
+ char *session; /* Session key inserted in ticket */
+ int16_t life; /* Lifetime of the ticket */
+ int32_t time_sec; /* Issue time and date */
+ char *sname; /* Service Name */
+ char *sinstance; /* Instance Name */
+ des_cblock *key; /* Service's secret key */
+{
+ des_key_schedule key_s;
+ register char *data; /* running index into ticket */
+
+ tkt->length = 0; /* Clear previous data */
+ flags |= HOST_BYTE_ORDER; /* ticket byte order */
+ bcopy((char *) &flags,(char *) (tkt->dat),sizeof(flags));
+ data = ((char *)tkt->dat) + sizeof(flags);
+ (void) strcpy(data, pname);
+ data += 1 + strlen(pname);
+ (void) strcpy(data, pinstance);
+ data += 1 + strlen(pinstance);
+ (void) strcpy(data, prealm);
+ data += 1 + strlen(prealm);
+ bcopy((char *) &paddress, data, 4);
+ data += 4;
+
+ bcopy((char *) session, data, 8);
+ data += 8;
+ *(data++) = (char) life;
+ /* issue time */
+ bcopy((char *) &time_sec, data, 4);
+ data += 4;
+ (void) strcpy(data, sname);
+ data += 1 + strlen(sname);
+ (void) strcpy(data, sinstance);
+ data += 1 + strlen(sinstance);
+
+ /* guarantee null padded ticket to multiple of 8 bytes */
+ bzero(data, 7);
+ tkt->length = ((data - ((char *)tkt->dat) + 7)/8)*8;
+
+ /* Check length of ticket */
+ if (tkt->length > (sizeof(KTEXT_ST) - 7)) {
+ bzero(tkt->dat, tkt->length);
+ tkt->length = 0;
+ return KFAILURE /* XXX */;
+ }
+
+#ifndef NOENCRYPTION
+ des_key_sched(key,key_s);
+ des_pcbc_encrypt((des_cblock *)tkt->dat,(des_cblock *)tkt->dat,(long)tkt->length,
+ key_s,key, DES_ENCRYPT);
+#endif
+ return 0;
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/debug_decl.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+/* Declare global debugging variables. */
+
+int krb_ap_req_debug = 0;
+int krb_debug = 0;
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/decomp_ticket.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This routine takes a ticket and pointers to the variables that
+ * should be filled in based on the information in the ticket. It
+ * fills in values for its arguments.
+ *
+ * Note: if the client realm field in the ticket is the null string,
+ * then the "prealm" variable is filled in with the local realm (as
+ * defined by KRB_REALM).
+ *
+ * If the ticket byte order is different than the host's byte order
+ * (as indicated by the byte order bit of the "flags" field), then
+ * the KDC timestamp "time_sec" is byte-swapped. The other fields
+ * potentially affected by byte order, "paddress" and "session" are
+ * not byte-swapped.
+ *
+ * The routine returns KFAILURE if any of the "pname", "pinstance",
+ * or "prealm" fields is too big, otherwise it returns KSUCCESS.
+ *
+ * The corresponding routine to generate tickets is create_ticket.
+ * When changes are made to this routine, the corresponding changes
+ * should also be made to that file.
+ *
+ * See create_ticket.c for the format of the ticket packet.
+ */
+
+int
+decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session,
+ life, time_sec, sname, sinstance, key, key_s)
+ KTEXT tkt; /* The ticket to be decoded */
+ unsigned char *flags; /* Kerberos ticket flags */
+ char *pname; /* Authentication name */
+ char *pinstance; /* Principal's instance */
+ char *prealm; /* Principal's authentication domain */
+ u_int32_t *paddress; /* Net address of entity
+ * requesting ticket */
+ unsigned char *session; /* Session key inserted in ticket */
+ int *life; /* Lifetime of the ticket */
+ u_int32_t *time_sec; /* Issue time and date */
+ char *sname; /* Service name */
+ char *sinstance; /* Service instance */
+ des_cblock *key; /* Service's secret key
+ * (to decrypt the ticket) */
+ struct des_ks_struct *key_s; /* The precomputed key schedule */
+{
+ static int tkt_swap_bytes;
+ unsigned char *uptr;
+ char *ptr = (char *)tkt->dat;
+
+#ifndef NOENCRYPTION
+ des_pcbc_encrypt((des_cblock *)tkt->dat,(des_cblock *)tkt->dat,(long)tkt->length,
+ key_s,key, DES_DECRYPT);
+#endif /* ! NOENCRYPTION */
+
+ *flags = *ptr; /* get flags byte */
+ ptr += sizeof(*flags);
+ tkt_swap_bytes = 0;
+ if (HOST_BYTE_ORDER != ((*flags >> K_FLAG_ORDER)& 1))
+ tkt_swap_bytes++;
+
+ if (strlen(ptr) > ANAME_SZ)
+ return(KFAILURE);
+ (void) strcpy(pname,ptr); /* pname */
+ ptr += strlen(pname) + 1;
+
+ if (strlen(ptr) > INST_SZ)
+ return(KFAILURE);
+ (void) strcpy(pinstance,ptr); /* instance */
+ ptr += strlen(pinstance) + 1;
+
+ if (strlen(ptr) > REALM_SZ)
+ return(KFAILURE);
+ (void) strcpy(prealm,ptr); /* realm */
+ ptr += strlen(prealm) + 1;
+ /* temporary hack until realms are dealt with properly */
+ if (*prealm == 0)
+ (void) strcpy(prealm,KRB_REALM);
+
+ bcopy(ptr,(char *)paddress,4); /* net address */
+ ptr += 4;
+
+ bcopy(ptr,(char *)session,8); /* session key */
+ ptr+= 8;
+#ifdef notdef /* DONT SWAP SESSION KEY spm 10/22/86 */
+ if (tkt_swap_bytes)
+ swap_C_Block(session);
+#endif
+
+ /* get lifetime, being certain we don't get negative lifetimes */
+ uptr = (unsigned char *) ptr++;
+ *life = (int) *uptr;
+
+ bcopy(ptr,(char *) time_sec,4); /* issue time */
+ ptr += 4;
+ if (tkt_swap_bytes)
+ swap_u_long(*time_sec);
+
+ (void) strcpy(sname,ptr); /* service name */
+ ptr += 1 + strlen(sname);
+
+ (void) strcpy(sinstance,ptr); /* instance */
+ ptr += 1 + strlen(sinstance);
+ return(KSUCCESS);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/dest_tkt.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef TKT_SHMEM
+#include <sys/param.h>
+#endif
+
+/*
+ * dest_tkt() is used to destroy the ticket store upon logout.
+ * If the ticket file does not exist, dest_tkt() returns RET_TKFIL.
+ * Otherwise the function returns RET_OK on success, KFAILURE on
+ * failure.
+ *
+ * The ticket file (TKT_FILE) is defined in "krb.h".
+ */
+
+int
+dest_tkt()
+{
+ char *file = TKT_FILE;
+ int i,fd;
+ struct stat statb;
+ char buf[BUFSIZ];
+#ifdef TKT_SHMEM
+ char shmidname[MaxPathLen];
+#endif /* TKT_SHMEM */
+
+ errno = 0;
+ if (lstat(file,&statb) < 0)
+ goto out;
+
+ if (!(statb.st_mode & S_IFREG)
+#ifdef notdef
+ || statb.st_mode & 077
+#endif
+ )
+ goto out;
+
+ if ((fd = open(file, O_RDWR, 0)) < 0)
+ goto out;
+
+ bzero(buf, BUFSIZ);
+
+ for (i = 0; i < statb.st_size; i += BUFSIZ)
+ if (write(fd, buf, BUFSIZ) != BUFSIZ) {
+ (void) fsync(fd);
+ (void) close(fd);
+ goto out;
+ }
+
+ (void) fsync(fd);
+ (void) close(fd);
+
+ (void) unlink(file);
+
+out:
+ if (errno == ENOENT) return RET_TKFIL;
+ else if (errno != 0) return KFAILURE;
+#ifdef TKT_SHMEM
+ /*
+ * handle the shared memory case
+ */
+ (void) strcpy(shmidname, file);
+ (void) strcat(shmidname, ".shm");
+ if ((i = krb_shm_dest(shmidname)) != KSUCCESS)
+ return(i);
+#endif /* TKT_SHMEM */
+ return(KSUCCESS);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/extract_ticket.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This routine is obsolete.
+ *
+ * This routine accepts the ciphertext returned by kerberos and
+ * extracts the nth ticket. It also fills in the variables passed as
+ * session, liftime and kvno.
+ */
+
+void
+extract_ticket(cipher, n, session, lifetime, kvno, realm, ticket)
+ KTEXT cipher; /* The ciphertext */
+ int n; /* Which ticket */
+ char *session; /* The session key for this tkt */
+ int *lifetime; /* The life of this ticket */
+ int *kvno; /* The kvno for the service */
+ char *realm; /* Realm in which tkt issued */
+ KTEXT ticket; /* The ticket itself */
+{
+ char *ptr;
+ int i;
+
+ /* Start after the ticket lengths */
+ ptr = (char *) cipher->dat;
+ ptr = ptr + 1 + (int) *(cipher->dat);
+
+ /* Step through earlier tickets */
+ for (i = 1; i < n; i++)
+ ptr = ptr + 11 + strlen(ptr+10) + (int) *(cipher->dat+i);
+ bcopy(ptr, (char *) session, 8); /* Save the session key */
+ ptr += 8;
+ *lifetime = (unsigned char) *(ptr++); /* Save the life of the ticket */
+ *kvno = *(ptr++); /* Save the kvno */
+ (void) strcpy(realm,ptr); /* instance */
+ ptr += strlen(realm) + 1;
+
+ /* Save the ticket if its length is non zero */
+ ticket->length = *(cipher->dat+n);
+ if (ticket->length)
+ bcopy(ptr, (char *) (ticket->dat), ticket->length);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/fgetst.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * fgetst takes a file descriptor, a character pointer, and a count.
+ * It reads from the file it has either read "count" characters, or
+ * until it reads a null byte. When finished, what has been read exists
+ * in "s". If "count" characters were actually read, the last is changed
+ * to a null, so the returned string is always null-terminated. fgetst
+ * returns the number of characters read, including the null terminator.
+ */
+
+int
+fgetst(f, s, n)
+ FILE *f;
+ register char *s;
+ int n;
+{
+ register count = n;
+ int ch; /* NOT char; otherwise you don't see EOF */
+
+ while ((ch = getc(f)) != EOF && ch && --count) {
+ *s++ = ch;
+ }
+ *s = '\0';
+ return (n - count);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_ad_tkt.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+static int swap_bytes;
+
+/*
+ * Given a pointer to an AUTH_MSG_KDC_REPLY packet, return the length of
+ * its ciphertext portion. The external variable "swap_bytes" is assumed
+ * to have been set to indicate whether or not the packet is in local
+ * byte order. pkt_clen() takes this into account when reading the
+ * ciphertext length out of the packet.
+ */
+
+static int
+pkt_clen(pkt)
+ KTEXT pkt;
+{
+ static unsigned short temp,temp2;
+ int clen = 0;
+
+ /* Start of ticket list */
+ unsigned char *ptr = pkt_a_realm(pkt) + 10
+ + strlen((char *)pkt_a_realm(pkt));
+
+ /* Finally the length */
+ bcopy((char *)(++ptr),(char *)&temp,2); /* alignment */
+ if (swap_bytes) {
+ /* assume a short is 2 bytes?? */
+ swab((char *)&temp,(char *)&temp2,2);
+ temp = temp2;
+ }
+
+ clen = (int) temp;
+
+ if (krb_debug)
+ printf("Clen is %d\n",clen);
+ return(clen);
+}
+
+/* use the bsd time.h struct defs for PC too! */
+#include <sys/time.h>
+#include <sys/types.h>
+
+static struct timeval tt_local = { 0, 0 };
+static unsigned long rep_err_code;
+
+/*
+ * get_ad_tkt obtains a new service ticket from Kerberos, using
+ * the ticket-granting ticket which must be in the ticket file.
+ * It is typically called by krb_mk_req() when the client side
+ * of an application is creating authentication information to be
+ * sent to the server side.
+ *
+ * get_ad_tkt takes four arguments: three pointers to strings which
+ * contain the name, instance, and realm of the service for which the
+ * ticket is to be obtained; and an integer indicating the desired
+ * lifetime of the ticket.
+ *
+ * It returns an error status if the ticket couldn't be obtained,
+ * or AD_OK if all went well. The ticket is stored in the ticket
+ * cache.
+ *
+ * The request sent to the Kerberos ticket-granting service looks
+ * like this:
+ *
+ * pkt->dat
+ *
+ * TEXT original contents of authenticator+ticket
+ * pkt->dat built in krb_mk_req call
+ *
+ * 4 bytes time_ws always 0 (?)
+ * char lifetime lifetime argument passed
+ * string service service name argument
+ * string sinstance service instance arg.
+ *
+ * See "prot.h" for the reply packet layout and definitions of the
+ * extraction macros like pkt_version(), pkt_msg_type(), etc.
+ */
+
+int
+get_ad_tkt(service, sinstance, realm, lifetime)
+ char *service;
+ char *sinstance;
+ char *realm;
+ int lifetime;
+{
+ static KTEXT_ST pkt_st;
+ KTEXT pkt = & pkt_st; /* Packet to KDC */
+ static KTEXT_ST rpkt_st;
+ KTEXT rpkt = &rpkt_st; /* Returned packet */
+ static KTEXT_ST cip_st;
+ KTEXT cip = &cip_st; /* Returned Ciphertext */
+ static KTEXT_ST tkt_st;
+ KTEXT tkt = &tkt_st; /* Current ticket */
+ des_cblock ses; /* Session key for tkt */
+ CREDENTIALS cr;
+ int kvno; /* Kvno for session key */
+ char lrealm[REALM_SZ];
+ des_cblock key; /* Key for decrypting cipher */
+ des_key_schedule key_s;
+ long time_ws = 0;
+
+ char s_name[SNAME_SZ];
+ char s_instance[INST_SZ];
+ int msg_byte_order;
+ int kerror;
+ char rlm[REALM_SZ];
+ char *ptr;
+
+ unsigned long kdc_time; /* KDC time */
+
+ if ((kerror = krb_get_tf_realm(TKT_FILE, lrealm)) != KSUCCESS)
+ return(kerror);
+
+ /* Create skeleton of packet to be sent */
+ (void) gettimeofday(&tt_local,(struct timezone *) 0);
+
+ pkt->length = 0;
+
+ /*
+ * Look for the session key (and other stuff we don't need)
+ * in the ticket file for krbtgt.realm@lrealm where "realm"
+ * is the service's realm (passed in "realm" argument) and
+ * lrealm is the realm of our initial ticket. If we don't
+ * have this, we will try to get it.
+ */
+
+ if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS) {
+ /*
+ * If realm == lrealm, we have no hope, so let's not even try.
+ */
+ if ((strncmp(realm, lrealm, REALM_SZ)) == 0)
+ return(AD_NOTGT);
+ else{
+ if ((kerror =
+ get_ad_tkt("krbtgt",realm,lrealm,lifetime)) != KSUCCESS)
+ return(kerror);
+ if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS)
+ return(kerror);
+ }
+ }
+
+ /*
+ * Make up a request packet to the "krbtgt.realm@lrealm".
+ * Start by calling krb_mk_req() which puts ticket+authenticator
+ * into "pkt". Then tack other stuff on the end.
+ */
+
+ kerror = krb_mk_req(pkt,"krbtgt",realm,lrealm,0L);
+
+ if (kerror)
+ return(AD_NOTGT);
+
+ /* timestamp */
+ bcopy((char *) &time_ws,(char *) (pkt->dat+pkt->length),4);
+ pkt->length += 4;
+ *(pkt->dat+(pkt->length)++) = (char) lifetime;
+ (void) strcpy((char *) (pkt->dat+pkt->length),service);
+ pkt->length += 1 + strlen(service);
+ (void) strcpy((char *)(pkt->dat+pkt->length),sinstance);
+ pkt->length += 1 + strlen(sinstance);
+
+ rpkt->length = 0;
+
+ /* Send the request to the local ticket-granting server */
+ if ((kerror = send_to_kdc(pkt, rpkt, realm))) return(kerror);
+
+ /* check packet version of the returned packet */
+ if (pkt_version(rpkt) != KRB_PROT_VERSION )
+ return(INTK_PROT);
+
+ /* Check byte order */
+ msg_byte_order = pkt_msg_type(rpkt) & 1;
+ swap_bytes = 0;
+ if (msg_byte_order != HOST_BYTE_ORDER)
+ swap_bytes++;
+
+ switch (pkt_msg_type(rpkt) & ~1) {
+ case AUTH_MSG_KDC_REPLY:
+ break;
+ case AUTH_MSG_ERR_REPLY:
+ bcopy(pkt_err_code(rpkt), (char *) &rep_err_code, 4);
+ if (swap_bytes)
+ swap_u_long(rep_err_code);
+ return(rep_err_code);
+
+ default:
+ return(INTK_PROT);
+ }
+
+ /* Extract the ciphertext */
+ cip->length = pkt_clen(rpkt); /* let clen do the swap */
+
+ bcopy((char *) pkt_cipher(rpkt),(char *) (cip->dat),cip->length);
+
+#ifndef NOENCRYPTION
+ /* Attempt to decrypt it */
+
+ des_key_sched(&cr.session,key_s);
+ if (krb_debug) printf("About to do decryption ...");
+ des_pcbc_encrypt((des_cblock *)cip->dat,(des_cblock *)cip->dat,
+ (long) cip->length,key_s,&cr.session,0);
+#endif /* !NOENCRYPTION */
+ /* Get rid of all traces of key */
+ bzero((char *) cr.session, sizeof(key));
+ bzero((char *) key_s, sizeof(key_s));
+
+ ptr = (char *) cip->dat;
+
+ bcopy(ptr,(char *)ses,8);
+ ptr += 8;
+
+ (void) strcpy(s_name,ptr);
+ ptr += strlen(s_name) + 1;
+
+ (void) strcpy(s_instance,ptr);
+ ptr += strlen(s_instance) + 1;
+
+ (void) strcpy(rlm,ptr);
+ ptr += strlen(rlm) + 1;
+
+ lifetime = (unsigned char) ptr[0];
+ kvno = (unsigned long) ptr[1];
+ tkt->length = (int) ptr[2];
+ ptr += 3;
+ bcopy(ptr,(char *)(tkt->dat),tkt->length);
+ ptr += tkt->length;
+
+ if (strcmp(s_name, service) || strcmp(s_instance, sinstance) ||
+ strcmp(rlm, realm)) /* not what we asked for */
+ return(INTK_ERR); /* we need a better code here XXX */
+
+ /* check KDC time stamp */
+ bcopy(ptr,(char *)&kdc_time,4); /* Time (coarse) */
+ if (swap_bytes) swap_u_long(kdc_time);
+
+ ptr += 4;
+
+ (void) gettimeofday(&tt_local,(struct timezone *) 0);
+ if (abs((int)(tt_local.tv_sec - kdc_time)) > CLOCK_SKEW) {
+ return(RD_AP_TIME); /* XXX should probably be better
+ code */
+ }
+
+ if ((kerror = save_credentials(s_name,s_instance,rlm,ses,lifetime,
+ kvno,tkt,tt_local.tv_sec)))
+ return(kerror);
+
+ return(AD_OK);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_admhst.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * Given a Kerberos realm, find a host on which the Kerberos database
+ * administration server can be found.
+ *
+ * krb_get_admhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer n, and
+ * returns (in h) the nth administrative host entry from the configuration
+ * file (KRB_CONF, defined in "krb.h") associated with the specified realm.
+ *
+ * On error, get_admhst returns KFAILURE. If all goes well, the routine
+ * returns KSUCCESS.
+ *
+ * For the format of the KRB_CONF file, see comments describing the routine
+ * krb_get_krbhst().
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * a Kerberos admin server. In the long run, this functionality will be
+ * provided by a nameserver.
+ */
+
+int
+krb_get_admhst(h, r, n)
+ char *h;
+ char *r;
+ int n;
+{
+ FILE *cnffile;
+ char tr[REALM_SZ];
+ char linebuf[BUFSIZ];
+ char scratch[64];
+ register int i;
+
+ if ((cnffile = fopen(KRB_CONF,"r")) == NULL) {
+ char tbuf[128];
+ char *tdir = (char *) getenv("KRBCONFDIR");
+ strncpy(tbuf, tdir ? tdir : "/etc", sizeof(tbuf));
+ strncat(tbuf, "/krb.conf", sizeof(tbuf));
+ tbuf[sizeof(tbuf)-1] = 0;
+ if ((cnffile = fopen(tbuf,"r")) == NULL)
+ return(KFAILURE);
+ }
+ if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
+ /* error reading */
+ (void) fclose(cnffile);
+ return(KFAILURE);
+ }
+ if (!strchr(linebuf, '\n')) {
+ /* didn't all fit into buffer, punt */
+ (void) fclose(cnffile);
+ return(KFAILURE);
+ }
+ for (i = 0; i < n; ) {
+ /* run through the file, looking for admin host */
+ if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
+ (void) fclose(cnffile);
+ return(KFAILURE);
+ }
+ /* need to scan for a token after 'admin' to make sure that
+ admin matched correctly */
+ if (sscanf(linebuf, "%s %s admin %s", tr, h, scratch) != 3)
+ continue;
+ if (!strcmp(tr,r))
+ i++;
+ }
+ (void) fclose(cnffile);
+ return(KSUCCESS);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_cred.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * krb_get_cred takes a service name, instance, and realm, and a
+ * structure of type CREDENTIALS to be filled in with ticket
+ * information. It then searches the ticket file for the appropriate
+ * ticket and fills in the structure with the corresponding
+ * information from the file. If successful, it returns KSUCCESS.
+ * On failure it returns a Kerberos error code.
+ */
+
+int
+krb_get_cred(service, instance, realm, c)
+ char *service; /* Service name */
+ char *instance; /* Instance */
+ char *realm; /* Auth domain */
+ CREDENTIALS *c; /* Credentials struct */
+{
+ int tf_status; /* return value of tf function calls */
+
+ /* Open ticket file and lock it for shared reading */
+ if ((tf_status = tf_init(TKT_FILE, R_TKT_FIL)) != KSUCCESS)
+ return(tf_status);
+
+ /* Copy principal's name and instance into the CREDENTIALS struc c */
+
+ if ( (tf_status = tf_get_pname(c->pname)) != KSUCCESS ||
+ (tf_status = tf_get_pinst(c->pinst)) != KSUCCESS )
+ return (tf_status);
+
+ /* Search for requested service credentials and copy into c */
+
+ while ((tf_status = tf_get_cred(c)) == KSUCCESS) {
+ /* Is this the right ticket? */
+ if ((strcmp(c->service,service) == 0) &&
+ (strcmp(c->instance,instance) == 0) &&
+ (strcmp(c->realm,realm) == 0))
+ break;
+ }
+ (void) tf_close();
+
+ if (tf_status == EOF)
+ return (GC_NOTKT);
+ return(tf_status);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_in_tkt.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This file contains two routines: passwd_to_key() converts
+ * a password into a DES key (prompting for the password if
+ * not supplied), and krb_get_pw_in_tkt() gets an initial ticket for
+ * a user.
+ */
+
+/*
+ * passwd_to_key(): given a password, return a DES key.
+ * There are extra arguments here which (used to be?)
+ * used by srvtab_to_key().
+ *
+ * If the "passwd" argument is not null, generate a DES
+ * key from it, using string_to_key().
+ *
+ * If the "passwd" argument is null, call des_read_password()
+ * to prompt for a password and then convert it into a DES key.
+ *
+ * In either case, the resulting key is put in the "key" argument,
+ * and 0 is returned.
+ */
+
+/*ARGSUSED */
+static int
+passwd_to_key(user, instance, realm, passwd, key)
+ char *user;
+ char *instance;
+ char *realm;
+ char *passwd;
+ des_cblock *key;
+{
+#ifdef NOENCRYPTION
+ if (!passwd)
+ placebo_read_password(key, "Password: ", 0);
+#else
+ if (passwd)
+ des_string_to_key(passwd,key);
+ else
+ des_read_password(key,"Password: ",0);
+#endif
+ return (0);
+}
+
+/*ARGSUSED */
+static int
+afs_passwd_to_key(user, instance, realm, passwd, key)
+ char *user;
+ char *instance;
+ char *realm;
+ char *passwd;
+ des_cblock *key;
+{
+#ifdef NOENCRYPTION
+ if (!passwd)
+ placebo_read_password(key, "Password: ", 0);
+#else /* Do encyryption */
+ if (passwd)
+ afs_string_to_key(passwd, realm, key);
+ else {
+ des_read_password(key, "Password: ", 0);
+ }
+#endif /* NOENCRYPTION */
+ return (0);
+}
+
+/*
+ * krb_get_pw_in_tkt() takes the name of the server for which the initial
+ * ticket is to be obtained, the name of the principal the ticket is
+ * for, the desired lifetime of the ticket, and the user's password.
+ * It passes its arguments on to krb_get_in_tkt(), which contacts
+ * Kerberos to get the ticket, decrypts it using the password provided,
+ * and stores it away for future use.
+ *
+ * krb_get_pw_in_tkt() passes two additional arguments to krb_get_in_tkt():
+ * the name of a routine (passwd_to_key()) to be used to get the
+ * password in case the "password" argument is null and NULL for the
+ * decryption procedure indicating that krb_get_in_tkt should use the
+ * default method of decrypting the response from the KDC.
+ *
+ * The result of the call to krb_get_in_tkt() is returned.
+ */
+
+int
+krb_get_pw_in_tkt(user, instance, realm, service, sinstance, life, password)
+ char *user;
+ char *instance;
+ char *realm;
+ char *service;
+ char *sinstance;
+ int life;
+ char *password;
+{
+ char pword[100]; /* storage for the password */
+ int code;
+
+ /* Only request password once! */
+ if (!password) {
+ if (des_read_pw_string(pword, sizeof(pword)-1, "Password: ", 0))
+ pword[0] = '\0'; /* something wrong */
+ password = pword;
+ }
+
+ code = krb_get_in_tkt(user,instance,realm,service,sinstance,life,
+ passwd_to_key, NULL, password);
+ if (code != INTK_BADPW)
+ goto done;
+
+ code = krb_get_in_tkt(user,instance,realm,service,sinstance,life,
+ afs_passwd_to_key, NULL, password);
+ if (code != INTK_BADPW)
+ goto done;
+
+ done:
+ if (password == pword)
+ bzero(pword, sizeof(pword));
+ return(code);
+}
+
+#ifdef NOENCRYPTION
+/*
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_in_tkt.c,v $
+ * $Author: tholo $
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * This routine prints the supplied string to standard
+ * output as a prompt, and reads a password string without
+ * echoing.
+ */
+
+#ifndef lint
+static char rcsid_read_password_c[] =
+"Bones$Header: /home/cvs/src/kerberosIV/krb/Attic/get_in_tkt.c,v 1.1.1.1 1995/12/14 06:52:39 tholo Exp $";
+#endif /* lint */
+
+#include <des.h>
+#include "conf.h"
+
+#include <stdio.h>
+#include <strings.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <setjmp.h>
+
+static jmp_buf env;
+
+static void sig_restore();
+static push_signals(), pop_signals();
+int placebo_read_pw_string();
+
+/*** Routines ****************************************************** */
+int
+placebo_read_password(k,prompt,verify)
+ des_cblock *k;
+ char *prompt;
+ int verify;
+{
+ int ok;
+ char key_string[BUFSIZ];
+
+ if (setjmp(env)) {
+ ok = -1;
+ goto lose;
+ }
+
+ ok = placebo_read_pw_string(key_string, BUFSIZ, prompt, verify);
+ if (ok == 0)
+ bzero(k, sizeof(C_Block));
+
+lose:
+ bzero(key_string, sizeof (key_string));
+ return ok;
+}
+
+/*
+ * This version just returns the string, doesn't map to key.
+ *
+ * Returns 0 on success, non-zero on failure.
+ */
+
+int
+placebo_read_pw_string(s,max,prompt,verify)
+ char *s;
+ int max;
+ char *prompt;
+ int verify;
+{
+ int ok = 0;
+ char *ptr;
+
+ jmp_buf old_env;
+ struct sgttyb tty_state;
+ char key_string[BUFSIZ];
+
+ if (max > BUFSIZ) {
+ return -1;
+ }
+
+ bcopy(old_env, env, sizeof(env));
+ if (setjmp(env))
+ goto lose;
+
+ /* save terminal state*/
+ if (ioctl(0,TIOCGETP,&tty_state) == -1)
+ return -1;
+
+ push_signals();
+ /* Turn off echo */
+ tty_state.sg_flags &= ~ECHO;
+ if (ioctl(0,TIOCSETP,&tty_state) == -1)
+ return -1;
+ while (!ok) {
+ printf(prompt);
+ fflush(stdout);
+ if (!fgets(s, max, stdin)) {
+ clearerr(stdin);
+ continue;
+ }
+ if ((ptr = index(s, '\n')))
+ *ptr = '\0';
+ if (verify) {
+ printf("\nVerifying, please re-enter %s",prompt);
+ fflush(stdout);
+ if (!fgets(key_string, sizeof(key_string), stdin)) {
+ clearerr(stdin);
+ continue;
+ }
+ if ((ptr = index(key_string, '\n')))
+ *ptr = '\0';
+ if (strcmp(s,key_string)) {
+ printf("\n\07\07Mismatch - try again\n");
+ fflush(stdout);
+ continue;
+ }
+ }
+ ok = 1;
+ }
+
+lose:
+ if (!ok)
+ bzero(s, max);
+ printf("\n");
+ /* turn echo back on */
+ tty_state.sg_flags |= ECHO;
+ if (ioctl(0,TIOCSETP,&tty_state))
+ ok = 0;
+ pop_signals();
+ bcopy(env, old_env, sizeof(env));
+ if (verify)
+ bzero(key_string, sizeof (key_string));
+ s[max-1] = 0; /* force termination */
+ return !ok; /* return nonzero if not okay */
+}
+
+/*
+ * this can be static since we should never have more than
+ * one set saved....
+ */
+static RETSIGTYPE (*old_sigfunc[NSIG])();
+
+static
+push_signals()
+{
+ register i;
+ for (i = 0; i < NSIG; i++)
+ old_sigfunc[i] = signal(i,sig_restore);
+}
+
+static
+pop_signals()
+{
+ register i;
+ for (i = 0; i < NSIG; i++)
+ signal(i,old_sigfunc[i]);
+}
+
+static void
+sig_restore(sig,code,scp)
+ int sig,code;
+ struct sigcontext *scp;
+{
+ longjmp(env,1);
+}
+#endif /* NOENCRYPTION */
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_krbhst.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * Given a Kerberos realm, find a host on which the Kerberos authenti-
+ * cation server can be found.
+ *
+ * krb_get_krbhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer, n, and
+ * returns (in h) the nth entry from the configuration file (KRB_CONF,
+ * defined in "krb.h") associated with the specified realm.
+ *
+ * On end-of-file, krb_get_krbhst returns KFAILURE. If n=1 and the
+ * configuration file does not exist, krb_get_krbhst will return KRB_HOST
+ * (also defined in "krb.h"). If all goes well, the routine returnes
+ * KSUCCESS.
+ *
+ * The KRB_CONF file contains the name of the local realm in the first
+ * line (not used by this routine), followed by lines indicating realm/host
+ * entries. The words "admin server" following the hostname indicate that
+ * the host provides an administrative database server.
+ *
+ * For example:
+ *
+ * ATHENA.MIT.EDU
+ * ATHENA.MIT.EDU kerberos-1.mit.edu admin server
+ * ATHENA.MIT.EDU kerberos-2.mit.edu
+ * LCS.MIT.EDU kerberos.lcs.mit.edu admin server
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * kerberos. In the long run, this functionality will be provided by a
+ * nameserver.
+ */
+
+int
+krb_get_krbhst(h, r, n)
+ char *h;
+ char *r;
+ int n;
+{
+ FILE *cnffile;
+ char tr[REALM_SZ];
+ char linebuf[BUFSIZ];
+ register int i;
+
+ if ((cnffile = fopen(KRB_CONF,"r")) == NULL) {
+ char tbuf[128];
+ char *tdir = (char *) getenv("KRBCONFDIR");
+ strncpy(tbuf, tdir ? tdir : "/etc", sizeof(tbuf));
+ strncat(tbuf, "/krb.conf", sizeof(tbuf));
+ tbuf[sizeof(tbuf)-1] = 0;
+ if ((cnffile = fopen(tbuf,"r")) == NULL)
+ if (n==1) {
+ (void) strcpy(h,KRB_HOST);
+ return(KSUCCESS);
+ }
+ else
+ return(KFAILURE);
+ }
+ if (fscanf(cnffile,"%s",tr) == EOF)
+ return(KFAILURE);
+ /* run through the file, looking for the nth server for this realm */
+ for (i = 1; i <= n;) {
+ if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
+ (void) fclose(cnffile);
+ return(KFAILURE);
+ }
+ if (sscanf(linebuf, "%s %s", tr, h) != 2)
+ continue;
+ if (!strcmp(tr,r))
+ i++;
+ }
+ (void) fclose(cnffile);
+ return(KSUCCESS);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_krbrlm.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * krb_get_lrealm takes a pointer to a string, and a number, n. It fills
+ * in the string, r, with the name of the nth realm specified on the
+ * first line of the kerberos config file (KRB_CONF, defined in "krb.h").
+ * It returns 0 (KSUCCESS) on success, and KFAILURE on failure. If the
+ * config file does not exist, and if n=1, a successful return will occur
+ * with r = KRB_REALM (also defined in "krb.h").
+ *
+ * NOTE: for archaic & compatibility reasons, this routine will only return
+ * valid results when n = 1.
+ *
+ * For the format of the KRB_CONF file, see comments describing the routine
+ * krb_get_krbhst().
+ */
+
+int
+krb_get_lrealm(r, n)
+ char *r;
+ int n;
+{
+ FILE *cnffile;
+
+ if (n > 1)
+ return(KFAILURE); /* Temporary restriction */
+
+ if ((cnffile = fopen(KRB_CONF, "r")) == NULL) {
+ char tbuf[128];
+ char *tdir = (char *) getenv("KRBCONFDIR");
+ strncpy(tbuf, tdir ? tdir : "/etc", sizeof(tbuf));
+ strncat(tbuf, "/krb.conf", sizeof(tbuf));
+ tbuf[sizeof(tbuf)-1] = 0;
+ if ((cnffile = fopen(tbuf,"r")) == NULL)
+ if (n == 1) {
+ (void) strcpy(r, KRB_REALM);
+ return(KSUCCESS);
+ }
+ else
+ return(KFAILURE);
+ }
+
+ if (fscanf(cnffile,"%s",r) != 1) {
+ (void) fclose(cnffile);
+ return(KFAILURE);
+ }
+ (void) fclose(cnffile);
+ return(KSUCCESS);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_phost.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#define USE_FULL_HOST_NAME 0
+
+#include <ctype.h>
+#include <netdb.h>
+
+/*
+ * This routine takes an alias for a host name and returns the first
+ * field, lower case, of its domain name. For example, if "menel" is
+ * an alias for host officially named "menelaus" (in /etc/hosts), for
+ * the host whose official name is "MENELAUS.MIT.EDU", the name "menelaus"
+ * is returned.
+ *
+ * This is done for historical Athena reasons: the Kerberos name of
+ * rcmd servers (rlogin, rsh, rcp) is of the form "rcmd.host@realm"
+ * where "host"is the lowercase for of the host name ("menelaus").
+ * This should go away: the instance should be the domain name
+ * (MENELAUS.MIT.EDU). But for now we need this routine...
+ *
+ * A pointer to the name is returned, if found, otherwise a pointer
+ * to the original "alias" argument is returned.
+ */
+
+char *
+krb_get_phost(alias)
+ char *alias;
+{
+ struct hostent *h;
+ char *phost = alias;
+ if ((h=gethostbyname(alias)) != (struct hostent *)NULL ) {
+#if USE_FULL_HOST_NAME
+ char *p;
+#else /* USE_FULL_HOST_NAME */
+ char *p = strchr( h->h_name, '.' );
+ if (p)
+ *p = 0;
+#endif /* USE_FULL_HOST_NAME */
+ p = phost = h->h_name;
+ do {
+ if (isupper(*p)) *p=tolower(*p);
+ } while (*p++);
+ }
+ return(phost);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_pw_tkt.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * Get a ticket for the password-changing server ("changepw.KRB_MASTER").
+ *
+ * Given the name, instance, realm, and current password of the
+ * principal for which the user wants a password-changing-ticket,
+ * return either:
+ *
+ * GT_PW_BADPW if current password was wrong,
+ * GT_PW_NULL if principal had a NULL password,
+ * or the result of the krb_get_pw_in_tkt() call.
+ *
+ * First, try to get a ticket for "user.instance@realm" to use the
+ * "changepw.KRB_MASTER" server (KRB_MASTER is defined in "krb.h").
+ * The requested lifetime for the ticket is "1", and the current
+ * password is the "cpw" argument given.
+ *
+ * If the password was bad, give up.
+ *
+ * If the principal had a NULL password in the Kerberos database
+ * (indicating that the principal is known to Kerberos, but hasn't
+ * got a password yet), try instead to get a ticket for the principal
+ * "default.changepw@realm" to use the "changepw.KRB_MASTER" server.
+ * Use the password "changepwkrb" instead of "cpw". Return GT_PW_NULL
+ * if all goes well, otherwise the error.
+ *
+ * If this routine succeeds, a ticket and session key for either the
+ * principal "user.instance@realm" or "default.changepw@realm" to use
+ * the password-changing server will be in the user's ticket file.
+ */
+
+int
+get_pw_tkt(user, instance, realm, cpw)
+ char *user;
+ char *instance;
+ char *realm;
+ char *cpw;
+{
+ int kerror;
+
+ kerror = krb_get_pw_in_tkt(user, instance, realm, "changepw",
+ KRB_MASTER, 1, cpw);
+
+ if (kerror == INTK_BADPW)
+ return(GT_PW_BADPW);
+
+ if (kerror == KDC_NULL_KEY) {
+ kerror = krb_get_pw_in_tkt("default","changepw",realm,"changepw",
+ KRB_MASTER,1,"changepwkrb");
+ if (kerror)
+ return(kerror);
+ return(GT_PW_NULL);
+ }
+
+ return(kerror);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_request.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This procedure is obsolete. It is used in the kerberos_slave
+ * code for Version 3 tickets.
+ *
+ * This procedure sets s_name, and instance to point to
+ * the corresponding fields from tne nth request in the packet.
+ * it returns the lifetime requested. Garbage will be returned
+ * if there are less than n requests in the packet.
+ */
+
+int
+get_request(pkt, n, s_name, instance)
+ KTEXT pkt; /* The packet itself */
+ int n; /* Which request do we want */
+ char **s_name; /* Service name to be filled in */
+ char **instance; /* Instance name to be filled in */
+{
+ /* Go to the beginning of the request list */
+ char *ptr = (char *) pkt_a_realm(pkt) + 6 +
+ strlen((char *)pkt_a_realm(pkt));
+
+ /* Read requests until we hit the right one */
+ while (n-- > 1) {
+ ptr++;
+ ptr += 1 + strlen(ptr);
+ ptr += 1 + strlen(ptr);
+ }
+
+ /* Set the arguments to point to the right place */
+ *s_name = 1 + ptr;
+ *instance = 2 + ptr + strlen(*s_name);
+
+ /* Return the requested lifetime */
+ return((int) *ptr);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_svc_in_tkt.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This file contains two routines: srvtab_to_key(), which gets
+ * a server's key from a srvtab file, and krb_get_svc_in_tkt() which
+ * gets an initial ticket for a server.
+ */
+
+/*
+ * srvtab_to_key(): given a "srvtab" file (where the keys for the
+ * service on a host are stored), return the private key of the
+ * given service (user.instance@realm).
+ *
+ * srvtab_to_key() passes its arguments on to read_service_key(),
+ * plus one additional argument, the key version number.
+ * (Currently, the key version number is always 0; this value
+ * is treated as a wildcard by read_service_key().)
+ *
+ * If the "srvtab" argument is null, KEYFILE (defined in "krb.h")
+ * is passed in its place.
+ *
+ * It returns the return value of the read_service_key() call.
+ * The service key is placed in "key".
+ */
+
+static int
+srvtab_to_key(user, instance, realm, srvtab, key)
+ char *user;
+ char *instance;
+ char *realm;
+ char *srvtab;
+ unsigned char *key;
+{
+ if (!srvtab)
+ srvtab = KEYFILE;
+
+ return(read_service_key(user, instance, realm, 0, srvtab,
+ (char *)key));
+}
+
+/*
+ * krb_get_svc_in_tkt() passes its arguments on to krb_get_in_tkt(),
+ * plus two additional arguments: a pointer to the srvtab_to_key()
+ * function to be used to get the key from the key file and a NULL
+ * for the decryption procedure indicating that krb_get_in_tkt should
+ * use the default method of decrypting the response from the KDC.
+ *
+ * It returns the return value of the krb_get_in_tkt() call.
+ */
+
+int
+krb_get_svc_in_tkt(user, instance, realm, service, sinstance, life, srvtab)
+ char *user;
+ char *instance;
+ char *realm;
+ char *service;
+ char *sinstance;
+ int life;
+ char *srvtab;
+{
+ return(krb_get_in_tkt(user, instance, realm, service, sinstance,
+ life, srvtab_to_key, NULL, srvtab));
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_tf_fullname.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This file contains a routine to extract the fullname of a user
+ * from the ticket file.
+ */
+
+/*
+ * krb_get_tf_fullname() takes four arguments: the name of the
+ * ticket file, and variables for name, instance, and realm to be
+ * returned in. Since the realm of a ticket file is not really fully
+ * supported, the realm used will be that of the the first ticket in
+ * the file as this is the one that was obtained with a password by
+ * krb_get_in_tkt().
+ */
+
+int
+krb_get_tf_fullname(ticket_file, name, instance, realm)
+ char *ticket_file;
+ char *name;
+ char *instance;
+ char *realm;
+{
+ int tf_status;
+ CREDENTIALS c;
+
+ if ((tf_status = tf_init(ticket_file, R_TKT_FIL)) != KSUCCESS)
+ return(tf_status);
+
+ if (((tf_status = tf_get_pname(c.pname)) != KSUCCESS) ||
+ ((tf_status = tf_get_pinst(c.pinst)) != KSUCCESS))
+ return (tf_status);
+
+ if (name)
+ strcpy(name, c.pname);
+ if (instance)
+ strcpy(instance, c.pinst);
+ if ((tf_status = tf_get_cred(&c)) == KSUCCESS) {
+ if (realm)
+ strcpy(realm, c.realm);
+ }
+ else {
+ if (tf_status == EOF)
+ return(KFAILURE);
+ else
+ return(tf_status);
+ }
+ (void) tf_close();
+
+ return(tf_status);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/get_tf_realm.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This file contains a routine to extract the realm of a kerberos
+ * ticket file.
+ */
+
+/*
+ * krb_get_tf_realm() takes two arguments: the name of a ticket
+ * and a variable to store the name of the realm in.
+ *
+ */
+
+int
+krb_get_tf_realm(ticket_file, realm)
+ char *ticket_file;
+ char *realm;
+{
+ return(krb_get_tf_fullname(ticket_file, 0, 0, realm));
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/getrealm.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#define MATCH_SUBDOMAINS 0
+
+/* for Ultrix and friends ... */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+/*
+ * krb_realmofhost.
+ * Given a fully-qualified domain-style primary host name,
+ * return the name of the Kerberos realm for the host.
+ * If the hostname contains no discernable domain, or an error occurs,
+ * return the local realm name, as supplied by get_krbrlm().
+ * If the hostname contains a domain, but no translation is found,
+ * the hostname's domain is converted to upper-case and returned.
+ *
+ * The format of each line of the translation file is:
+ * domain_name kerberos_realm
+ * -or-
+ * host_name kerberos_realm
+ *
+ * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU)
+ * host names should be in the usual form (e.g. FOO.BAR.BAZ)
+ */
+
+static char ret_realm[REALM_SZ+1];
+
+char *
+krb_realmofhost(host)
+ char *host;
+{
+ char *domain;
+ FILE *trans_file;
+ char trans_host[MAXHOSTNAMELEN+1];
+ char trans_realm[REALM_SZ+1];
+ int retval;
+
+ domain = strchr(host, '.');
+
+ /* prepare default */
+ if (domain) {
+ char *cp;
+
+ strncpy(ret_realm, &domain[1], REALM_SZ);
+ ret_realm[REALM_SZ] = '\0';
+ /* Upper-case realm */
+ for (cp = ret_realm; *cp; cp++)
+ if (islower(*cp))
+ *cp = toupper(*cp);
+ } else {
+ krb_get_lrealm(ret_realm, 1);
+ }
+
+ if ((trans_file = fopen(KRB_RLM_TRANS, "r")) == (FILE *) 0) {
+ char tbuf[128];
+ char *tdir = (char *) getenv("KRBCONFDIR");
+ strncpy(tbuf, tdir ? tdir : "/etc", sizeof(tbuf));
+ strncat(tbuf, "/krb.realms", sizeof(tbuf));
+ tbuf[sizeof(tbuf)-1] = 0;
+ if ((trans_file = fopen(tbuf,"r")) == NULL)
+ return(ret_realm); /* krb_errno = KRB_NO_TRANS */
+ }
+ while (1) {
+ if ((retval = fscanf(trans_file, "%s %s",
+ trans_host, trans_realm)) != 2) {
+ if (retval == EOF) {
+ fclose(trans_file);
+ return(ret_realm);
+ }
+ continue; /* ignore broken lines */
+ }
+ trans_host[MAXHOSTNAMELEN] = '\0';
+ trans_realm[REALM_SZ] = '\0';
+ if (!strcasecmp(trans_host, host)) {
+ /* exact match of hostname, so return the realm */
+ (void) strcpy(ret_realm, trans_realm);
+ fclose(trans_file);
+ return(ret_realm);
+ }
+ if ((trans_host[0] == '.') && domain) {
+#if MATCH_SUBDOMAINS
+ char *cp;
+ for (cp = domain; cp != NULL; cp = strchr(cp+1, '.')) {
+ /* this is a domain match */
+ if (!strcasecmp(trans_host, cp)) {
+ /* domain match, save for later */
+ (void) strcpy(ret_realm, trans_realm);
+ continue;
+ }
+ }
+#else /* MATCH_SUBDOMAINS */
+ /* this is a domain match */
+ if (!strcasecmp(trans_host, domain)) {
+ /* domain match, save for later */
+ (void) strcpy(ret_realm, trans_realm);
+ continue;
+ }
+#endif /* MATCH_SUBDOMAINS */
+ }
+ }
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/getst.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * getst() takes a file descriptor, a string and a count. It reads
+ * from the file until either it has read "count" characters, or until
+ * it reads a null byte. When finished, what has been read exists in
+ * the given string "s". If "count" characters were actually read, the
+ * last is changed to a null, so the returned string is always null-
+ * terminated. getst() returns the number of characters read, including
+ * the null terminator.
+ */
+
+int
+getst(fd, s, n)
+ int fd;
+ register char *s;
+ int n;
+{
+ register count = n;
+ while (read(fd, s, 1) > 0 && --count)
+ if (*s++ == '\0')
+ return (n - count);
+ *s = '\0';
+ return (n - count);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/in_tkt.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef TKT_SHMEM
+#include <sys/param.h>
+#endif
+
+/*
+ * in_tkt() is used to initialize the ticket store. It creates the
+ * file to contain the tickets and writes the given user's name "pname"
+ * and instance "pinst" in the file. in_tkt() returns KSUCCESS on
+ * success, or KFAILURE if something goes wrong.
+ */
+
+int
+in_tkt(pname, pinst)
+ char *pname;
+ char *pinst;
+{
+ int tktfile;
+ uid_t me, metoo;
+ struct stat buf;
+ int count;
+ char *file = TKT_FILE;
+ int fd;
+ register int i;
+ char charbuf[BUFSIZ];
+#ifdef TKT_SHMEM
+ char shmidname[MaxPathLen];
+#endif /* TKT_SHMEM */
+
+ me = getuid ();
+ metoo = geteuid();
+ if (lstat(file,&buf) == 0) {
+ if (buf.st_uid != me || !(buf.st_mode & S_IFREG) ||
+ buf.st_mode & 077) {
+ if (krb_debug)
+ fprintf(stderr,"Error initializing %s",file);
+ return(KFAILURE);
+ }
+ /* file already exists, and permissions appear ok, so nuke it */
+ if ((fd = open(file, O_RDWR, 0)) < 0)
+ goto out; /* can't zero it, but we can still try truncating it */
+
+ bzero(charbuf, sizeof(charbuf));
+
+ for (i = 0; i < buf.st_size; i += sizeof(charbuf))
+ if (write(fd, charbuf, sizeof(charbuf)) != sizeof(charbuf)) {
+ (void) fsync(fd);
+ (void) close(fd);
+ goto out;
+ }
+
+ (void) fsync(fd);
+ (void) close(fd);
+ }
+ out:
+ /* arrange so the file is owned by the ruid
+ (swap real & effective uid if necessary).
+ This isn't a security problem, since the ticket file, if it already
+ exists, has the right uid (== ruid) and mode. */
+ if (me != metoo) {
+ if (setreuid(metoo, me) < 0) {
+ /* can't switch??? barf! */
+ if (krb_debug)
+ perror("in_tkt: setreuid");
+ return(KFAILURE);
+ } else
+ if (krb_debug)
+ printf("swapped UID's %d and %d\n",(int)metoo,(int)me);
+ }
+ if ((tktfile = creat(file,0600)) < 0) {
+ if (krb_debug)
+ fprintf(stderr,"Error initializing %s",TKT_FILE);
+ return(KFAILURE);
+ }
+ if (me != metoo) {
+ if (setreuid(me, metoo) < 0) {
+ /* can't switch??? barf! */
+ if (krb_debug)
+ perror("in_tkt: setreuid2");
+ return(KFAILURE);
+ } else
+ if (krb_debug)
+ printf("swapped UID's %d and %d\n",(int)me,(int)metoo);
+ }
+ if (lstat(file,&buf) < 0) {
+ if (krb_debug)
+ fprintf(stderr,"Error initializing %s",TKT_FILE);
+ return(KFAILURE);
+ }
+
+ if (buf.st_uid != me || !(buf.st_mode & S_IFREG) ||
+ buf.st_mode & 077) {
+ if (krb_debug)
+ fprintf(stderr,"Error initializing %s",TKT_FILE);
+ return(KFAILURE);
+ }
+
+ count = strlen(pname)+1;
+ if (write(tktfile,pname,count) != count) {
+ (void) close(tktfile);
+ return(KFAILURE);
+ }
+ count = strlen(pinst)+1;
+ if (write(tktfile,pinst,count) != count) {
+ (void) close(tktfile);
+ return(KFAILURE);
+ }
+ (void) close(tktfile);
+#ifdef TKT_SHMEM
+ (void) strcpy(shmidname, file);
+ (void) strcat(shmidname, ".shm");
+ return(krb_shm_create(shmidname));
+#else /* !TKT_SHMEM */
+ return(KSUCCESS);
+#endif /* TKT_SHMEM */
+}
--- /dev/null
+/*
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/k_localtime.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <kerberosIV/krb.h>
+
+#include <time.h>
+
+struct tm *
+k_localtime(tp)
+ u_int32_t *tp;
+{
+ time_t t;
+ t = *tp;
+ return localtime(&t);
+}
--- /dev/null
+.\" $Source: /home/cvs/src/kerberosIV/krb/Attic/kerberos.3,v $
+.\" $Author: tholo $
+.\" $Header: /home/cvs/src/kerberosIV/krb/Attic/kerberos.3,v 1.1.1.1 1995/12/14 06:52:41 tholo Exp $
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.TH KERBEROS 3 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+krb_mk_req, krb_rd_req, krb_kntoln, krb_set_key, krb_get_cred,
+krb_mk_priv, krb_rd_priv, krb_mk_safe, krb_rd_safe, krb_mk_err,
+krb_rd_err, krb_ck_repl \- Kerberos authentication library
+.SH SYNOPSIS
+.nf
+.nj
+.ft B
+#include <des.h>
+#include <krb.h>
+.PP
+.ft B
+extern char *krb_err_txt[];
+.PP
+.ft B
+int krb_mk_req(authent,service,instance,realm,checksum)
+KTEXT authent;
+char *service;
+char *instance;
+char *realm;
+u_long checksum;
+.PP
+.ft B
+int krb_rd_req(authent,service,instance,from_addr,ad,fn)
+KTEXT authent;
+char *service;
+char *instance;
+u_long from_addr;
+AUTH_DAT *ad;
+char *fn;
+.PP
+.ft B
+int krb_kntoln(ad,lname)
+AUTH_DAT *ad;
+char *lname;
+.PP
+.ft B
+int krb_set_key(key,cvt)
+char *key;
+int cvt;
+.PP
+.ft B
+int krb_get_cred(service,instance,realm,c)
+char *service;
+char *instance;
+char *realm;
+CREDENTIALS *c;
+.PP
+.ft B
+long krb_mk_priv(in,out,in_length,schedule,key,sender,receiver)
+u_char *in;
+u_char *out;
+u_long in_length;
+des_cblock key;
+des_key_schedule schedule;
+struct sockaddr_in *sender;
+struct sockaddr_in *receiver;
+.PP
+.ft B
+long krb_rd_priv(in,in_length,schedule,key,sender,receiver,msg_data)
+u_char *in;
+u_long in_length;
+Key_schedule schedule;
+des_cblock key;
+struct sockaddr_in *sender;
+struct sockaddr_in *receiver;
+MSG_DAT *msg_data;
+.PP
+.ft B
+long krb_mk_safe(in,out,in_length,key,sender,receiver)
+u_char *in;
+u_char *out;
+u_long in_length;
+des_cblock key;
+struct sockaddr_in *sender;
+struct sockaddr_in *receiver;
+.PP
+.ft B
+long krb_rd_safe(in,length,key,sender,receiver,msg_data)
+u_char *in;
+u_long length;
+des_cblock key;
+struct sockaddr_in *sender;
+struct sockaddr_in *receiver;
+MSG_DAT *msg_data;
+.PP
+.ft B
+long krb_mk_err(out,code,string)
+u_char *out;
+long code;
+char *string;
+.PP
+.ft B
+long krb_rd_err(in,length,code,msg_data)
+u_char *in;
+u_long length;
+long code;
+MSG_DAT *msg_data;
+.fi
+.ft R
+.SH DESCRIPTION
+This library supports network authentication and various related
+operations. The library contains many routines beyond those described
+in this man page, but they are not intended to be used directly.
+Instead, they are called by the routines that are described, the
+authentication server and the login program.
+.PP
+.I krb_err_txt[]
+contains text string descriptions of various Kerberos error codes returned
+by some of the routines below.
+.PP
+.I krb_mk_req
+takes a pointer to a text structure in which an authenticator is to be
+built. It also takes the name, instance, and realm of the service to be
+used and an optional checksum. It is up to the application to decide
+how to generate the checksum.
+.I krb_mk_req
+then retrieves a ticket for the desired service and creates an
+authenticator. The authenticator is built in
+.I authent
+and is accessible
+to the calling procedure.
+.PP
+It is up to the application to get the authenticator to the service
+where it will be read by
+.I krb_rd_req.
+Unless an attacker posesses the session key contained in the ticket, it
+will be unable to modify the authenticator. Thus, the checksum can be
+used to verify the authenticity of the other data that will pass through
+a connection.
+.PP
+.I krb_rd_req
+takes an authenticator of type
+.B KTEXT,
+a service name, an instance, the address of the
+host originating the request, and a pointer to a structure of type
+.B AUTH_DAT
+which is filled in with information obtained from the authenticator.
+It also optionally takes the name of the file in which it will find the
+secret key(s) for the service.
+If the supplied
+.I instance
+contains "*", then the first service key with the same service name
+found in the service key file will be used, and the
+.I instance
+argument will be filled in with the chosen instance. This means that
+the caller must provide space for such an instance name.
+.PP
+It is used to find out information about the principal when a request
+has been made to a service. It is up to the application protocol to get
+the authenticator from the client to the service. The authenticator is
+then passed to
+.I krb_rd_req
+to extract the desired information.
+.PP
+.I krb_rd_req
+returns zero (RD_AP_OK) upon successful authentication. If a packet was
+forged, modified, or replayed, authentication will fail. If the
+authentication fails, a non-zero value is returned indicating the
+particular problem encountered. See
+.I krb.h
+for the list of error codes.
+.PP
+If the last argument is the null string (""), krb_rd_req will use the
+file /etc/srvtab to find its keys. If the last argument is NULL, it
+will assume that the key has been set by
+.I krb_set_key
+and will not bother looking further.
+.PP
+.I krb_kntoln
+converts a Kerberos name to a local name. It takes a structure
+of type AUTH_DAT and uses the name and instance to look in the database
+/etc/aname to find the corresponding local name. The local name is
+returned and can be used by an application to change uids, directories,
+or other parameters. It is not an integral part of Kerberos, but is
+instead provided to support the use of Kerberos in existing utilities.
+.PP
+.I krb_set_key
+takes as an argument a des key. It then creates
+a key schedule from it and saves the original key to be used as an
+initialization vector.
+It is used to set the server's key which
+must be used to decrypt tickets.
+.PP
+If called with a non-zero second argument,
+.I krb_set_key
+will first convert the input from a string of arbitrary length to a DES
+key by encrypting it with a one-way function.
+.PP
+In most cases it should not be necessary to call
+.I krb_set_key.
+The necessary keys will usually be obtained and set inside
+.I krb_rd_req. krb_set_key
+is provided for those applications that do not wish to place the
+application keys on disk.
+.PP
+.I krb_get_cred
+searches the caller's ticket file for a ticket for the given service, instance,
+and realm; and, if a ticket is found, fills in the given CREDENTIALS structure
+with the ticket information.
+.PP
+If the ticket was found,
+.I krb_get_cred
+returns GC_OK.
+If the ticket file can't be found, can't be read, doesn't belong to
+the user (other than root), isn't a regular file, or is in the wrong
+mode, the error GC_TKFIL is returned.
+.PP
+.I krb_mk_priv
+creates an encrypted, authenticated
+message from any arbitrary application data, pointed to by
+.I in
+and
+.I in_length
+bytes long.
+The private session key, pointed to by
+.I key
+and the key schedule,
+.I schedule,
+are used to encrypt the data and some header information using
+.I pcbc_encrypt.
+.I sender
+and
+.I receiver
+point to the Internet address of the two parties.
+In addition to providing privacy, this protocol message protects
+against modifications, insertions or replays. The encapsulated message and
+header are placed in the area pointed to by
+.I out
+and the routine returns the length of the output, or -1 indicating
+an error.
+.PP
+.I krb_rd_priv
+decrypts and authenticates a received
+.I krb_mk_priv
+message.
+.I in
+points to the beginning of the received message, whose length
+is specified in
+.I in_length.
+The private session key, pointed to by
+.I key,
+and the key schedule,
+.I schedule,
+are used to decrypt and verify the received message.
+.I msg_data
+is a pointer to a
+.I MSG_DAT
+struct, defined in
+.I krb.h.
+The routine fills in the
+.I app_data
+field with a pointer to the decrypted application data,
+.I app_length
+with the length of the
+.I app_data
+field,
+.I time_sec
+and
+.I time_5ms
+with the timestamps in the message, and
+.I swap
+with a 1 if the byte order of the receiver is different than that of
+the sender. (The application must still determine if it is appropriate
+to byte-swap application data; the Kerberos protocol fields are already taken
+care of). The
+.I hash
+field returns a value useful as input to the
+.I krb_ck_repl
+routine.
+
+The routine returns zero if ok, or a Kerberos error code. Modified messages
+and old messages cause errors, but it is up to the caller to
+check the time sequence of messages, and to check against recently replayed
+messages using
+.I krb_ck_repl
+if so desired.
+.PP
+.I krb_mk_safe
+creates an authenticated, but unencrypted message from any arbitrary
+application data,
+pointed to by
+.I in
+and
+.I in_length
+bytes long.
+The private session key, pointed to by
+.I key,
+is used to seed the
+.I quad_cksum()
+checksum algorithm used as part of the authentication.
+.I sender
+and
+.I receiver
+point to the Internet address of the two parties.
+This message does not provide privacy, but does protect (via detection)
+against modifications, insertions or replays. The encapsulated message and
+header are placed in the area pointed to by
+.I out
+and the routine returns the length of the output, or -1 indicating
+an error.
+The authentication provided by this routine is not as strong as that
+provided by
+.I krb_mk_priv
+or by computing the checksum using
+.I cbc_cksum
+instead, both of which authenticate via DES.
+.PP
+
+.I krb_rd_safe
+authenticates a received
+.I krb_mk_safe
+message.
+.I in
+points to the beginning of the received message, whose length
+is specified in
+.I in_length.
+The private session key, pointed to by
+.I key,
+is used to seed the quad_cksum() routine as part of the authentication.
+.I msg_data
+is a pointer to a
+.I MSG_DAT
+struct, defined in
+.I krb.h .
+The routine fills in these
+.I MSG_DAT
+fields:
+the
+.I app_data
+field with a pointer to the application data,
+.I app_length
+with the length of the
+.I app_data
+field,
+.I time_sec
+and
+.I time_5ms
+with the timestamps in the message, and
+.I swap
+with a 1 if the byte order of the receiver is different than that of
+the sender.
+(The application must still determine if it is appropriate
+to byte-swap application data; the Kerberos protocol fields are already taken
+care of). The
+.I hash
+field returns a value useful as input to the
+.I krb_ck_repl
+routine.
+
+The routine returns zero if ok, or a Kerberos error code. Modified messages
+and old messages cause errors, but it is up to the caller to
+check the time sequence of messages, and to check against recently replayed
+messages using
+.I krb_ck_repl
+if so desired.
+.PP
+.I krb_mk_err
+constructs an application level error message that may be used along
+with
+.I krb_mk_priv
+or
+.I krb_mk_safe.
+.I out
+is a pointer to the output buffer,
+.I code
+is an application specific error code, and
+.I string
+is an application specific error string.
+
+.PP
+.I krb_rd_err
+unpacks a received
+.I krb_mk_err
+message.
+.I in
+points to the beginning of the received message, whose length
+is specified in
+.I in_length.
+.I code
+is a pointer to a value to be filled in with the error
+value provided by the application.
+.I msg_data
+is a pointer to a
+.I MSG_DAT
+struct, defined in
+.I krb.h .
+The routine fills in these
+.I MSG_DAT
+fields: the
+.I app_data
+field with a pointer to the application error text,
+.I app_length
+with the length of the
+.I app_data
+field, and
+.I swap
+with a 1 if the byte order of the receiver is different than that of
+the sender. (The application must still determine if it is appropriate
+to byte-swap application data; the Kerberos protocol fields are already taken
+care of).
+
+The routine returns zero if the error message has been successfully received,
+or a Kerberos error code.
+.PP
+The
+.I KTEXT
+structure is used to pass around text of varying lengths. It consists
+of a buffer for the data, and a length. krb_rd_req takes an argument of this
+type containing the authenticator, and krb_mk_req returns the
+authenticator in a structure of this type. KTEXT itself is really a
+pointer to the structure. The actual structure is of type KTEXT_ST.
+.PP
+The
+.I AUTH_DAT
+structure is filled in by krb_rd_req. It must be allocated before
+calling krb_rd_req, and a pointer to it is passed. The structure is
+filled in with data obtained from Kerberos.
+.I MSG_DAT
+structure is filled in by either krb_rd_priv, krb_rd_safe, or
+krb_rd_err. It must be allocated before the call and a pointer to it
+is passed. The structure is
+filled in with data obtained from Kerberos.
+.PP
+.SH FILES
+/usr/include/krb.h
+.br
+/usr/lib/libkrb.a
+.br
+/usr/include/des.h
+.br
+/usr/lib/libdes.a
+.br
+/etc/aname
+.br
+/etc/srvtab
+.br
+/tmp/tkt[uid]
+.SH "SEE ALSO"
+kerberos(1), des_crypt(3)
+.SH DIAGNOSTICS
+.SH BUGS
+The caller of
+.I krb_rd_req, krb_rd_priv, and krb_rd_safe
+must check time order and for replay attempts.
+.I krb_ck_repl
+is not implemented yet.
+.SH AUTHORS
+Clifford Neuman, MIT Project Athena
+.br
+Steve Miller, MIT Project Athena/Digital Equipment Corporation
+.SH RESTRICTIONS
+COPYRIGHT 1985,1986,1989 Massachusetts Institute of Technology
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/klog.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/time.h>
+
+#include <klog.h>
+
+static char *log_name = KRBLOG;
+static int is_open;
+static char logtxt[1000];
+
+/*
+ * This file contains two logging routines: kset_logfile()
+ * to determine the file to which log entries should be written;
+ * and klog() to write log entries to the file.
+ */
+
+/*
+ * klog() is used to add entries to the logfile (see kset_logfile()
+ * below). Note that it is probably not portable since it makes
+ * assumptions about what the compiler will do when it is called
+ * with less than the correct number of arguments which is the
+ * way it is usually called.
+ *
+ * The log entry consists of a timestamp and the given arguments
+ * printed according to the given "format" string.
+ *
+ * The log file is opened and closed for each log entry.
+ *
+ * If the given log type "type" is unknown, or if the log file
+ * cannot be opened, no entry is made to the log file.
+ *
+ * The return value is always a pointer to the formatted log
+ * text string "logtxt".
+ */
+
+char *
+klog(type, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a0)
+ int type;
+ char *format;
+ int a1, a2, a3, a4, a5, a6, a7, a8, a9, a0;
+{
+ FILE *logfile;
+ time_t now;
+ char *month_sname(int n);
+ struct tm *tm;
+ static int logtype_array[NLOGTYPE] = {0,0};
+ static int array_initialized;
+
+ if (!(array_initialized++)) {
+ logtype_array[L_NET_ERR] = 1;
+ logtype_array[L_KRB_PERR] = 1;
+ logtype_array[L_KRB_PWARN] = 1;
+ logtype_array[L_APPL_REQ] = 1;
+ logtype_array[L_INI_REQ] = 1;
+ logtype_array[L_DEATH_REQ] = 1;
+ logtype_array[L_NTGT_INTK] = 1;
+ logtype_array[L_ERR_SEXP] = 1;
+ logtype_array[L_ERR_MKV] = 1;
+ logtype_array[L_ERR_NKY] = 1;
+ logtype_array[L_ERR_NUN] = 1;
+ logtype_array[L_ERR_UNK] = 1;
+ }
+
+ (void) sprintf(logtxt,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0);
+
+ if (!logtype_array[type])
+ return(logtxt);
+
+ if ((logfile = fopen(log_name,"a")) == NULL)
+ return(logtxt);
+
+ (void) time(&now);
+ tm = localtime(&now);
+
+ fprintf(logfile,"%2d-%s-%02d %02d:%02d:%02d ",tm->tm_mday,
+ month_sname(tm->tm_mon + 1),tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ fprintf(logfile,"%s\n",logtxt);
+ (void) fclose(logfile);
+ return(logtxt);
+}
+
+/*
+ * kset_logfile() changes the name of the file to which
+ * messages are logged. If kset_logfile() is not called,
+ * the logfile defaults to KRBLOG, defined in "krb.h".
+ */
+
+void
+kset_logfile(filename)
+ char *filename;
+{
+ log_name = filename;
+ is_open = 0;
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/kname_parse.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#define INSTANCE_DOTS_OK 0
+
+/* max size of full name */
+#define FULL_SZ (ANAME_SZ + INST_SZ + REALM_SZ)
+
+#define NAME 0 /* which field are we in? */
+#define INST 1
+#define REALM 2
+
+/*
+ * This file contains four routines for handling Kerberos names.
+ *
+ * kname_parse() breaks a Kerberos name into its name, instance,
+ * and realm components.
+ *
+ * k_isname(), k_isinst(), and k_isrealm() check a given string to see if
+ * it's a syntactically legitimate respective part of a Kerberos name,
+ * returning 1 if it is, 0 if it isn't.
+ *
+ * Definition of "syntactically legitimate" names is according to
+ * the Project Athena Technical Plan Section E.2.1, page 7 "Specifying
+ * names", version dated 21 Dec 1987.
+ */
+
+/*
+ * kname_parse() takes a Kerberos name "fullname" of the form:
+ *
+ * username[.instance][@realm]
+ *
+ * and returns the three components ("name", "instance", and "realm"
+ * in the example above) in the given arguments "np", "ip", and "rp".
+ *
+ * If successful, it returns KSUCCESS. If there was an error,
+ * KNAME_FMT is returned.
+ */
+
+int
+kname_parse(np, ip, rp, fullname)
+ char *np;
+ char *ip;
+ char *rp;
+ char *fullname;
+{
+ static char buf[FULL_SZ];
+ char *rnext, *wnext; /* next char to read, write */
+ register char c;
+ int backslash;
+ int field;
+
+ backslash = 0;
+ rnext = buf;
+ wnext = np;
+ field = NAME;
+
+ if (strlen(fullname) > FULL_SZ)
+ return KNAME_FMT;
+ (void) strcpy(buf, fullname);
+
+ while ((c = *rnext++)) {
+ if (backslash) {
+ *wnext++ = c;
+ backslash = 0;
+ continue;
+ }
+ switch (c) {
+ case '\\':
+ backslash++;
+ break;
+ case '.':
+ switch (field) {
+ case NAME:
+ if (wnext == np)
+ return KNAME_FMT;
+ *wnext = '\0';
+ field = INST;
+ wnext = ip;
+ break;
+ case INST:
+#if INSTANCE_DOTS_OK
+ *wnext++ = c;
+ break;
+#else /* INSTANCE_DOTS_OK */
+ return KNAME_FMT;
+#endif /* INSTANCE_DOTS_OK */
+ /* break; */
+ case REALM:
+ *wnext++ = c;
+ break;
+ default:
+ fprintf(stderr, "unknown field value\n");
+ exit(1);
+ }
+ break;
+ case '@':
+ switch (field) {
+ case NAME:
+ if (wnext == np)
+ return KNAME_FMT;
+ *ip = '\0';
+ /* fall through */
+ case INST:
+ *wnext = '\0';
+ field = REALM;
+ wnext = rp;
+ break;
+ case REALM:
+ return KNAME_FMT;
+ default:
+ fprintf(stderr, "unknown field value\n");
+ exit(1);
+ }
+ break;
+ default:
+ *wnext++ = c;
+ }
+ }
+ *wnext = '\0';
+ if ((strlen(np) > ANAME_SZ - 1) ||
+ (strlen(ip) > INST_SZ - 1) ||
+ (strlen(rp) > REALM_SZ - 1))
+ return KNAME_FMT;
+ return KSUCCESS;
+}
+
+/*
+ * k_isname() returns 1 if the given name is a syntactically legitimate
+ * Kerberos name; returns 0 if it's not.
+ */
+
+int
+k_isname(s)
+ char *s;
+{
+ register char c;
+ int backslash = 0;
+
+ if (!*s)
+ return 0;
+ if (strlen(s) > ANAME_SZ - 1)
+ return 0;
+ while ((c = *s++)) {
+ if (backslash) {
+ backslash = 0;
+ continue;
+ }
+ switch(c) {
+ case '\\':
+ backslash = 1;
+ break;
+ case '.':
+ return 0;
+ /* break; */
+ case '@':
+ return 0;
+ /* break; */
+ }
+ }
+ return 1;
+}
+
+
+/*
+ * k_isinst() returns 1 if the given name is a syntactically legitimate
+ * Kerberos instance; returns 0 if it's not.
+ */
+
+int
+k_isinst(s)
+ char *s;
+{
+ register char c;
+ int backslash = 0;
+
+ if (strlen(s) > INST_SZ - 1)
+ return 0;
+ while ((c = *s++)) {
+ if (backslash) {
+ backslash = 0;
+ continue;
+ }
+ switch(c) {
+ case '\\':
+ backslash = 1;
+ break;
+ case '.':
+#if INSTANCE_DOTS_OK
+ break;
+#else /* INSTANCE_DOTS_OK */
+ return 0;
+#endif /* INSTANCE_DOTS_OK */
+ /* break; */
+ case '@':
+ return 0;
+ /* break; */
+ }
+ }
+ return 1;
+}
+
+/*
+ * k_isrealm() returns 1 if the given name is a syntactically legitimate
+ * Kerberos realm; returns 0 if it's not.
+ */
+
+int
+k_isrealm(s)
+ char *s;
+{
+ register char c;
+ int backslash = 0;
+
+ if (!*s)
+ return 0;
+ if (strlen(s) > REALM_SZ - 1)
+ return 0;
+ while ((c = *s++)) {
+ if (backslash) {
+ backslash = 0;
+ continue;
+ }
+ switch(c) {
+ case '\\':
+ backslash = 1;
+ break;
+ case '@':
+ return 0;
+ /* break; */
+ }
+ }
+ return 1;
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/kntoln.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+/*
+ * krb_kntoln converts an auth name into a local name by looking up
+ * the auth name in the /etc/aname file. The format of the aname
+ * file is:
+ *
+ * +-----+-----+-----+-----+------+----------+-------+-------+
+ * | anl | inl | rll | lnl | name | instance | realm | lname |
+ * +-----+-----+-----+-----+------+----------+-------+-------+
+ * | 1by | 1by | 1by | 1by | name | instance | realm | lname |
+ * +-----+-----+-----+-----+------+----------+-------+-------+
+ *
+ * If the /etc/aname file can not be opened it will set the
+ * local name to the auth name. Thus, in this case it performs as
+ * the identity function.
+ *
+ * The name instance and realm are passed to krb_kntoln through
+ * the AUTH_DAT structure (ad).
+ *
+ * Now here's what it *really* does:
+ *
+ * Given a Kerberos name in an AUTH_DAT structure, check that the
+ * instance is null, and that the realm is the same as the local
+ * realm, and return the principal's name in "lname". Return
+ * KSUCCESS if all goes well, otherwise KFAILURE.
+ */
+
+#include "krb_locl.h"
+
+int
+krb_kntoln(ad, lname)
+ AUTH_DAT *ad;
+ char *lname;
+{
+ static char lrealm[REALM_SZ] = "";
+
+ if (!(*lrealm) && (krb_get_lrealm(lrealm,1) == KFAILURE))
+ return(KFAILURE);
+
+ if (strcmp(ad->pinst,""))
+ return(KFAILURE);
+ if (strcmp(ad->prealm,lrealm))
+ return(KFAILURE);
+ (void) strcpy(lname,ad->pname);
+ return(KSUCCESS);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/kparse.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+/*
+ * Purpose:
+ * This module was developed to parse the "~/.klogin" files for
+ * Kerberos-authenticated rlogin/rcp/rsh services. However, it is
+ * general purpose and can be used to parse any such parameter file.
+ *
+ * The parameter file should consist of one or more entries, with each
+ * entry on a separate line and consisting of zero or more
+ * "keyword=value" combinations. The keyword is case insensitive, but
+ * the value is not. Any string may be enclosed in quotes, and
+ * c-style "\" literals are supported. A comma may be used to
+ * separate the k/v combinations, and multiple commas are ignored.
+ * Whitespace (blank or tab) may be used freely and is ignored.
+ *
+ * Full error processing is available. When PS_BAD_KEYWORD or
+ * PS_SYNTAX is returned from fGetParameterSet(), the string ErrorMsg
+ * contains a meaningful error message.
+ *
+ * Keywords and their default values are programmed by an external
+ * table.
+ *
+ * Routines:
+ * fGetParameterSet() parse one line of the parameter file
+ * fGetKeywordValue() parse one "keyword=value" combo
+ * fGetToken() parse one token
+ *
+ * " <- emacs fix
+ */
+
+#include "krb_locl.h"
+
+#include <kerberosIV/kparse.h>
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+#define MAXKEY 80
+#define MAXVALUE 80
+
+int LineNbr=1; /* current line nbr in parameter file */
+char ErrorMsg[80]; /* meaningful only when KV_SYNTAX, PS_SYNTAX,
+ * or PS_BAD_KEYWORD is returned by
+ * fGetKeywordValue or fGetParameterSet */
+
+int
+fGetParameterSet(fp, parm, parmcount)
+ FILE *fp;
+ parmtable *parm;
+ int parmcount;
+{
+ int rc,i;
+ char keyword[MAXKEY];
+ char value[MAXVALUE];
+
+ while (TRUE) {
+ rc=fGetKeywordValue(fp,keyword,MAXKEY,value,MAXVALUE);
+
+ switch (rc) {
+
+ case KV_EOF:
+ return(PS_EOF);
+
+ case KV_EOL:
+ return(PS_OKAY);
+
+ case KV_SYNTAX:
+ return(PS_SYNTAX);
+
+ case KV_OKAY:
+ /*
+ * got a reasonable keyword/value pair. Search the
+ * parameter table to see if we recognize the keyword; if
+ * not, return an error. If we DO recognize it, make sure
+ * it has not already been given. If not already given,
+ * save the value.
+ */
+ for (i=0; i<parmcount; i++) {
+ if (strcmp(strutol(keyword),parm[i].keyword)==0) {
+ if (parm[i].value) {
+ sprintf(ErrorMsg,"duplicate keyword \"%s\" found",
+ keyword);
+ return(PS_BAD_KEYWORD);
+ }
+ parm[i].value = strsave( value );
+ break;
+ }
+ }
+ if (i >= parmcount) {
+ sprintf(ErrorMsg, "unrecognized keyword \"%s\" found",
+ keyword);
+ return(PS_BAD_KEYWORD);
+ }
+ break;
+
+ default:
+ sprintf(ErrorMsg,
+ "panic: bad return (%d) from fGetToken()",rc);
+ break;
+ }
+ }
+}
+
+/*
+ * Routine: ParmCompare
+ *
+ * Purpose:
+ * ParmCompare checks a specified value for a particular keyword.
+ * fails if keyword not found or keyword found but the value was
+ * different. Like strcmp, ParmCompare returns 0 for a match found, -1
+ * otherwise
+ */
+int
+ParmCompare(parm, parmcount, keyword, value)
+ parmtable *parm;
+ int parmcount;
+ char *keyword;
+ char *value;
+{
+ int i;
+
+ for (i=0; i<parmcount; i++) {
+ if (strcmp(parm[i].keyword,keyword)==0) {
+ if (parm[i].value) {
+ return(strcmp(parm[i].value,value));
+ } else {
+ return(strcmp(parm[i].defvalue,value));
+ }
+ }
+ }
+ return(-1);
+}
+
+void
+FreeParameterSet(parm, parmcount)
+ parmtable *parm;
+ int parmcount;
+{
+ int i;
+
+ for (i=0; i<parmcount; i++) {
+ if (parm[i].value) {
+ free(parm[i].value);
+ parm[i].value = (char *)NULL;
+ }
+ }
+}
+
+int
+fGetKeywordValue(fp, keyword, klen, value, vlen)
+ FILE *fp;
+ char *keyword;
+ int klen;
+ char *value;
+ int vlen;
+{
+ int rc;
+ int gotit;
+
+ *keyword = *value = '\0'; /* preset strings to NULL */
+
+ /*
+ * Looking for a keyword.
+ * return an exception for EOF or BAD_QSTRING
+ * ignore leading WHITEspace
+ * ignore any number of leading commas
+ * newline means we have all the parms for this
+ * statement; give an indication that there is
+ * nothing more on this line.
+ * stop looking if we find QSTRING, STRING, or NUMBER
+ * return syntax error for any other PUNKtuation
+ */
+ gotit = FALSE;
+ do {
+ rc = fGetToken(fp,keyword,klen);
+
+ switch (rc) {
+
+ case GTOK_WHITE:
+ break;
+
+ case GTOK_EOF:
+ return(KV_EOF);
+
+ case GTOK_BAD_QSTRING:
+ sprintf(ErrorMsg,"unterminated string \"%s found",keyword);
+ return(KV_SYNTAX);
+
+ case GTOK_PUNK:
+ if (strcmp("\n",keyword)==0) {
+ return(KV_EOL);
+ } else if (strcmp(",",keyword)!=0) {
+ sprintf(ErrorMsg,"expecting rvalue, found \'%s\'",keyword);
+ }
+ break;
+
+ case GTOK_STRING:
+ case GTOK_QSTRING:
+ case GTOK_NUMBER:
+ gotit = TRUE;
+ break;
+
+ default:
+ sprintf(ErrorMsg,"panic: bad return (%d) from fGetToken()",rc);
+ return(KV_SYNTAX);
+ }
+
+ } while (!gotit);
+
+ /*
+ * now we expect an equal sign.
+ * skip any whitespace
+ * stop looking if we find an equal sign
+ * anything else causes a syntax error
+ */
+ gotit = FALSE;
+ do {
+ rc = fGetToken(fp,value,vlen);
+
+ switch (rc) {
+
+ case GTOK_WHITE:
+ break;
+
+ case GTOK_BAD_QSTRING:
+ sprintf(ErrorMsg,
+ "expecting \'=\', found unterminated string \"%s",
+ value);
+ return(KV_SYNTAX);
+
+ case GTOK_PUNK:
+ if (strcmp("=",value)==0) {
+ gotit = TRUE;
+ } else {
+ if (strcmp("\n",value)==0) {
+ sprintf(ErrorMsg,"expecting \"=\", found newline");
+ fUngetChar('\n',fp);
+ } else {
+ sprintf(ErrorMsg,
+ "expecting rvalue, found \'%s\'",keyword);
+ }
+ return(KV_SYNTAX);
+ }
+ break;
+
+ case GTOK_STRING:
+ case GTOK_QSTRING:
+ case GTOK_NUMBER:
+ sprintf(ErrorMsg,"expecting \'=\', found \"%s\"",value);
+ return(KV_SYNTAX);
+
+ case GTOK_EOF:
+ sprintf(ErrorMsg,"expecting \'=\', found EOF");
+ return(KV_SYNTAX);
+
+ default:
+ sprintf(ErrorMsg,
+ "panic: bad return (%d) from fGetToken()",rc);
+ return(KV_SYNTAX);
+ }
+
+ } while ( !gotit );
+
+ /*
+ * got the keyword and equal sign, now get a value.
+ * ignore any whitespace
+ * any punctuation is a syntax error
+ */
+ gotit = FALSE;
+ do {
+ rc = fGetToken(fp,value,vlen);
+
+ switch (rc) {
+
+ case GTOK_WHITE:
+ break;
+
+ case GTOK_EOF:
+ sprintf(ErrorMsg,"expecting rvalue, found EOF");
+ return(KV_SYNTAX);
+
+ case GTOK_BAD_QSTRING:
+ sprintf(ErrorMsg,"unterminated quoted string \"%s",value);
+ return(KV_SYNTAX);
+
+ case GTOK_PUNK:
+ if (strcmp("\n",value)==0) {
+ sprintf(ErrorMsg,"expecting rvalue, found newline");
+ fUngetChar('\n',fp);
+ } else {
+ sprintf(ErrorMsg,
+ "expecting rvalue, found \'%s\'",value);
+ }
+ return(KV_SYNTAX);
+ break;
+
+ case GTOK_STRING:
+ case GTOK_QSTRING:
+ case GTOK_NUMBER:
+ gotit = TRUE;
+ return(KV_OKAY);
+
+ default:
+ sprintf(ErrorMsg,
+ "panic: bad return (%d) from fGetToken()",rc);
+ return(KV_SYNTAX);
+ }
+
+ } while ( !gotit );
+ /*NOTREACHED*/
+ return(KV_SYNTAX);
+}
+
+/*
+ * Routine Name: fGetToken
+ *
+ * Function: read the next token from the specified file.
+ * A token is defined as a group of characters
+ * terminated by a white space char (SPACE, CR,
+ * LF, FF, TAB). The token returned is stripped of
+ * both leading and trailing white space, and is
+ * terminated by a NULL terminator. An alternate
+ * definition of a token is a string enclosed in
+ * single or double quotes.
+ *
+ * Explicit Parameters:
+ * fp pointer to the input FILE
+ * dest pointer to destination buffer
+ * maxlen length of the destination buffer. The buffer
+ * length INCLUDES the NULL terminator.
+ *
+ * Implicit Parameters: stderr where the "token too long" message goes
+ *
+ * External Procedures: fgetc
+ *
+ * Side Effects: None
+ *
+ * Return Value: A token classification value, as
+ * defined in kparse.h. Note that the
+ * classification for end of file is
+ * always zero.
+ */
+int
+fGetToken(fp, dest, maxlen)
+ FILE *fp;
+ char *dest;
+ int maxlen;
+{
+ int ch='\0';
+ int len=0;
+ char *p = dest;
+ int digits;
+
+ ch=fGetChar(fp);
+
+ /*
+ * check for a quoted string. If found, take all characters
+ * that fit until a closing quote is found. Note that this
+ * algorithm will not behave well for a string which is too long.
+ */
+ if (ISQUOTE(ch)) {
+ int done = FALSE;
+ do {
+ ch = fGetChar(fp);
+ done = ((maxlen<++len)||ISLINEFEED(ch)||(ch==EOF)
+ ||ISQUOTE(ch));
+ if (ch=='\\')
+ ch = fGetLiteral(fp);
+ if (!done)
+ *p++ = ch;
+ else if ((ch!=EOF) && !ISQUOTE(ch))
+ fUngetChar(ch,fp);
+ } while (!done);
+ *p = '\0';
+ if (ISLINEFEED(ch)) return(GTOK_BAD_QSTRING);
+ return(GTOK_QSTRING);
+ }
+
+ /*
+ * Not a quoted string. If its a token character (rules are
+ * defined via the ISTOKENCHAR macro, in kparse.h) take it and all
+ * token chars following it until we run out of space.
+ */
+ digits=TRUE;
+ if (ISTOKENCHAR(ch)) {
+ while ( (ISTOKENCHAR(ch)) && len<maxlen-1 ) {
+ if (!isdigit(ch)) digits=FALSE;
+ *p++ = ch;
+ len++;
+ ch = fGetChar(fp);
+ };
+ *p = '\0';
+
+ if (ch!=EOF) {
+ fUngetChar(ch,fp);
+ }
+ if (digits) {
+ return(GTOK_NUMBER);
+ } else {
+ return(GTOK_STRING);
+ }
+ }
+
+ /*
+ * Neither a quoted string nor a token character. Return a string
+ * with just that one character in it.
+ */
+ if (ch==EOF) {
+ return(GTOK_EOF);
+ }
+ if (!ISWHITESPACE(ch)) {
+ *p++ = ch;
+ *p='\0';
+ } else {
+ *p++ = ' '; /* white space is always the
+ * blank character */
+ *p='\0';
+ /*
+ * The character is a white space. Flush all additional white
+ * space.
+ */
+ while (ISWHITESPACE(ch) && ((ch=fGetChar(fp)) != EOF))
+ ;
+ if (ch!=EOF) {
+ fUngetChar(ch,fp);
+ }
+ return(GTOK_WHITE);
+ }
+ return(GTOK_PUNK);
+}
+
+/*
+ * fGetLiteral is called after we find a '\' in the input stream. A
+ * string of numbers following the backslash are converted to the
+ * appropriate value; hex (0xn), octal (0n), and decimal (otherwise)
+ * are all supported. If the char after the \ is not a number, we
+ * special case certain values (\n, \f, \r, \b) or return a literal
+ * otherwise (useful for \", for example).
+ *
+ * " <- emacs fix
+ */
+
+int
+fGetLiteral(fp)
+ FILE *fp;
+{
+ int ch;
+ int n=0;
+ int base;
+
+ ch = fGetChar(fp);
+
+ if (!isdigit(ch)) {
+ switch (ch) {
+ case 'n': return('\n');
+ case 'f': return('\f');
+ case 'r': return('\r');
+ case 'b': return('\b');
+ default: return(ch);
+ }
+ }
+
+ /*
+ * got a number. might be decimal (no prefix), octal (prefix 0),
+ * or hexadecimal (prefix 0x). Set the base appropriately.
+ */
+ if (ch!='0') {
+ base=10; /* its a decimal number */
+ } else {
+ /*
+ * found a zero, its either hex or octal
+ */
+ ch = fGetChar(fp);
+ if ((ch!='x') && (ch!='X')) {
+ base=010;
+ } else {
+ ch = fGetChar(fp);
+ base=0x10;
+ }
+ }
+
+ switch (base) {
+
+ case 010: /* octal */
+ while (ISOCTAL(ch)) {
+ n = (n*base) + ch - '0';
+ ch = fGetChar(fp);
+ }
+ break;
+
+ case 10: /* decimal */
+ while (isdigit(ch)) {
+ n = (n*base) + ch - '0';
+ ch = fGetChar(fp);
+ }
+ break;
+ case 0x10: /* hexadecimal */
+ while (isxdigit(ch)) {
+ if (isdigit(ch)) {
+ n = (n*base) + ch - '0';
+ } else {
+ n = (n*base) + toupper(ch) - 'A' + 0xA ;
+ }
+ ch = fGetChar(fp);
+ }
+ break;
+ default:
+ fprintf(stderr,"fGetLiteral() died real bad. Fix gettoken.c.");
+ exit(1);
+ break;
+ }
+ fUngetChar(ch,fp);
+ return(n);
+}
+
+/*
+ * exactly the same as ungetc(3) except that the line number of the
+ * input file is maintained.
+ */
+int
+fUngetChar(ch, fp)
+ int ch;
+ FILE *fp;
+{
+ if (ch=='\n') LineNbr--;
+ return(ungetc(ch,fp));
+}
+
+/*
+ * exactly the same as fgetc(3) except that the line number of the
+ * input file is maintained.
+ */
+int
+fGetChar(fp)
+ FILE *fp;
+{
+ int ch = fgetc(fp);
+ if (ch=='\n') LineNbr++;
+ return(ch);
+}
+
+
+/*
+ * Routine Name: strsave
+ *
+ * Function: return a pointer to a saved copy of the
+ * input string. the copy will be allocated
+ * as large as necessary.
+ *
+ * Explicit Parameters: pointer to string to save
+ *
+ * Implicit Parameters: None
+ *
+ * External Procedures: malloc,strcpy,strlen
+ *
+ * Side Effects: None
+ *
+ * Return Value: pointer to copied string
+ *
+ */
+char *
+strsave(p)
+ char *p;
+{
+ return(strcpy(malloc(strlen(p)+1),p));
+}
+
+
+/*
+ * strutol changes all characters in a string to lower case, in place.
+ * the pointer to the beginning of the string is returned.
+ */
+
+char *
+strutol(start)
+ char *start;
+{
+ char *q;
+ for (q=start; *q; q++)
+ if (isupper(*q))
+ *q=tolower(*q);
+ return(start);
+}
+
+#ifdef GTOK_TEST /* mainline test routine for fGetToken() */
+
+#define MAXTOKEN 100
+
+char *pgm = "gettoken";
+
+main(argc,argv)
+ int argc;
+ char **argv;
+{
+ char *p;
+ int type;
+ FILE *fp;
+
+ if (--argc) {
+ fp = fopen(*++argv,"ra");
+ if (fp == (FILE *)NULL) {
+ fprintf(stderr,"can\'t open \"%s\"\n",*argv);
+ }
+ } else
+ fp = stdin;
+
+ p = malloc(MAXTOKEN);
+ while (type = fGetToken(fp,p,MAXTOKEN)) {
+ switch(type) {
+ case GTOK_BAD_QSTRING:
+ printf("BAD QSTRING!\t");
+ break;
+ case GTOK_EOF:
+ printf("EOF!\t");
+ break;
+ case GTOK_QSTRING:
+ printf("QSTRING\t");
+ break;
+ case GTOK_STRING:
+ printf("STRING\t");
+ break;
+ case GTOK_NUMBER:
+ printf("NUMBER\t");
+ break;
+ case GTOK_PUNK:
+ printf("PUNK\t");
+ break;
+ case GTOK_WHITE:
+ printf("WHITE\t");
+ break;
+ default:
+ printf("HUH?\t");
+ break;
+ }
+ if (*p=='\n')
+ printf("\\n\n");
+ else
+ printf("%s\n",p);
+ }
+ exit(0);
+}
+#endif
+
+#ifdef KVTEST
+
+main(argc,argv)
+ int argc;
+ char **argv;
+{
+ int rc,ch;
+ FILE *fp;
+ char key[MAXKEY],valu[MAXVALUE];
+ char *filename;
+
+ if (argc != 2) {
+ fprintf(stderr,"usage: test <filename>\n");
+ exit(1);
+ }
+
+ if (!(fp=fopen(*++argv,"r"))) {
+ fprintf(stderr,"can\'t open input file \"%s\"\n",filename);
+ exit(1);
+ }
+ filename = *argv;
+
+ while ((rc=fGetKeywordValue(fp,key,MAXKEY,valu,MAXVALUE))!=KV_EOF){
+
+ switch (rc) {
+
+ case KV_EOL:
+ printf("%s, line %d: nada mas.\n",filename,LineNbr-1);
+ break;
+
+ case KV_SYNTAX:
+ printf("%s, line %d: syntax error: %s\n",
+ filename,LineNbr,ErrorMsg);
+ while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+ break;
+
+ case KV_OKAY:
+ printf("%s, line %d: okay, %s=\"%s\"\n",
+ filename,LineNbr,key,valu);
+ break;
+
+ default:
+ printf("panic: bad return (%d) from fGetKeywordValue\n",rc);
+ break;
+ }
+ }
+ printf("EOF");
+ fclose(fp);
+ exit(0);
+}
+#endif
+
+#ifdef PSTEST
+
+parmtable kparm[] = {
+ /* keyword, default, found value */
+ { "user", "", (char *)NULL },
+ { "realm", "Athena", (char *)NULL },
+ { "instance", "", (char *)NULL }
+};
+
+main(argc,argv)
+ int argc;
+ char **argv;
+{
+ int rc,i,ch;
+ FILE *fp;
+ char *filename;
+
+ if (argc != 2) {
+ fprintf(stderr,"usage: test <filename>\n");
+ exit(1);
+ }
+
+ if (!(fp=fopen(*++argv,"r"))) {
+ fprintf(stderr,"can\'t open input file \"%s\"\n",filename);
+ exit(1);
+ }
+ filename = *argv;
+
+ while ((rc=fGetParameterSet(fp,kparm,PARMCOUNT(kparm))) != PS_EOF) {
+
+ switch (rc) {
+
+ case PS_BAD_KEYWORD:
+ printf("%s, line %d: %s\n",filename,LineNbr,ErrorMsg);
+ while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+ break;
+
+ case PS_SYNTAX:
+ printf("%s, line %d: syntax error: %s\n",
+ filename,LineNbr,ErrorMsg);
+ while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+ break;
+
+ case PS_OKAY:
+ printf("%s, line %d: valid parameter set found:\n",
+ filename,LineNbr-1);
+ for (i=0; i<PARMCOUNT(kparm); i++) {
+ printf("\t%s = \"%s\"\n",kparm[i].keyword,
+ (kparm[i].value ? kparm[i].value
+ : kparm[i].defvalue));
+ }
+ break;
+
+ default:
+ printf("panic: bad return (%d) from fGetParameterSet\n",rc);
+ break;
+ }
+ FreeParameterSet(kparm,PARMCOUNT(kparm));
+ }
+ printf("EOF");
+ fclose(fp);
+ exit(0);
+}
+#endif
--- /dev/null
+/*
+ * int krb_equiv(u_int32_t ipaddr_a, u_int32_t ipaddr_b);
+ *
+ * Given two IP adresses return true if they match
+ * or are considered to belong to the same host.
+ *
+ * For example if /etc/krb.equiv looks like
+ *
+ * 130.237.223.3 192.16.126.3 # alv alv1
+ * 130.237.223.4 192.16.126.4 # byse byse1
+ * 130.237.228.152 192.16.126.9 # topsy topsy1
+ *
+ * krb_equiv(alv, alv1) would return true but
+ * krb_equiv(alv, byse1) would not.
+ *
+ * A comment starts with an '#' and ends with '\n'.
+ *
+ */
+#include "krb_locl.h"
+
+int
+krb_equiv(a, b)
+ u_int32_t a;
+ u_int32_t b;
+{
+#ifdef NO_IPADDR_CHECK
+ return 1;
+#else
+
+ FILE *fil;
+ int result = 0;
+ char line[256];
+
+ if (a == b) /* trivial match */
+ return 1;
+
+ fil = fopen(KRB_EQUIV, "r");
+ if (fil == NULL) /* open failed */
+ return 0;
+
+ while (fgets(line, sizeof(line)-1, fil) != NULL) /* for each line */
+ {
+ int hit_a = 0, hit_b = 0;
+ char *t = line;
+
+ /* for each item on this line */
+ while (*t != 0) /* more addresses on this line? */
+ if (*t == '#') /* rest is comment */
+ *t = 0;
+ else if (isspace(*t)) /* skip space */
+ t++;
+ else if (isdigit(*t)) /* an address? */
+ {
+ u_int32_t tmp = inet_addr(t);
+ if (tmp == -1)
+ ; /* not an address (or broadcast) */
+ else if (tmp == a)
+ hit_a = 1;
+ else if (tmp == b)
+ hit_b = 1;
+
+ while (*t == '.' || isdigit(*t)) /* done with this address */
+ t++;
+ }
+ else
+ *t = 0; /* garbage on this line, skip it */
+
+ /* line is now parsed, if we found 2 matches were done */
+ if (hit_a && hit_b)
+ {
+ result = 1;
+ goto done;
+ }
+ }
+
+ done:
+ fclose(fil);
+ return result;
+#endif /* !NO_IPADDR_CHECK */
+}
--- /dev/null
+# Copyright 1987,1988 Massachusetts Institute of Technology
+#
+# For copying and distribution information, see the file
+# "mit-copyright.h".
+#
+# $Source: /home/cvs/src/kerberosIV/krb/Attic/krb_err.et,v $
+# $Author: tholo $
+# $Header: /home/cvs/src/kerberosIV/krb/Attic/krb_err.et,v 1.1.1.1 1995/12/14 06:52:37 tholo Exp $
+#
+ error_table krb
+
+ ec KRBET_KSUCCESS,
+ "Kerberos successful"
+
+ ec KRBET_KDC_NAME_EXP,
+ "Kerberos principal expired"
+
+ ec KRBET_KDC_SERVICE_EXP,
+ "Kerberos service expired"
+
+ ec KRBET_KDC_AUTH_EXP,
+ "Kerberos auth expired"
+
+ ec KRBET_KDC_PKT_VER,
+ "Incorrect kerberos master key version"
+
+ ec KRBET_KDC_P_MKEY_VER,
+ "Incorrect kerberos master key version"
+
+ ec KRBET_KDC_S_MKEY_VER,
+ "Incorrect kerberos master key version"
+
+ ec KRBET_KDC_BYTE_ORDER,
+ "Kerberos error: byte order unknown"
+
+ ec KRBET_KDC_PR_UNKNOWN,
+ "Kerberos principal unknown"
+
+ ec KRBET_KDC_PR_N_UNIQUE,
+ "Kerberos principal not unique"
+
+ ec KRBET_KDC_NULL_KEY,
+ "Kerberos principal has null key"
+
+ ec KRBET_KRB_RES11,
+ "Reserved 11"
+
+ ec KRBET_KRB_RES12,
+ "Reserved 12"
+
+ ec KRBET_KRB_RES13,
+ "Reserved 13"
+
+ ec KRBET_KRB_RES14,
+ "Reserved 14"
+
+ ec KRBET_KRB_RES15,
+ "Reserved 15"
+
+ ec KRBET_KRB_RES16,
+ "Reserved 16"
+
+ ec KRBET_KRB_RES17,
+ "Reserved 17"
+
+ ec KRBET_KRB_RES18,
+ "Reserved 18"
+
+ ec KRBET_KRB_RES19,
+ "Reserved 19"
+
+ ec KRBET_KDC_GEN_ERR,
+ "Generic error from Kerberos KDC"
+
+ ec KRBET_GC_TKFIL,
+ "Can't read Kerberos ticket file"
+
+ ec KRBET_GC_NOTKT,
+ "Can't find Kerberos ticket or TGT"
+
+ ec KRBET_KRB_RES23,
+ "Reserved 23"
+
+ ec KRBET_KRB_RES24,
+ "Reserved 24"
+
+ ec KRBET_KRB_RES25,
+ "Reserved 25"
+
+ ec KRBET_MK_AP_TGTEXP,
+ "Kerberos TGT Expired"
+
+ ec KRBET_KRB_RES27,
+ "Reserved 27"
+
+ ec KRBET_KRB_RES28,
+ "Reserved 28"
+
+ ec KRBET_KRB_RES29,
+ "Reserved 29"
+
+ ec KRBET_KRB_RES30,
+ "Reserved 30"
+
+ ec KRBET_RD_AP_UNDEC,
+ "Kerberos error: Can't decode authenticator"
+
+ ec KRBET_RD_AP_EXP,
+ "Kerberos ticket expired"
+
+ ec KRBET_RD_AP_NYV,
+ "Kerberos ticket not yet valid"
+
+ ec KRBET_RD_AP_REPEAT,
+ "Kerberos error: Repeated request"
+
+ ec KRBET_RD_AP_NOT_US,
+ "The kerberos ticket isn't for us"
+
+ ec KRBET_RD_AP_INCON,
+ "Kerberos request inconsistent"
+
+ ec KRBET_RD_AP_TIME,
+ "Kerberos error: delta_t too big"
+
+ ec KRBET_RD_AP_BADD,
+ "Kerberos error: incorrect net address"
+
+ ec KRBET_RD_AP_VERSION,
+ "Kerberos protocol version mismatch"
+
+ ec KRBET_RD_AP_MSG_TYPE,
+ "Kerberos error: invalid msg type"
+
+ ec KRBET_RD_AP_MODIFIED,
+ "Kerberos error: message stream modified"
+
+ ec KRBET_RD_AP_ORDER,
+ "Kerberos error: message out of order"
+
+ ec KRBET_RD_AP_UNAUTHOR,
+ "Kerberos error: unauthorized request"
+
+ ec KRBET_KRB_RES44,
+ "Reserved 44"
+
+ ec KRBET_KRB_RES45,
+ "Reserved 45"
+
+ ec KRBET_KRB_RES46,
+ "Reserved 46"
+
+ ec KRBET_KRB_RES47,
+ "Reserved 47"
+
+ ec KRBET_KRB_RES48,
+ "Reserved 48"
+
+ ec KRBET_KRB_RES49,
+ "Reserved 49"
+
+ ec KRBET_KRB_RES50,
+ "Reserved 50"
+
+ ec KRBET_GT_PW_NULL,
+ "Kerberos error: current PW is null"
+
+ ec KRBET_GT_PW_BADPW,
+ "Kerberos error: Incorrect current password"
+
+ ec KRBET_GT_PW_PROT,
+ "Kerberos protocol error"
+
+ ec KRBET_GT_PW_KDCERR,
+ "Error returned by Kerberos KDC"
+
+ ec KRBET_GT_PW_NULLTKT,
+ "Null Kerberos ticket returned by KDC"
+
+ ec KRBET_SKDC_RETRY,
+ "Kerberos error: Retry count exceeded"
+
+ ec KRBET_SKDC_CANT,
+ "Kerberos error: Can't send request"
+
+ ec KRBET_KRB_RES58,
+ "Reserved 58"
+
+ ec KRBET_KRB_RES59,
+ "Reserved 59"
+
+ ec KRBET_KRB_RES60,
+ "Reserved 60"
+
+ ec KRBET_INTK_W_NOTALL,
+ "Kerberos error: not all tickets returned"
+
+ ec KRBET_INTK_BADPW,
+ "Kerberos error: incorrect password"
+
+ ec KRBET_INTK_PROT,
+ "Kerberos error: Protocol Error"
+
+ ec KRBET_KRB_RES64,
+ "Reserved 64"
+
+ ec KRBET_KRB_RES65,
+ "Reserved 65"
+
+ ec KRBET_KRB_RES66,
+ "Reserved 66"
+
+ ec KRBET_KRB_RES67,
+ "Reserved 67"
+
+ ec KRBET_KRB_RES68,
+ "Reserved 68"
+
+ ec KRBET_KRB_RES69,
+ "Reserved 69"
+
+ ec KRBET_INTK_ERR,
+ "Other error"
+
+ ec KRBET_AD_NOTGT,
+ "Don't have Kerberos ticket-granting ticket"
+
+ ec KRBET_KRB_RES72,
+ "Reserved 72"
+
+ ec KRBET_KRB_RES73,
+ "Reserved 73"
+
+ ec KRBET_KRB_RES74,
+ "Reserved 74"
+
+ ec KRBET_KRB_RES75,
+ "Reserved 75"
+
+ ec KRBET_NO_TKT_FIL,
+ "No ticket file found"
+
+ ec KRBET_TKT_FIL_ACC,
+ "Couldn't access ticket file"
+
+ ec KRBET_TKT_FIL_LCK,
+ "Couldn't lock ticket file"
+
+ ec KRBET_TKT_FIL_FMT,
+ "Bad ticket file format"
+
+ ec KRBET_TKT_FIL_INI,
+ "tf_init not called first"
+
+ ec KRBET_KNAME_FMT,
+ "Bad Kerberos name format"
+
+ end
+
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/krb_err_txt.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This file contains an array of error text strings.
+ * The associated error codes (which are defined in "krb.h")
+ * follow the string in the comments at the end of each line.
+ */
+
+const char *krb_err_txt[256] = {
+ "OK", /* 000 */
+ "Principal expired (kerberos)", /* 001 */
+ "Service expired (kerberos)", /* 002 */
+ "Authentication expired (kerberos)", /* 003 */
+ "Unknown protocol version number (kerberos)", /* 004 */
+ "Principal: Incorrect master key version (kerberos)", /* 005 */
+ "Service: Incorrect master key version (kerberos)", /* 006 */
+ "Bad byte order (kerberos)", /* 007 */
+ "Principal unknown (kerberos)", /* 008 */
+ "Principal not unique (kerberos)", /* 009 */
+ "Principal has null key (kerberos)", /* 010 */
+ "Reserved error message 11 (kerberos)", /* 011 */
+ "Reserved error message 12 (kerberos)", /* 012 */
+ "Reserved error message 13 (kerberos)", /* 013 */
+ "Reserved error message 14 (kerberos)", /* 014 */
+ "Reserved error message 15 (kerberos)", /* 015 */
+ "Reserved error message 16 (kerberos)", /* 016 */
+ "Reserved error message 17 (kerberos)", /* 017 */
+ "Reserved error message 18 (kerberos)", /* 018 */
+ "Reserved error message 19 (kerberos)", /* 019 */
+ "Permission Denied (kerberos)", /* 020 */
+ "Can't read ticket file (krb_get_cred)", /* 021 */
+ "Can't find ticket (krb_get_cred)", /* 022 */
+ "Reserved error message 23 (krb_get_cred)", /* 023 */
+ "Reserved error message 24 (krb_get_cred)", /* 024 */
+ "Reserved error message 25 (krb_get_cred)", /* 025 */
+ "Ticket granting ticket expired (krb_mk_req)", /* 026 */
+ "Reserved error message 27 (krb_mk_req)", /* 027 */
+ "Reserved error message 28 (krb_mk_req)", /* 028 */
+ "Reserved error message 29 (krb_mk_req)", /* 029 */
+ "Reserved error message 30 (krb_mk_req)", /* 030 */
+ "Can't decode authenticator (krb_rd_req)", /* 031 */
+ "Ticket expired (krb_rd_req)", /* 032 */
+ "Ticket issue date too far in the future (krb_rd_req)",/* 033 */
+ "Repeat request (krb_rd_req)", /* 034 */
+ "Ticket for wrong server (krb_rd_req)", /* 035 */
+ "Request inconsistent (krb_rd_req)", /* 036 */
+ "Time is out of bounds (krb_rd_req)", /* 037 */
+ "Incorrect network address (krb_rd_req)", /* 038 */
+ "Protocol version mismatch (krb_rd_req)", /* 039 */
+ "Illegal message type (krb_rd_req)", /* 040 */
+ "Message integrity error (krb_rd_req)", /* 041 */
+ "Message duplicate or out of order (krb_rd_req)", /* 042 */
+ "Unauthorized request (krb_rd_req)", /* 043 */
+ "Reserved error message 44 (krb_rd_req)", /* 044 */
+ "Reserved error message 45 (krb_rd_req)", /* 045 */
+ "Reserved error message 46 (krb_rd_req)", /* 046 */
+ "Reserved error message 47 (krb_rd_req)", /* 047 */
+ "Reserved error message 48 (krb_rd_req)", /* 048 */
+ "Reserved error message 49 (krb_rd_req)", /* 049 */
+ "Reserved error message 50 (krb_rd_req)", /* 050 */
+ "Current password is NULL (get_pw_tkt)", /* 051 */
+ "Current password incorrect (get_pw_tkt)", /* 052 */
+ "Protocol error (gt_pw_tkt)", /* 053 */
+ "Error returned by KDC (gt_pw_tkt)", /* 054 */
+ "Null ticket returned by KDC (gt_pw_tkt)", /* 055 */
+ "Retry count exceeded (send_to_kdc)", /* 056 */
+ "Can't send request (send_to_kdc)", /* 057 */
+ "Reserved error message 58 (send_to_kdc)", /* 058 */
+ "Reserved error message 59 (send_to_kdc)", /* 059 */
+ "Reserved error message 60 (send_to_kdc)", /* 060 */
+ "Warning: Not ALL tickets returned", /* 061 */
+ "Password incorrect", /* 062 */
+ "Protocol error (get_intkt)", /* 063 */
+ "Reserved error message 64 (get_in_tkt)", /* 064 */
+ "Reserved error message 65 (get_in_tkt)", /* 065 */
+ "Reserved error message 66 (get_in_tkt)", /* 066 */
+ "Reserved error message 67 (get_in_tkt)", /* 067 */
+ "Reserved error message 68 (get_in_tkt)", /* 068 */
+ "Reserved error message 69 (get_in_tkt)", /* 069 */
+ "Generic error (get_intkt)", /* 070 */
+ "Don't have ticket granting ticket (get_ad_tkt)", /* 071 */
+ "Reserved error message 72 (get_ad_tkt)", /* 072 */
+ "Reserved error message 73 (get_ad_tkt)", /* 073 */
+ "Reserved error message 74 (get_ad_tkt)", /* 074 */
+ "Reserved error message 75 (get_ad_tkt)", /* 075 */
+ "No ticket file (tf_util)", /* 076 */
+ "Can't access ticket file (tf_util)", /* 077 */
+ "Can't lock ticket file; try later (tf_util)", /* 078 */
+ "Bad ticket file format (tf_util)", /* 079 */
+ "Read ticket file before tf_init (tf_util)", /* 080 */
+ "Bad Kerberos name format (kname_parse)", /* 081 */
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "Generic kerberos error (kfailure)", /* 255 */
+};
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/krb_get_in_tkt.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/time.h>
+
+int swap_bytes;
+
+static int
+pkt_clen(pkt)
+ KTEXT pkt;
+{
+ static unsigned short temp,temp2;
+ int clen = 0;
+
+ /* Start of ticket list */
+ unsigned char *ptr = pkt_a_realm(pkt) + 10
+ + strlen((char *)pkt_a_realm(pkt));
+
+ /* Finally the length */
+ bcopy((char *)(++ptr),(char *)&temp,2); /* alignment */
+ if (swap_bytes) {
+ /* assume a short is 2 bytes?? */
+ swab((char *)&temp,(char *)&temp2,2);
+ temp = temp2;
+ }
+
+ clen = (int) temp;
+
+ if (krb_debug)
+ printf("Clen is %d\n",clen);
+ return(clen);
+}
+
+/*
+ * decrypt_tkt(): Given user, instance, realm, passwd, key_proc
+ * and the cipher text sent from the KDC, decrypt the cipher text
+ * using the key returned by key_proc.
+ */
+
+static int
+decrypt_tkt(user, instance, realm, arg, key_proc, cipp)
+ char *user;
+ char *instance;
+ char *realm;
+ char *arg;
+ int (*key_proc)();
+ KTEXT *cipp;
+{
+ KTEXT cip = *cipp;
+ des_cblock key; /* Key for decrypting cipher */
+ des_key_schedule key_s;
+
+#ifndef NOENCRYPTION
+ /* Attempt to decrypt it */
+#endif
+
+ /* generate a key */
+
+ {
+ register int rc;
+ rc = (*key_proc)(user,instance,realm,arg,key);
+ if (rc)
+ return(rc);
+ }
+
+#ifndef NOENCRYPTION
+ des_key_sched(&key,key_s);
+ des_pcbc_encrypt((des_cblock *)cip->dat,(des_cblock *)cip->dat,
+ (long) cip->length,key_s,&key,DES_DECRYPT);
+#endif /* !NOENCRYPTION */
+ /* Get rid of all traces of key */
+ bzero((char *)key,sizeof(key));
+ bzero((char *)key_s,sizeof(key_s));
+
+ return(0);
+}
+
+/*
+ * krb_get_in_tkt() gets a ticket for a given principal to use a given
+ * service and stores the returned ticket and session key for future
+ * use.
+ *
+ * The "user", "instance", and "realm" arguments give the identity of
+ * the client who will use the ticket. The "service" and "sinstance"
+ * arguments give the identity of the server that the client wishes
+ * to use. (The realm of the server is the same as the Kerberos server
+ * to whom the request is sent.) The "life" argument indicates the
+ * desired lifetime of the ticket; the "key_proc" argument is a pointer
+ * to the routine used for getting the client's private key to decrypt
+ * the reply from Kerberos. The "decrypt_proc" argument is a pointer
+ * to the routine used to decrypt the reply from Kerberos; and "arg"
+ * is an argument to be passed on to the "key_proc" routine.
+ *
+ * If all goes well, krb_get_in_tkt() returns INTK_OK, otherwise it
+ * returns an error code: If an AUTH_MSG_ERR_REPLY packet is returned
+ * by Kerberos, then the error code it contains is returned. Other
+ * error codes returned by this routine include INTK_PROT to indicate
+ * wrong protocol version, INTK_BADPW to indicate bad password (if
+ * decrypted ticket didn't make sense), INTK_ERR if the ticket was for
+ * the wrong server or the ticket store couldn't be initialized.
+ *
+ * The format of the message sent to Kerberos is as follows:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * 1 byte KRB_PROT_VERSION protocol version number
+ * 1 byte AUTH_MSG_KDC_REQUEST | message type
+ * HOST_BYTE_ORDER local byte order in lsb
+ * string user client's name
+ * string instance client's instance
+ * string realm client's realm
+ * 4 bytes tlocal.tv_sec timestamp in seconds
+ * 1 byte life desired lifetime
+ * string service service's name
+ * string sinstance service's instance
+ */
+
+int
+krb_get_in_tkt(user, instance, realm, service, sinstance, life,
+ key_proc, decrypt_proc, arg)
+ char *user;
+ char *instance;
+ char *realm;
+ char *service;
+ char *sinstance;
+ int life;
+ int (*key_proc)();
+ int (*decrypt_proc)();
+ char *arg;
+{
+ KTEXT_ST pkt_st;
+ KTEXT pkt = &pkt_st; /* Packet to KDC */
+ KTEXT_ST rpkt_st;
+ KTEXT rpkt = &rpkt_st; /* Returned packet */
+ KTEXT_ST cip_st;
+ KTEXT cip = &cip_st; /* Returned Ciphertext */
+ KTEXT_ST tkt_st;
+ KTEXT tkt = &tkt_st; /* Current ticket */
+ des_cblock ses; /* Session key for tkt */
+ int kvno; /* Kvno for session key */
+ unsigned char *v = pkt->dat; /* Prot vers no */
+ unsigned char *t = (pkt->dat+1); /* Prot msg type */
+
+ char s_name[SNAME_SZ];
+ char s_instance[INST_SZ];
+ char rlm[REALM_SZ];
+ int lifetime;
+ int msg_byte_order;
+ int kerror;
+ unsigned long exp_date;
+ char *ptr;
+
+ struct timeval t_local;
+
+ unsigned long rep_err_code;
+
+ unsigned long kdc_time; /* KDC time */
+
+ /* BUILD REQUEST PACKET */
+
+ /* Set up the fixed part of the packet */
+ *v = (unsigned char) KRB_PROT_VERSION;
+ *t = (unsigned char) AUTH_MSG_KDC_REQUEST;
+ *t |= HOST_BYTE_ORDER;
+
+ /* Now for the variable info */
+ (void) strcpy((char *)(pkt->dat+2),user); /* aname */
+ pkt->length = 3 + strlen(user);
+ (void) strcpy((char *)(pkt->dat+pkt->length),
+ instance); /* instance */
+ pkt->length += 1 + strlen(instance);
+ (void) strcpy((char *)(pkt->dat+pkt->length),realm); /* realm */
+ pkt->length += 1 + strlen(realm);
+
+ (void) gettimeofday(&t_local,(struct timezone *) 0);
+ /* timestamp */
+ bcopy((char *)&(t_local.tv_sec),(char *)(pkt->dat+pkt->length), 4);
+ pkt->length += 4;
+
+ *(pkt->dat+(pkt->length)++) = (char) life;
+ (void) strcpy((char *)(pkt->dat+pkt->length),service);
+ pkt->length += 1 + strlen(service);
+ (void) strcpy((char *)(pkt->dat+pkt->length),sinstance);
+ pkt->length += 1 + strlen(sinstance);
+
+ rpkt->length = 0;
+
+ /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */
+
+ if ((kerror = send_to_kdc(pkt, rpkt, realm))) return(kerror);
+
+ /* check packet version of the returned packet */
+ if (pkt_version(rpkt) != KRB_PROT_VERSION)
+ return(INTK_PROT);
+
+ /* Check byte order */
+ msg_byte_order = pkt_msg_type(rpkt) & 1;
+ swap_bytes = 0;
+ if (msg_byte_order != HOST_BYTE_ORDER) {
+ swap_bytes++;
+ }
+
+ switch (pkt_msg_type(rpkt) & ~1) {
+ case AUTH_MSG_KDC_REPLY:
+ break;
+ case AUTH_MSG_ERR_REPLY:
+ bcopy(pkt_err_code(rpkt),(char *) &rep_err_code,4);
+ if (swap_bytes) swap_u_long(rep_err_code);
+ return((int)rep_err_code);
+ default:
+ return(INTK_PROT);
+ }
+
+ /* EXTRACT INFORMATION FROM RETURN PACKET */
+
+ /* get the principal's expiration date */
+ bcopy(pkt_x_date(rpkt),(char *) &exp_date,sizeof(exp_date));
+ if (swap_bytes) swap_u_long(exp_date);
+
+ /* Extract the ciphertext */
+ cip->length = pkt_clen(rpkt); /* let clen do the swap */
+
+ if ((cip->length < 0) || (cip->length > sizeof(cip->dat)))
+ return(INTK_ERR); /* no appropriate error code
+ currently defined for INTK_ */
+ /* copy information from return packet into "cip" */
+ bcopy((char *) pkt_cipher(rpkt),(char *)(cip->dat),cip->length);
+
+ /* Attempt to decrypt the reply. */
+ if (decrypt_proc == NULL)
+ decrypt_proc = decrypt_tkt;
+ (*decrypt_proc)(user, instance, realm, arg, key_proc, &cip);
+
+ ptr = (char *) cip->dat;
+
+ /* extract session key */
+ bcopy(ptr,(char *)ses,8);
+ ptr += 8;
+
+ if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
+ return(INTK_BADPW);
+
+ /* extract server's name */
+ (void) strcpy(s_name,ptr);
+ ptr += strlen(s_name) + 1;
+
+ if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
+ return(INTK_BADPW);
+
+ /* extract server's instance */
+ (void) strcpy(s_instance,ptr);
+ ptr += strlen(s_instance) + 1;
+
+ if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
+ return(INTK_BADPW);
+
+ /* extract server's realm */
+ (void) strcpy(rlm,ptr);
+ ptr += strlen(rlm) + 1;
+
+ /* extract ticket lifetime, server key version, ticket length */
+ /* be sure to avoid sign extension on lifetime! */
+ lifetime = (unsigned char) ptr[0];
+ kvno = (unsigned char) ptr[1];
+ tkt->length = (unsigned char) ptr[2];
+ ptr += 3;
+
+ if ((tkt->length < 0) ||
+ ((tkt->length + (ptr - (char *) cip->dat)) > cip->length))
+ return(INTK_BADPW);
+
+ /* extract ticket itself */
+ bcopy(ptr,(char *)(tkt->dat),tkt->length);
+ ptr += tkt->length;
+
+ if (strcmp(s_name, service) || strcmp(s_instance, sinstance) ||
+ strcmp(rlm, realm)) /* not what we asked for */
+ return(INTK_ERR); /* we need a better code here XXX */
+
+ /* check KDC time stamp */
+ bcopy(ptr,(char *)&kdc_time,4); /* Time (coarse) */
+ if (swap_bytes) swap_u_long(kdc_time);
+
+ ptr += 4;
+
+ (void) gettimeofday(&t_local,(struct timezone *) 0);
+ if (abs((int)(t_local.tv_sec - kdc_time)) > CLOCK_SKEW) {
+ return(RD_AP_TIME); /* XXX should probably be better
+ code */
+ }
+
+ /* initialize ticket cache */
+ if (in_tkt(user,instance) != KSUCCESS)
+ return(INTK_ERR);
+
+ /* stash ticket, session key, etc. for future use */
+ if ((kerror = save_credentials(s_name, s_instance, rlm, ses,
+ lifetime, kvno, tkt, t_local.tv_sec)))
+ return(kerror);
+
+ return(INTK_OK);
+}
--- /dev/null
+/* $Id: krb_locl.h,v 1.1.1.1 1995/12/14 06:52:38 tholo Exp $ */
+
+#ifndef __krb_locl_h
+#define __krb_locl_h
+
+#include <sys/cdefs.h>
+#include "kerberosIV/site.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <errno.h>
+
+#include <kerberosIV/krb.h>
+#include <prot.h>
+
+/* --- */
+
+/* Globals! */
+extern int krb_debug;
+extern int krb_ap_req_debug;
+
+/* Utils */
+char *pkt_cipher __P((KTEXT));
+
+int new_log __P((time_t, char *));
+char *klog ();
+
+char *month_sname __P((int));
+int fgetst __P((FILE *, char *, int));
+
+#endif /* __krb_locl_h */
--- /dev/null
+.\" $Source: /home/cvs/src/kerberosIV/krb/Attic/krb_realmofhost.3,v $
+.\" $Author: tholo $
+.\" $Header: /home/cvs/src/kerberosIV/krb/Attic/krb_realmofhost.3,v 1.1.1.1 1995/12/14 06:52:41 tholo Exp $
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.TH KRB_REALMOFHOST 3 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+krb_realmofhost, krb_get_phost, krb_get_krbhst, krb_get_admhst,
+krb_get_lrealm \- additional Kerberos utility routines
+.SH SYNOPSIS
+.nf
+.nj
+.ft B
+#include <krb.h>
+#include <des.h>
+#include <netinet/in.h>
+.PP
+.ft B
+char *krb_realmofhost(host)
+char *host;
+.PP
+.ft B
+char *krb_get_phost(alias)
+char *alias;
+.PP
+.ft B
+krb_get_krbhst(host,realm,n)
+char *host;
+char *realm;
+int n;
+.PP
+.ft B
+krb_get_admhst(host,realm,n)
+char *host;
+char *realm;
+int n;
+.PP
+.ft B
+krb_get_lrealm(realm,n)
+char *realm;
+int n;
+.fi
+.ft R
+.SH DESCRIPTION
+.I krb_realmofhost
+returns the Kerberos realm of the host
+.IR host ,
+as determined by the translation table
+.IR /etc/krb.realms .
+.I host
+should be the fully-qualified domain-style primary host name of the host
+in question. In order to prevent certain security attacks, this routine
+must either have
+.I a priori
+knowledge of a host's realm, or obtain such information securely.
+.PP
+The format of the translation file is described by
+.IR krb.realms (5).
+If
+.I host
+exactly matches a host_name line, the corresponding realm
+is returned.
+Otherwise, if the domain portion of
+.I host
+matches a domain_name line, the corresponding realm
+is returned.
+If
+.I host
+contains a domain, but no translation is found,
+.IR host 's
+domain is converted to upper-case and returned.
+If
+.I host
+contains no discernable domain, or an error occurs,
+the local realm name, as supplied by
+.IR krb_get_lrealm (3),
+is returned.
+.PP
+.I krb_get_phost
+converts the hostname
+.I alias
+(which can be either an official name or an alias) into the instance
+name to be used in obtaining Kerberos tickets for most services,
+including the Berkeley rcmd suite (rlogin, rcp, rsh).
+.br
+The current convention is to return the first segment of the official
+domain-style name after conversion to lower case.
+.PP
+.I krb_get_krbhst
+fills in
+.I host
+with the hostname of the
+.IR n th
+host running a Kerberos key distribution center (KDC)
+for realm
+.IR realm ,
+as specified in the configuration file (\fI/etc/krb.conf\fR).
+The configuration file is described by
+.IR krb.conf (5).
+If the host is successfully filled in, the routine
+returns KSUCCESS.
+If the file cannot be opened, and
+.I n
+equals 1, then the value of KRB_HOST as defined in
+.I <krb.h>
+is filled in, and KSUCCESS is returned. If there are fewer than
+.I n
+hosts running a Kerberos KDC for the requested realm, or the
+configuration file is malformed, the routine
+returns KFAILURE.
+.PP
+.I krb_get_admhst
+fills in
+.I host
+with the hostname of the
+.IR n th
+host running a Kerberos KDC database administration server
+for realm
+.IR realm ,
+as specified in the configuration file (\fI/etc/krb.conf\fR).
+If the file cannot be opened or is malformed, or there are fewer than
+.I n
+hosts running a Kerberos KDC database administration server,
+the routine returns KFAILURE.
+.PP
+The character arrays used as return values for
+.IR krb_get_krbhst ,
+.IR krb_get_admhst ,
+should be large enough to
+hold any hostname (MAXHOSTNAMELEN from <sys/param.h>).
+.PP
+.I krb_get_lrealm
+fills in
+.I realm
+with the
+.IR n th
+realm of the local host, as specified in the configuration file.
+.I realm
+should be at least REALM_SZ (from
+.IR <krb.h>) characters long.
+.PP
+.SH SEE ALSO
+kerberos(3), krb.conf(5), krb.realms(5)
+.SH FILES
+.TP 20n
+/etc/krb.realms
+translation file for host-to-realm mapping.
+.TP
+/etc/krb.conf
+local realm-name and realm/server configuration file.
+.SH BUGS
+The current convention for instance names is too limited; the full
+domain name should be used.
+.PP
+.I krb_get_lrealm
+currently only supports
+.I n
+= 1. It should really consult the user's ticket cache to determine the
+user's current realm, rather than consulting a file on the host.
--- /dev/null
+.\" $Source: /home/cvs/src/kerberosIV/krb/Attic/krb_sendauth.3,v $
+.\" $Author: tholo $
+.\" $Header: /home/cvs/src/kerberosIV/krb/Attic/krb_sendauth.3,v 1.1.1.1 1995/12/14 06:52:41 tholo Exp $
+.\" Copyright 1988 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.TH KRB_SENDAUTH 3 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+krb_sendauth, krb_recvauth, krb_net_write, krb_net_read \-
+Kerberos routines for sending authentication via network stream sockets
+.SH SYNOPSIS
+.nf
+.nj
+.ft B
+#include <krb.h>
+#include <des.h>
+#include <netinet/in.h>
+.PP
+.fi
+.HP 1i
+.ft B
+int krb_sendauth(options, fd, ktext, service, inst, realm, checksum,
+msg_data, cred, schedule, laddr, faddr, version)
+.nf
+.RS 0
+.ft B
+long options;
+int fd;
+KTEXT ktext;
+char *service, *inst, *realm;
+u_long checksum;
+MSG_DAT *msg_data;
+CREDENTIALS *cred;
+Key_schedule schedule;
+struct sockaddr_in *laddr, *faddr;
+char *version;
+.PP
+.fi
+.HP 1i
+.ft B
+int krb_recvauth(options, fd, ktext, service, inst, faddr, laddr,
+auth_data, filename, schedule, version)
+.nf
+.RS 0
+.ft B
+long options;
+int fd;
+KTEXT ktext;
+char *service, *inst;
+struct sockaddr_in *faddr, *laddr;
+AUTH_DAT *auth_data;
+char *filename;
+Key_schedule schedule;
+char *version;
+.PP
+.ft B
+int krb_net_write(fd, buf, len)
+int fd;
+char *buf;
+int len;
+.PP
+.ft B
+int krb_net_read(fd, buf, len)
+int fd;
+char *buf;
+int len;
+.fi
+.SH DESCRIPTION
+.PP
+These functions,
+which are built on top of the core Kerberos library,
+provide a convenient means for client and server
+programs to send authentication messages
+to one another through network connections.
+The
+.I krb_sendauth
+function sends an authenticated ticket from the client program to
+the server program by writing the ticket to a network socket.
+The
+.I krb_recvauth
+function receives the ticket from the client by
+reading from a network socket.
+
+.SH KRB_SENDAUTH
+.PP
+This function writes the ticket to
+the network socket specified by the
+file descriptor
+.IR fd,
+returning KSUCCESS if the write proceeds successfully,
+and an error code if it does not.
+
+The
+.I ktext
+argument should point to an allocated KTEXT_ST structure.
+The
+.IR service,
+.IR inst,
+and
+.IR realm
+arguments specify the server program's Kerberos principal name,
+instance, and realm.
+If you are writing a client that uses the local realm exclusively,
+you can set the
+.I realm
+argument to NULL.
+
+The
+.I version
+argument allows the client program to pass an application-specific
+version string that the server program can then match against
+its own version string.
+The
+.I version
+string can be up to KSEND_VNO_LEN (see
+.IR <krb.h> )
+characters in length.
+
+The
+.I checksum
+argument can be used to pass checksum information to the
+server program.
+The client program is responsible for specifying this information.
+This checksum information is difficult to corrupt because
+.I krb_sendauth
+passes it over the network in encrypted form.
+The
+.I checksum
+argument is passed as the checksum argument to
+.IR krb_mk_req .
+
+You can set
+.IR krb_sendauth's
+other arguments to NULL unless you want the
+client and server programs to mutually authenticate
+themselves.
+In the case of mutual authentication,
+the client authenticates itself to the server program,
+and demands that the server in turn authenticate itself to
+the client.
+
+.SH KRB_SENDAUTH AND MUTUAL AUTHENTICATION
+.PP
+If you want mutual authentication,
+make sure that you read all pending data from the local socket
+before calling
+.IR krb_sendauth.
+Set
+.IR krb_sendauth's
+.I options
+argument to
+.BR KOPT_DO_MUTUAL
+(this macro is defined in the
+.IR krb.h
+file);
+make sure that the
+.I laddr
+argument points to
+the address of the local socket,
+and that
+.I faddr
+points to the foreign socket's network address.
+
+.I Krb_sendauth
+fills in the other arguments--
+.IR msg_data ,
+.IR cred ,
+and
+.IR schedule --before
+sending the ticket to the server program.
+You must, however, allocate space for these arguments
+before calling the function.
+
+.I Krb_sendauth
+supports two other options:
+.BR KOPT_DONT_MK_REQ,
+and
+.BR KOPT_DONT_CANON.
+If called with
+.I options
+set as KOPT_DONT_MK_REQ,
+.I krb_sendauth
+will not use the
+.I krb_mk_req
+function to retrieve the ticket from the Kerberos server.
+The
+.I ktext
+argument must point to an existing ticket and authenticator (such as
+would be created by
+.IR krb_mk_req ),
+and the
+.IR service,
+.IR inst,
+and
+.IR realm
+arguments can be set to NULL.
+
+If called with
+.I options
+set as KOPT_DONT_CANON,
+.I krb_sendauth
+will not convert the service's instance to canonical form using
+.IR krb_get_phost (3).
+
+If you want to call
+.I krb_sendauth
+with a multiple
+.I options
+specification,
+construct
+.I options
+as a bitwise-OR of the options you want to specify.
+
+.SH KRB_RECVAUTH
+.PP
+The
+.I krb_recvauth
+function
+reads a ticket/authenticator pair from the socket pointed to by the
+.I fd
+argument.
+Set the
+.I options
+argument
+as a bitwise-OR of the options desired.
+Currently only KOPT_DO_MUTUAL is useful to the receiver.
+
+The
+.I ktext
+argument
+should point to an allocated KTEXT_ST structure.
+.I Krb_recvauth
+fills
+.I ktext
+with the
+ticket/authenticator pair read from
+.IR fd ,
+then passes it to
+.IR krb_rd_req .
+
+The
+.I service
+and
+.I inst
+arguments
+specify the expected service and instance for which the ticket was
+generated. They are also passed to
+.IR krb_rd_req.
+The
+.I inst
+argument may be set to "*" if the caller wishes
+.I krb_mk_req
+to fill in the instance used (note that there must be space in the
+.I inst
+argument to hold a full instance name, see
+.IR krb_mk_req (3)).
+
+The
+.I faddr
+argument
+should point to the address of the peer which is presenting the ticket.
+It is also passed to
+.IR krb_rd_req .
+
+If the client and server plan to mutually authenticate
+one another,
+the
+.I laddr
+argument
+should point to the local address of the file descriptor.
+Otherwise you can set this argument to NULL.
+
+The
+.I auth_data
+argument
+should point to an allocated AUTH_DAT area.
+It is passed to and filled in by
+.IR krb_rd_req .
+The checksum passed to the corresponding
+.I krb_sendauth
+is available as part of the filled-in AUTH_DAT area.
+
+The
+.I filename
+argument
+specifies the filename
+which the service program should use to obtain its service key.
+.I Krb_recvauth
+passes
+.I filename
+to the
+.I krb_rd_req
+function.
+If you set this argument to "",
+.I krb_rd_req
+looks for the service key in the file
+.IR /etc/srvtab.
+
+If the client and server are performing mutual authenication,
+the
+.I schedule
+argument
+should point to an allocated Key_schedule.
+Otherwise it is ignored and may be NULL.
+
+The
+.I version
+argument should point to a character array of at least KSEND_VNO_LEN
+characters. It is filled in with the version string passed by the client to
+.IR krb_sendauth.
+.PP
+.SH KRB_NET_WRITE AND KRB_NET_READ
+.PP
+The
+.I krb_net_write
+function
+emulates the write(2) system call, but guarantees that all data
+specified is written to
+.I fd
+before returning, unless an error condition occurs.
+.PP
+The
+.I krb_net_read
+function
+emulates the read(2) system call, but guarantees that the requested
+amount of data is read from
+.I fd
+before returning, unless an error condition occurs.
+.PP
+.SH BUGS
+.IR krb_sendauth,
+.IR krb_recvauth,
+.IR krb_net_write,
+and
+.IR krb_net_read
+will not work properly on sockets set to non-blocking I/O mode.
+
+.SH SEE ALSO
+
+krb_mk_req(3), krb_rd_req(3), krb_get_phost(3)
+
+.SH AUTHOR
+John T. Kohl, MIT Project Athena
+.SH RESTRICTIONS
+Copyright 1988, Massachusetts Instititute of Technology.
+For copying and distribution information,
+please see the file <mit-copyright.h>.
--- /dev/null
+.\" $Source: /home/cvs/src/kerberosIV/krb/Attic/krb_set_tkt_string.3,v $
+.\" $Author: tholo $
+.\" $Header: /home/cvs/src/kerberosIV/krb/Attic/krb_set_tkt_string.3,v 1.1.1.1 1995/12/14 06:52:40 tholo Exp $
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.TH KRB_SET_TKT_STRING 3 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+krb_set_tkt_string \- set Kerberos ticket cache file name
+.SH SYNOPSIS
+.nf
+.nj
+.ft B
+#include <krb.h>
+.PP
+.ft B
+void krb_set_tkt_string(filename)
+char *filename;
+.fi
+.ft R
+.SH DESCRIPTION
+.I krb_set_tkt_string
+sets the name of the file that holds the user's
+cache of Kerberos server tickets and associated session keys.
+.PP
+The string
+.I filename
+passed in is copied into local storage.
+Only MAXPATHLEN-1 (see <sys/param.h>) characters of the filename are
+copied in for use as the cache file name.
+.PP
+This routine should be called during initialization, before other
+Kerberos routines are called; otherwise the routines which fetch the
+ticket cache file name may be called and return an undesired ticket file
+name until this routine is called.
+.SH FILES
+.TP 20n
+/tmp/tkt[uid]
+default ticket file name, unless the environment variable KRBTKFILE is set.
+[uid] denotes the user's uid, in decimal.
+.SH SEE ALSO
+kerberos(3), setenv(3)
--- /dev/null
+.\" $Source: /home/cvs/src/kerberosIV/krb/Attic/kuserok.3,v $
+.\" $Author: tholo $
+.\" $Header: /home/cvs/src/kerberosIV/krb/Attic/kuserok.3,v 1.1.1.1 1995/12/14 06:52:40 tholo Exp $
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.TH KUSEROK 3 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kuserok \- Kerberos version of ruserok
+.SH SYNOPSIS
+.nf
+.nj
+.ft B
+#include <krb.h>
+.PP
+.ft B
+kuserok(kdata, localuser)
+AUTH_DAT *auth_data;
+char *localuser;
+.fi
+.ft R
+.SH DESCRIPTION
+.I kuserok
+determines whether a Kerberos principal described by the structure
+.I auth_data
+is authorized to login as user
+.I localuser
+according to the authorization file
+("~\fIlocaluser\fR/.klogin" by default). It returns 0 (zero) if authorized,
+1 (one) if not authorized.
+.PP
+If there is no account for
+.I localuser
+on the local machine, authorization is not granted.
+If there is no authorization file, and the Kerberos principal described
+by
+.I auth_data
+translates to
+.I localuser
+(using
+.IR krb_kntoln (3)),
+authorization is granted.
+If the authorization file
+can't be accessed, or the file is not owned by
+.IR localuser,
+authorization is denied. Otherwise, the file is searched for
+a matching principal name, instance, and realm. If a match is found,
+authorization is granted, else authorization is denied.
+.PP
+The file entries are in the format:
+.nf
+.in +5n
+ name.instance@realm
+.in -5n
+.fi
+with one entry per line.
+.SH SEE ALSO
+kerberos(3), ruserok(3), krb_kntoln(3)
+.SH FILES
+.TP 20n
+~\fIlocaluser\fR/.klogin
+authorization list
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/kuserok.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+/*
+ * kuserok: check if a kerberos principal has
+ * access to a local account
+ */
+
+#include "krb_locl.h"
+
+#include <pwd.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+
+#define OK 0
+#define NOTOK 1
+#define MAX_USERNAME 10
+
+/*
+ * Given a Kerberos principal "kdata", and a local username "luser",
+ * determine whether user is authorized to login according to the
+ * authorization file ("~luser/.klogin" by default). Returns OK
+ * if authorized, NOTOK if not authorized.
+ *
+ * If there is no account for "luser" on the local machine, returns
+ * NOTOK. If there is no authorization file, and the given Kerberos
+ * name "kdata" translates to the same name as "luser" (using
+ * krb_kntoln()), returns OK. Otherwise, if the authorization file
+ * can't be accessed, returns NOTOK. Otherwise, the file is read for
+ * a matching principal name, instance, and realm. If one is found,
+ * returns OK, if none is found, returns NOTOK.
+ *
+ * The file entries are in the format:
+ *
+ * name.instance@realm
+ *
+ * one entry per line.
+ *
+ * The ATHENA_COMPAT code supports old-style Athena ~luser/.klogin
+ * file entries. See the file "kparse.c".
+ */
+
+#ifdef ATHENA_COMPAT
+
+#include <kparse.h>
+
+/*
+ * The parmtable defines the keywords we will recognize with their
+ * default values, and keeps a pointer to the found value. The found
+ * value should be filled in with strsave(), since FreeParameterSet()
+ * will release memory for all non-NULL found strings.
+ *
+*** NOTE WELL! ***
+ *
+ * The table below is very nice, but we cannot hard-code a default for the
+ * realm: we have to get the realm via krb_get_lrealm(). Even though the
+ * default shows as "from krb_get_lrealm, below", it gets changed in
+ * kuserok to whatever krb_get_lrealm() tells us. That code assumes that
+ * the realm will be the entry number in the table below, so if you
+ * change the order of the entries below, you have to change the
+ * #definition of REALM_SCRIPT to reflect it.
+ */
+#define REALM_SUBSCRIPT 1
+parmtable kparm[] = {
+
+/* keyword default found value */
+{"user", "", (char *) NULL},
+{"realm", "see krb_get_lrealm, below", (char *) NULL},
+{"instance", "", (char *) NULL},
+};
+#define KPARMS kparm,PARMCOUNT(kparm)
+#endif /* ATHENA_COMPAT */
+
+int
+kuserok(kdata, luser)
+ AUTH_DAT *kdata;
+ char *luser;
+{
+ struct stat sbuf;
+ struct passwd *pwd;
+ char pbuf[MAXPATHLEN];
+ int isok = NOTOK, rc;
+ FILE *fp;
+ char kuser[MAX_USERNAME];
+ char principal[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
+ char linebuf[BUFSIZ];
+ char *newline;
+ int gobble;
+#ifdef ATHENA_COMPAT
+ char local_realm[REALM_SZ];
+#endif /* ATHENA_COMPAT */
+
+ /* no account => no access */
+ if ((pwd = getpwnam(luser)) == NULL) {
+ return(NOTOK);
+ }
+ (void) strcpy(pbuf, pwd->pw_dir);
+ (void) strcat(pbuf, "/.klogin");
+
+ if (access(pbuf, F_OK)) { /* not accessible */
+ /*
+ * if he's trying to log in as himself, and there is no .klogin file,
+ * let him. To find out, call
+ * krb_kntoln to convert the triple in kdata to a name which we can
+ * string compare.
+ */
+ if (!krb_kntoln(kdata, kuser) && (strcmp(kuser, luser) == 0)) {
+ return(OK);
+ }
+ }
+ /* open ~/.klogin */
+ if ((fp = fopen(pbuf, "r")) == NULL) {
+ return(NOTOK);
+ }
+ /*
+ * security: if the user does not own his own .klogin file,
+ * do not grant access
+ */
+ if (fstat(fileno(fp), &sbuf)) {
+ fclose(fp);
+ return(NOTOK);
+ }
+ if (sbuf.st_uid != pwd->pw_uid) {
+ fclose(fp);
+ return(NOTOK);
+ }
+
+#ifdef ATHENA_COMPAT
+ /* Accept old-style .klogin files */
+
+ /*
+ * change the default realm from the hard-coded value to the
+ * accepted realm that Kerberos specifies.
+ */
+ rc = krb_get_lrealm(local_realm, 1);
+ if (rc == KSUCCESS)
+ kparm[REALM_SUBSCRIPT].defvalue = local_realm;
+ else
+ return (rc);
+
+ /* check each line */
+ while ((isok != OK) && (rc = fGetParameterSet(fp, KPARMS)) != PS_EOF) {
+ switch (rc) {
+ case PS_BAD_KEYWORD:
+ case PS_SYNTAX:
+ while (((gobble = fGetChar(fp)) != EOF) && (gobble != '\n'));
+ break;
+
+ case PS_OKAY:
+ isok = (ParmCompare(KPARMS, "user", kdata->pname) ||
+ ParmCompare(KPARMS, "instance", kdata->pinst) ||
+ ParmCompare(KPARMS, "realm", kdata->prealm));
+ break;
+
+ default:
+ break;
+ }
+ FreeParameterSet(kparm, PARMCOUNT(kparm));
+ }
+ /* reset the stream for parsing new-style names, if necessary */
+ rewind(fp);
+#endif /* ATHENA_COMPAT */
+
+ /* check each line */
+ while ((isok != OK) && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
+ /* null-terminate the input string */
+ linebuf[BUFSIZ-1] = '\0';
+ newline = NULL;
+ /* nuke the newline if it exists */
+ if ((newline = strchr(linebuf, '\n')))
+ *newline = '\0';
+ rc = kname_parse(principal, inst, realm, linebuf);
+ if (rc == KSUCCESS) {
+ isok = (strncmp(kdata->pname, principal, ANAME_SZ) ||
+ strncmp(kdata->pinst, inst, INST_SZ) ||
+ strncmp(kdata->prealm, realm, REALM_SZ));
+ }
+ /* clean up the rest of the line if necessary */
+ if (!newline)
+ while (((gobble = getc(fp)) != EOF) && gobble != '\n');
+ }
+ fclose(fp);
+ return(isok);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/lifetime.c,v $
+ *
+ * $Locker: $
+ */
+
+/***************************************************************************
+ * PRE-HISTORY
+ *
+ * Revision 2.1.2.2 91/11/08 00:35:25 mja
+ * Lower NEVERDATE to a positive value since time values are not
+ * handled properly by most of the rest of the system when
+ * negative; add krb_life_to_atime() and krb_atime_to_life().
+ * [91/11/07 22:52:50 mja]
+ *
+ * Revision 2.1.2.1 91/07/09 22:50:42 mja
+ * Created.
+ * [91/01/30 jm36@ANDREW.CMU.EDU]
+ *
+ ***************************************************************************/
+
+/*
+ * Ticket lifetime. This defines the table used to lookup lifetime
+ * for the fixed part of rande of the one byte lifetime field. Values
+ * less than 0x80 are intrpreted as the number of 5 minute intervals.
+ * Values from 0x80 to 0xBF should be looked up in this table. The
+ * value of 0x80 is the same using both methods: 10 and two-thirds
+ * hours . The lifetime of 0xBF is 30 days. The intervening values
+ * of have a fixed ratio of roughly 1.06914. The value 0xFF is
+ * defined to mean a ticket has no expiration time. This should be
+ * used advisedly since individual servers may impose defacto
+ * upperbounds on ticket lifetimes.
+ */
+
+#include "krb_locl.h"
+
+#define TKTLIFENUMFIXED 64
+#define TKTLIFEMINFIXED 0x80
+#define TKTLIFEMAXFIXED 0xBF
+#define TKTLIFENOEXPIRE 0xFF
+#define MAXTKTLIFETIME (30*24*3600) /* 30 days */
+#ifndef NEVERDATE
+#define NEVERDATE ((unsigned long)0x7fffffffL)
+#endif
+
+static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
+ 38400, /* 10.67 hours, 0.44 days */
+ 41055, /* 11.40 hours, 0.48 days */
+ 43894, /* 12.19 hours, 0.51 days */
+ 46929, /* 13.04 hours, 0.54 days */
+ 50174, /* 13.94 hours, 0.58 days */
+ 53643, /* 14.90 hours, 0.62 days */
+ 57352, /* 15.93 hours, 0.66 days */
+ 61318, /* 17.03 hours, 0.71 days */
+ 65558, /* 18.21 hours, 0.76 days */
+ 70091, /* 19.47 hours, 0.81 days */
+ 74937, /* 20.82 hours, 0.87 days */
+ 80119, /* 22.26 hours, 0.93 days */
+ 85658, /* 23.79 hours, 0.99 days */
+ 91581, /* 25.44 hours, 1.06 days */
+ 97914, /* 27.20 hours, 1.13 days */
+ 104684, /* 29.08 hours, 1.21 days */
+ 111922, /* 31.09 hours, 1.30 days */
+ 119661, /* 33.24 hours, 1.38 days */
+ 127935, /* 35.54 hours, 1.48 days */
+ 136781, /* 37.99 hours, 1.58 days */
+ 146239, /* 40.62 hours, 1.69 days */
+ 156350, /* 43.43 hours, 1.81 days */
+ 167161, /* 46.43 hours, 1.93 days */
+ 178720, /* 49.64 hours, 2.07 days */
+ 191077, /* 53.08 hours, 2.21 days */
+ 204289, /* 56.75 hours, 2.36 days */
+ 218415, /* 60.67 hours, 2.53 days */
+ 233517, /* 64.87 hours, 2.70 days */
+ 249664, /* 69.35 hours, 2.89 days */
+ 266926, /* 74.15 hours, 3.09 days */
+ 285383, /* 79.27 hours, 3.30 days */
+ 305116, /* 84.75 hours, 3.53 days */
+ 326213, /* 90.61 hours, 3.78 days */
+ 348769, /* 96.88 hours, 4.04 days */
+ 372885, /* 103.58 hours, 4.32 days */
+ 398668, /* 110.74 hours, 4.61 days */
+ 426234, /* 118.40 hours, 4.93 days */
+ 455705, /* 126.58 hours, 5.27 days */
+ 487215, /* 135.34 hours, 5.64 days */
+ 520904, /* 144.70 hours, 6.03 days */
+ 556921, /* 154.70 hours, 6.45 days */
+ 595430, /* 165.40 hours, 6.89 days */
+ 636601, /* 176.83 hours, 7.37 days */
+ 680618, /* 189.06 hours, 7.88 days */
+ 727680, /* 202.13 hours, 8.42 days */
+ 777995, /* 216.11 hours, 9.00 days */
+ 831789, /* 231.05 hours, 9.63 days */
+ 889303, /* 247.03 hours, 10.29 days */
+ 950794, /* 264.11 hours, 11.00 days */
+ 1016537, /* 282.37 hours, 11.77 days */
+ 1086825, /* 301.90 hours, 12.58 days */
+ 1161973, /* 322.77 hours, 13.45 days */
+ 1242318, /* 345.09 hours, 14.38 days */
+ 1328218, /* 368.95 hours, 15.37 days */
+ 1420057, /* 394.46 hours, 16.44 days */
+ 1518247, /* 421.74 hours, 17.57 days */
+ 1623226, /* 450.90 hours, 18.79 days */
+ 1735464, /* 482.07 hours, 20.09 days */
+ 1855462, /* 515.41 hours, 21.48 days */
+ 1983758, /* 551.04 hours, 22.96 days */
+ 2120925, /* 589.15 hours, 24.55 days */
+ 2267576, /* 629.88 hours, 26.25 days */
+ 2424367, /* 673.44 hours, 28.06 days */
+ 2592000}; /* 720.00 hours, 30.00 days */
+
+/*
+ * krb_life_to_time - takes a start time and a Kerberos standard
+ * lifetime char and returns the corresponding end time. There are
+ * four simple cases to be handled. The first is a life of 0xff,
+ * meaning no expiration, and results in an end time of 0xffffffff.
+ * The second is when life is less than the values covered by the
+ * table. In this case, the end time is the start time plus the
+ * number of 5 minute intervals specified by life. The third case
+ * returns start plus the MAXTKTLIFETIME if life is greater than
+ * TKTLIFEMAXFIXED. The last case, uses the life value (minus
+ * TKTLIFEMINFIXED) as an index into the table to extract the lifetime
+ * in seconds, which is added to start to produce the end time.
+ */
+u_int32_t
+krb_life_to_time(start, life)
+ u_int32_t start;
+ int life;
+{
+ life = (unsigned char) life;
+ if (life == TKTLIFENOEXPIRE) return NEVERDATE;
+ if (life < TKTLIFEMINFIXED) return start + life*5*60;
+ if (life > TKTLIFEMAXFIXED) return start + MAXTKTLIFETIME;
+ return start + tkt_lifetimes[life - TKTLIFEMINFIXED];
+}
+
+/*
+ * krb_time_to_life - takes start and end times for the ticket and
+ * returns a Kerberos standard lifetime char, possibily using the
+ * tkt_lifetimes table for lifetimes above 127*5 minutes. First, the
+ * special case of (end == NEVERDATE) is handled to mean no
+ * expiration. Then negative lifetimes and those greater than the
+ * maximum ticket lifetime are rejected. Then lifetimes less than the
+ * first table entry are handled by rounding the requested lifetime
+ * *up* to the next 5 minute interval. The final step is to search
+ * the table for the smallest entry *greater than or equal* to the
+ * requested entry.
+ */
+int
+krb_time_to_life(start, end)
+ u_int32_t start;
+ u_int32_t end;
+{
+ long lifetime;
+ int i;
+
+ if (end >= NEVERDATE) return TKTLIFENOEXPIRE;
+ lifetime = end - start;
+ if (lifetime > MAXTKTLIFETIME || lifetime <= 0) return 0;
+ if (lifetime < tkt_lifetimes[0]) return (lifetime + 5*60 - 1)/(5*60);
+ for (i=0; i<TKTLIFENUMFIXED; i++) {
+ if (lifetime <= tkt_lifetimes[i]) {
+ return i+TKTLIFEMINFIXED;
+ }
+ }
+ return 0;
+}
+
+char *
+krb_life_to_atime(life)
+ int life;
+{
+ static char atime[11+1+2+1+2+1+2+1];
+ unsigned long when;
+ int secs, mins, hours;
+
+ if (life == TKTLIFENOEXPIRE)
+ return("Forever");
+ when = krb_life_to_time(0, life);
+ secs = when%60;
+ when /= 60;
+ mins = when%60;
+ when /= 60;
+ hours = when%24;
+ when /= 24;
+ sprintf(atime, "%d+%02d:%02d:%02d", (int)when, hours, mins, secs);
+ return(atime);
+}
+
+int
+krb_atime_to_life(atime)
+ char *atime;
+{
+ unsigned long when = 0;
+ register char *cp;
+ int colon = 0, plus = 0;
+ int n = 0;
+
+ if (strcasecmp(atime, "forever") == 0)
+ return(TKTLIFENOEXPIRE);
+
+ for (cp=atime; *cp; cp++) {
+ switch(*cp) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = n*10 + *cp-'0';
+ break;
+ case '+':
+ plus++;
+ when += n;
+ when *= 24;
+ n = 0;
+ break;
+ case ':':
+ colon++;
+ when += n;
+ when *= 60;
+ n = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ when += n;
+ if (plus == 0 && colon == 0)
+ return((unsigned char)when);
+ while (colon < 2) {
+ when *= 60;
+ colon++;
+ }
+ return(krb_time_to_life(0,when));
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/log.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/time.h>
+
+#include <klog.h>
+
+static char *log_name = KRBLOG;
+static is_open;
+
+/*
+ * This file contains three logging routines: set_logfile()
+ * to determine the file that log entries should be written to;
+ * and log() and new_log() to write log entries to the file.
+ */
+
+/*
+ * log() is used to add entries to the logfile (see set_logfile()
+ * below). Note that it is probably not portable since it makes
+ * assumptions about what the compiler will do when it is called
+ * with less than the correct number of arguments which is the
+ * way it is usually called.
+ *
+ * The log entry consists of a timestamp and the given arguments
+ * printed according to the given "format".
+ *
+ * The log file is opened and closed for each log entry.
+ *
+ * The return value is undefined.
+ */
+
+/*VARARGS1 */
+void
+log(format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a0)
+ char *format;
+ int a1, a2, a3, a4, a5, a6, a7, a8, a9, a0;
+{
+ FILE *logfile;
+ time_t now;
+ struct tm *tm;
+
+ if ((logfile = fopen(log_name,"a")) == NULL)
+ return;
+
+ (void) time(&now);
+ tm = localtime(&now);
+
+ fprintf(logfile,"%2d-%s-%02d %02d:%02d:%02d ",tm->tm_mday,
+ month_sname(tm->tm_mon + 1),tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ fprintf(logfile,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0);
+ fprintf(logfile,"\n");
+ (void) fclose(logfile);
+ return;
+}
+
+/*
+ * set_logfile() changes the name of the file to which
+ * messages are logged. If set_logfile() is not called,
+ * the logfile defaults to KRBLOG, defined in "krb.h".
+ */
+
+void
+set_logfile(filename)
+ char *filename;
+{
+ log_name = filename;
+ is_open = 0;
+}
+
+/*
+ * new_log() appends a log entry containing the give time "t" and the
+ * string "string" to the logfile (see set_logfile() above). The file
+ * is opened once and left open. The routine returns 1 on failure, 0
+ * on success.
+ */
+
+int
+new_log(t, string)
+ time_t t;
+ char *string;
+{
+ static FILE *logfile;
+
+ struct tm *tm;
+
+ if (!is_open) {
+ if ((logfile = fopen(log_name,"a")) == NULL) return(1);
+ is_open = 1;
+ }
+
+ if (t) {
+ tm = localtime(&t);
+
+ fprintf(logfile,"\n%2d-%s-%02d %02d:%02d:%02d %s",tm->tm_mday,
+ month_sname(tm->tm_mon + 1),tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec, string);
+ }
+ else {
+ fprintf(logfile,"\n%20s%s","",string);
+ }
+
+ (void) fflush(logfile);
+ return(0);
+}
--- /dev/null
+/*
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/lsb_addr_comp.h,v $
+ */
+
+/*
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Comparison macros to emulate LSBFIRST comparison results of network
+ * byte-order quantities
+ */
+
+#ifndef LSB_ADDR_COMP_DEFS
+#define LSB_ADDR_COMP_DEFS
+
+#if BYTE_ORDER == BIG_ENDIAN
+
+#define u_char_comp(x,y) \
+ (((x)>(y))?(1):(((x)==(y))?(0):(-1)))
+/* This is gross, but... */
+#define lsb_net_ulong_less(x, y) long_less_than((u_char *)&x, (u_char *)&y)
+#define lsb_net_ushort_less(x, y) short_less_than((u_char *)&x, (u_char *)&y)
+
+#define long_less_than(x,y) \
+ (u_char_comp((x)[3],(y)[3])?u_char_comp((x)[3],(y)[3]): \
+ (u_char_comp((x)[2],(y)[2])?u_char_comp((x)[2],(y)[2]): \
+ (u_char_comp((x)[1],(y)[1])?u_char_comp((x)[1],(y)[1]): \
+ (u_char_comp((x)[0],(y)[0])))))
+#define short_less_than(x,y) \
+ (u_char_comp((x)[1],(y)[1])?u_char_comp((x)[1],(y)[1]): \
+ (u_char_comp((x)[0],(y)[0])))
+
+#else /* !WORDS_BIGENDIAN */
+
+#define lsb_net_ulong_less(x,y) ((x < y) ? -1 : ((x > y) ? 1 : 0))
+#define lsb_net_ushort_less(x,y) ((x < y) ? -1 : ((x > y) ? 1 : 0))
+
+#endif /* !WORDS_BIGENDIAN */
+
+#endif /* LSB_ADDR_COMP_DEFS */
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/mk_err.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/types.h>
+
+/*
+ * This routine creates a general purpose error reply message. It
+ * doesn't use KTEXT because application protocol may have long
+ * messages, and may want this part of buffer contiguous to other
+ * stuff.
+ *
+ * The error reply is built in "p", using the error code "e" and
+ * error text "e_string" given. The length of the error reply is
+ * returned.
+ *
+ * The error reply is in the following format:
+ *
+ * unsigned char KRB_PROT_VERSION protocol version no.
+ * unsigned char AUTH_MSG_APPL_ERR message type
+ * (least significant
+ * bit of above) HOST_BYTE_ORDER local byte order
+ * 4 bytes e given error code
+ * string e_string given error text
+ */
+
+int32_t
+krb_mk_err(p, e, e_string)
+ u_char *p; /* Where to build error packet */
+ int32_t e; /* Error code */
+ char *e_string; /* Text of error */
+{
+ u_char *start;
+
+ start = p;
+
+ /* Create fixed part of packet */
+ *p++ = (unsigned char) KRB_PROT_VERSION;
+ *p = (unsigned char) AUTH_MSG_APPL_ERR;
+ *p++ |= HOST_BYTE_ORDER;
+
+ /* Add the basic info */
+ bcopy((char *)&e,(char *)p,4); /* err code */
+ p += sizeof(e);
+ (void) strcpy((char *)p,e_string); /* err text */
+ p += strlen(e_string);
+
+ /* And return the length */
+ return p-start;
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/mk_priv.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+/*
+ * This routine constructs a Kerberos 'private msg', i.e.
+ * cryptographically sealed with a private session key.
+ *
+ * Note-- bcopy is used to avoid alignment problems on IBM RT.
+ *
+ * Note-- It's too bad that it did a long int compare on the RT before.
+ *
+ * Returns either < 0 ===> error, or resulting size of message
+ *
+ * Steve Miller Project Athena MIT/DEC
+ */
+
+#include "krb_locl.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+
+/* application include files */
+#include "lsb_addr_comp.h"
+
+/* static storage */
+static u_int32_t c_length;
+static struct timeval msg_time;
+static u_char msg_time_5ms;
+static long msg_time_sec;
+
+/*
+ * krb_mk_priv() constructs an AUTH_MSG_PRIVATE message. It takes
+ * some user data "in" of "length" bytes and creates a packet in "out"
+ * consisting of the user data, a timestamp, and the sender's network
+ * address.
+#ifndef NOENCRYTION
+ * The packet is encrypted by pcbc_encrypt(), using the given
+ * "key" and "schedule".
+#endif
+ * The length of the resulting packet "out" is
+ * returned.
+ *
+ * It is similar to krb_mk_safe() except for the additional key
+ * schedule argument "schedule" and the fact that the data is encrypted
+ * rather than appended with a checksum. Also, the protocol version
+ * number is "private_msg_ver", defined in krb_rd_priv.c, rather than
+ * KRB_PROT_VERSION, defined in "krb.h".
+ *
+ * The "out" packet consists of:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * 1 byte private_msg_ver protocol version number
+ * 1 byte AUTH_MSG_PRIVATE | message type plus local
+ * HOST_BYTE_ORDER byte order in low bit
+ *
+ * 4 bytes c_length length of data
+#ifndef NOENCRYPT
+ * we encrypt from here with pcbc_encrypt
+#endif
+ *
+ * 4 bytes length length of user data
+ * length in user data
+ * 1 byte msg_time_5ms timestamp milliseconds
+ * 4 bytes sender->sin.addr.s_addr sender's IP address
+ *
+ * 4 bytes msg_time_sec or timestamp seconds with
+ * -msg_time_sec direction in sign bit
+ *
+ * 0<=n<=7 bytes pad to 8 byte multiple zeroes
+ */
+
+int32_t
+krb_mk_priv(in, out, length, schedule, key, sender, receiver)
+ u_char *in; /* application data */
+ u_char *out; /* put msg here, leave room for
+ * header! breaks if in and out
+ * (header stuff) overlap */
+ u_int32_t length; /* of in data */
+ struct des_ks_struct *schedule; /* precomputed key schedule */
+ des_cblock *key; /* encryption key for seed and ivec */
+ struct sockaddr_in *sender; /* sender address */
+ struct sockaddr_in *receiver; /* receiver address */
+{
+ register u_char *p,*q;
+ static u_char *c_length_ptr;
+
+ /*
+ * get the current time to use instead of a sequence #, since
+ * process lifetime may be shorter than the lifetime of a session
+ * key.
+ */
+ if (gettimeofday(&msg_time,(struct timezone *)0)) {
+ return -1;
+ }
+ msg_time_sec = (long) msg_time.tv_sec;
+ msg_time_5ms = msg_time.tv_usec/5000; /* 5ms quanta */
+
+ p = out;
+
+ *p++ = private_msg_ver;
+ *p++ = AUTH_MSG_PRIVATE | HOST_BYTE_ORDER;
+
+ /* calculate cipher length */
+ c_length_ptr = p;
+ p += sizeof(c_length);
+
+ q = p;
+
+ /* stuff input length */
+ bcopy((char *)&length,(char *)p,sizeof(length));
+ p += sizeof(length);
+
+#ifdef NOENCRYPTION
+ /* make all the stuff contiguous for checksum */
+#else
+ /* make all the stuff contiguous for checksum and encryption */
+#endif
+ bcopy((char *)in,(char *)p,(int) length);
+ p += length;
+
+ /* stuff time 5ms */
+ bcopy((char *)&msg_time_5ms,(char *)p,sizeof(msg_time_5ms));
+ p += sizeof(msg_time_5ms);
+
+ /* stuff source address */
+ bcopy((char *)&sender->sin_addr.s_addr,(char *)p,
+ sizeof(sender->sin_addr.s_addr));
+ p += sizeof(sender->sin_addr.s_addr);
+
+ /*
+ * direction bit is the sign bit of the timestamp. Ok
+ * until 2038??
+ */
+ /* For compatibility with broken old code, compares are done in VAX
+ byte order (LSBFIRST) */
+ if (lsb_net_ulong_less(sender->sin_addr.s_addr, /* src < recv */
+ receiver->sin_addr.s_addr)==-1)
+ msg_time_sec = -msg_time_sec;
+ else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==0)
+ if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port) == -1)
+ msg_time_sec = -msg_time_sec;
+ /* stuff time sec */
+ bcopy((char *)&msg_time_sec,(char *)p,sizeof(msg_time_sec));
+ p += sizeof(msg_time_sec);
+
+ /*
+ * All that for one tiny bit! Heaven help those that talk to
+ * themselves.
+ */
+
+#ifdef notdef
+ /*
+ * calculate the checksum of the length, address, sequence, and
+ * inp data
+ */
+ cksum = des_quad_cksum(q,NULL,p-q,0,key);
+ if (krb_debug)
+ printf("\ncksum = %u",cksum);
+ /* stuff checksum */
+ bcopy((char *) &cksum,(char *) p,sizeof(cksum));
+ p += sizeof(cksum);
+#endif
+
+ /*
+ * All the data have been assembled, compute length
+ */
+
+ c_length = p - q;
+ c_length = ((c_length + sizeof(des_cblock) -1)/sizeof(des_cblock)) *
+ sizeof(des_cblock);
+ /* stuff the length */
+ bcopy((char *) &c_length,(char *)c_length_ptr,sizeof(c_length));
+
+#ifndef NOENCRYPTION
+ des_pcbc_encrypt((des_cblock *)q,(des_cblock *)q,(long)(p-q),schedule,key, DES_ENCRYPT);
+#endif /* NOENCRYPTION */
+
+ return (q - out + c_length); /* resulting size */
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/mk_req.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/time.h>
+
+static struct timeval tv_local = { 0, 0 };
+static int lifetime = 255; /* But no longer than TGT says. */
+
+/*
+ * krb_mk_req takes a text structure in which an authenticator is to
+ * be built, the name of a service, an instance, a realm,
+ * and a checksum. It then retrieves a ticket for
+ * the desired service and creates an authenticator in the text
+ * structure passed as the first argument. krb_mk_req returns
+ * KSUCCESS on success and a Kerberos error code on failure.
+ *
+ * The peer procedure on the other end is krb_rd_req. When making
+ * any changes to this routine it is important to make corresponding
+ * changes to krb_rd_req.
+ *
+ * The authenticator consists of the following:
+ *
+ * authent->dat
+ *
+ * unsigned char KRB_PROT_VERSION protocol version no.
+ * unsigned char AUTH_MSG_APPL_REQUEST message type
+ * (least significant
+ * bit of above) HOST_BYTE_ORDER local byte ordering
+ * unsigned char kvno from ticket server's key version
+ * string realm server's realm
+ * unsigned char tl ticket length
+ * unsigned char idl request id length
+ * text ticket->dat ticket for server
+ * text req_id->dat request id
+ *
+ * The ticket information is retrieved from the ticket cache or
+ * fetched from Kerberos. The request id (called the "authenticator"
+ * in the papers on Kerberos) contains the following:
+ *
+ * req_id->dat
+ *
+ * string cr.pname {name, instance, and
+ * string cr.pinst realm of principal
+ * string myrealm making this request}
+ * 4 bytes checksum checksum argument given
+ * unsigned char tv_local.tf_usec time (milliseconds)
+ * 4 bytes tv_local.tv_sec time (seconds)
+ *
+ * req_id->length = 3 strings + 3 terminating nulls + 5 bytes for time,
+ * all rounded up to multiple of 8.
+ */
+
+int
+krb_mk_req(authent, service, instance, realm, checksum)
+ register KTEXT authent; /* Place to build the authenticator */
+ char *service; /* Name of the service */
+ char *instance; /* Service instance */
+ char *realm; /* Authentication domain of service */
+ int32_t checksum; /* Checksum of data (optional) */
+{
+ static KTEXT_ST req_st; /* Temp storage for req id */
+ register KTEXT req_id = &req_st;
+ unsigned char *v = authent->dat; /* Prot version number */
+ unsigned char *t = (authent->dat+1); /* Message type */
+ unsigned char *kv = (authent->dat+2); /* Key version no */
+ unsigned char *tl = (authent->dat+4+strlen(realm)); /* Tkt len */
+ unsigned char *idl = (authent->dat+5+strlen(realm)); /* Reqid len */
+ CREDENTIALS cr; /* Credentials used by retr */
+ register KTEXT ticket = &(cr.ticket_st); /* Pointer to tkt_st */
+ int retval; /* Returned by krb_get_cred */
+ static des_key_schedule key_s;
+ char myrealm[REALM_SZ];
+
+ /* The fixed parts of the authenticator */
+ *v = (unsigned char) KRB_PROT_VERSION;
+ *t = (unsigned char) AUTH_MSG_APPL_REQUEST;
+ *t |= HOST_BYTE_ORDER;
+
+ /* Get the ticket and move it into the authenticator */
+ if (krb_ap_req_debug)
+ printf("Realm: %s\n",realm);
+ /*
+ * Determine realm of these tickets. We will send this to the
+ * KDC from which we are requesting tickets so it knows what to
+ * with our session key.
+ */
+ if ((retval = krb_get_tf_realm(TKT_FILE, myrealm)) != KSUCCESS)
+ return(retval);
+
+ retval = krb_get_cred(service,instance,realm,&cr);
+
+ if (retval == RET_NOTKT) {
+ if ((retval = get_ad_tkt(service,instance,realm,lifetime)))
+ return(retval);
+ if ((retval = krb_get_cred(service,instance,realm,&cr)))
+ return(retval);
+ }
+
+ if (retval != KSUCCESS) return (retval);
+
+ if (krb_ap_req_debug)
+ printf("%s %s %s %s %s\n", service, instance, realm,
+ cr.pname, cr.pinst);
+ *kv = (unsigned char) cr.kvno;
+ (void) strcpy((char *)(authent->dat+3),realm);
+ *tl = (unsigned char) ticket->length;
+ bcopy((char *)(ticket->dat),(char *)(authent->dat+6+strlen(realm)),
+ ticket->length);
+ authent->length = 6 + strlen(realm) + ticket->length;
+ if (krb_ap_req_debug)
+ printf("Ticket->length = %d\n",ticket->length);
+ if (krb_ap_req_debug)
+ printf("Issue date: %d\n",cr.issue_date);
+
+ /* Build request id */
+ (void) strcpy((char *)(req_id->dat),cr.pname); /* Auth name */
+ req_id->length = strlen(cr.pname)+1;
+ /* Principal's instance */
+ (void) strcpy((char *)(req_id->dat+req_id->length),cr.pinst);
+ req_id->length += strlen(cr.pinst)+1;
+ /* Authentication domain */
+ (void) strcpy((char *)(req_id->dat+req_id->length),myrealm);
+ req_id->length += strlen(myrealm)+1;
+ /* Checksum */
+ bcopy((char *)&checksum,(char *)(req_id->dat+req_id->length),4);
+ req_id->length += 4;
+
+ /* Fill in the times on the request id */
+ (void) gettimeofday(&tv_local,(struct timezone *) 0);
+ *(req_id->dat+(req_id->length)++) =
+ (unsigned char) tv_local.tv_usec;
+ /* Time (coarse) */
+ bcopy((char *)&(tv_local.tv_sec),
+ (char *)(req_id->dat+req_id->length), 4);
+ req_id->length += 4;
+
+ /* Fill to a multiple of 8 bytes for DES */
+ req_id->length = ((req_id->length+7)/8)*8;
+
+#ifndef NOENCRYPTION
+ des_key_sched(&cr.session,key_s);
+ des_pcbc_encrypt((des_cblock *)req_id->dat,(des_cblock *)req_id->dat,
+ (long)req_id->length,key_s,&cr.session, DES_ENCRYPT);
+ bzero((char *) key_s, sizeof(key_s));
+#endif /* NOENCRYPTION */
+
+ /* Copy it into the authenticator */
+ bcopy((char *)(req_id->dat),(char *)(authent->dat+authent->length),
+ req_id->length);
+ authent->length += req_id->length;
+ /* And set the id length */
+ *idl = (unsigned char) req_id->length;
+ /* clean up */
+ bzero((char *)req_id, sizeof(*req_id));
+
+ if (krb_ap_req_debug)
+ printf("Authent->length = %d\n",authent->length);
+ if (krb_ap_req_debug)
+ printf("idl = %d, tl = %d\n",(int) *idl, (int) *tl);
+
+ return(KSUCCESS);
+}
+
+/*
+ * krb_set_lifetime sets the default lifetime for additional tickets
+ * obtained via krb_mk_req().
+ *
+ * It returns the previous value of the default lifetime.
+ */
+
+int
+krb_set_lifetime(newval)
+ int newval;
+{
+ int olife = lifetime;
+
+ lifetime = newval;
+ return(olife);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/mk_safe.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+/*
+ * This routine constructs a Kerberos 'safe msg', i.e. authenticated
+ * using a private session key to seed a checksum. Msg is NOT
+ * encrypted.
+ *
+ * Note-- bcopy is used to avoid alignment problems on IBM RT
+ *
+ * Returns either <0 ===> error, or resulting size of message
+ *
+ * Steve Miller Project Athena MIT/DEC
+ */
+
+#include "krb_locl.h"
+
+/* system include files */
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+
+/* application include files */
+#include "lsb_addr_comp.h"
+
+/* static storage */
+static u_int32_t cksum;
+static des_cblock big_cksum[2];
+static struct timeval msg_time;
+static u_char msg_time_5ms;
+static long msg_time_sec;
+
+/*
+ * krb_mk_safe() constructs an AUTH_MSG_SAFE message. It takes some
+ * user data "in" of "length" bytes and creates a packet in "out"
+ * consisting of the user data, a timestamp, and the sender's network
+ * address, followed by a checksum computed on the above, using the
+ * given "key". The length of the resulting packet is returned.
+ *
+ * The "out" packet consists of:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * 1 byte KRB_PROT_VERSION protocol version number
+ * 1 byte AUTH_MSG_SAFE | message type plus local
+ * HOST_BYTE_ORDER byte order in low bit
+ *
+ * ===================== begin checksum ================================
+ *
+ * 4 bytes length length of user data
+ * length in user data
+ * 1 byte msg_time_5ms timestamp milliseconds
+ * 4 bytes sender->sin.addr.s_addr sender's IP address
+ *
+ * 4 bytes msg_time_sec or timestamp seconds with
+ * -msg_time_sec direction in sign bit
+ *
+ * ======================= end checksum ================================
+ *
+ * 16 bytes big_cksum quadratic checksum of
+ * above using "key"
+ */
+
+int32_t
+krb_mk_safe(in, out, length, key, sender, receiver)
+ u_char *in; /* application data */
+ u_char *out; /*
+ * put msg here, leave room for header!
+ * breaks if in and out (header stuff)
+ * overlap
+ */
+ u_int32_t length; /* of in data */
+ des_cblock *key; /* encryption key for seed and ivec */
+ struct sockaddr_in *sender; /* sender address */
+ struct sockaddr_in *receiver; /* receiver address */
+{
+ register u_char *p,*q;
+
+ /*
+ * get the current time to use instead of a sequence #, since
+ * process lifetime may be shorter than the lifetime of a session
+ * key.
+ */
+ if (gettimeofday(&msg_time,(struct timezone *)0)) {
+ return -1;
+ }
+ msg_time_sec = (long) msg_time.tv_sec;
+ msg_time_5ms = msg_time.tv_usec/5000; /* 5ms quanta */
+
+ p = out;
+
+ *p++ = KRB_PROT_VERSION;
+ *p++ = AUTH_MSG_SAFE | HOST_BYTE_ORDER;
+
+ q = p; /* start for checksum stuff */
+ /* stuff input length */
+ bcopy((char *)&length,(char *)p,sizeof(length));
+ p += sizeof(length);
+
+ /* make all the stuff contiguous for checksum */
+ bcopy((char *)in,(char *)p,(int) length);
+ p += length;
+
+ /* stuff time 5ms */
+ bcopy((char *)&msg_time_5ms,(char *)p,sizeof(msg_time_5ms));
+ p += sizeof(msg_time_5ms);
+
+ /* stuff source address */
+ bcopy((char *) &sender->sin_addr.s_addr,(char *)p,
+ sizeof(sender->sin_addr.s_addr));
+ p += sizeof(sender->sin_addr.s_addr);
+
+ /*
+ * direction bit is the sign bit of the timestamp. Ok until
+ * 2038??
+ */
+ /* For compatibility with broken old code, compares are done in VAX
+ byte order (LSBFIRST) */
+ if (lsb_net_ulong_less(sender->sin_addr.s_addr, /* src < recv */
+ receiver->sin_addr.s_addr)==-1)
+ msg_time_sec = -msg_time_sec;
+ else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==0)
+ if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port) == -1)
+ msg_time_sec = -msg_time_sec;
+ /*
+ * all that for one tiny bit! Heaven help those that talk to
+ * themselves.
+ */
+
+ /* stuff time sec */
+ bcopy((char *)&msg_time_sec,(char *)p,sizeof(msg_time_sec));
+ p += sizeof(msg_time_sec);
+
+#ifdef NOENCRYPTION
+ cksum = 0;
+ bzero(big_cksum, sizeof(big_cksum));
+#else
+ cksum = des_quad_cksum((des_cblock *)q,big_cksum,p-q,2,key);
+#endif
+ if (krb_debug)
+ printf("\ncksum = %u",(u_int) cksum);
+
+ /* stuff checksum */
+ bcopy((char *)big_cksum,(char *)p,sizeof(big_cksum));
+ p += sizeof(big_cksum);
+
+ return ((long)(p - out)); /* resulting size */
+
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/month_sname.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * Given an integer 1-12, month_sname() returns a string
+ * containing the first three letters of the corresponding
+ * month. Returns 0 if the argument is out of range.
+ */
+
+char *
+month_sname(n)
+ int n;
+{
+ static char *name[] = {
+ "Jan","Feb","Mar","Apr","May","Jun",
+ "Jul","Aug","Sep","Oct","Nov","Dec"
+ };
+ return((n < 1 || n > 12) ? 0 : name [n-1]);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/netread.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * krb_net_read() reads from the file descriptor "fd" to the buffer
+ * "buf", until either 1) "len" bytes have been read or 2) cannot
+ * read anymore from "fd". It returns the number of bytes read
+ * or a read() error. (The calling interface is identical to
+ * read(2).)
+ *
+ * XXX must not use non-blocking I/O
+ */
+
+int
+krb_net_read(fd, buf, len)
+ int fd;
+ register char *buf;
+ register int len;
+{
+ int cc, len2 = 0;
+
+ do {
+ cc = read(fd, buf, len);
+ if (cc < 0)
+ return(cc); /* errno is already set */
+ else if (cc == 0) {
+ return(len2);
+ } else {
+ buf += cc;
+ len2 += cc;
+ len -= cc;
+ }
+ } while (len > 0);
+ return(len2);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/netwrite.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * krb_net_write() writes "len" bytes from "buf" to the file
+ * descriptor "fd". It returns the number of bytes written or
+ * a write() error. (The calling interface is identical to
+ * write(2).)
+ *
+ * XXX must not use non-blocking I/O
+ */
+
+int
+krb_net_write(fd, buf, len)
+ int fd;
+ register char *buf;
+ int len;
+{
+ int cc;
+ register int wrlen = len;
+ do {
+ cc = write(fd, buf, wrlen);
+ if (cc < 0)
+ return(cc);
+ else {
+ buf += cc;
+ wrlen -= cc;
+ }
+ } while (wrlen > 0);
+ return(len);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/one.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+ WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ distribute this software and its documentation for any purpose and
+ without fee is hereby granted, provided that the above copyright
+ notice appear in all copies and that both that copyright notice and
+ this permission notice appear in supporting documentation, and that
+ the name of M.I.T. not be used in advertising or publicity pertaining
+ to distribution of the software without specific, written prior
+ permission. M.I.T. makes no representations about the suitability of
+ this software for any purpose. It is provided "as is" without express
+ or implied warranty.
+
+ */
+
+/*
+ * definition of variable set to 1.
+ * used in krb_conf.h to determine host byte order.
+ */
+
+int krbONE = 1;
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/pkt_cipher.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This routine takes a reply packet from the Kerberos ticket-granting
+ * service and returns a pointer to the beginning of the ciphertext in it.
+ *
+ * See "prot.h" for packet format.
+ */
+
+char *
+pkt_cipher(packet)
+ KTEXT packet;
+{
+ unsigned char *ptr = pkt_a_realm(packet) + 6
+ + strlen((char *)pkt_a_realm(packet));
+ /* Skip a few more fields */
+ ptr += 3 + 4; /* add 4 for exp_date */
+
+ /* And return the pointer */
+ return((char*)ptr);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/pkt_clen.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#if defined(horrible_function_using_global_variable_had_to_be_inlined)
+
+#include "krb_locl.h"
+
+/*
+ * Given a pointer to an AUTH_MSG_KDC_REPLY packet, return the length of
+ * its ciphertext portion. The external variable "swap_bytes" is assumed
+ * to have been set to indicate whether or not the packet is in local
+ * byte order. pkt_clen() takes this into account when reading the
+ * ciphertext length out of the packet.
+ */
+
+int
+pkt_clen(pkt)
+ KTEXT pkt;
+{
+ static unsigned short temp,temp2;
+ int clen = 0;
+
+ /* Start of ticket list */
+ unsigned char *ptr = pkt_a_realm(pkt) + 10
+ + strlen((char *)pkt_a_realm(pkt));
+
+ /* Finally the length */
+ bcopy((char *)(++ptr),(char *)&temp,2); /* alignment */
+ if (swap_bytes) {
+ /* assume a short is 2 bytes?? */
+ swab((char *)&temp,(char *)&temp2,2);
+ temp = temp2;
+ }
+
+ clen = (int) temp;
+
+ if (krb_debug)
+ printf("Clen is %d\n",clen);
+ return(clen);
+}
+
+#endif /* defined(horrible_function_using_global_variable_had_to_be_inlined) */
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/rd_err.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+/*
+ * This routine dissects a a Kerberos 'safe msg',
+ * checking its integrity, and returning a pointer to the application
+ * data contained and its length.
+ *
+ * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...)
+ *
+ * Steve Miller Project Athena MIT/DEC
+ */
+
+#include "krb_locl.h"
+
+/* system include files */
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+
+/*
+ * Given an AUTH_MSG_APPL_ERR message, "in" and its length "in_length",
+ * return the error code from the message in "code" and the text in
+ * "m_data" as follows:
+ *
+ * m_data->app_data points to the error text
+ * m_data->app_length points to the length of the error text
+ *
+ * If all goes well, return RD_AP_OK. If the version number
+ * is wrong, return RD_AP_VERSION, and if it's not an AUTH_MSG_APPL_ERR
+ * type message, return RD_AP_MSG_TYPE.
+ *
+ * The AUTH_MSG_APPL_ERR message format can be found in mk_err.c
+ */
+
+int
+krb_rd_err(in, in_length, code, m_data)
+ u_char *in; /* pointer to the msg received */
+ u_int32_t in_length; /* of in msg */
+ int32_t *code; /* received error code */
+ MSG_DAT *m_data;
+{
+ register u_char *p;
+ int swap_bytes = 0;
+ p = in; /* beginning of message */
+
+ if (*p++ != KRB_PROT_VERSION)
+ return(RD_AP_VERSION);
+ if (((*p) & ~1) != AUTH_MSG_APPL_ERR)
+ return(RD_AP_MSG_TYPE);
+ if ((*p++ & 1) != HOST_BYTE_ORDER)
+ swap_bytes++;
+
+ /* safely get code */
+ bcopy((char *)p,(char *)code,sizeof(*code));
+ if (swap_bytes)
+ swap_u_long(*code);
+ p += sizeof(*code); /* skip over */
+
+ m_data->app_data = p; /* we're now at the error text
+ * message */
+ m_data->app_length = in_length;
+
+ return(RD_AP_OK); /* OK == 0 */
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/rd_priv.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+/*
+ * This routine dissects a a Kerberos 'private msg', decrypting it,
+ * checking its integrity, and returning a pointer to the application
+ * data contained and its length.
+ *
+ * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...). If
+ * the return value is RD_AP_TIME, then either the times are too far
+ * out of synch, OR the packet was modified.
+ *
+ * Steve Miller Project Athena MIT/DEC
+ */
+
+#include "krb_locl.h"
+
+/* system include files */
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+
+/* application include files */
+#include "lsb_addr_comp.h"
+
+/* static storage */
+static u_int32_t c_length;
+static int swap_bytes;
+static struct timeval local_time;
+static long delta_t;
+
+/* Global! */
+int private_msg_ver = KRB_PROT_VERSION;
+
+/*
+#ifdef NOENCRPYTION
+ * krb_rd_priv() checks the integrity of an
+#else
+ * krb_rd_priv() decrypts and checks the integrity of an
+#endif
+ * AUTH_MSG_PRIVATE message. Given the message received, "in",
+ * the length of that message, "in_length", the key "schedule"
+ * and "key", and the network addresses of the
+ * "sender" and "receiver" of the message, krb_rd_safe() returns
+ * RD_AP_OK if the message is okay, otherwise some error code.
+ *
+ * The message data retrieved from "in" are returned in the structure
+ * "m_data". The pointer to the application data
+ * (m_data->app_data) refers back to the appropriate place in "in".
+ *
+ * See the file "mk_priv.c" for the format of the AUTH_MSG_PRIVATE
+ * message. The structure containing the extracted message
+ * information, MSG_DAT, is defined in "krb.h".
+ */
+
+int32_t
+krb_rd_priv(in, in_length, schedule, key, sender, receiver, m_data)
+ u_char *in; /* pointer to the msg received */
+ u_int32_t in_length; /* length of "in" msg */
+ struct des_ks_struct *schedule; /* precomputed key schedule */
+ des_cblock *key; /* encryption key for seed and ivec */
+ struct sockaddr_in *sender;
+ struct sockaddr_in *receiver;
+ MSG_DAT *m_data; /*various input/output data from msg */
+{
+ register u_char *p,*q;
+ static u_int32_t src_addr; /* Can't send structs since no
+ * guarantees on size */
+
+ if (gettimeofday(&local_time,(struct timezone *)0))
+ return -1;
+
+ p = in; /* beginning of message */
+ swap_bytes = 0;
+
+ if (*p++ != KRB_PROT_VERSION && *(p-1) != 3)
+ return RD_AP_VERSION;
+ private_msg_ver = *(p-1);
+ if (((*p) & ~1) != AUTH_MSG_PRIVATE)
+ return RD_AP_MSG_TYPE;
+ if ((*p++ & 1) != HOST_BYTE_ORDER)
+ swap_bytes++;
+
+ /* get cipher length */
+ bcopy((char *)p,(char *)&c_length,sizeof(c_length));
+ if (swap_bytes)
+ swap_u_long(c_length);
+ p += sizeof(c_length);
+ /* check for rational length so we don't go comatose */
+ if (VERSION_SZ + MSG_TYPE_SZ + c_length > in_length)
+ return RD_AP_MODIFIED;
+
+
+ q = p; /* mark start of encrypted stuff */
+
+#ifndef NOENCRYPTION
+ des_pcbc_encrypt((des_cblock *)q,(des_cblock *)q,(long)c_length,schedule,key,DES_DECRYPT);
+#endif
+
+ /* safely get application data length */
+ bcopy((char *) p,(char *)&(m_data->app_length),
+ sizeof(m_data->app_length));
+ if (swap_bytes)
+ swap_u_long(m_data->app_length);
+ p += sizeof(m_data->app_length); /* skip over */
+
+ if (m_data->app_length + sizeof(c_length) + sizeof(in_length) +
+ sizeof(m_data->time_sec) + sizeof(m_data->time_5ms) +
+ sizeof(src_addr) + VERSION_SZ + MSG_TYPE_SZ
+ > in_length)
+ return RD_AP_MODIFIED;
+
+#ifndef NOENCRYPTION
+ /* we're now at the decrypted application data */
+#endif
+ m_data->app_data = p;
+
+ p += m_data->app_length;
+
+ /* safely get time_5ms */
+ bcopy((char *) p, (char *)&(m_data->time_5ms),
+ sizeof(m_data->time_5ms));
+ /* don't need to swap-- one byte for now */
+ p += sizeof(m_data->time_5ms);
+
+ /* safely get src address */
+ bcopy((char *) p,(char *)&src_addr,sizeof(src_addr));
+ /* don't swap, net order always */
+ p += sizeof(src_addr);
+
+ if (!krb_equiv(src_addr, sender->sin_addr.s_addr))
+ return RD_AP_MODIFIED;
+
+ /* safely get time_sec */
+ bcopy((char *) p, (char *)&(m_data->time_sec),
+ sizeof(m_data->time_sec));
+ if (swap_bytes) swap_u_long(m_data->time_sec);
+
+ p += sizeof(m_data->time_sec);
+
+ /* check direction bit is the sign bit */
+ /* For compatibility with broken old code, compares are done in VAX
+ byte order (LSBFIRST) */
+ if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==-1)
+ /* src < recv */
+ m_data->time_sec = - m_data->time_sec;
+ else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==0)
+ if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port)==-1)
+ /* src < recv */
+ m_data->time_sec = - m_data->time_sec;
+ /*
+ * all that for one tiny bit!
+ * Heaven help those that talk to themselves.
+ */
+
+ /* check the time integrity of the msg */
+ delta_t = abs((int)((long) local_time.tv_sec
+ - m_data->time_sec));
+ if (delta_t > CLOCK_SKEW)
+ return RD_AP_TIME;
+ if (krb_debug)
+ printf("\ndelta_t = %d", (int) delta_t);
+
+ /*
+ * caller must check timestamps for proper order and
+ * replays, since server might have multiple clients
+ * each with its own timestamps and we don't assume
+ * tightly synchronized clocks.
+ */
+
+#ifdef notdef
+ bcopy((char *) p,(char *)&cksum,sizeof(cksum));
+ if (swap_bytes) swap_u_long(cksum)
+ /*
+ * calculate the checksum of the length, sequence,
+ * and input data, on the sending byte order!!
+ */
+ calc_cksum = des_quad_cksum(q,NULL,p-q,0,key);
+
+ if (krb_debug)
+ printf("\ncalc_cksum = %u, received cksum = %u",
+ calc_cksum, cksum);
+ if (cksum != calc_cksum)
+ return RD_AP_MODIFIED;
+#endif
+ return RD_AP_OK; /* OK == 0 */
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/rd_req.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/time.h>
+
+static struct timeval t_local = { 0, 0 };
+
+/*
+ * Keep the following information around for subsequent calls
+ * to this routine by the same server using the same key.
+ */
+
+static des_key_schedule serv_key; /* Key sched to decrypt ticket */
+static des_cblock ky; /* Initialization vector */
+static int st_kvno; /* version number for this key */
+static char st_rlm[REALM_SZ]; /* server's realm */
+static char st_nam[ANAME_SZ]; /* service name */
+static char st_inst[INST_SZ]; /* server's instance */
+
+/*
+ * This file contains two functions. krb_set_key() takes a DES
+ * key or password string and returns a DES key (either the original
+ * key, or the password converted into a DES key) and a key schedule
+ * for it.
+ *
+ * krb_rd_req() reads an authentication request and returns information
+ * about the identity of the requestor, or an indication that the
+ * identity information was not authentic.
+ */
+
+/*
+ * krb_set_key() takes as its first argument either a DES key or a
+ * password string. The "cvt" argument indicates how the first
+ * argument "key" is to be interpreted: if "cvt" is null, "key" is
+ * taken to be a DES key; if "cvt" is non-null, "key" is taken to
+ * be a password string, and is converted into a DES key using
+ * string_to_key(). In either case, the resulting key is returned
+ * in the external static variable "ky". A key schedule is
+ * generated for "ky" and returned in the external static variable
+ * "serv_key".
+ *
+ * This routine returns the return value of des_key_sched.
+ *
+ * krb_set_key() needs to be in the same .o file as krb_rd_req() so that
+ * the key set by krb_set_key() is available in private storage for
+ * krb_rd_req().
+ */
+
+int
+krb_set_key(key, cvt)
+ char *key;
+ int cvt;
+{
+#ifdef NOENCRYPTION
+ bzero(ky, sizeof(ky));
+ return KSUCCESS;
+#else /* Encrypt */
+ if (cvt)
+ des_string_to_key(key,&ky);
+ else
+ bcopy(key,(char *)ky,8);
+ return(des_key_sched(&ky,serv_key));
+#endif /* NOENCRYPTION */
+}
+
+
+/*
+ * krb_rd_req() takes an AUTH_MSG_APPL_REQUEST or
+ * AUTH_MSG_APPL_REQUEST_MUTUAL message created by krb_mk_req(),
+ * checks its integrity and returns a judgement as to the requestor's
+ * identity.
+ *
+ * The "authent" argument is a pointer to the received message.
+ * The "service" and "instance" arguments name the receiving server,
+ * and are used to get the service's ticket to decrypt the ticket
+ * in the message, and to compare against the server name inside the
+ * ticket. "from_addr" is the network address of the host from which
+ * the message was received; this is checked against the network
+ * address in the ticket. If "from_addr" is zero, the check is not
+ * performed. "ad" is an AUTH_DAT structure which is
+ * filled in with information about the sender's identity according
+ * to the authenticator and ticket sent in the message. Finally,
+ * "fn" contains the name of the file containing the server's key.
+ * (If "fn" is NULL, the server's key is assumed to have been set
+ * by krb_set_key(). If "fn" is the null string ("") the default
+ * file KEYFILE, defined in "krb.h", is used.)
+ *
+ * krb_rd_req() returns RD_AP_OK if the authentication information
+ * was genuine, or one of the following error codes (defined in
+ * "krb.h"):
+ *
+ * RD_AP_VERSION - wrong protocol version number
+ * RD_AP_MSG_TYPE - wrong message type
+ * RD_AP_UNDEC - couldn't decipher the message
+ * RD_AP_INCON - inconsistencies found
+ * RD_AP_BADD - wrong network address
+ * RD_AP_TIME - client time (in authenticator)
+ * too far off server time
+ * RD_AP_NYV - Kerberos time (in ticket) too
+ * far off server time
+ * RD_AP_EXP - ticket expired
+ *
+ * For the message format, see krb_mk_req().
+ *
+ * Mutual authentication is not implemented.
+ */
+
+int
+krb_rd_req(authent, service, instance, from_addr, ad, fn)
+ register KTEXT authent; /* The received message */
+ char *service; /* Service name */
+ char *instance; /* Service instance */
+ int32_t from_addr; /* Net address of originating host */
+ AUTH_DAT *ad; /* Structure to be filled in */
+ char *fn; /* Filename to get keys from */
+{
+ static KTEXT_ST ticket; /* Temp storage for ticket */
+ static KTEXT tkt = &ticket;
+ static KTEXT_ST req_id_st; /* Temp storage for authenticator */
+ register KTEXT req_id = &req_id_st;
+
+ char realm[REALM_SZ]; /* Realm of issuing kerberos */
+ static des_key_schedule seskey_sched; /* Key sched for session key */
+ unsigned char skey[KKEY_SZ]; /* Session key from ticket */
+ char sname[SNAME_SZ]; /* Service name from ticket */
+ char iname[INST_SZ]; /* Instance name from ticket */
+ char r_aname[ANAME_SZ]; /* Client name from authenticator */
+ char r_inst[INST_SZ]; /* Client instance from authenticator */
+ char r_realm[REALM_SZ]; /* Client realm from authenticator */
+ unsigned int r_time_ms; /* Fine time from authenticator */
+ unsigned long r_time_sec; /* Coarse time from authenticator */
+ register char *ptr; /* For stepping through */
+ unsigned long delta_t; /* Time in authenticator - local time */
+ long tkt_age; /* Age of ticket */
+ static int swap_bytes; /* Need to swap bytes? */
+ static int mutual; /* Mutual authentication requested? */
+ static unsigned char s_kvno;/* Version number of the server's key
+ * Kerberos used to encrypt ticket */
+ int status;
+
+ if (authent->length <= 0)
+ return(RD_AP_MODIFIED);
+
+ ptr = (char *) authent->dat;
+
+ /* get msg version, type and byte order, and server key version */
+
+ /* check version */
+ if (KRB_PROT_VERSION != (unsigned int) *ptr++)
+ return(RD_AP_VERSION);
+
+ /* byte order */
+ swap_bytes = 0;
+ if ((*ptr & 1) != HOST_BYTE_ORDER)
+ swap_bytes++;
+
+ /* check msg type */
+ mutual = 0;
+ switch (*ptr++ & ~1) {
+ case AUTH_MSG_APPL_REQUEST:
+ break;
+ case AUTH_MSG_APPL_REQUEST_MUTUAL:
+ mutual++;
+ break;
+ default:
+ return(RD_AP_MSG_TYPE);
+ }
+
+#ifdef lint
+ /* XXX mutual is set but not used; why??? */
+ /* this is a crock to get lint to shut up */
+ if (mutual)
+ mutual = 0;
+#endif /* lint */
+ s_kvno = *ptr++; /* get server key version */
+ (void) strcpy(realm,ptr); /* And the realm of the issuing KDC */
+ ptr += strlen(ptr) + 1; /* skip the realm "hint" */
+
+ /*
+ * If "fn" is NULL, key info should already be set; don't
+ * bother with ticket file. Otherwise, check to see if we
+ * already have key info for the given server and key version
+ * (saved in the static st_* variables). If not, go get it
+ * from the ticket file. If "fn" is the null string, use the
+ * default ticket file.
+ */
+ if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance) ||
+ strcmp(st_rlm,realm) || (st_kvno != s_kvno))) {
+ if (*fn == 0) fn = KEYFILE;
+ st_kvno = s_kvno;
+#ifndef NOENCRYPTION
+ if (read_service_key(service,instance,realm,(int) s_kvno,
+ fn,(char *)skey))
+ return(RD_AP_UNDEC);
+ if ((status = krb_set_key((char *)skey,0)))
+ return(status);
+#endif /* !NOENCRYPTION */
+ (void) strcpy(st_rlm,realm);
+ (void) strcpy(st_nam,service);
+ (void) strcpy(st_inst,instance);
+ }
+
+ /* Get ticket from authenticator */
+ tkt->length = (int) *ptr++;
+ if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length)
+ return(RD_AP_MODIFIED);
+ bcopy(ptr+1,(char *)(tkt->dat),tkt->length);
+
+ if (krb_ap_req_debug)
+ log("ticket->length: %d",tkt->length);
+
+#ifndef NOENCRYPTION
+ /* Decrypt and take apart ticket */
+#endif
+
+ if (decomp_ticket(tkt,&ad->k_flags,ad->pname,ad->pinst,ad->prealm,
+ &(ad->address),ad->session, &(ad->life),
+ &(ad->time_sec),sname,iname,&ky,serv_key))
+ return(RD_AP_UNDEC);
+
+ if (krb_ap_req_debug) {
+ log("Ticket Contents.");
+ log(" Aname: %s.%s",ad->pname,
+ ((int)*(ad->prealm) ? ad->prealm : "Athena"));
+ log(" Service: %s%s%s",sname,((int)*iname ? "." : ""),iname);
+ }
+
+ /* Extract the authenticator */
+ req_id->length = (int) *(ptr++);
+ if ((req_id->length + (ptr + tkt->length - (char *) authent->dat)) >
+ authent->length)
+ return(RD_AP_MODIFIED);
+ bcopy(ptr + tkt->length, (char *)(req_id->dat),req_id->length);
+
+#ifndef NOENCRYPTION
+ /* And decrypt it with the session key from the ticket */
+ if (krb_ap_req_debug) log("About to decrypt authenticator");
+ des_key_sched(&ad->session,seskey_sched);
+ des_pcbc_encrypt((des_cblock *)req_id->dat,(des_cblock *)req_id->dat,
+ (long) req_id->length, seskey_sched,&ad->session,DES_DECRYPT);
+ if (krb_ap_req_debug) log("Done.");
+#endif /* NOENCRYPTION */
+
+#define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED);
+
+ ptr = (char *) req_id->dat;
+ (void) strcpy(r_aname,ptr); /* Authentication name */
+ ptr += strlen(r_aname)+1;
+ check_ptr();
+ (void) strcpy(r_inst,ptr); /* Authentication instance */
+ ptr += strlen(r_inst)+1;
+ check_ptr();
+ (void) strcpy(r_realm,ptr); /* Authentication name */
+ ptr += strlen(r_realm)+1;
+ check_ptr();
+ bcopy(ptr,(char *)&ad->checksum,4); /* Checksum */
+ ptr += 4;
+ check_ptr();
+ if (swap_bytes) swap_u_long(ad->checksum);
+ r_time_ms = *(ptr++); /* Time (fine) */
+#ifdef lint
+ /* XXX r_time_ms is set but not used. why??? */
+ /* this is a crock to get lint to shut up */
+ if (r_time_ms)
+ r_time_ms = 0;
+#endif /* lint */
+ check_ptr();
+ /* assume sizeof(r_time_sec) == 4 ?? */
+ bcopy(ptr,(char *)&r_time_sec,4); /* Time (coarse) */
+ if (swap_bytes) swap_u_long(r_time_sec);
+
+ /* Check for authenticity of the request */
+ if (krb_ap_req_debug)
+ log("Pname: %s %s",ad->pname,r_aname);
+ if (strcmp(ad->pname,r_aname) != 0)
+ return(RD_AP_INCON);
+ if (strcmp(ad->pinst,r_inst) != 0)
+ return(RD_AP_INCON);
+ if (krb_ap_req_debug)
+ log("Realm: %s %s",ad->prealm,r_realm);
+ if ((strcmp(ad->prealm,r_realm) != 0))
+ return(RD_AP_INCON);
+
+ if (krb_ap_req_debug)
+ log("Address: %d %d",ad->address,from_addr);
+ if (from_addr && (!krb_equiv(ad->address, from_addr)))
+ return(RD_AP_BADD);
+
+ (void) gettimeofday(&t_local,(struct timezone *) 0);
+ delta_t = abs((int)(t_local.tv_sec - r_time_sec));
+ if (delta_t > CLOCK_SKEW) {
+ if (krb_ap_req_debug)
+ log("Time out of range: %d - %d = %d",
+ t_local.tv_sec,r_time_sec,delta_t);
+ return(RD_AP_TIME);
+ }
+
+ /* Now check for expiration of ticket */
+
+ tkt_age = t_local.tv_sec - ad->time_sec;
+ if (krb_ap_req_debug)
+ log("Time: %d Issue Date: %d Diff: %d Life %x",
+ t_local.tv_sec,ad->time_sec,tkt_age,ad->life);
+
+ if (t_local.tv_sec < ad->time_sec) {
+ if ((ad->time_sec - t_local.tv_sec) > CLOCK_SKEW)
+ return(RD_AP_NYV);
+ }
+ else if (t_local.tv_sec > krb_life_to_time(ad->time_sec, ad->life))
+ return(RD_AP_EXP);
+
+ /* All seems OK */
+ ad->reply.length = 0;
+
+ return(RD_AP_OK);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/rd_safe.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+/*
+ * This routine dissects a a Kerberos 'safe msg', checking its
+ * integrity, and returning a pointer to the application data
+ * contained and its length.
+ *
+ * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...)
+ *
+ * Steve Miller Project Athena MIT/DEC
+ */
+
+#include "krb_locl.h"
+
+/* system include files */
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+
+/* application include files */
+#include "lsb_addr_comp.h"
+
+/* static storage */
+static des_cblock calc_cksum[2];
+static des_cblock big_cksum[2];
+static int swap_bytes;
+static struct timeval local_time;
+static u_int32_t delta_t;
+
+/*
+ * krb_rd_safe() checks the integrity of an AUTH_MSG_SAFE message.
+ * Given the message received, "in", the length of that message,
+ * "in_length", the "key" to compute the checksum with, and the
+ * network addresses of the "sender" and "receiver" of the message,
+ * krb_rd_safe() returns RD_AP_OK if message is okay, otherwise
+ * some error code.
+ *
+ * The message data retrieved from "in" is returned in the structure
+ * "m_data". The pointer to the application data (m_data->app_data)
+ * refers back to the appropriate place in "in".
+ *
+ * See the file "mk_safe.c" for the format of the AUTH_MSG_SAFE
+ * message. The structure containing the extracted message
+ * information, MSG_DAT, is defined in "krb.h".
+ */
+
+int32_t
+krb_rd_safe(in, in_length, key, sender, receiver, m_data)
+ u_char *in; /* pointer to the msg received */
+ u_int32_t in_length; /* length of "in" msg */
+ des_cblock *key; /* encryption key for seed and ivec */
+ struct sockaddr_in *sender; /* sender's address */
+ struct sockaddr_in *receiver; /* receiver's address -- me */
+ MSG_DAT *m_data; /* where to put message information */
+{
+ register u_char *p,*q;
+ static u_int32_t src_addr; /* Can't send structs since no
+ * guarantees on size */
+ /* Be very conservative */
+ if (sizeof(src_addr) != sizeof(struct in_addr)) {
+ fprintf(stderr,"\n\
+krb_rd_safe protocol err sizeof(src_addr) != sizeof(struct in_addr)");
+ exit(-1);
+ }
+
+ if (gettimeofday(&local_time,(struct timezone *)0))
+ return -1;
+
+ p = in; /* beginning of message */
+ swap_bytes = 0;
+
+ if (*p++ != KRB_PROT_VERSION) return RD_AP_VERSION;
+ if (((*p) & ~1) != AUTH_MSG_SAFE) return RD_AP_MSG_TYPE;
+ if ((*p++ & 1) != HOST_BYTE_ORDER) swap_bytes++;
+
+ q = p; /* mark start of cksum stuff */
+
+ /* safely get length */
+ bcopy((char *)p,(char *)&(m_data->app_length),
+ sizeof(m_data->app_length));
+ if (swap_bytes) swap_u_long(m_data->app_length);
+ p += sizeof(m_data->app_length); /* skip over */
+
+ if (m_data->app_length + sizeof(in_length)
+ + sizeof(m_data->time_sec) + sizeof(m_data->time_5ms)
+ + sizeof(big_cksum) + sizeof(src_addr)
+ + VERSION_SZ + MSG_TYPE_SZ > in_length)
+ return(RD_AP_MODIFIED);
+
+ m_data->app_data = p; /* we're now at the application data */
+
+ /* skip app data */
+ p += m_data->app_length;
+
+ /* safely get time_5ms */
+ bcopy((char *)p, (char *)&(m_data->time_5ms),
+ sizeof(m_data->time_5ms));
+
+ /* don't need to swap-- one byte for now */
+ p += sizeof(m_data->time_5ms);
+
+ /* safely get src address */
+ bcopy((char *)p,(char *)&src_addr,sizeof(src_addr));
+
+ /* don't swap, net order always */
+ p += sizeof(src_addr);
+
+ if (!krb_equiv(src_addr, sender->sin_addr.s_addr))
+ return RD_AP_MODIFIED;
+
+ /* safely get time_sec */
+ bcopy((char *)p, (char *)&(m_data->time_sec),
+ sizeof(m_data->time_sec));
+ if (swap_bytes)
+ swap_u_long(m_data->time_sec);
+ p += sizeof(m_data->time_sec);
+
+ /* check direction bit is the sign bit */
+ /* For compatibility with broken old code, compares are done in VAX
+ byte order (LSBFIRST) */
+ if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==-1)
+ /* src < recv */
+ m_data->time_sec = - m_data->time_sec;
+ else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==0)
+ if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port)==-1)
+ /* src < recv */
+ m_data->time_sec = - m_data->time_sec;
+
+ /*
+ * All that for one tiny bit! Heaven help those that talk to
+ * themselves.
+ */
+
+ /* check the time integrity of the msg */
+ delta_t = abs((int)((long) local_time.tv_sec - m_data->time_sec));
+ if (delta_t > CLOCK_SKEW) return RD_AP_TIME;
+
+ /*
+ * caller must check timestamps for proper order and replays, since
+ * server might have multiple clients each with its own timestamps
+ * and we don't assume tightly synchronized clocks.
+ */
+
+ bcopy((char *)p,(char *)big_cksum,sizeof(big_cksum));
+ if (swap_bytes) swap_u_16(big_cksum);
+
+#ifdef NOENCRYPTION
+ bzero(calc_cksum, sizeof(calc_cksum));
+#else
+ des_quad_cksum((des_cblock *)q,calc_cksum,p-q,2,key);
+#endif
+
+ if (krb_debug)
+ printf("\ncalc_cksum = %u, received cksum = %u",
+ (u_int) calc_cksum[0], (u_int) big_cksum[0]);
+ if (bcmp((char *)big_cksum,(char *)calc_cksum,sizeof(big_cksum)))
+ return(RD_AP_MODIFIED);
+
+ return(RD_AP_OK); /* OK == 0 */
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/read_service_key.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * The private keys for servers on a given host are stored in a
+ * "srvtab" file (typically "/etc/srvtab"). This routine extracts
+ * a given server's key from the file.
+ *
+ * read_service_key() takes the server's name ("service"), "instance",
+ * and "realm" and a key version number "kvno", and looks in the given
+ * "file" for the corresponding entry, and if found, returns the entry's
+ * key field in "key".
+ *
+ * If "instance" contains the string "*", then it will match
+ * any instance, and the chosen instance will be copied to that
+ * string. For this reason it is important that the there is enough
+ * space beyond the "*" to receive the entry.
+ *
+ * If "kvno" is 0, it is treated as a wild card and the first
+ * matching entry regardless of the "vno" field is returned.
+ *
+ * This routine returns KSUCCESS on success, otherwise KFAILURE.
+ *
+ * The format of each "srvtab" entry is as follows:
+ *
+ * Size Variable Field in file
+ * ---- -------- -------------
+ * string serv server name
+ * string inst server instance
+ * string realm server realm
+ * 1 byte vno server key version #
+ * 8 bytes key server's key
+ * ... ... ...
+ */
+
+
+/*ARGSUSED */
+int
+read_service_key(service, instance, realm, kvno, file, key)
+ char *service; /* Service Name */
+ char *instance; /* Instance name or "*" */
+ char *realm; /* Realm */
+ int kvno; /* Key version number */
+ char *file; /* Filename */
+ char *key; /* Pointer to key to be filled in */
+{
+ char serv[SNAME_SZ];
+ char inst[INST_SZ];
+ char rlm[REALM_SZ];
+ unsigned char vno; /* Key version number */
+ int wcard;
+
+ int stab, open(const char *, int, ...);
+
+ if ((stab = open(file, 0, 0)) < 0)
+ return(KFAILURE);
+
+ wcard = (instance[0] == '*') && (instance[1] == '\0');
+
+ while (getst(stab,serv,SNAME_SZ) > 0) { /* Read sname */
+ (void) getst(stab,inst,INST_SZ); /* Instance */
+ (void) getst(stab,rlm,REALM_SZ); /* Realm */
+ /* Vers number */
+ if (read(stab,(char *)&vno,1) != 1) {
+ close(stab);
+ return(KFAILURE);
+ }
+ /* Key */
+ if (read(stab,key,8) != 8) {
+ close(stab);
+ return(KFAILURE);
+ }
+ /* Is this the right service */
+ if (strcmp(serv,service))
+ continue;
+ /* How about instance */
+ if (!wcard && strcmp(inst,instance))
+ continue;
+ if (wcard)
+ (void) strncpy(instance,inst,INST_SZ);
+ /* Is this the right realm */
+#ifdef ATHENA_COMPAT
+ /* XXX For backward compatibility: if keyfile says "Athena"
+ and caller wants "ATHENA.MIT.EDU", call it a match */
+ if (strcmp(rlm,realm) &&
+ (strcmp(rlm,"Athena") ||
+ strcmp(realm,"ATHENA.MIT.EDU")))
+ continue;
+#else /* ! ATHENA_COMPAT */
+ if (strcmp(rlm,realm))
+ continue;
+#endif /* ATHENA_COMPAT */
+
+ /* How about the key version number */
+ if (kvno && kvno != (int) vno)
+ continue;
+
+ (void) close(stab);
+ return(KSUCCESS);
+ }
+
+ /* Can't find the requested service */
+ (void) close(stab);
+ return(KFAILURE);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/recvauth.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <syslog.h>
+
+/*
+ * If the protocol changes, you will need to change the version string
+ * and make appropriate changes in krb_sendauth.c
+ * be sure to support old versions of krb_sendauth!
+ */
+#define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
+ chars */
+
+/*
+ * krb_recvauth() reads (and optionally responds to) a message sent
+ * using krb_sendauth(). The "options" argument is a bit-field of
+ * selected options (see "sendauth.c" for options description).
+ * The only option relevant to krb_recvauth() is KOPT_DO_MUTUAL
+ * (mutual authentication requested). The "fd" argument supplies
+ * a file descriptor to read from (and write to, if mutual authenti-
+ * cation is requested).
+ *
+ * Part of the received message will be a Kerberos ticket sent by the
+ * client; this is read into the "ticket" argument. The "service" and
+ * "instance" arguments supply the server's Kerberos name. If the
+ * "instance" argument is the string "*", it is treated as a wild card
+ * and filled in during the krb_rd_req() call (see read_service_key()).
+ *
+ * The "faddr" and "laddr" give the sending (client) and receiving
+ * (local server) network addresses. ("laddr" may be left NULL unless
+ * mutual authentication is requested, in which case it must be set.)
+ *
+ * The authentication information extracted from the message is returned
+ * in "kdata". The "filename" argument indicates the file where the
+ * server's key can be found. (It is passed on to krb_rd_req().) If
+ * left null, the default "/etc/srvtab" will be used.
+ *
+ * If mutual authentication is requested, the session key schedule must
+ * be computed in order to reply; this schedule is returned in the
+ * "schedule" argument. A string containing the application version
+ * number from the received message is returned in "version", which
+ * should be large enough to hold a KRB_SENDAUTH_VLEN-character string.
+ *
+ * See krb_sendauth() for the format of the received client message.
+ *
+ * This routine supports another client format, for backward
+ * compatibility, consisting of:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * string tmp_buf, tkt_len length of ticket, in
+ * ascii
+ *
+ * char ' ' (space char) separator
+ *
+ * tkt_len ticket->dat the ticket
+ *
+ * This old-style version does not support mutual authentication.
+ *
+ * krb_recvauth() first reads the protocol version string from the
+ * given file descriptor. If it doesn't match the current protocol
+ * version (KRB_SENDAUTH_VERS), the old-style format is assumed. In
+ * that case, the string of characters up to the first space is read
+ * and interpreted as the ticket length, then the ticket is read.
+ *
+ * If the first string did match KRB_SENDAUTH_VERS, krb_recvauth()
+ * next reads the application protocol version string. Then the
+ * ticket length and ticket itself are read.
+ *
+ * The ticket is decrypted and checked by the call to krb_rd_req().
+ * If no mutual authentication is required, the result of the
+ * krb_rd_req() call is retured by this routine. If mutual authenti-
+ * cation is required, a message in the following format is returned
+ * on "fd":
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * 4 bytes tkt_len length of ticket or -1
+ * if error occurred
+ *
+ * priv_len tmp_buf "private" message created
+ * by krb_mk_priv() which
+ * contains the incremented
+ * checksum sent by the client
+ * encrypted in the session
+ * key. (This field is not
+ * present in case of error.)
+ *
+ * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some
+ * other error code is returned.
+ */
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif /* max */
+
+int
+krb_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata,
+ filename, schedule, version)
+ int32_t options; /* bit-pattern of options */
+ int fd; /* file descr. to read from */
+ KTEXT ticket; /* storage for client's ticket */
+ char *service; /* service expected */
+ char *instance; /* inst expected (may be filled in) */
+ struct sockaddr_in *faddr; /* address of foreign host on fd */
+ struct sockaddr_in *laddr; /* local address */
+ AUTH_DAT *kdata; /* kerberos data (returned) */
+ char *filename; /* name of file with service keys */
+ struct des_ks_struct *schedule; /* key schedule (return) */
+ char *version; /* version string (filled in) */
+{
+
+ int i, cc, old_vers = 0;
+ char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */
+ char *cp;
+ int rem;
+ long tkt_len, priv_len;
+ u_int32_t cksum;
+ u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)];
+
+ /* read the protocol version number */
+ if (krb_net_read(fd, krb_vers, KRB_SENDAUTH_VLEN) !=
+ KRB_SENDAUTH_VLEN)
+ return(errno);
+ krb_vers[KRB_SENDAUTH_VLEN] = '\0';
+
+ /* check version string */
+ if (strcmp(krb_vers,KRB_SENDAUTH_VERS)) {
+ /* Assume the old version of sendkerberosdata: send ascii
+ length, ' ', and ticket. */
+ if (options & KOPT_DO_MUTUAL)
+ return(KFAILURE); /* XXX can't do old style with mutual auth */
+ old_vers = 1;
+
+ /* copy what we have read into tmp_buf */
+ (void) bcopy(krb_vers, (char *) tmp_buf, KRB_SENDAUTH_VLEN);
+
+ /* search for space, and make it a null */
+ for (i = 0; i < KRB_SENDAUTH_VLEN; i++)
+ if (tmp_buf[i]== ' ') {
+ tmp_buf[i] = '\0';
+ /* point cp to the beginning of the real ticket */
+ cp = (char *) &tmp_buf[i+1];
+ break;
+ }
+
+ if (i == KRB_SENDAUTH_VLEN)
+ /* didn't find the space, keep reading to find it */
+ for (; i<20; i++) {
+ if (read(fd, (char *)&tmp_buf[i], 1) != 1) {
+ return(KFAILURE);
+ }
+ if (tmp_buf[i] == ' ') {
+ tmp_buf[i] = '\0';
+ /* point cp to the beginning of the real ticket */
+ cp = (char *) &tmp_buf[i+1];
+ break;
+ }
+ }
+
+ tkt_len = (long) atoi((char *) tmp_buf);
+
+ /* sanity check the length */
+ if ((i==20)||(tkt_len<=0)||(tkt_len>MAX_KTXT_LEN))
+ return(KFAILURE);
+
+ if (i < KRB_SENDAUTH_VLEN) {
+ /* since we already got the space, and part of the ticket,
+ we read fewer bytes to get the rest of the ticket */
+ if (krb_net_read(fd, (char *)(tmp_buf+KRB_SENDAUTH_VLEN),
+ (int) (tkt_len - KRB_SENDAUTH_VLEN + 1 + i))
+ != (int)(tkt_len - KRB_SENDAUTH_VLEN + 1 + i))
+ return(errno);
+ } else {
+ if (krb_net_read(fd, (char *)(tmp_buf+i), (int)tkt_len) !=
+ (int) tkt_len)
+ return(errno);
+ }
+ ticket->length = tkt_len;
+ /* copy the ticket into the struct */
+ (void) bcopy(cp, (char *) ticket->dat, ticket->length);
+
+ } else {
+ /* read the application version string */
+ if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) !=
+ KRB_SENDAUTH_VLEN)
+ return(errno);
+ version[KRB_SENDAUTH_VLEN] = '\0';
+
+ /* get the length of the ticket */
+ if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) !=
+ sizeof(tkt_len))
+ return(errno);
+
+ /* sanity check */
+ ticket->length = ntohl((unsigned long)tkt_len);
+ if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) {
+ if (options & KOPT_DO_MUTUAL) {
+ rem = KFAILURE;
+ goto mutual_fail;
+ } else
+ return(KFAILURE); /* XXX there may still be junk on the fd? */
+ }
+
+ /* read the ticket */
+ if (krb_net_read(fd, (char *) ticket->dat, ticket->length)
+ != ticket->length)
+ return(errno);
+ }
+ /*
+ * now have the ticket. decrypt it to get the authenticated
+ * data.
+ */
+ rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr,
+ kdata,filename);
+
+ if (old_vers) return(rem); /* XXX can't do mutual with old client */
+
+ /* if we are doing mutual auth, compose a response */
+ if (options & KOPT_DO_MUTUAL) {
+ if (rem != KSUCCESS)
+ /* the krb_rd_req failed */
+ goto mutual_fail;
+
+ /* add one to the (formerly) sealed checksum, and re-seal it
+ for return to the client */
+ cksum = kdata->checksum + 1;
+ cksum = htonl(cksum);
+#ifndef NOENCRYPTION
+ des_key_sched(&kdata->session,schedule);
+#endif
+ priv_len = krb_mk_priv((unsigned char *)&cksum,
+ tmp_buf,
+ (unsigned long) sizeof(cksum),
+ schedule,
+ &kdata->session,
+ laddr,
+ faddr);
+ if (priv_len < 0) {
+ /* re-sealing failed; notify the client */
+ rem = KFAILURE; /* XXX */
+mutual_fail:
+ priv_len = -1;
+ tkt_len = htonl((unsigned long) priv_len);
+ /* a length of -1 is interpreted as an authentication
+ failure by the client */
+ if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
+ != sizeof(tkt_len))
+ return(cc);
+ return(rem);
+ } else {
+ /* re-sealing succeeded, send the private message */
+ tkt_len = htonl((unsigned long)priv_len);
+ if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
+ != sizeof(tkt_len))
+ return(cc);
+ if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len))
+ != (int) priv_len)
+ return(cc);
+ }
+ }
+ return(rem);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/save_credentials.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+/*
+ * This routine takes a ticket and associated info and calls
+ * tf_save_cred() to store them in the ticket cache. The peer
+ * routine for extracting a ticket and associated info from the
+ * ticket cache is krb_get_cred(). When changes are made to
+ * this routine, the corresponding changes should be made
+ * in krb_get_cred() as well.
+ *
+ * Returns KSUCCESS if all goes well, otherwise an error returned
+ * by the tf_init() or tf_save_cred() routines.
+ */
+
+int
+save_credentials(service, instance, realm, session, lifetime, kvno,
+ ticket, issue_date)
+ char *service; /* Service name */
+ char *instance; /* Instance */
+ char *realm; /* Auth domain */
+ unsigned char *session; /* Session key */
+ int lifetime; /* Lifetime */
+ int kvno; /* Key version number */
+ KTEXT ticket; /* The ticket itself */
+ int32_t issue_date; /* The issue time */
+{
+ int tf_status; /* return values of the tf_util calls */
+
+ /* Open and lock the ticket file for writing */
+ if ((tf_status = tf_init(TKT_FILE, W_TKT_FIL)) != KSUCCESS)
+ return(tf_status);
+
+ /* Save credentials by appending to the ticket file */
+ tf_status = tf_save_cred(service, instance, realm, session,
+ lifetime, kvno, ticket, issue_date);
+ (void) tf_close();
+ return (tf_status);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/send_to_kdc.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#define S_AD_SZ sizeof(struct sockaddr_in)
+
+static int krb_udp_port = 0;
+
+/* CLIENT_KRB_TIMEOUT indicates the time to wait before
+ * retrying a server. It's defined in "krb.h".
+ */
+static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0};
+static char *prog = "send_to_kdc";
+static send_recv(KTEXT pkt, KTEXT rpkt, int f, struct sockaddr_in *_to, struct hostent *addrs);
+
+/*
+ * This file contains two routines, send_to_kdc() and send_recv().
+ * send_recv() is a static routine used by send_to_kdc().
+ */
+
+/*
+ * send_to_kdc() sends a message to the Kerberos authentication
+ * server(s) in the given realm and returns the reply message.
+ * The "pkt" argument points to the message to be sent to Kerberos;
+ * the "rpkt" argument will be filled in with Kerberos' reply.
+ * The "realm" argument indicates the realm of the Kerberos server(s)
+ * to transact with. If the realm is null, the local realm is used.
+ *
+ * If more than one Kerberos server is known for a given realm,
+ * different servers will be queried until one of them replies.
+ * Several attempts (retries) are made for each server before
+ * giving up entirely.
+ *
+ * If an answer was received from a Kerberos host, KSUCCESS is
+ * returned. The following errors can be returned:
+ *
+ * SKDC_CANT - can't get local realm
+ * - can't find "kerberos" in /etc/services database
+ * - can't open socket
+ * - can't bind socket
+ * - all ports in use
+ * - couldn't find any Kerberos host
+ *
+ * SKDC_RETRY - couldn't get an answer from any Kerberos server,
+ * after several retries
+ */
+
+int
+send_to_kdc(pkt, rpkt, realm)
+ KTEXT pkt;
+ KTEXT rpkt;
+ char *realm;
+{
+ int i, f;
+ int no_host; /* was a kerberos host found? */
+ int retry;
+ int n_hosts;
+ int retval;
+ struct sockaddr_in to;
+ struct hostent *host, *hostlist;
+ char *cp;
+ char krbhst[MAX_HSTNM];
+ char lrealm[REALM_SZ];
+
+ /*
+ * If "realm" is non-null, use that, otherwise get the
+ * local realm.
+ */
+ if (realm)
+ (void) strcpy(lrealm, realm);
+ else
+ if (krb_get_lrealm(lrealm,1)) {
+ if (krb_debug)
+ fprintf(stderr, "%s: can't get local realm\n", prog);
+ return(SKDC_CANT);
+ }
+ if (krb_debug)
+ printf("lrealm is %s\n", lrealm);
+ if (krb_udp_port == 0) {
+ register struct servent *sp;
+ if ((sp = getservbyname("kerberos","udp")) == 0) {
+ if (krb_debug)
+ fprintf(stderr, "%s: Can't get kerberos/udp service\n",
+ prog);
+ krb_udp_port = 750; /* Was return(SKDC_CANT); */
+ }
+ else
+ krb_udp_port = sp->s_port;
+ if (krb_debug)
+ printf("krb_udp_port is %d\n", krb_udp_port);
+ }
+ bzero((char *)&to, S_AD_SZ);
+ hostlist = (struct hostent *) malloc(sizeof(struct hostent));
+ if (!hostlist)
+ return (/*errno */SKDC_CANT);
+ if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ if (krb_debug)
+ fprintf(stderr,"%s: Can't open socket\n", prog);
+ return(SKDC_CANT);
+ }
+ /* from now on, exit through rtn label for cleanup */
+
+ no_host = 1;
+ /* get an initial allocation */
+ n_hosts = 0;
+ bzero((char *)&hostlist[n_hosts], sizeof(struct hostent));
+ for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) {
+ if (krb_debug) {
+ printf("Getting host entry for %s...",krbhst);
+ (void) fflush(stdout);
+ }
+ host = gethostbyname(krbhst);
+ if (krb_debug) {
+ printf("%s.\n",
+ host ? "Got it" : "Didn't get it");
+ (void) fflush(stdout);
+ }
+ if (!host)
+ continue;
+ no_host = 0; /* found at least one */
+ n_hosts++;
+ /* preserve host network address to check later
+ * (would be better to preserve *all* addresses,
+ * take care of that later)
+ */
+ hostlist = (struct hostent *)
+ realloc((char *)hostlist,
+ (unsigned)
+ sizeof(struct hostent)*(n_hosts+1));
+ if (!hostlist)
+ return /*errno */SKDC_CANT;
+ bcopy((char *)host, (char *)&hostlist[n_hosts-1],
+ sizeof(struct hostent));
+ host = &hostlist[n_hosts-1];
+ cp = malloc((unsigned)host->h_length);
+ if (!cp) {
+ retval = /*errno */SKDC_CANT;
+ goto rtn;
+ }
+ bcopy((char *)host->h_addr, cp, host->h_length);
+/* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2
+ (or worse) only return one name ... */
+#if defined(h_addr)
+ host->h_addr_list = (char **)malloc(2*sizeof(char *));
+ if (!host->h_addr_list) {
+ retval = /*errno */SKDC_CANT;
+ goto rtn;
+ }
+ host->h_addr_list[1] = NULL;
+#endif /* defined(h_addr) */
+ host->h_addr = cp;
+ bzero((char *)&hostlist[n_hosts],
+ sizeof(struct hostent));
+ to.sin_family = host->h_addrtype;
+ bcopy(host->h_addr, (char *)&to.sin_addr,
+ host->h_length);
+ to.sin_port = krb_udp_port;
+ if (send_recv(pkt, rpkt, f, &to, hostlist)) {
+ retval = KSUCCESS;
+ goto rtn;
+ }
+ if (krb_debug) {
+ printf("Timeout, error, or wrong descriptor\n");
+ (void) fflush(stdout);
+ }
+ }
+ if (no_host) {
+ if (krb_debug)
+ fprintf(stderr, "%s: can't find any Kerberos host.\n",
+ prog);
+ retval = SKDC_CANT;
+ goto rtn;
+ }
+ /* retry each host in sequence */
+ for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) {
+ for (host = hostlist; host->h_name != (char *)NULL; host++) {
+ to.sin_family = host->h_addrtype;
+ bcopy(host->h_addr, (char *)&to.sin_addr,
+ host->h_length);
+ if (send_recv(pkt, rpkt, f, &to, hostlist)) {
+ retval = KSUCCESS;
+ goto rtn;
+ }
+ }
+ }
+ retval = SKDC_RETRY;
+rtn:
+ (void) close(f);
+ if (hostlist) {
+ register struct hostent *hp;
+ for (hp = hostlist; hp->h_name; hp++)
+#if defined(h_addr)
+ if (hp->h_addr_list) {
+#endif /* defined(h_addr) */
+ if (hp->h_addr)
+ free(hp->h_addr);
+#if defined(h_addr)
+ free((char *)hp->h_addr_list);
+ }
+#endif /* defined(h_addr) */
+ free((char *)hostlist);
+ }
+ return(retval);
+}
+
+/*
+ * try to send out and receive message.
+ * return 1 on success, 0 on failure
+ */
+
+static int
+send_recv(pkt, rpkt, f, _to, addrs)
+ KTEXT pkt;
+ KTEXT rpkt;
+ int f;
+ struct sockaddr_in *_to;
+ struct hostent *addrs;
+{
+ fd_set readfds;
+ register struct hostent *hp;
+ struct sockaddr_in from;
+ int sin_size;
+ int numsent;
+
+ if (krb_debug) {
+ if (_to->sin_family == AF_INET)
+ printf("Sending message to %s...",
+ inet_ntoa(_to->sin_addr));
+ else
+ printf("Sending message...");
+ (void) fflush(stdout);
+ }
+ if ((numsent = sendto(f,(char *)(pkt->dat), pkt->length, 0,
+ (struct sockaddr *)_to,
+ S_AD_SZ)) != pkt->length) {
+ if (krb_debug)
+ printf("sent only %d/%d\n",numsent, pkt->length);
+ return 0;
+ }
+ if (krb_debug) {
+ printf("Sent\nWaiting for reply...");
+ (void) fflush(stdout);
+ }
+ FD_ZERO(&readfds);
+ FD_SET(f, &readfds);
+ errno = 0;
+ /* select - either recv is ready, or timeout */
+ /* see if timeout or error or wrong descriptor */
+ if (select(f + 1, &readfds, (fd_set *)0, (fd_set *)0, &timeout) < 1
+ || !FD_ISSET(f, &readfds)) {
+ if (krb_debug) {
+ long rfds;
+ bcopy(&readfds, &rfds, sizeof(rfds));
+ fprintf(stderr, "select failed: readfds=%lx",
+ rfds);
+ perror("");
+ }
+ return 0;
+ }
+ sin_size = sizeof(from);
+ if (recvfrom(f, (char *)(rpkt->dat), sizeof(rpkt->dat), 0,
+ (struct sockaddr *)&from, &sin_size)
+ < 0) {
+ if (krb_debug)
+ perror("recvfrom");
+ return 0;
+ }
+ if (krb_debug) {
+ printf("received packet from %s\n", inet_ntoa(from.sin_addr));
+ fflush(stdout);
+ }
+ for (hp = addrs; hp->h_name != (char *)NULL; hp++) {
+ if (!bcmp(hp->h_addr, (char *)&from.sin_addr.s_addr,
+ hp->h_length)) {
+ if (krb_debug) {
+ printf("Received it\n");
+ (void) fflush(stdout);
+ }
+ return 1;
+ }
+ if (krb_debug)
+ fprintf(stderr,
+ "packet not from %lx\n",
+ (long)hp->h_addr);
+ }
+ if (krb_debug)
+ fprintf(stderr, "%s: received packet from wrong host! (%x)\n",
+ "send_to_kdc(send_rcv)", (int)from.sin_addr.s_addr);
+ return 0;
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/sendauth.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <syslog.h>
+
+/*
+ * If the protocol changes, you will need to change the version string
+ * and make appropriate changes in krb_recvauth.c
+ */
+#define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */
+
+
+/*
+ * This file contains two routines: krb_sendauth() and krb_sendsrv().
+ *
+ * krb_sendauth() transmits a ticket over a file descriptor for a
+ * desired service, instance, and realm, doing mutual authentication
+ * with the server if desired.
+ *
+ * krb_sendsvc() sends a service name to a remote knetd server.
+ */
+
+/*
+ * The first argument to krb_sendauth() 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 "fd" argument is a file descriptor to write to the remote
+ * server on. 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 arguments are 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 "msg_data" argument
+ * holds the returned mutual-authentication message from the server
+ * (i.e., the checksum+1); the "cred" structure is used to hold the
+ * session key of the server, extracted from the ticket file, for use
+ * in decrypting the mutual authentication message from the server;
+ * and "schedule" holds the key schedule for that decryption. The
+ * the local and server addresses are given in "laddr" and "faddr".
+ *
+ * The application protocol version number (of up to KRB_SENDAUTH_VLEN
+ * characters) is passed in "version".
+ *
+ * If all goes well, KSUCCESS is returned, otherwise some error code.
+ *
+ * The format of the message sent to the 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
+ */
+
+/*
+ * XXX: Note that krb_rd_priv() is coded in such a way that
+ * "msg_data->app_data" will be pointing into "priv_buf", which
+ * will disappear when krb_sendauth() returns.
+ */
+
+int
+krb_sendauth(options, fd, ticket, service, inst, realm, checksum,
+ msg_data, cred, schedule, laddr, faddr, version)
+ int32_t options; /* bit-pattern of options */
+ int fd; /* file descriptor to write onto */
+ KTEXT ticket; /* where to put ticket (return); or
+ * supplied in case of KOPT_DONT_MK_REQ */
+ char *service; /* service name, instance, realm */
+ char *inst; /* checksum to include in request */
+ char *realm; /* mutual auth MSG_DAT (return) */
+ u_int32_t checksum; /* credentials (return) */
+ MSG_DAT *msg_data; /* key schedule (return) */
+ CREDENTIALS *cred; /* local address */
+ struct des_ks_struct *schedule;
+ struct sockaddr_in *faddr; /* address of foreign host on fd */
+ struct sockaddr_in *laddr;
+ char *version; /* version string */
+{
+ int rem, i, cc;
+ char srv_inst[INST_SZ];
+ char krb_realm[REALM_SZ];
+ char buf[BUFSIZ];
+ u_int32_t tkt_len;
+ u_char priv_buf[1024];
+ u_int32_t cksum;
+
+ 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;
+ }
+
+ /* copy instance into local storage, canonicalizing if desired */
+ if (options & KOPT_DONT_CANON)
+ (void) strncpy(srv_inst, inst, INST_SZ);
+ else
+ (void) strncpy(srv_inst, krb_get_phost(inst), INST_SZ);
+
+ /* get the ticket if desired */
+ if (!(options & KOPT_DONT_MK_REQ)) {
+ rem = krb_mk_req(ticket, service, srv_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,"%d ",ticket->length);
+ (void) write(fd, buf, strlen(buf));
+ (void) write(fd, (char *) ticket->dat, ticket->length);
+ return(rem);
+ }
+#endif /* ATHENA_COMPAT */
+ /* if mutual auth, get credentials so we have service session
+ keys for decryption below */
+ if (options & KOPT_DO_MUTUAL)
+ if ((cc = krb_get_cred(service, srv_inst, realm, cred)))
+ return(cc);
+
+ /* zero the buffer */
+ (void) bzero(buf, BUFSIZ);
+
+ /* insert version strings */
+ (void) strncpy(buf, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN);
+ (void) strncpy(buf+KRB_SENDAUTH_VLEN, version, KRB_SENDAUTH_VLEN);
+
+ /* increment past vers strings */
+ i = 2*KRB_SENDAUTH_VLEN;
+
+ /* put ticket length into buffer */
+ tkt_len = htonl(ticket->length);
+ (void) bcopy((char *) &tkt_len, buf+i, sizeof(tkt_len));
+ i += sizeof(tkt_len);
+
+ /* put ticket into buffer */
+ (void) bcopy((char *) ticket->dat, buf+i, ticket->length);
+ i += ticket->length;
+
+ /* write the request to the server */
+ if ((cc = krb_net_write(fd, buf, i)) != i)
+ return(cc);
+
+ /* mutual authentication, if desired */
+ if (options & KOPT_DO_MUTUAL) {
+ /* get the length of the reply */
+ if (krb_net_read(fd, (char *) &tkt_len, sizeof(tkt_len)) !=
+ sizeof(tkt_len))
+ return(errno);
+ tkt_len = ntohl(tkt_len);
+
+ /* if the length is negative, the server failed to recognize us. */
+ if ((tkt_len < 0) || (tkt_len > sizeof(priv_buf)))
+ return(KFAILURE); /* XXX */
+ /* read the reply... */
+ if (krb_net_read(fd, (char *)priv_buf, (int) tkt_len) != (int) tkt_len)
+ return(errno);
+
+ /* ...and decrypt it */
+#ifndef NOENCRYPTION
+ des_key_sched(&cred->session,schedule);
+#endif
+ if ((cc = krb_rd_priv(priv_buf, tkt_len, schedule,
+ &cred->session, faddr, laddr, msg_data)))
+ return(cc);
+
+ /* fetch the (modified) checksum */
+ (void) bcopy((char *)msg_data->app_data, (char *)&cksum,
+ sizeof(cksum));
+ cksum = ntohl(cksum);
+
+ /* if it doesn't match, fail */
+ if (cksum != checksum + 1)
+ return(KFAILURE); /* XXX */
+ }
+ return(KSUCCESS);
+}
+
+#ifdef ATHENA_COMPAT
+/*
+ * krb_sendsvc
+ */
+
+int
+krb_sendsvc(fd, service)
+ int fd;
+ char *service;
+{
+ /* write the service name length and then the service name to
+ the fd */
+ u_int32_t serv_length;
+ int cc;
+
+ serv_length = htonl(strlen(service));
+ if ((cc = krb_net_write(fd, (char *) &serv_length,
+ sizeof(serv_length)))
+ != sizeof(serv_length))
+ return(cc);
+ if ((cc = krb_net_write(fd, service, strlen(service)))
+ != strlen(service))
+ return(cc);
+ return(KSUCCESS);
+}
+#endif /* ATHENA_COMPAT */
--- /dev/null
+major=4
+minor=0
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/str2key.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ * This defines the Andrew string_to_key function. It accepts a password
+ * string as input and converts its via a one-way encryption algorithm to a DES
+ * encryption key. It is compatible with the original Andrew authentication
+ * service password database.
+ */
+
+#include "krb_locl.h"
+
+/*
+EXPORT void afs_string_to_key(char *passwd, char *cell, des_cblock *key);
+*/
+
+static void
+mklower(s)
+ char *s;
+{
+ for (; *s; s++)
+ if ('A' <= *s && *s <= 'Z')
+ *s = *s - 'A' + 'a';
+}
+
+/*
+ * Short passwords, i.e 8 characters or less.
+ */
+static void
+afs_cmu_StringToKey (str, cell, key)
+ char *str;
+ char *cell;
+ des_cblock *key;
+{
+ char password[8+1]; /* crypt is limited to 8 chars anyway */
+ int i;
+ int passlen;
+
+ bzero (key, sizeof(key));
+ bzero(password, sizeof(password));
+
+ strncpy (password, cell, 8);
+ passlen = strlen (str);
+ if (passlen > 8) passlen = 8;
+
+ for (i=0; i<passlen; i++)
+ password[i] = str[i] ^ cell[i]; /* make sure cell is zero padded */
+
+ for (i=0; i<8; i++)
+ if (password[i] == '\0') password[i] = 'X';
+
+ /* crypt only considers the first 8 characters of password but for some
+ reason returns eleven characters of result (plus the two salt chars). */
+ strncpy((void *)key, (char *)crypt(password, "#~") + 2, sizeof(des_cblock));
+
+ /* parity is inserted into the LSB so leftshift each byte up one bit. This
+ allows ascii characters with a zero MSB to retain as much significance
+ as possible. */
+ { char *keybytes = (char *)key;
+ unsigned int temp;
+
+ for (i = 0; i < 8; i++) {
+ temp = (unsigned int) keybytes[i];
+ keybytes[i] = (unsigned char) (temp << 1);
+ }
+ }
+ des_fixup_key_parity (key);
+}
+
+#undef BUFSIZ
+#define BUFSIZ 512
+
+/*
+ * Long passwords, i.e 9 characters or more.
+*/
+static void
+afs_transarc_StringToKey (str, cell, key)
+ char *str;
+ char *cell;
+ des_cblock *key;
+{
+ des_key_schedule schedule;
+ des_cblock temp_key;
+ des_cblock ivec;
+ char password[BUFSIZ];
+ int passlen;
+
+ strncpy (password, str, sizeof(password));
+ if ((passlen = strlen (password)) < sizeof(password)-1)
+ strncat (password, cell, sizeof(password)-passlen);
+ if ((passlen = strlen(password)) > sizeof(password)) passlen = sizeof(password);
+
+ bcopy ("kerberos", &ivec, 8);
+ bcopy ("kerberos", &temp_key, 8);
+ des_fixup_key_parity (&temp_key);
+ des_key_sched (&temp_key, schedule);
+ des_cbc_cksum ((des_cblock *)password, &ivec, passlen, schedule, &ivec);
+
+ bcopy (&ivec, &temp_key, 8);
+ des_fixup_key_parity (&temp_key);
+ des_key_sched (&temp_key, schedule);
+ des_cbc_cksum ((des_cblock *)password, key, passlen, schedule, &ivec);
+
+ des_fixup_key_parity (key);
+}
+
+#undef REALM_SZ
+#define REALM_SZ 41
+
+void
+afs_string_to_key(str, cell, key)
+ char *str;
+ char *cell;
+ des_cblock *key;
+{
+ char realm[REALM_SZ];
+ (void)strcpy(realm, cell);
+ (void)mklower(realm);
+
+ if (strlen(str) > 8)
+ afs_transarc_StringToKey (str, realm, key);
+ else
+ afs_cmu_StringToKey (str, realm, key);
+}
--- /dev/null
+.\" $Source: /home/cvs/src/kerberosIV/krb/Attic/tf_util.3,v $
+.\" $Author: tholo $
+.\" $Header: /home/cvs/src/kerberosIV/krb/Attic/tf_util.3,v 1.1.1.1 1995/12/14 06:52:40 tholo Exp $
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.TH TF_UTIL 3 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+tf_init, tf_get_pname, tf_get_pinst, tf_get_cred, tf_close \
+\- Routines for manipulating a Kerberos ticket file
+.SH SYNOPSIS
+.nf
+.nj
+.ft B
+#include <krb.h>
+.PP
+.ft B
+extern char *krb_err_txt[];
+.PP
+.ft B
+tf_init(tf_name, rw)
+char *tf_name;
+int rw;
+.PP
+.ft B
+tf_get_pname(pname)
+char *pname;
+.PP
+.ft B
+tf_get_pinst(pinst)
+char *pinst;
+.PP
+.ft B
+tf_get_cred(c)
+CREDENTIALS *c;
+.PP
+.ft B
+tf_close()
+.PP
+.fi
+.SH DESCRIPTION
+This group of routines are provided to manipulate the Kerberos tickets
+file. A ticket file has the following format:
+.nf
+.in +4
+.sp
+principal's name (null-terminated string)
+principal's instance (null-terminated string)
+CREDENTIAL_1
+CREDENTIAL_2
+ ...
+CREDENTIAL_n
+EOF
+.sp
+.in -4
+.LP
+Where "CREDENTIAL_x" consists of the following fixed-length
+fields from the CREDENTIALS structure (defined in <krb.h>):
+.nf
+.sp
+.in +4
+ char service[ANAME_SZ]
+ char instance[INST_SZ]
+ char realm[REALM_SZ]
+ des_cblock session
+ int lifetime
+ int kvno
+ KTEXT_ST ticket_st
+ long issue_date
+.in -4
+.sp
+.fi
+.PP
+.I tf_init
+must be called before the other ticket file
+routines.
+It takes the name of the ticket file to use,
+and a read/write flag as arguments.
+It tries to open the ticket file, checks the mode and if
+everything is okay, locks the file. If it's opened for
+reading, the lock is shared. If it's opened for writing,
+the lock is exclusive.
+KSUCCESS is returned if all went well, otherwise one of the
+following:
+.nf
+.sp
+NO_TKT_FIL - file wasn't there
+TKT_FIL_ACC - file was in wrong mode, etc.
+TKT_FIL_LCK - couldn't lock the file, even after a retry
+.sp
+.fi
+.PP
+The
+.I tf_get_pname
+reads the principal's name from a ticket file.
+It should only be called after tf_init has been called. The
+principal's name is filled into the
+.I pname
+parameter. If all goes
+well, KSUCCESS is returned.
+If tf_init wasn't called, TKT_FIL_INI
+is returned.
+If the principal's name was null, or EOF was encountered, or the
+name was longer than ANAME_SZ, TKT_FIL_FMT is returned.
+.PP
+The
+.I tf_get_pinst
+reads the principal's instance from a ticket file.
+It should only be called after tf_init and tf_get_pname
+have been called.
+The principal's instance is filled into the
+.I pinst
+parameter.
+If all goes
+well, KSUCCESS is returned.
+If tf_init wasn't called, TKT_FIL_INI
+is returned.
+If EOF was encountered, or the
+name was longer than INST_SZ, TKT_FIL_FMT is returned.
+Note that, unlike the principal name, the instance name may be null.
+.PP
+The
+.I tf_get_cred
+routine reads a CREDENTIALS record from a ticket file and
+fills in the given structure.
+It should only be called after
+tf_init, tf_get_pname, and tf_get_pinst have been called.
+If all goes well, KSUCCESS is returned. Possible error codes
+are:
+.nf
+.sp
+TKT_FIL_INI - tf_init wasn't called first
+TKT_FIL_FMT - bad format
+EOF - end of file encountered
+.sp
+.fi
+.PP
+.I tf_close
+closes the ticket file and releases the lock on it.
+.SH "SEE ALSO"
+krb(3)
+.SH DIAGNOSTICS
+.SH BUGS
+The ticket file routines have to be called in a certain order.
+.SH AUTHORS
+Jennifer Steiner, MIT Project Athena
+.br
+Bill Bryant, MIT Project Athena
+.SH RESTRICTIONS
+Copyright 1987 Massachusetts Institute of Technology
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/tf_util.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+
+#ifdef TKT_SHMEM
+#include <sys/param.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* TKT_SHMEM */
+
+#define TOO_BIG -1
+#define TF_LCK_RETRY ((unsigned)2) /* seconds to sleep before
+ * retry if ticket file is
+ * locked */
+
+#ifdef TKT_SHMEM
+static char *krb_shm_addr = 0;
+static char *tmp_shm_addr = 0;
+static char krb_dummy_skey[8] = {0,0,0,0,0,0,0,0};
+#endif /* TKT_SHMEM */
+
+/*
+ * fd must be initialized to something that won't ever occur as a real
+ * file descriptor. Since open(2) returns only non-negative numbers as
+ * valid file descriptors, and tf_init always stuffs the return value
+ * from open in here even if it is an error flag, we must
+ * a. Initialize fd to a negative number, to indicate that it is
+ * not initially valid.
+ * b. When checking for a valid fd, assume that negative values
+ * are invalid (ie. when deciding whether tf_init has been
+ * called.)
+ * c. In tf_close, be sure it gets reinitialized to a negative
+ * number.
+ */
+static fd = -1;
+static curpos; /* Position in tfbfr */
+static lastpos; /* End of tfbfr */
+static char tfbfr[BUFSIZ]; /* Buffer for ticket data */
+
+static tf_gets(register char *s, int n), tf_read(register char *s, register int n);
+
+/*
+ * This file contains routines for manipulating the ticket cache file.
+ *
+ * The ticket file is in the following format:
+ *
+ * principal's name (null-terminated string)
+ * principal's instance (null-terminated string)
+ * CREDENTIAL_1
+ * CREDENTIAL_2
+ * ...
+ * CREDENTIAL_n
+ * EOF
+ *
+ * Where "CREDENTIAL_x" consists of the following fixed-length
+ * fields from the CREDENTIALS structure (see "krb.h"):
+ *
+ * char service[ANAME_SZ]
+ * char instance[INST_SZ]
+ * char realm[REALM_SZ]
+ * C_Block session
+ * int lifetime
+ * int kvno
+ * KTEXT_ST ticket_st
+ * u_int32_t issue_date
+ *
+ * Short description of routines:
+ *
+ * tf_init() opens the ticket file and locks it.
+ *
+ * tf_get_pname() returns the principal's name.
+ *
+ * tf_get_pinst() returns the principal's instance (may be null).
+ *
+ * tf_get_cred() returns the next CREDENTIALS record.
+ *
+ * tf_save_cred() appends a new CREDENTIAL record to the ticket file.
+ *
+ * tf_close() closes the ticket file and releases the lock.
+ *
+ * tf_gets() returns the next null-terminated string. It's an internal
+ * routine used by tf_get_pname(), tf_get_pinst(), and tf_get_cred().
+ *
+ * tf_read() reads a given number of bytes. It's an internal routine
+ * used by tf_get_cred().
+ */
+
+/*
+ * tf_init() should be called before the other ticket file routines.
+ * It takes the name of the ticket file to use, "tf_name", and a
+ * read/write flag "rw" as arguments.
+ *
+ * It tries to open the ticket file, checks the mode, and if everything
+ * is okay, locks the file. If it's opened for reading, the lock is
+ * shared. If it's opened for writing, the lock is exclusive.
+ *
+ * Returns KSUCCESS if all went well, otherwise one of the following:
+ *
+ * NO_TKT_FIL - file wasn't there
+ * TKT_FIL_ACC - file was in wrong mode, etc.
+ * TKT_FIL_LCK - couldn't lock the file, even after a retry
+ */
+
+int
+tf_init(tf_name, rw)
+ char *tf_name;
+ int rw;
+{
+ int wflag;
+ uid_t me, getuid(void);
+ struct stat stat_buf;
+#ifdef TKT_SHMEM
+ char shmidname[MaxPathLen];
+ FILE *sfp;
+ int shmid;
+#endif
+
+ switch (rw) {
+ case R_TKT_FIL:
+ wflag = 0;
+ break;
+ case W_TKT_FIL:
+ wflag = 1;
+ break;
+ default:
+ if (krb_debug) fprintf(stderr, "tf_init: illegal parameter\n");
+ return TKT_FIL_ACC;
+ }
+ if (lstat(tf_name, &stat_buf) < 0)
+ switch (errno) {
+ case ENOENT:
+ return NO_TKT_FIL;
+ default:
+ return TKT_FIL_ACC;
+ }
+ me = getuid();
+ if ((stat_buf.st_uid != me && me != 0) ||
+ ((stat_buf.st_mode & S_IFMT) != S_IFREG))
+ return TKT_FIL_ACC;
+#ifdef TKT_SHMEM
+ (void) strcpy(shmidname, tf_name);
+ (void) strcat(shmidname, ".shm");
+ if (stat(shmidname,&stat_buf) < 0)
+ return(TKT_FIL_ACC);
+ if ((stat_buf.st_uid != me && me != 0) ||
+ ((stat_buf.st_mode & S_IFMT) != S_IFREG))
+ return TKT_FIL_ACC;
+#endif /* TKT_SHMEM */
+
+ /*
+ * If "wflag" is set, open the ticket file in append-writeonly mode
+ * and lock the ticket file in exclusive mode. If unable to lock
+ * the file, sleep and try again. If we fail again, return with the
+ * proper error message.
+ */
+
+ curpos = sizeof(tfbfr);
+
+#ifdef TKT_SHMEM
+ sfp = fopen(shmidname, "r"); /* only need read/write on the
+ actual tickets */
+ if (sfp == 0)
+ return TKT_FIL_ACC;
+ shmid = -1;
+ {
+ char buf[BUFSIZ];
+ int val; /* useful for debugging fscanf */
+ /* We provide our own buffer here since some STDIO libraries
+ barf on unbuffered input with fscanf() */
+
+ setbuf(sfp, buf);
+ if ((val = fscanf(sfp,"%d",&shmid)) != 1) {
+ (void) fclose(sfp);
+ return TKT_FIL_ACC;
+ }
+ if (shmid < 0) {
+ (void) fclose(sfp);
+ return TKT_FIL_ACC;
+ }
+ (void) fclose(sfp);
+ }
+ /*
+ * global krb_shm_addr is initialized to 0. Ultrix bombs when you try and
+ * attach the same segment twice so we need this check.
+ */
+ if (!krb_shm_addr) {
+ if ((krb_shm_addr = shmat(shmid,0,0)) == -1){
+ if (krb_debug)
+ fprintf(stderr,
+ "cannot attach shared memory for segment %d\n",
+ shmid);
+ krb_shm_addr = 0; /* reset so we catch further errors */
+ return TKT_FIL_ACC;
+ }
+ }
+ tmp_shm_addr = krb_shm_addr;
+#endif /* TKT_SHMEM */
+
+ if (wflag) {
+ fd = open(tf_name, O_RDWR, 0600);
+ if (fd < 0) {
+ return TKT_FIL_ACC;
+ }
+ if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
+ sleep(TF_LCK_RETRY);
+ if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
+ (void) close(fd);
+ fd = -1;
+ return TKT_FIL_LCK;
+ }
+ }
+ return KSUCCESS;
+ }
+ /*
+ * Otherwise "wflag" is not set and the ticket file should be opened
+ * for read-only operations and locked for shared access.
+ */
+
+ fd = open(tf_name, O_RDONLY, 0600);
+ if (fd < 0) {
+ return TKT_FIL_ACC;
+ }
+ if (flock(fd, LOCK_SH | LOCK_NB) < 0) {
+ sleep(TF_LCK_RETRY);
+ if (flock(fd, LOCK_SH | LOCK_NB) < 0) {
+ (void) close(fd);
+ fd = -1;
+ return TKT_FIL_LCK;
+ }
+ }
+ return KSUCCESS;
+}
+
+/*
+ * tf_get_pname() reads the principal's name from the ticket file. It
+ * should only be called after tf_init() has been called. The
+ * principal's name is filled into the "p" parameter. If all goes well,
+ * KSUCCESS is returned. If tf_init() wasn't called, TKT_FIL_INI is
+ * returned. If the name was null, or EOF was encountered, or the name
+ * was longer than ANAME_SZ, TKT_FIL_FMT is returned.
+ */
+
+int
+tf_get_pname(p)
+ char *p;
+{
+ if (fd < 0) {
+ if (krb_debug)
+ fprintf(stderr, "tf_get_pname called before tf_init.\n");
+ return TKT_FIL_INI;
+ }
+ if (tf_gets(p, ANAME_SZ) < 2) /* can't be just a null */
+ return TKT_FIL_FMT;
+ return KSUCCESS;
+}
+
+/*
+ * tf_get_pinst() reads the principal's instance from a ticket file.
+ * It should only be called after tf_init() and tf_get_pname() have been
+ * called. The instance is filled into the "inst" parameter. If all
+ * goes well, KSUCCESS is returned. If tf_init() wasn't called,
+ * TKT_FIL_INI is returned. If EOF was encountered, or the instance
+ * was longer than ANAME_SZ, TKT_FIL_FMT is returned. Note that the
+ * instance may be null.
+ */
+
+int
+tf_get_pinst(inst)
+ char *inst;
+{
+ if (fd < 0) {
+ if (krb_debug)
+ fprintf(stderr, "tf_get_pinst called before tf_init.\n");
+ return TKT_FIL_INI;
+ }
+ if (tf_gets(inst, INST_SZ) < 1)
+ return TKT_FIL_FMT;
+ return KSUCCESS;
+}
+
+/*
+ * tf_get_cred() reads a CREDENTIALS record from a ticket file and fills
+ * in the given structure "c". It should only be called after tf_init(),
+ * tf_get_pname(), and tf_get_pinst() have been called. If all goes well,
+ * KSUCCESS is returned. Possible error codes are:
+ *
+ * TKT_FIL_INI - tf_init wasn't called first
+ * TKT_FIL_FMT - bad format
+ * EOF - end of file encountered
+ */
+
+int
+tf_get_cred(c)
+ CREDENTIALS *c;
+{
+ KTEXT ticket = &c->ticket_st; /* pointer to ticket */
+ int k_errno;
+
+ if (fd < 0) {
+ if (krb_debug)
+ fprintf(stderr, "tf_get_cred called before tf_init.\n");
+ return TKT_FIL_INI;
+ }
+ if ((k_errno = tf_gets(c->service, SNAME_SZ)) < 2)
+ switch (k_errno) {
+ case TOO_BIG:
+ case 1: /* can't be just a null */
+ tf_close();
+ return TKT_FIL_FMT;
+ case 0:
+ return EOF;
+ }
+ if ((k_errno = tf_gets(c->instance, INST_SZ)) < 1)
+ switch (k_errno) {
+ case TOO_BIG:
+ return TKT_FIL_FMT;
+ case 0:
+ return EOF;
+ }
+ if ((k_errno = tf_gets(c->realm, REALM_SZ)) < 2)
+ switch (k_errno) {
+ case TOO_BIG:
+ case 1: /* can't be just a null */
+ tf_close();
+ return TKT_FIL_FMT;
+ case 0:
+ return EOF;
+ }
+ if (
+ tf_read((char *) (c->session), DES_KEY_SZ) < 1 ||
+ tf_read((char *) &(c->lifetime), sizeof(c->lifetime)) < 1 ||
+ tf_read((char *) &(c->kvno), sizeof(c->kvno)) < 1 ||
+ tf_read((char *) &(ticket->length), sizeof(ticket->length))
+ < 1 ||
+ /* don't try to read a silly amount into ticket->dat */
+ ticket->length > MAX_KTXT_LEN ||
+ tf_read((char *) (ticket->dat), ticket->length) < 1 ||
+ tf_read((char *) &(c->issue_date), sizeof(c->issue_date)) < 1
+ ) {
+ tf_close();
+ return TKT_FIL_FMT;
+ }
+#ifdef TKT_SHMEM
+ bcopy(tmp_shm_addr,c->session,KEY_SZ);
+ tmp_shm_addr += KEY_SZ;
+#endif /* TKT_SHMEM */
+ return KSUCCESS;
+}
+
+/*
+ * tf_close() closes the ticket file and sets "fd" to -1. If "fd" is
+ * not a valid file descriptor, it just returns. It also clears the
+ * buffer used to read tickets.
+ *
+ * The return value is not defined.
+ */
+
+void
+tf_close()
+{
+ if (!(fd < 0)) {
+#ifdef TKT_SHMEM
+ if (shmdt(krb_shm_addr)) {
+ /* what kind of error? */
+ if (krb_debug)
+ fprintf(stderr, "shmdt 0x%x: errno %d",krb_shm_addr, errno);
+ } else {
+ krb_shm_addr = 0;
+ }
+#endif /* TKT_SHMEM */
+ (void) flock(fd, LOCK_UN);
+ (void) close(fd);
+ fd = -1; /* see declaration of fd above */
+ }
+ bzero(tfbfr, sizeof(tfbfr));
+}
+
+/*
+ * tf_gets() is an internal routine. It takes a string "s" and a count
+ * "n", and reads from the file until either it has read "n" characters,
+ * or until it reads a null byte. When finished, what has been read exists
+ * in "s". If it encounters EOF or an error, it closes the ticket file.
+ *
+ * Possible return values are:
+ *
+ * n the number of bytes read (including null terminator)
+ * when all goes well
+ *
+ * 0 end of file or read error
+ *
+ * TOO_BIG if "count" characters are read and no null is
+ * encountered. This is an indication that the ticket
+ * file is seriously ill.
+ */
+
+static int
+tf_gets(s, n)
+ register char *s;
+ int n;
+{
+ register count;
+
+ if (fd < 0) {
+ if (krb_debug)
+ fprintf(stderr, "tf_gets called before tf_init.\n");
+ return TKT_FIL_INI;
+ }
+ for (count = n - 1; count > 0; --count) {
+ if (curpos >= sizeof(tfbfr)) {
+ lastpos = read(fd, tfbfr, sizeof(tfbfr));
+ curpos = 0;
+ }
+ if (curpos == lastpos) {
+ tf_close();
+ return 0;
+ }
+ *s = tfbfr[curpos++];
+ if (*s++ == '\0')
+ return (n - count);
+ }
+ tf_close();
+ return TOO_BIG;
+}
+
+/*
+ * tf_read() is an internal routine. It takes a string "s" and a count
+ * "n", and reads from the file until "n" bytes have been read. When
+ * finished, what has been read exists in "s". If it encounters EOF or
+ * an error, it closes the ticket file.
+ *
+ * Possible return values are:
+ *
+ * n the number of bytes read when all goes well
+ *
+ * 0 on end of file or read error
+ */
+
+static int
+tf_read(s, n)
+ register char *s;
+ register int n;
+{
+ register count;
+
+ for (count = n; count > 0; --count) {
+ if (curpos >= sizeof(tfbfr)) {
+ lastpos = read(fd, tfbfr, sizeof(tfbfr));
+ curpos = 0;
+ }
+ if (curpos == lastpos) {
+ tf_close();
+ return 0;
+ }
+ *s++ = tfbfr[curpos++];
+ }
+ return n;
+}
+
+char *tkt_string(void);
+
+/*
+ * tf_save_cred() appends an incoming ticket to the end of the ticket
+ * file. You must call tf_init() before calling tf_save_cred().
+ *
+ * The "service", "instance", and "realm" arguments specify the
+ * server's name; "session" contains the session key to be used with
+ * the ticket; "kvno" is the server key version number in which the
+ * ticket is encrypted, "ticket" contains the actual ticket, and
+ * "issue_date" is the time the ticket was requested (local host's time).
+ *
+ * Returns KSUCCESS if all goes well, TKT_FIL_INI if tf_init() wasn't
+ * called previously, and KFAILURE for anything else that went wrong.
+ */
+
+int
+tf_save_cred(service, instance, realm, session,
+ lifetime, kvno, ticket, issue_date)
+ char *service; /* Service name */
+ char *instance; /* Instance */
+ char *realm; /* Auth domain */
+ unsigned char *session; /* Session key */
+ int lifetime; /* Lifetime */
+ int kvno; /* Key version number */
+ KTEXT ticket; /* The ticket itself */
+ u_int32_t issue_date; /* The issue time */
+{
+
+ off_t lseek(int, off_t, int);
+ int count; /* count for write */
+#ifdef TKT_SHMEM
+ int *skey_check;
+#endif /* TKT_SHMEM */
+
+ if (fd < 0) { /* fd is ticket file as set by tf_init */
+ if (krb_debug)
+ fprintf(stderr, "tf_save_cred called before tf_init.\n");
+ return TKT_FIL_INI;
+ }
+ /* Find the end of the ticket file */
+ (void) lseek(fd, 0L, 2);
+#ifdef TKT_SHMEM
+ /* scan to end of existing keys: pick first 'empty' slot.
+ we assume that no real keys will be completely zero (it's a weak
+ key under DES) */
+
+ skey_check = (int *) krb_shm_addr;
+
+ while (*skey_check && *(skey_check+1))
+ skey_check += 2;
+ tmp_shm_addr = (char *)skey_check;
+#endif /* TKT_SHMEM */
+
+ /* Write the ticket and associated data */
+ /* Service */
+ count = strlen(service) + 1;
+ if (write(fd, service, count) != count)
+ goto bad;
+ /* Instance */
+ count = strlen(instance) + 1;
+ if (write(fd, instance, count) != count)
+ goto bad;
+ /* Realm */
+ count = strlen(realm) + 1;
+ if (write(fd, realm, count) != count)
+ goto bad;
+ /* Session key */
+#ifdef TKT_SHMEM
+ bcopy(session,tmp_shm_addr,8);
+ tmp_shm_addr+=8;
+ if (write(fd,krb_dummy_skey,8) != 8)
+ goto bad;
+#else /* ! TKT_SHMEM */
+ if (write(fd, (char *) session, 8) != 8)
+ goto bad;
+#endif /* TKT_SHMEM */
+ /* Lifetime */
+ if (write(fd, (char *) &lifetime, sizeof(int)) != sizeof(int))
+ goto bad;
+ /* Key vno */
+ if (write(fd, (char *) &kvno, sizeof(int)) != sizeof(int))
+ goto bad;
+ /* Tkt length */
+ if (write(fd, (char *) &(ticket->length), sizeof(int)) !=
+ sizeof(int))
+ goto bad;
+ /* Ticket */
+ count = ticket->length;
+ if (write(fd, (char *) (ticket->dat), count) != count)
+ goto bad;
+ /* Issue date */
+ if (write(fd, (char *) &issue_date, sizeof(issue_date))
+ != sizeof(issue_date))
+ goto bad;
+
+ /* Actually, we should check each write for success */
+ return (KSUCCESS);
+bad:
+ return (KFAILURE);
+}
--- /dev/null
+/*
+ * This software may now be redistributed outside the US.
+ *
+ * $Source: /home/cvs/src/kerberosIV/krb/Attic/tkt_string.c,v $
+ *
+ * $Locker: $
+ */
+
+/*
+ Copyright (C) 1989 by the Massachusetts Institute of Technology
+
+ Export of this software from the United States of America is assumed
+ to require a specific license from the United States Government.
+ It is the responsibility of any person or organization contemplating
+ export to obtain such a license before exporting.
+
+WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+distribute this software and its documentation for any purpose and
+without fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation, and that
+the name of M.I.T. not be used in advertising or publicity pertaining
+to distribution of the software without specific, written prior
+permission. M.I.T. makes no representations about the suitability of
+this software for any purpose. It is provided "as is" without express
+or implied warranty.
+
+ */
+
+#include "krb_locl.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+/*
+ * This routine is used to generate the name of the file that holds
+ * the user's cache of server tickets and associated session keys.
+ *
+ * If it is set, krb_ticket_string contains the ticket file name.
+ * Otherwise, the filename is constructed as follows:
+ *
+ * If it is set, the environment variable "KRBTKFILE" will be used as
+ * the ticket file name. Otherwise TKT_ROOT (defined in "krb.h") and
+ * the user's uid are concatenated to produce the ticket file name
+ * (e.g., "/tmp/tkt123"). A pointer to the string containing the ticket
+ * file name is returned.
+ */
+
+static char krb_ticket_string[MAXPATHLEN] = "";
+
+char *
+tkt_string()
+{
+ char *env;
+ uid_t getuid(void);
+
+ if (!*krb_ticket_string) {
+ if ((env = getenv("KRBTKFILE"))) {
+ (void) strncpy(krb_ticket_string, env,
+ sizeof(krb_ticket_string)-1);
+ krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
+ } else {
+ /* 32 bits of signed integer will always fit in 11 characters
+ (including the sign), so no need to worry about overflow */
+ (void) sprintf(krb_ticket_string, "%s%d",TKT_ROOT,(int)getuid());
+ }
+ }
+ return krb_ticket_string;
+}
+
+/*
+ * This routine is used to set the name of the file that holds the user's
+ * cache of server tickets and associated session keys.
+ *
+ * The value passed in is copied into local storage.
+ *
+ * NOTE: This routine should be called during initialization, before other
+ * Kerberos routines are called; otherwise tkt_string() above may be called
+ * and return an undesired ticket file name until this routine is called.
+ */
+
+void
+krb_set_tkt_string(val)
+ char *val;
+{
+
+ (void) strncpy(krb_ticket_string, val, sizeof(krb_ticket_string)-1);
+ krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
+
+ return;
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:51 tholo Exp $
+
+PROG= ksrvtgt
+CFLAGS+=-DKERBEROS
+DPADD= ${LIBKRB} ${LIBDES}
+LDADD= -lkrb -ldes
+BINDIR= /usr/bin
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: ksrvtgt.1,v 1.1.1.1 1995/12/14 06:52:51 tholo Exp $
+.TH KSRVTGT 1 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+ksrvtgt \- fetch and store Kerberos ticket-granting-ticket using a
+service key
+.SH SYNOPSIS
+.B ksrvtgt
+name instance [[realm] srvtab]
+.SH DESCRIPTION
+.I ksrvtgt
+retrieves a ticket-granting ticket with a lifetime of five (5) minutes
+for the principal
+.I name.instance@realm
+(or
+.I name.instance@localrealm
+if
+.I realm
+is not supplied on the command line), decrypts the response using
+the service key found in
+.I srvtab
+(or in
+.B /etc/kerberosIV/srvtab
+if
+.I srvtab
+is not specified on the command line), and stores the ticket in the
+standard ticket cache.
+.PP
+This command is intended primarily for use in shell scripts and other
+batch-type facilities.
+.SH DIAGNOSTICS
+"Generic kerberos failure (kfailure)" can indicate a whole range of
+problems, the most common of which is the inability to read the service
+key file.
+.SH FILES
+.TP 2i
+/etc/kerberosIV/krb.conf
+to get the name of the local realm.
+.TP
+/tmp/tkt[uid]
+The default ticket file.
+.TP
+/etc/kerberosIV/srvtab
+The default service key file.
+.SH SEE ALSO
+kerberos(1), kinit(1), kdestroy(1)
--- /dev/null
+/* $Id: ksrvtgt.c,v 1.1.1.1 1995/12/14 06:52:51 tholo Exp $ */
+
+/*-
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Get a ticket-granting-ticket given a service key file (srvtab)
+ * The lifetime is the shortest allowed [1 five-minute interval]
+ */
+
+#include <stdio.h>
+#include <strings.h>
+#include <sys/param.h>
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+const char rcsid[] =
+ "$Id: ksrvtgt.c,v 1.1.1.1 1995/12/14 06:52:51 tholo Exp $";
+
+main(argc,argv)
+ int argc;
+ char **argv;
+{
+ char realm[REALM_SZ + 1];
+ register int code;
+ char srvtab[MAXPATHLEN + 1];
+
+ bzero(realm, sizeof(realm));
+ bzero(srvtab, sizeof(srvtab));
+
+ if (argc < 3 || argc > 5) {
+ fprintf(stderr, "Usage: %s name instance [[realm] srvtab]\n",
+ argv[0]);
+ exit(1);
+ }
+
+ if (argc == 4)
+ (void) strncpy(srvtab, argv[3], sizeof(srvtab) -1);
+
+ if (argc == 5) {
+ (void) strncpy(realm, argv[3], sizeof(realm) - 1);
+ (void) strncpy(srvtab, argv[4], sizeof(srvtab) -1);
+ }
+
+ if (srvtab[0] == 0)
+ (void) strcpy(srvtab, KEYFILE);
+
+ if (realm[0] == 0)
+ if (krb_get_lrealm(realm, 1) != KSUCCESS)
+ exit(1);
+
+ code = krb_get_svc_in_tkt(argv[1], argv[2], realm,
+ "krbtgt", realm, 1, srvtab);
+ if (code)
+ fprintf(stderr, "%s\n", krb_err_txt[code]);
+ exit(code);
+}
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:53 tholo Exp $
+
+PROG= ksrvutil
+.if exists(${.CURDIR}/../kadm/obj)
+CFLAGS+=-I${.CURDIR}/../kadm/obj
+.else
+CFLAGS+=-I${.CURDIR}/../kadm
+.endif
+.if exists(${.CURDIR}/../krb/obj)
+CFLAGS+=-I${.CURDIR}/../krb/obj
+.else
+CFLAGS+=-I${.CURDIR}/../krb
+.endif
+.if exists(${.CURDIR}/../ss/obj)
+CFLAGS+=-I${.CURDIR}/../ss/obj
+.else
+CFLAGS+=-I${.CURDIR}/../ss
+.endif
+LDADD+= -lkadm -lkrb -ldes -lcom_err
+DPADD+= ${LIBKADM} ${LIBKRB} ${LIBDES} ${LIBCOM_ERR}
+MAN= ksrvutil.8
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: ksrvutil.8,v 1.1.1.1 1995/12/14 06:52:53 tholo Exp $
+.TH KSRVUTIL 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+ksrvutil \- host kerberos keyfile (srvtab) manipulation utility
+.SH SYNOPSIS
+ksrvutil
+.B operation
+[
+.B \-k
+] [
+.B \-i
+] [
+.B \-f filename
+]
+.SH DESCRIPTION
+.I ksrvutil
+allows a system manager to list or change keys currently in his
+keyfile or to add new keys to the keyfile.
+.PP
+
+Operation must be one of the following:
+.TP 10n
+.I list
+lists the keys in a keyfile showing version number and principal
+name. If the \-k option is given, keys will also be shown.
+.TP 10n
+.I change
+changes all the keys in the keyfile by using the regular admin
+protocol. If the \-i flag is given,
+.I ksrvutil
+will prompt for yes or no before changing each key. If the \-k
+option is used, the old and new keys will be displayed.
+.TP 10n
+.I add
+allows the user to add a key.
+.I add
+prompts for name, instance, realm, and key version number, asks
+for confirmation, and then asks for a password.
+.I ksrvutil
+then converts the password to a key and appends the keyfile with
+the new information. If the \-k option is used, the key is
+displayed.
+
+.PP
+In all cases, the default file used is KEY_FILE as defined in
+krb.h unless this is overridden by the \-f option.
+
+.PP
+A good use for
+.I ksrvutil
+would be for adding keys to a keyfile. A system manager could
+ask a kerberos administrator to create a new service key with
+.IR kadmin (8)
+and could supply an initial password. Then, he could use
+.I ksrvutil
+to add the key to the keyfile and then to change the key so that
+it will be random and unknown to either the system manager or
+the kerberos administrator.
+
+.I ksrvutil
+always makes a backup copy of the keyfile before making any
+changes.
+
+.SH DIAGNOSTICS
+If
+.I ksrvutil
+should exit on an error condition at any time during a change or
+add, a copy of the
+original keyfile can be found in
+.IR filename .old
+where
+.I filename
+is the name of the keyfile, and a copy of the file with all new
+keys changed or added so far can be found in
+.IR filename .work.
+The original keyfile is left unmodified until the program exits
+at which point it is removed and replaced it with the workfile.
+Appending the workfile to the backup copy and replacing the
+keyfile with the result should always give a usable keyfile,
+although the resulting keyfile will have some out of date keys
+in it.
+
+.SH SEE ALSO
+kadmin(8), ksrvtgt(1)
+
+.SH AUTHOR
+Emanuel Jay Berkenbilt, MIT Project Athena
--- /dev/null
+/* $Id: ksrvutil.c,v 1.1.1.1 1995/12/14 06:52:53 tholo Exp $ */
+
+/*-
+ * Copyright (C) 1989 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * list and update contents of srvtab files
+ */
+
+/*
+ * ksrvutil
+ * list and update the contents of srvtab files
+ */
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#include <kadm_locl.h>
+#include <sys/param.h>
+
+#ifdef NOENCRYPTION
+#define read_long_pw_string placebo_read_pw_string
+#else /* NOENCRYPTION */
+#define read_long_pw_string des_read_pw_string
+#endif /* NOENCRYPTION */
+
+#define SRVTAB_MODE 0600 /* rw------- */
+#define PAD " "
+#define VNO_HEADER "Version"
+#define VNO_FORMAT "%4d "
+#define KEY_HEADER " Key " /* 17 characters long */
+#define PRINC_HEADER " Principal\n"
+#define PRINC_FORMAT "%s"
+
+static unsigned short
+get_mode(char *filename)
+{
+ struct stat statbuf;
+ unsigned short mode;
+
+ (void) bzero((char *)&statbuf, sizeof(statbuf));
+
+ if (stat(filename, &statbuf) < 0)
+ mode = SRVTAB_MODE;
+ else
+ mode = statbuf.st_mode;
+
+ return(mode);
+}
+
+static void
+copy_keyfile(char *progname, char *keyfile, char *backup_keyfile)
+{
+ int keyfile_fd;
+ int backup_keyfile_fd;
+ int keyfile_mode;
+ char buf[BUFSIZ]; /* for copying keyfiles */
+ int rcount; /* for copying keyfiles */
+ int try_again;
+
+ (void) bzero((char *)buf, sizeof(buf));
+
+ do {
+ try_again = FALSE;
+ if ((keyfile_fd = open(keyfile, O_RDONLY, 0)) < 0) {
+ if (errno != ENOENT) {
+ (void)fprintf(stderr, "%s: Unable to read %s: %s\n", progname,
+ keyfile, strerror(errno));
+ exit(1);
+ }
+ else {
+ try_again = TRUE;
+ if ((keyfile_fd =
+ open(keyfile,
+ O_WRONLY | O_TRUNC | O_CREAT, SRVTAB_MODE)) < 0) {
+ (void) fprintf(stderr, "%s: Unable to create %s: %s\n",
+ progname, keyfile, strerror(errno));
+ exit(1);
+ }
+ else
+ if (close(keyfile_fd) < 0) {
+ (void) fprintf(stderr, "%s: Failure closing %s: %s\n",
+ progname, keyfile, strerror(errno));
+ exit(1);
+ }
+ }
+ }
+ } while(try_again);
+
+ keyfile_mode = get_mode(keyfile);
+
+ if ((backup_keyfile_fd =
+ open(backup_keyfile, O_WRONLY | O_TRUNC | O_CREAT,
+ keyfile_mode)) < 0) {
+ (void) fprintf(stderr, "%s: Unable to write %s: %s\n", progname,
+ backup_keyfile, strerror(errno));
+ exit(1);
+ }
+ do {
+ if ((rcount = read(keyfile_fd, (char *)buf, sizeof(buf))) < 0) {
+ (void) fprintf(stderr, "%s: Error reading %s: %s\n", progname,
+ keyfile, strerror(errno));
+ exit(1);
+ }
+ if (rcount && (write(backup_keyfile_fd, buf, rcount) != rcount)) {
+ (void) fprintf(stderr, "%s: Error writing %s: %s\n", progname,
+ backup_keyfile, strerror(errno));
+ exit(1);
+ }
+ } while (rcount);
+ if (close(backup_keyfile_fd) < 0) {
+ (void) fprintf(stderr, "%s: Error closing %s: %s\n", progname,
+ backup_keyfile, strerror(errno));
+ exit(1);
+ }
+ if (close(keyfile_fd) < 0) {
+ (void) fprintf(stderr, "%s: Error closing %s: %s\n", progname,
+ keyfile, strerror(errno));
+ exit(1);
+ }
+}
+
+static void
+leave(char *str, int x)
+{
+ if (str)
+ (void) fprintf(stderr, "%s\n", str);
+ (void) dest_tkt();
+ exit(x);
+}
+
+static void
+safe_read_stdin(char *prompt, char *buf, int size)
+{
+ (void) printf(prompt);
+ (void) fflush(stdout);
+ (void) bzero(buf, size);
+ if (read(0, buf, size - 1) < 0) {
+ (void) fprintf(stderr, "Failure reading from stdin: %s\n",
+ strerror(errno));
+ leave((char *)NULL, 1);
+ }
+ fflush(stdin);
+ buf[strlen(buf)-1] = 0;
+}
+
+
+static void
+safe_write(char *progname, char *filename, int fd, char *buf, int len)
+{
+ if (write(fd, buf, len) != len) {
+ (void) fprintf(stderr, "%s: Failure writing to %s: %s\n", progname,
+ filename, strerror(errno));
+ (void) close(fd);
+ leave("In progress srvtab in this file.", 1);
+ }
+}
+
+static int
+yn(char *string)
+{
+ char ynbuf[5];
+
+ (void) printf("%s (y,n) [y] ", string);
+ for (;;) {
+ safe_read_stdin("", ynbuf, sizeof(ynbuf));
+
+ if ((ynbuf[0] == 'n') || (ynbuf[0] == 'N'))
+ return(0);
+ else if ((ynbuf[0] == 'y') || (ynbuf[0] == 'Y') || (ynbuf[0] == 0))
+ return(1);
+ else {
+ (void) printf("Please enter 'y' or 'n': ");
+ fflush(stdout);
+ }
+ }
+}
+
+static void
+append_srvtab(char *progname, char *filename, int fd, char *sname, char *sinst, char *srealm, unsigned char key_vno, unsigned char *key)
+{
+ /* Add one to append null */
+ safe_write(progname, filename, fd, sname, strlen(sname) + 1);
+ safe_write(progname, filename, fd, sinst, strlen(sinst) + 1);
+ safe_write(progname, filename, fd, srealm, strlen(srealm) + 1);
+ safe_write(progname, filename, fd, (char *)&key_vno, 1);
+ safe_write(progname, filename, fd, (char *)key, sizeof(des_cblock));
+ (void) fsync(fd);
+}
+
+static void
+print_key(unsigned char *key)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ (void) printf("%02x", key[i]);
+ (void) printf(" ");
+ for (i = 4; i < 8; i++)
+ (void) printf("%02x", key[i]);
+}
+
+static void
+print_name(char *name, char *inst, char *realm)
+{
+ (void) printf("%s%s%s%s%s", name, inst[0] ? "." : "", inst,
+ realm[0] ? "@" : "", realm);
+}
+
+static int
+get_svc_new_key(unsigned char *new_key, char *sname, char *sinst, char *srealm, char *keyfile)
+{
+ int status = KADM_SUCCESS;
+
+ if (((status = krb_get_svc_in_tkt(sname, sinst, srealm, PWSERV_NAME,
+ KADM_SINST, 1, keyfile)) == KSUCCESS) &&
+ ((status = kadm_init_link("changepw", KRB_MASTER, srealm)) ==
+ KADM_SUCCESS)) {
+#ifdef NOENCRYPTION
+ (void) bzero((char *) new_key, sizeof(des_cblock));
+ new_key[0] = (unsigned char) 1;
+#else /* NOENCRYPTION */
+ (void) des_new_random_key((des_cblock*)&new_key);
+#endif /* NOENCRYPTION */
+ return(KADM_SUCCESS);
+ }
+
+ return(status);
+}
+
+static void
+get_key_from_password(des_cblock (*key))
+{
+ char password[MAX_KPW_LEN]; /* storage for the password */
+
+ if (read_long_pw_string(password, sizeof(password)-1, "Password: ", 1))
+ leave("Error reading password.", 1);
+
+#ifdef NOENCRYPTION
+ (void) bzero((char *) key, sizeof(des_cblock));
+ key[0] = (unsigned char) 1;
+#else /* NOENCRYPTION */
+ (void) des_string_to_key(password, key);
+#endif /* NOENCRYPTION */
+ (void) bzero((char *)password, sizeof(password));
+}
+
+static void
+usage(void)
+{
+ (void) fprintf(stderr, "Usage: ksrvutil [-f keyfile] [-i] [-k] ");
+ (void) fprintf(stderr, "{list | change | add | get}\n");
+ (void) fprintf(stderr, " -i causes the program to ask for ");
+ (void) fprintf(stderr, "confirmation before changing keys.\n");
+ (void) fprintf(stderr, " -k causes the key to printed for list or ");
+ (void) fprintf(stderr, "change.\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ char sname[ANAME_SZ]; /* name of service */
+ char sinst[INST_SZ]; /* instance of service */
+ char srealm[REALM_SZ]; /* realm of service */
+ unsigned char key_vno; /* key version number */
+ int status; /* general purpose error status */
+ des_cblock new_key;
+ des_cblock old_key;
+ char change_tkt[MAXPATHLEN]; /* Ticket to use for key change */
+ char keyfile[MAXPATHLEN]; /* Original keyfile */
+ char work_keyfile[MAXPATHLEN]; /* Working copy of keyfile */
+ char backup_keyfile[MAXPATHLEN]; /* Backup copy of keyfile */
+ unsigned short keyfile_mode; /* Protections on keyfile */
+ int work_keyfile_fd = -1; /* Initialize so that */
+ int backup_keyfile_fd = -1; /* compiler doesn't complain */
+ char local_realm[REALM_SZ]; /* local kerberos realm */
+ int i;
+ int interactive = FALSE;
+ int list = FALSE;
+ int change = FALSE;
+ int add = FALSE;
+ int get = FALSE;
+ int key = FALSE; /* do we show keys? */
+ int arg_entered = FALSE;
+ int change_this_key = FALSE;
+ char databuf[BUFSIZ];
+ int first_printed = FALSE; /* have we printed the first item? */
+
+ (void) bzero((char *)sname, sizeof(sname));
+ (void) bzero((char *)sinst, sizeof(sinst));
+ (void) bzero((char *)srealm, sizeof(srealm));
+
+ (void) bzero((char *)change_tkt, sizeof(change_tkt));
+ (void) bzero((char *)keyfile, sizeof(keyfile));
+ (void) bzero((char *)work_keyfile, sizeof(work_keyfile));
+ (void) bzero((char *)backup_keyfile, sizeof(backup_keyfile));
+ (void) bzero((char *)local_realm, sizeof(local_realm));
+
+ (void) sprintf(change_tkt, "/tmp/tkt_ksrvutil.%d", (int)getpid());
+ krb_set_tkt_string(change_tkt);
+
+ /* This is used only as a default for adding keys */
+ if (krb_get_lrealm(local_realm, 1) != KSUCCESS)
+ (void) strcpy(local_realm, KRB_REALM);
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-i") == 0)
+ interactive++;
+ else if (strcmp(argv[i], "-k") == 0)
+ key++;
+ else if (strcmp(argv[i], "list") == 0) {
+ if (arg_entered)
+ usage();
+ else {
+ arg_entered++;
+ list++;
+ }
+ }
+ else if (strcmp(argv[i], "change") == 0) {
+ if (arg_entered)
+ usage();
+ else {
+ arg_entered++;
+ change++;
+ }
+ }
+ else if (strcmp(argv[i], "add") == 0) {
+ if (arg_entered)
+ usage();
+ else {
+ arg_entered++;
+ add++;
+ }
+ }
+ else if (strcmp(argv[i], "get") == 0) {
+ if (arg_entered)
+ usage();
+ else {
+ arg_entered++;
+ get++;
+ }
+ }
+ else if (strcmp(argv[i], "-f") == 0) {
+ if (++i == argc)
+ usage();
+ else
+ (void) strcpy(keyfile, argv[i]);
+ }
+ else
+ usage();
+ }
+
+ if (!arg_entered)
+ usage();
+
+ if (!keyfile[0])
+ (void) strcpy(keyfile, KEYFILE);
+
+ (void) strcpy(work_keyfile, keyfile);
+ (void) strcpy(backup_keyfile, keyfile);
+
+ if (change || add || get) {
+ (void) strcat(work_keyfile, ".work");
+ (void) strcat(backup_keyfile, ".old");
+
+ copy_keyfile(argv[0], keyfile, backup_keyfile);
+ }
+
+ if (add || get)
+ copy_keyfile(argv[0], backup_keyfile, work_keyfile);
+
+ keyfile_mode = get_mode(keyfile);
+
+ if (change || list) {
+ if ((backup_keyfile_fd = open(backup_keyfile, O_RDONLY, 0)) < 0) {
+ (void) fprintf(stderr, "%s: Unable to read %s: %s\n", argv[0],
+ backup_keyfile, strerror(errno));
+ exit(1);
+ }
+ }
+
+ if (change) {
+ if ((work_keyfile_fd =
+ open(work_keyfile, O_WRONLY | O_CREAT | O_TRUNC,
+ SRVTAB_MODE)) < 0) {
+ (void) fprintf(stderr, "%s: Unable to write %s: %s\n", argv[0],
+ work_keyfile, strerror(errno));
+ exit(1);
+ }
+ }
+ else if (add || get) {
+ if ((work_keyfile_fd =
+ open(work_keyfile, O_APPEND | O_WRONLY, SRVTAB_MODE)) < 0) {
+ (void) fprintf(stderr, "%s: Unable to open %s for append: %s\n",
+ argv[0], work_keyfile, strerror(errno));
+ exit(1);
+ }
+ }
+
+ if (change || list) {
+ while ((getst(backup_keyfile_fd, sname, SNAME_SZ) > 0) &&
+ (getst(backup_keyfile_fd, sinst, INST_SZ) > 0) &&
+ (getst(backup_keyfile_fd, srealm, REALM_SZ) > 0) &&
+ (read(backup_keyfile_fd, &key_vno, 1) > 0) &&
+ (read(backup_keyfile_fd,(char *)old_key,sizeof(old_key)) > 0)) {
+ if (list) {
+ if (!first_printed) {
+ (void) printf(VNO_HEADER);
+ (void) printf(PAD);
+ if (key) {
+ (void) printf(KEY_HEADER);
+ (void) printf(PAD);
+ }
+ (void) printf(PRINC_HEADER);
+ first_printed = 1;
+ }
+ (void) printf(VNO_FORMAT, key_vno);
+ (void) printf(PAD);
+ if (key) {
+ print_key(old_key);
+ (void) printf(PAD);
+ }
+ print_name(sname, sinst, srealm);
+ (void) printf("\n");
+ }
+ else if (change) {
+ (void) printf("\nPrincipal: ");
+ print_name(sname, sinst, srealm);
+ (void) printf("; version %d\n", key_vno);
+ if (interactive)
+ change_this_key = yn("Change this key?");
+ else if (change)
+ change_this_key = 1;
+ else
+ change_this_key = 0;
+
+ if (change_this_key)
+ (void) printf("Changing to version %d.\n", key_vno + 1);
+ else if (change)
+ (void) printf("Not changing this key.\n");
+
+ if (change_this_key) {
+ /* Initialize non shared random sequence old key. */
+ des_init_random_number_generator(&old_key);
+
+ /*
+ * Pick a new key and determine whether or not
+ * it is safe to change
+ */
+ if ((status =
+ get_svc_new_key(new_key, sname, sinst,
+ srealm, keyfile)) == KADM_SUCCESS)
+ key_vno++;
+ else {
+ (void) bcopy(old_key, new_key, sizeof(new_key));
+ (void) fprintf(stderr, "%s: Key NOT changed: %s\n",
+ argv[0], krb_err_txt[status]);
+ change_this_key = FALSE;
+ }
+ }
+ else
+ (void) bcopy(old_key, new_key, sizeof(new_key));
+ append_srvtab(argv[0], work_keyfile, work_keyfile_fd,
+ sname, sinst, srealm, key_vno, new_key);
+ if (key && change_this_key) {
+ (void) printf("Old key: ");
+ print_key(old_key);
+ (void) printf("; new key: ");
+ print_key(new_key);
+ (void) printf("\n");
+ }
+ if (change_this_key) {
+ if ((status = kadm_change_pw(new_key)) == KADM_SUCCESS) {
+ (void) printf("Key changed.\n");
+ (void) dest_tkt();
+ }
+ else {
+ com_err(argv[0], status,
+ " attempting to change password.");
+ (void) dest_tkt();
+ /* XXX This knows the format of a keyfile */
+ if (lseek(work_keyfile_fd, -9, SEEK_CUR) >= 0) {
+ key_vno--;
+ safe_write(argv[0], work_keyfile,
+ work_keyfile_fd, (char *)&key_vno, 1);
+ safe_write(argv[0], work_keyfile, work_keyfile_fd,
+ (char *)old_key, sizeof(des_cblock));
+ (void) fsync(work_keyfile_fd);
+ (void) fprintf(stderr,"Key NOT changed.\n");
+ }
+ else {
+ (void)fprintf(stderr,
+ "%s: Unable to revert keyfile: %s\n",
+ argv[0], strerror(errno));
+ leave("", 1);
+ }
+ }
+ }
+ }
+ bzero((char *)old_key, sizeof(des_cblock));
+ bzero((char *)new_key, sizeof(des_cblock));
+ }
+ }
+ else if (add) {
+ do {
+ do {
+ safe_read_stdin("Name: ", databuf, sizeof(databuf));
+ (void) strncpy(sname, databuf, sizeof(sname) - 1);
+ safe_read_stdin("Instance: ", databuf, sizeof(databuf));
+ (void) strncpy(sinst, databuf, sizeof(sinst) - 1);
+ safe_read_stdin("Realm: ", databuf, sizeof(databuf));
+ (void) strncpy(srealm, databuf, sizeof(srealm) - 1);
+ safe_read_stdin("Version number: ", databuf, sizeof(databuf));
+ key_vno = atoi(databuf);
+ if (!srealm[0])
+ (void) strcpy(srealm, local_realm);
+ (void) printf("New principal: ");
+ print_name(sname, sinst, srealm);
+ (void) printf("; version %d\n", key_vno);
+ } while (!yn("Is this correct?"));
+ get_key_from_password(&new_key);
+ if (key) {
+ (void) printf("Key: ");
+ print_key(new_key);
+ (void) printf("\n");
+ }
+ append_srvtab(argv[0], work_keyfile, work_keyfile_fd,
+ sname, sinst, srealm, key_vno, new_key);
+ (void) printf("Key successfully added.\n");
+ } while (yn("Would you like to add another key?"));
+ }
+ else if (get) {
+ ksrvutil_get();
+ }
+
+ if (change || list)
+ if (close(backup_keyfile_fd) < 0) {
+ (void) fprintf(stderr, "%s: Failure closing %s: %s\n",
+ argv[0], backup_keyfile, strerror(errno));
+ (void) fprintf(stderr, "continuing...\n");
+ }
+
+ if (change || add || get) {
+ if (close(work_keyfile_fd) < 0) {
+ (void) fprintf(stderr, "%s: Failure closing %s: %s\n",
+ argv[0], work_keyfile, strerror(errno));
+ exit(1);
+ }
+ if (rename(work_keyfile, keyfile) < 0) {
+ (void) fprintf(stderr, "%s: Failure renaming %s to %s: %s\n",
+ argv[0], work_keyfile, keyfile,
+ strerror(errno));
+ exit(1);
+ }
+ (void) chmod(backup_keyfile, keyfile_mode);
+ (void) chmod(keyfile, keyfile_mode);
+ (void) printf("Old keyfile in %s.\n", backup_keyfile);
+ }
+
+ exit(0);
+}
+
+ksrvutil_get()
+{
+ char sname[ANAME_SZ]; /* name of service */
+ char sinst[INST_SZ]; /* instance of service */
+ char srealm[REALM_SZ]; /* realm of service */
+ char databuf[BUFSIZ];
+ char local_realm[REALM_SZ]; /* local kerberos realm */
+ char local_hostname[100];
+
+ if (krb_get_lrealm(local_realm, 1) != KSUCCESS)
+ strcpy(local_realm, KRB_REALM);
+ gethostname(local_hostname, sizeof(local_hostname));
+ strcpy(local_hostname, krb_get_phost(local_hostname));
+ do {
+ do {
+ safe_read_stdin("Name [rcmd]: ", databuf, sizeof(databuf));
+ if (databuf[0])
+ strncpy(sname, databuf, sizeof(sname) - 1);
+ else
+ strcpy(sname, "rcmd");
+
+ safe_read_stdin("Instance [hostname]: ", databuf, sizeof(databuf));
+ if (databuf[0])
+ strncpy(sinst, databuf, sizeof(sinst) - 1);
+ else
+ strcpy(sinst, local_hostname);
+
+ safe_read_stdin("Realm [localrealm]: ", databuf, sizeof(databuf));
+ if (databuf[0])
+ strncpy(srealm, databuf, sizeof(srealm) - 1);
+ else
+ strcpy(srealm, local_realm);
+
+ printf("New principal: ");
+ print_name(sname, sinst, srealm);
+ } while (!yn("Is this correct?"));
+ printf("NOT adding anything!!! Key successfully added.\n");
+ } while (yn("Would you like to add another key?"));
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:41 tholo Exp $
+
+PROG= kstash
+DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES}
+LDADD= -lkdb -lkrb -ldes
+MAN= kstash.8
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: kstash.8,v 1.1.1.1 1995/12/14 06:52:41 tholo Exp $
+.TH KSTASH 8 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kstash \- stash Kerberos key distribution center database master key
+.SH SYNOPSIS
+kstash
+.SH DESCRIPTION
+.I kstash
+saves the Kerberos key distribution center (KDC) database master key in
+the master key cache file.
+.PP
+The user is prompted to enter the key, to verify the authenticity of the
+key and the authorization to store the key in the file.
+.SH DIAGNOSTICS
+.TP 20n
+"verify_master_key: Invalid master key, does not match database."
+The master key string entered was incorrect.
+.TP
+"kstash: Unable to open master key file"
+The attempt to open the cache file for writing failed (probably due to a
+system or access permission error).
+.TP
+"kstash: Write I/O error on master key file"
+The
+.BR write (2)
+system call returned an error while
+.I kstash
+was attempting to write the key to the file.
+.SH FILES
+.TP 20n
+/kerberos/principal.pag, /kerberos/principal.dir
+DBM files containing database
+.TP
+/.k
+Master key cache file.
--- /dev/null
+/* $Id: kstash.c,v 1.1.1.1 1995/12/14 06:52:41 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <adm_locl.h>
+
+/* change this later, but krblib_dbm needs it for now */
+char *progname;
+
+static des_cblock master_key;
+static des_key_schedule master_key_schedule;
+static int kfile;
+
+static void
+clear_secrets(void)
+{
+ bzero(master_key_schedule, sizeof(master_key_schedule));
+ bzero(master_key, sizeof(master_key));
+}
+
+int
+main(int argc, char **argv)
+{
+ long n;
+ if ((n = kerb_init())) {
+ fprintf(stderr, "Kerberos db and cache init failed = %ld\n", n);
+ exit(1);
+ }
+
+ if (kdb_get_master_key (TRUE, &master_key, master_key_schedule) != 0) {
+ fprintf (stderr, "%s: Couldn't read master key.\n", argv[0]);
+ fflush (stderr);
+ clear_secrets();
+ exit (-1);
+ }
+
+ if (kdb_verify_master_key (&master_key, master_key_schedule, stderr) < 0) {
+ clear_secrets();
+ exit (-1);
+ }
+
+ kfile = open(MKEYFILE, O_TRUNC | O_RDWR | O_CREAT, 0600);
+ if (kfile < 0) {
+ clear_secrets();
+ fprintf(stderr, "\n\07\07%s: Unable to open master key file\n",
+ argv[0]);
+ exit(1);
+ }
+ if (write(kfile, (char *) master_key, 8) < 0) {
+ clear_secrets();
+ fprintf(stderr, "\n%s: Write I/O error on master key file\n",
+ argv[0]);
+ exit(1);
+ }
+ (void) close(kfile);
+ clear_secrets();
+ exit(0);
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:53 tholo Exp $
+
+PROG= make_keypair
+MAN= make_keypair.8
+CFLAGS+=-DKERBEROS -I${.CURDIR}/../register
+DPADD= ${LIBKRB} ${LIBDES}
+LDADD= -lkdb -lkrb -ldes
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright (c) 1988, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from @(#)make_keypair.8 8.2 (Berkeley) 12/11/93
+.\" $Id: make_keypair.8,v 1.1.1.1 1995/12/14 06:52:53 tholo Exp $
+.\"
+.Dd December 11, 1993
+.Dt MAKE_KEYPAIR 8
+.Os
+.Sh NAME
+.Nm make_keypair
+.Nd generate Kerberos host key pair
+.Sh SYNOPSIS
+.Nm make_keypair
+.Ar hostname
+.Op Ar hostname ...
+.Sh DESCRIPTION
+The
+.Nm make_keypair
+command
+is used to create pairs of
+.Tn DES
+keys for
+each
+.Ar hostname .
+The keys are used by privileged programs such as
+.Xr register 1
+to make remote updates to the Kerberos database without
+having to have first acquired a Kerberos ticket granting ticket
+.Pq Tn TGT .
+The keys created by
+.Nm make_keypair
+are placed (by hand) in the filesystems of the
+kerberos server in
+.Pa /etc/kerberosIV/register_keys ,
+and in the root directory of the clients.
+For example, the file
+.Pa /.update.key128.32.130.3
+would
+contain a copy of the key of the client with
+IP address 128.32.130.3.
+These keys provide a shared secret which may be used to establish
+a secure channel between the client hosts and the Kerberos server.
+.Sh FILES
+.Bl -tag -width /etc/kerberosIV/register_keysxx -compact
+.It Pa /.update.keyxx.xx.xx.xx
+shared
+.Tn DES
+key with server
+.It Pa /etc/kerberosIV/register_keys
+server's key storage directory
+.El
+.Sh SEE ALSO
+.Xr register 1 ,
+.Xr registerd 8 ,
+.Xr kerberos 1
+.Sh HISTORY
+The
+.Nm make_keypair
+utility first appeared in 4.4BSD.
--- /dev/null
+/* $Id: make_keypair.c,v 1.1.1.1 1995/12/14 06:52:53 tholo Exp $ */
+
+/*-
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)make_keypair.c 8.1 (Berkeley) 6/1/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <strings.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include "pathnames.h"
+#include "register_proto.h"
+
+extern void herror();
+void make_key(), usage();
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct hostent *hp;
+ char *addr;
+ int i;
+ struct sockaddr_in sin;
+
+ if (argc != 2) {
+ usage(argv[0]);
+ exit(1);
+ }
+
+ if ((hp = gethostbyname(argv[1])) == NULL) {
+ herror(argv[1]);
+ exit(1);
+ }
+
+ for (i = 0; addr = hp->h_addr_list[i]; i++) {
+ addr = hp->h_addr_list[i];
+ bcopy(addr, &sin.sin_addr, hp->h_length);
+
+ printf("Making key for host %s (%s)\n",
+ argv[1], inet_ntoa(sin.sin_addr));
+ make_key(sin.sin_addr);
+ }
+ printf("==========\n");
+ printf("One copy of the each key should be put in %s on the\n",
+ SERVER_KEYDIR);
+ printf("Kerberos server machine (mode 600, owner root).\n");
+ printf("Another copy of each key should be put on the named\n");
+ printf("client as %sXXX.XXX.XXX.XXX (same modes as above),\n",
+ CLIENT_KEYFILE);
+ printf("where the X's refer to digits of the host's inet address.\n");
+ (void)fflush(stdout);
+ exit(0);
+}
+
+void
+make_key(addr)
+ struct in_addr addr;
+{
+ struct keyfile_data kfile;
+ char namebuf[255];
+ int fd;
+
+ (void)sprintf(namebuf, ".%s%s",
+ CLIENT_KEYFILE,
+ inet_ntoa(addr));
+ fd = open(namebuf, O_WRONLY|O_CREAT, 0600);
+ if (fd < 0) {
+ perror("open");
+ exit(1);
+ }
+ random_key(kfile.kf_key);
+ printf("writing to file -> %s ...", namebuf);
+ if (write(fd, &kfile, sizeof(kfile)) != sizeof(kfile)) {
+ fprintf(stderr, "error writing file %s\n", namebuf);
+ }
+ printf("done.\n");
+ (void)close(fd);
+ return;
+}
+
+void
+usage(name)
+ char *name;
+{
+ fprintf(stderr, "usage: %s host\n", name);
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:35 tholo Exp $
+
+MAN= kerberos.1 krb.conf.5 krb.equiv.5 krb.realms.5
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: kerberos.1,v 1.1.1.1 1995/12/14 06:52:35 tholo Exp $
+.TH KERBEROS 1 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+kerberos \- introduction to the Kerberos system
+
+.SH DESCRIPTION
+The
+Kerberos
+system authenticates
+individual users in a network environment.
+After authenticating yourself to
+Kerberos,
+you can use network utilities such as
+.IR rlogin ,
+.IR rcp ,
+and
+.IR rsh
+without
+having to present passwords to remote hosts and without having to bother
+with
+.I \.rhosts
+files.
+Note that these utilities will work without passwords only if
+the remote machines you deal with
+support the
+Kerberos
+system.
+All Athena timesharing machines and public workstations support
+Kerberos.
+.PP
+Before you can use
+Kerberos,
+you must register as an Athena user,
+and you must make sure you have been added to
+the
+Kerberos
+database.
+You can use the
+.I kinit
+command to find out.
+This command
+tries to log you into the
+Kerberos
+system.
+.I kinit
+will prompt you for a username and password.
+Enter your username and password.
+If the utility lets you login without giving you a message,
+you have already been registered.
+.PP
+If you enter your username and
+.I kinit
+responds with this message:
+.nf
+
+Principal unknown (kerberos)
+
+.fi
+you haven't been registered as a
+Kerberos
+user.
+See your system administrator.
+.PP
+A Kerberos name contains three parts.
+The first is the
+.I principal name,
+which is usually a user's or service's name.
+The second is the
+.I instance,
+which in the case of a user is usually null.
+Some users may have privileged instances, however,
+such as ``root'' or ``admin''.
+In the case of a service, the instance is the
+name of the machine on which it runs; i.e. there
+can be an
+.I rlogin
+service running on the machine ABC, which
+is different from the rlogin service running on
+the machine XYZ.
+The third part of a Kerberos name
+is the
+.I realm.
+The realm corresponds to the Kerberos service providing
+authentication for the principal.
+For example, at MIT there is a Kerberos running at the
+Laboratory for Computer Science and one running at
+Project Athena.
+.PP
+When writing a Kerberos name, the principal name is
+separated from the instance (if not null) by a period,
+and the realm (if not the local realm) follows, preceded by
+an ``@'' sign.
+The following are examples of valid Kerberos names:
+.sp
+.nf
+.in +8
+billb
+jis.admin
+srz@lcs.mit.edu
+treese.root@athena.mit.edu
+.in -8
+.fi
+.PP
+When you authenticate yourself with
+Kerberos,
+through either the workstation
+.I toehold
+system or the
+.I kinit
+command,
+Kerberos
+gives you an initial
+Kerberos
+.IR ticket .
+(A
+Kerberos
+ticket
+is an encrypted protocol message that provides authentication.)
+Kerberos
+uses this ticket for network utilities
+such as
+.I rlogin
+and
+.IR rcp .
+The ticket transactions are done transparently,
+so you don't have to worry about their management.
+.PP
+Note, however, that tickets expire.
+Privileged tickets, such as root instance tickets,
+expire in a few minutes, while tickets that carry more ordinary
+privileges may be good for several hours or a day, depending on the
+installation's policy.
+If your login session extends beyond the time limit,
+you will have to re-authenticate yourself to
+Kerberos
+to get new tickets.
+Use the
+.IR kinit
+command to re-authenticate yourself.
+.PP
+If you use the
+.I kinit
+command to get your tickets,
+make sure you use the
+.I kdestroy
+command
+to destroy your tickets before you end your login session.
+You should probably put the
+.I kdestroy
+command in your
+.I \.logout
+file so that your tickets will be destroyed automatically when you logout.
+For more information about the
+.I kinit
+and
+.I kdestroy
+commands,
+see the
+.I kinit(1)
+and
+.I kdestroy(1)
+manual pages.
+.PP
+Currently,
+Kerberos
+supports the following network services:
+.IR rlogin ,
+.IR rsh ,
+and
+.IR rcp .
+Other services are being worked on,
+such as the
+.IR pop
+mail system and NFS (network file system),
+but are not yet available.
+
+.SH "SEE ALSO"
+kdestroy(1), kinit(1), klist(1), kpasswd(1), des_crypt(3), kerberos(3),
+kadmin(8)
+.SH BUGS
+Kerberos
+will not do authentication forwarding.
+In other words,
+if you use
+.I rlogin
+to login to a remote host,
+you cannot use
+Kerberos
+services from that host
+until you authenticate yourself explicitly on that host.
+Although you may need to authenticate yourself on the remote
+host,
+be aware that when you do so,
+.I rlogin
+sends your password across the network in clear text.
+
+.SH AUTHORS
+Steve Miller, MIT Project Athena/Digital Equipment Corporation
+.br
+Clifford Neuman, MIT Project Athena
+
+The following people helped out on various aspects of the system:
+
+Jeff Schiller designed and wrote the administration server and its
+user interface, kadmin.
+He also wrote the dbm version of the database management system.
+
+Mark Colan developed the
+Kerberos
+versions of
+.IR rlogin ,
+.IR rsh ,
+and
+.IR rcp ,
+as well as contributing work on the servers.
+
+John Ostlund developed the
+Kerberos
+versions of
+.I passwd
+and
+.IR userreg .
+
+Stan Zanarotti pioneered Kerberos in a foreign realm (LCS),
+and made many contributions based on that experience.
+
+Many people contributed code and/or useful ideas, including
+Jim Aspnes,
+Bob Baldwin,
+John Barba,
+Richard Basch,
+Jim Bloom,
+Bill Bryant,
+Rob French,
+Dan Geer,
+David Jedlinsky,
+John Kohl,
+John Kubiatowicz,
+Bob McKie,
+Brian Murphy,
+Ken Raeburn,
+Chris Reed,
+Jon Rochlis,
+Mike Shanzer,
+Bill Sommerfeld,
+Jennifer Steiner,
+Ted Ts'o,
+and
+Win Treese.
+
+.SH RESTRICTIONS
+
+COPYRIGHT 1985,1986 Massachusetts Institute of Technology
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: krb.conf.5,v 1.1.1.1 1995/12/14 06:52:35 tholo Exp $
+.TH KRB.CONF 5 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+/etc/kerberosIV/krb.conf \- Kerberos configuration file
+.SH DESCRIPTION
+.I krb.conf
+contains configuration information describing the Kerberos realm and the
+Kerberos key distribution center (KDC) servers for known realms.
+.PP
+.I krb.conf
+contains the name of the local realm in the first
+line, followed by lines indicating realm/host
+entries. The first token is a realm name, and the second is the hostname
+of a host running a KDC for that realm.
+The words "admin server" following the hostname indicate that
+the host also provides an administrative database server.
+For example:
+.nf
+.in +1i
+ATHENA.MIT.EDU
+ATHENA.MIT.EDU kerberos-1.mit.edu admin server
+ATHENA.MIT.EDU kerberos-2.mit.edu
+LCS.MIT.EDU kerberos.lcs.mit.edu admin server
+.in -1i
+.SH SEE ALSO
+krb.realms(5), krb_get_krbhst(3), krb_get_lrealm(3)
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: krb.equiv.5,v 1.1.1.1 1995/12/14 06:52:35 tholo Exp $
+.TH KRB.EQUIV 5 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+/etc/kerberosIV/krb.equiv \- Kerberos equivalent hosts file
+.SH DESCRIPTION
+.I krb.equiv
+contains a list of IP address pairs that is to be considered being
+the same host for Kerberos purposes.
+.PP
+.I krb.equiv
+contains one pair of IP addresses per line.
+For example:
+.nf
+.in +1i
+130.237.223.3 192.16.126.3 # alv alv1
+130.237.223.4 192.16.126.4 # byse byse1
+130.237.228.152 192.16.126.9 # topsy topsy1
+.in -1i
+.SH SEE ALSO
+krb.conf(5), krb.realms(5), krb_equiv(3)
--- /dev/null
+.\" Copyright 1989 by the Massachusetts Institute of Technology.
+.\"
+.\" For copying and distribution information,
+.\" please see the file <mit-copyright.h>.
+.\"
+.\" $Id: krb.realms.5,v 1.1.1.1 1995/12/14 06:52:35 tholo Exp $
+.TH KRB.REALMS 5 "Kerberos Version 4.0" "MIT Project Athena"
+.SH NAME
+/etc/kerberosIV/krb.realms \- host to Kerberos realm translation file
+.SH DESCRIPTION
+.I krb.realms
+provides a translation from a hostname to the Kerberos realm name for
+the services provided by that host.
+.PP
+Each line of the translation file is in one of the following forms
+(domain_name should be of the form .XXX.YYY, e.g. .LCS.MIT.EDU):
+.nf
+.in +5n
+host_name kerberos_realm
+domain_name kerberos_realm
+.in -5n
+.fi
+If a hostname exactly matches the
+.I host_name
+field in a line of the first
+form, the corresponding realm is the realm of the host.
+If a hostname does not match any
+.I host_name
+in the file, but its
+domain exactly matches the
+.I domain_name
+field in a line of the second
+form, the corresponding realm is the realm of the host.
+.PP
+If no translation entry applies, the host's realm is considered to be
+the hostname's domain portion converted to upper case.
+.SH SEE ALSO
+krb_realmofhost(3)
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $
+
+PROG= mk_cmds
+SRCS= mk_cmds.c options.c utils.c ct.c cmd_tbl.c
+CFLAGS+=-I. -I${.CURDIR}/../ss
+LFLAGS= -l
+LDADD+= -ll
+DPADD+= ${LIBL}
+CLEANFILES+= y.tab.c y.tab.h lex.yy.c cmd_tbl.c ct.c
+BINDIR= /usr/bin
+NOMAN= noman
+
+# don't install -- only needed during build of kerberos (so far)
+install:
+
+.include <bsd.prog.mk>
--- /dev/null
+%{
+/* $Id: cmd_tbl.l,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+%}
+
+N [0-9]
+PC [^\"]
+AN [A-Z_a-z0-9]
+
+%{
+unsigned lineno = 1;
+
+static l_command_table(), l_request(), l_unimplemented(), l_end(),
+ l_quoted_string(), l_string();
+%}
+
+%%
+
+%{
+/* emptied */
+%}
+
+command_table return l_command_table();
+request return l_request();
+unimplemented return l_unimplemented();
+end return l_end();
+
+[\t ] ;
+
+\n ++lineno;
+
+\"{PC}*\" return l_quoted_string();
+
+{AN}* return l_string();
+
+#.*\n ++lineno;
+
+. return (*yytext);
+
+%%
+
+/*
+ * User-subroutines section.
+ *
+ * Have to put all this stuff here so that the include file
+ * from YACC output can be included, since LEX doesn't allow
+ * an include file before the code it generates for the above
+ * rules.
+ */
+
+#include <string.h>
+#include "y.tab.h"
+/* #include "copyright.h" */
+
+extern char *last_token, *ds();
+
+static l_command_table()
+{
+ last_token = "command_table";
+ return COMMAND_TABLE;
+}
+
+static l_request()
+{
+ last_token = "request";
+ return REQUEST;
+}
+
+static l_unimplemented()
+{
+ last_token = "unimplemented";
+ return UNIMPLEMENTED;
+}
+
+static l_end()
+{
+ last_token = "end";
+ return END;
+}
+
+static l_quoted_string()
+{
+ register char *p;
+ yylval.dynstr = ds(yytext+1);
+ if (p=strrchr(yylval.dynstr, '"'))
+ *p='\0';
+ last_token = ds(yylval.dynstr);
+ return STRING;
+}
+
+static l_string()
+{
+ yylval.dynstr = ds(yytext);
+ last_token = ds(yylval.dynstr);
+ return STRING;
+}
--- /dev/null
+%{
+/* $Id: ct.y,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+char *str_concat3(), *ds(), *generate_rqte(), *quote();
+long flag_value();
+char *last_token = (char *)NULL;
+FILE *output_file;
+long gensym_n = 0;
+%}
+
+%union {
+ char *dynstr;
+ long flags;
+}
+
+%token COMMAND_TABLE REQUEST UNKNOWN UNIMPLEMENTED END
+%token <dynstr> STRING
+%token <dynstr> FLAGNAME
+%type <dynstr> namelist header request_list
+%type <dynstr> request_entry
+%type <flags> flag_list options
+%left OPTIONS
+%{
+#define NO_SS_ERR_H
+#include <ss/ss.h>
+%}
+%start command_table
+%%
+command_table : header request_list END ';'
+ { write_ct($1, $2); }
+ ;
+
+header : COMMAND_TABLE STRING ';'
+ { $$ = $2; }
+ ;
+
+request_list : request_list request_entry
+ { $$ = str_concat3($1, $2, ""); }
+ |
+ { $$ = ""; }
+ ;
+
+request_entry : REQUEST STRING ',' STRING ',' namelist ',' options ';'
+ { $$ = generate_rqte($2, quote($4), $6, $8); }
+ | REQUEST STRING ',' STRING ',' namelist ';'
+ { $$ = generate_rqte($2, quote($4), $6, 0); }
+ | UNKNOWN namelist ';'
+ { $$ = generate_rqte("ss_unknown_request",
+ (char *)NULL, $2, 0); }
+ | UNIMPLEMENTED STRING ',' STRING ',' namelist ';'
+ { $$ = generate_rqte("ss_unimplemented", quote($4), $6, 3); }
+ ;
+
+options : '(' flag_list ')'
+ { $$ = $2; }
+ | '(' ')'
+ { $$ = 0; }
+ ;
+
+flag_list : flag_list ',' STRING
+ { $$ = $1 | flag_val($3); }
+ | STRING
+ { $$ = flag_val($1); }
+ ;
+
+namelist: STRING
+ { $$ = quote(ds($1)); }
+ | namelist ',' STRING
+ { $$ = str_concat3($1, quote($3), ",\n "); }
+ ;
+
+%%
--- /dev/null
+/* $Id: mk_cmds.c,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#ifndef NPOSIX
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include "mk_cmds_defs.h"
+
+static const char copyright[] =
+ "Copyright 1987 by MIT Student Information Processing Board";
+
+extern pointer malloc PROTOTYPE((unsigned));
+extern char *last_token;
+extern FILE *output_file;
+
+extern FILE *yyin, *yyout;
+extern unsigned lineno;
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char c_file[MAXPATHLEN];
+ int result;
+ char *path, *p;
+
+ if (argc != 2) {
+ fputs("Usage: ", stderr);
+ fputs(argv[0], stderr);
+ fputs("cmdtbl.ct\n", stderr);
+ exit(1);
+ }
+
+ path = malloc(strlen(argv[1])+4); /* extra space to add ".ct" */
+ strcpy(path, argv[1]);
+ p = strrchr(path, '/');
+ if (p == (char *)NULL)
+ p = path;
+ else
+ p++;
+ p = strrchr(p, '.');
+ if (p == (char *)NULL || strcmp(p, ".ct"))
+ strcat(path, ".ct");
+ yyin = fopen(path, "r");
+ if (!yyin) {
+ perror(path);
+ exit(1);
+ }
+
+ p = strrchr(path, '.');
+ *p = '\0';
+ strcpy(c_file, path);
+ strcat(c_file, ".c");
+ *p = '.';
+
+ output_file = fopen(c_file, "w+");
+ if (!output_file) {
+ perror(c_file);
+ exit(1);
+ }
+
+ fputs("/* ", output_file); /* emacs fix -> */
+ fputs(c_file, output_file);
+ fputs(" - automatically generated from ", output_file);
+ fputs(path, output_file);
+ fputs(" */\n", output_file);
+ fputs("#include <ss/ss.h>\n\n", output_file);
+ fputs("#ifndef __STDC__\n#define const\n#endif\n\n", output_file);
+ /* parse it */
+ result = yyparse();
+ /* put file descriptors back where they belong */
+ fclose(yyin); /* bye bye input file */
+ fclose(output_file); /* bye bye output file */
+
+ return result;
+}
+
+yyerror(s)
+ char *s;
+{
+ fputs(s, stderr);
+ fprintf(stderr, "\nLine %d; last token was '%s'\n",
+ lineno, last_token);
+}
--- /dev/null
+/* $Id: mk_cmds_defs.h,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $ */
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __STDC__
+
+#define PROTOTYPE(p) p
+typedef void * pointer;
+
+#else
+
+#define const
+#define volatile
+#define PROTOTYPE(p) ()
+typedef char * pointer;
+
+#endif /* not __STDC__ */
+
+#if defined(__GNUC__)
+#define LOCAL_ALLOC(x) __builtin_alloca(x)
+#define LOCAL_FREE(x)
+#else
+#if defined(vax)
+#define LOCAL_ALLOC(x) alloca(x)
+#define LOCAL_FREE(x)
+extern pointer alloca PROTOTYPE((unsigned));
+#else
+#if defined(__HIGHC__) /* Barf! */
+pragma on(alloca);
+#define LOCAL_ALLOC(x) alloca(x)
+#define LOCAL_FREE(x)
+extern pointer alloca PROTOTYPE((unsigned));
+#else
+/* no alloca? */
+#define LOCAL_ALLOC(x) malloc(x)
+#define LOCAL_FREE(x) free(x)
+#endif
+#endif
+#endif /* LOCAL_ALLOC stuff */
--- /dev/null
+/* $Id: options.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#define NO_SS_ERR_H
+#include <ss/ss.h>
+
+struct option {
+ char *text;
+ long value;
+};
+
+static struct option options[] = {
+ { "dont_list", SS_OPT_DONT_LIST },
+ { "^list", SS_OPT_DONT_LIST },
+ { "dont_summarize", SS_OPT_DONT_SUMMARIZE },
+ { "^summarize", SS_OPT_DONT_SUMMARIZE },
+ { (char *)NULL, 0 }
+};
+
+long
+flag_val(string)
+ register char *string;
+{
+ register struct option *opt;
+ for (opt = options; opt->text; opt++)
+ if (!strcmp(opt->text, string))
+ return(opt->value);
+ return(0);
+}
--- /dev/null
+/* $Id: utils.c,v 1.1.1.1 1995/12/14 06:52:48 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by MIT Student Information Processing Board
+ *
+ * For copyright information, see copyright.h.
+ */
+
+#include <stdlib.h>
+#ifndef NPOSIX
+#include <string.h>
+#else
+#include <strings.h>
+#define memcpy(a, b, c) bcopy(b, a, c)
+#endif
+#define NO_SS_ERR_H
+#include "ss_internal.h" /* includes stdio and string */
+
+extern FILE *output_file;
+char *gensym(), *str_concat3(), *quote(), *ds();
+extern long gensym_n;
+
+void write_ct(hdr, rql)
+ char const *hdr, *rql;
+{
+ char *sym;
+ sym = gensym("ssu");
+ fputs("static ss_request_entry ", output_file);
+ fputs(sym, output_file);
+ fputs("[] = {\n", output_file);
+ fputs(rql, output_file);
+ fputs(" { 0, 0, 0, 0 }\n", output_file);
+ fputs("};\n\nss_request_table ", output_file);
+ fputs(hdr, output_file);
+ fprintf(output_file, " = { %d, ", SS_RQT_TBL_V2);
+ fputs(sym, output_file);
+ fputs(" };\n", output_file);
+}
+
+char * generate_cmds_string(cmds)
+ char const *cmds;
+{
+ char * var_name = gensym("ssu");
+ fputs("static char const * const ", output_file);
+ fputs(var_name, output_file);
+ fputs("[] = {\n", output_file);
+ fputs(cmds, output_file);
+ fputs(",\n (char const *)0\n};\n", output_file);
+ return(var_name);
+}
+
+void generate_function_definition(func)
+ char const *func;
+{
+ fputs("extern void ", output_file);
+ fputs(func, output_file);
+ fputs(" __P((int, const char * const *, int, void *));\n", output_file);
+}
+
+char * generate_rqte(func_name, info_string, cmds, options)
+ char const *func_name;
+ char const *info_string;
+ char const *cmds;
+ int options;
+{
+ int size;
+ char *string, *var_name, numbuf[16];
+ var_name = generate_cmds_string(cmds);
+ generate_function_definition(func_name);
+ size = 6; /* " { " */
+ size += strlen(var_name)+7; /* "quux, " */
+ size += strlen(func_name)+7; /* "foo, " */
+ size += strlen(info_string)+9; /* "\"Info!\", " */
+ sprintf(numbuf, "%d", options);
+ size += strlen(numbuf);
+ size += 4; /* " }," + NL */
+ string = malloc(size * sizeof(char *));
+ strcpy(string, " { ");
+ strcat(string, var_name);
+ strcat(string, ",\n ");
+ strcat(string, func_name);
+ strcat(string, ",\n ");
+ strcat(string, info_string);
+ strcat(string, ",\n ");
+ strcat(string, numbuf);
+ strcat(string, " },\n");
+ return(string);
+}
+
+char *
+gensym(name)
+ char *name;
+{
+ char *symbol;
+
+ symbol = malloc((strlen(name)+6) * sizeof(char));
+ gensym_n++;
+ sprintf(symbol, "%s%05ld", name, gensym_n);
+ return(symbol);
+}
+
+/* concatenate three strings and return the result */
+char *str_concat3(a, b, c)
+ register char *a, *b, *c;
+{
+ char *result;
+ int size_a = strlen(a);
+ int size_b = strlen(b);
+ int size_c = strlen(c);
+
+ result = malloc((size_a + size_b + size_c + 2)*sizeof(char));
+ strcpy(result, a);
+ strcpy(&result[size_a], c);
+ strcpy(&result[size_a+size_c], b);
+ return(result);
+}
+
+/* return copy of string enclosed in double-quotes */
+char *quote(string)
+ register char *string;
+{
+ register char *result;
+ int len;
+ len = strlen(string)+1;
+ result = malloc(len+2);
+ result[0] = '"';
+ memcpy(&result[1], string, len-1);
+ result[len] = '"';
+ result[len+1] = '\0';
+ return(result);
+}
+
+/* make duplicate of string and return pointer */
+char *ds(s)
+ register char *s;
+{
+ register int len = strlen(s) + 1;
+ register char *new;
+ new = malloc(len);
+ memcpy(new, s, len);
+ return(new);
+}
--- /dev/null
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $
+
+PROG= register
+SRCS= register.c des_rw.c
+.PATH: ${.CURDIR}/../../usr.bin/rlogin
+CFLAGS+=-DKERBEROS
+DPADD+= ${LIBKRB} ${LIBCRYPT} ${LIBDES}
+LDADD+= -lkrb -lcrypt -ldes
+BINDIR= /usr/bin
+BINOWN= root
+BINMODE=4555
+
+.include <bsd.prog.mk>
--- /dev/null
+/* $Id: pathnames.h,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from @(#)pathnames.h 8.1 (Berkeley) 6/1/93
+ */
+
+#define SERVER_KEYDIR "/etc/kerberosIV/register_keys"
+#define CLIENT_KEYFILE "/etc/kerberosIV/.update.key"
+#define _PATH_KPASSWD "/usr/bin/passwd"
--- /dev/null
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from @(#)register.1 8.1 (Berkeley) 6/1/93
+.\" $Id: register.1,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $
+.\"
+.TH REGISTER 1 "June 1, 1993"
+.UC 7
+.SH NAME
+register \- register with Kerberos
+.SH SYNOPSIS
+.B register
+.SH DESCRIPTION
+The
+.I register
+command
+is used to register a new user with Kerberos.
+The Kerberos server keeps record of certain trusted hosts
+from which it will accept new registrations.
+If the host on which
+.I register
+is run is trusted by Kerberos, the user
+is asked for his current password, and then
+a new password to be used with Kerberos.
+A user may only register with Kerberos one time.
+.SH FILES
+.br
+/.update.keyxx.xx.xx.xx shared DES key with server
+.SH "SEE ALSO"
+registerd(8), kerberos(1)
+.SH DIAGNOSTICS
+\*(lqPrincipal not unique\*(rq
+if the user already exists in the Kerberos database.
+.br
+\*(lqPermission Denied,\*(rq
+if the host on which register is being run is untrusted.
--- /dev/null
+/* $Id: register.c,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $ */
+
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)register.c 8.1 (Berkeley) 6/1/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/signal.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <strings.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include "pathnames.h"
+#include "register_proto.h"
+
+#define SERVICE "krbupdate" /* service to add to KDC's database */
+#define PROTO "tcp"
+
+char realm[REALM_SZ];
+char krbhst[MAX_HSTNM];
+
+static char pname[ANAME_SZ];
+static char iname[INST_SZ];
+static char password[_PASSWORD_LEN];
+
+/* extern char *sys_errlist; */
+void die();
+void setup_key(), type_info(), cleanup();
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct servent *se;
+ struct hostent *host;
+ struct sockaddr_in sin, local;
+ int rval;
+ int sock, llen;
+ u_char code;
+ static struct rlimit rl = { 0, 0 };
+
+ signal(SIGPIPE, die);
+
+ if (setrlimit(RLIMIT_CORE, &rl) < 0) {
+ perror("rlimit");
+ exit(1);
+ }
+
+ if ((se = getservbyname(SERVICE, PROTO)) == NULL) {
+ fprintf(stderr, "couldn't find entry for service %s\n",
+ SERVICE);
+ exit(1);
+ }
+ if ((rval = krb_get_lrealm(realm,0)) != KSUCCESS) {
+ fprintf(stderr, "couldn't get local Kerberos realm: %s\n",
+ krb_err_txt[rval]);
+ exit(1);
+ }
+
+ if ((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
+ fprintf(stderr, "couldn't get Kerberos host: %s\n",
+ krb_err_txt[rval]);
+ exit(1);
+ }
+
+ if ((host = gethostbyname(krbhst)) == NULL) {
+ fprintf(stderr, "couldn't get host entry for host %s\n",
+ krbhst);
+ exit(1);
+ }
+
+ sin.sin_family = host->h_addrtype;
+ (void)bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length);
+ sin.sin_port = se->s_port;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
+ perror("connect");
+ (void)close(sock);
+ exit(1);
+ }
+
+ llen = sizeof(local);
+ if (getsockname(sock, (struct sockaddr *) &local, &llen) < 0) {
+ perror("getsockname");
+ (void)close(sock);
+ exit(1);
+ }
+
+ setup_key(local);
+
+ type_info();
+
+ if (!get_user_info()) {
+ code = ABORT;
+ (void)des_write(sock, &code, 1);
+ cleanup();
+ exit(1);
+ }
+
+ code = APPEND_DB;
+ if (des_write(sock, &code, 1) != 1) {
+ perror("write 1");
+ cleanup();
+ exit(1);
+ }
+
+ if (des_write(sock, pname, ANAME_SZ) != ANAME_SZ) {
+ perror("write principal name");
+ cleanup();
+ exit(1);
+ }
+
+ if (des_write(sock, iname, INST_SZ) != INST_SZ) {
+ perror("write instance name");
+ cleanup();
+ exit(1);
+ }
+
+ if (des_write(sock, password, 255) != 255) {
+ perror("write password");
+ cleanup();
+ exit(1);
+ }
+
+ /* get return message */
+
+ {
+ int cc;
+ char msgbuf[BUFSIZ];
+
+ cc = read(sock, msgbuf, BUFSIZ);
+ if (cc <= 0) {
+ fprintf(stderr, "protocol error during key verification\n");
+ cleanup();
+ exit(1);
+ }
+ if (strncmp(msgbuf, GOTKEY_MSG, 6) != 0) {
+ fprintf(stderr, "%s: %s", krbhst, msgbuf);
+ cleanup();
+ exit(1);
+ }
+
+ cc = des_read(sock, msgbuf, BUFSIZ);
+ if (cc <= 0) {
+ fprintf(stderr, "protocol error during read\n");
+ cleanup();
+ exit(1);
+ } else {
+ printf("%s: %s", krbhst, msgbuf);
+ }
+ }
+
+ cleanup();
+ (void)close(sock);
+}
+
+void
+cleanup()
+{
+ bzero(password, 255);
+}
+
+extern char *crypt();
+extern char *getpass();
+
+int
+get_user_info()
+{
+ int uid = getuid();
+ int valid = 0, i;
+ struct passwd *pw;
+ char *pas, *namep;
+
+ /* NB: we must run setuid-root to get at the real pw file */
+
+ if ((pw = getpwuid(uid)) == NULL) {
+ fprintf(stderr, "Who are you?\n");
+ return(0);
+ }
+ (void)seteuid(uid);
+ (void)strcpy(pname, pw->pw_name); /* principal name */
+
+ for (i = 1; i < 3; i++) {
+ pas = getpass("login password:");
+ namep = crypt(pas, pw->pw_passwd);
+ if (strcmp(namep, pw->pw_passwd)) {
+ fprintf(stderr, "Password incorrect\n");
+ continue;
+ } else {
+ valid = 1;
+ break;
+ }
+ }
+ if (!valid)
+ return(0);
+ pas = getpass("Kerberos password (may be the same):");
+ while (*pas == NULL) {
+ printf("<NULL> password not allowed\n");
+ pas = getpass("Kerberos password (may be the same):");
+ }
+ (void)strcpy(password, pas); /* password */
+ pas = getpass("Retype Kerberos password:");
+ if (strcmp(password, pas)) {
+ fprintf(stderr, "Password mismatch -- aborted\n");
+ return(0);
+ }
+
+ iname[0] = NULL; /* null instance name */
+ return(1);
+}
+
+void
+setup_key(local)
+ struct sockaddr_in local;
+{
+ static struct keyfile_data kdata;
+ static Key_schedule schedule;
+ int fd;
+ char namebuf[MAXPATHLEN];
+ extern int errno;
+
+ (void) sprintf(namebuf, "%s%s",
+ CLIENT_KEYFILE,
+ inet_ntoa(local.sin_addr));
+
+ fd = open(namebuf, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "couldn't open key file %s for local host: ",
+ namebuf);
+ perror("");
+ exit(1);
+ }
+
+ if (read(fd, (char *)&kdata, sizeof(kdata)) != sizeof(kdata)) {
+ fprintf(stderr,"size error reading key file for local host %s\n",
+ inet_ntoa(local.sin_addr));
+ exit(1);
+ }
+ key_sched(&kdata.kf_key, schedule);
+ des_set_key(&kdata.kf_key, schedule);
+ return;
+}
+
+void
+type_info()
+{
+ printf("Kerberos user registration (realm %s)\n\n", realm);
+ printf("Please enter your login password followed by your new Kerberos password.\n");
+ printf("The Kerberos password you enter now will be used in the future\n");
+ printf("as your Kerberos password for all machines in the %s realm.\n", realm);
+ printf("You will only be allowed to perform this operation once, although you may run\n");
+ printf("the %s program from now on to change your Kerberos password.\n\n", _PATH_KPASSWD);
+}
+
+void
+die()
+{
+ fprintf(stderr, "\nServer no longer listening\n");
+ fflush(stderr);
+ cleanup();
+ exit(1);
+}
--- /dev/null
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from @(#)register_proto.h 8.1 (Berkeley) 6/1/93
+ * $Id: register_proto.h,v 1.1.1.1 1995/12/14 06:52:33 tholo Exp $
+ */
+
+#define APPEND_DB 0x01
+#define ABORT 0x02
+
+#define GOTKEY_MSG "GOTKEY"
+
+struct keyfile_data {
+ C_Block kf_key;
+};
--- /dev/null
+# Copyright (c) 1990 The Regents of the University of California.
+# All rights reserved.
+#
+# from @(#)Makefile 8.1 (Berkeley) 6/1/93
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $
+
+PROG= registerd
+SRCS= registerd.c des_rw.c
+.PATH: ${.CURDIR}/../../usr.bin/rlogin
+CFLAGS+=-DKERBEROS -I${.CURDIR}/../register
+DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES}
+LDADD= -lkdb -lkrb -ldes
+MAN= registerd.8
+BINDIR= /usr/libexec
+
+.include <bsd.prog.mk>
--- /dev/null
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from @(#)registerd.8 8.2 (Berkeley) 12/11/93
+.\" $Id: registerd.8,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $
+.\"
+.Dd December 11, 1993
+.Dt REGISTERD 8
+.Os
+.Sh NAME
+.Nm registerd
+.Nd Kerberos registration daemon
+.Sh SYNOPSIS
+.Nm registerd
+.Sh DESCRIPTION
+Act as a registration agent for a Kerberos domain.
+.Sh FILES
+.Bl -tag -width /etc/kerberosIV/register_keys -compact
+.It Pa /.update.keyxx.xx.xx.xx
+shared
+.Tn DES
+key with server
+.It Pa /etc/kerberosIV/principal*
+Kerberos database
+.It Pa /etc/kerberosIV/register_keys
+directory containing keys for trusted hosts
+.El
+.Sh SEE ALSO
+.Xr registerd 8 ,
+.Xr kerberos 1
+.Sh DIAGNOSTICS
+.Dq Already exists ,
+if the user already exists in the Kerberos database.
+.Pp
+.Dq Permission Denied ,
+if the host on which register is being run is untrusted.
+.Sh HISTORY
+The
+.Nm registerd
+utility
+first appeared in 4.4BSD.
+
--- /dev/null
+/* $Id: registerd.c,v 1.1.1.1 1995/12/14 06:52:36 tholo Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)registerd.c 8.1 (Berkeley) 6/1/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/signal.h>
+#include <sys/resource.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+#include <kerberosIV/krb_db.h>
+#include <stdio.h>
+#include <strings.h>
+#include "register_proto.h"
+#include "pathnames.h"
+
+#define KBUFSIZ (sizeof(struct keyfile_data))
+#define RCRYPT 0x00
+#define CLEAR 0x01
+
+char *progname, msgbuf[BUFSIZ];
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ static Key_schedule schedule;
+ static struct rlimit rl = { 0, 0 };
+ struct keyfile_data *kfile;
+ u_char code;
+ int kf, retval, sval;
+ struct sockaddr_in sina;
+ char keyfile[MAXPATHLEN], keybuf[KBUFSIZ];
+ void die();
+
+ progname = argv[0]; /* for the library routines */
+
+ openlog("registerd", LOG_PID, LOG_AUTH);
+
+ (void)signal(SIGHUP, SIG_IGN);
+ (void)signal(SIGINT, SIG_IGN);
+ (void)signal(SIGTSTP, SIG_IGN);
+ (void)signal(SIGPIPE, die);
+
+ if (setrlimit(RLIMIT_CORE, &rl) < 0) {
+ syslog(LOG_ERR, "setrlimit: %m");
+ exit(1);
+ }
+
+
+ /* figure out who we are talking to */
+
+ sval = sizeof(sina);
+ if (getpeername(0, (struct sockaddr *) &sina, &sval) < 0) {
+ syslog(LOG_ERR, "getpeername: %m");
+ exit(1);
+ }
+
+ /* get encryption key */
+
+ (void) sprintf(keyfile, "%s%s%s",
+ SERVER_KEYDIR,
+ CLIENT_KEYFILE,
+ inet_ntoa(sina.sin_addr));
+
+ if ((kf = open(keyfile, O_RDONLY)) < 0) {
+ syslog(LOG_ERR,
+ "error opening Kerberos update keyfile (%s): %m", keyfile);
+ (void) sprintf(msgbuf,
+ "couldn't open session keyfile for your host");
+ send_packet(msgbuf, CLEAR);
+ exit(1);
+ }
+
+ if (read(kf, keybuf, KBUFSIZ) != KBUFSIZ) {
+ syslog(LOG_ERR, "wrong read size of Kerberos update keyfile");
+ (void) sprintf(msgbuf,
+ "couldn't read session key from your host's keyfile");
+ send_packet(msgbuf, CLEAR);
+ exit(1);
+ }
+ (void) sprintf(msgbuf, GOTKEY_MSG);
+ send_packet(msgbuf, CLEAR);
+ kfile = (struct keyfile_data *) keybuf;
+ key_sched(&kfile->kf_key, schedule);
+ des_set_key(&kfile->kf_key, schedule);
+
+ /* read the command code byte */
+
+ if (des_read(0, &code, 1) == 1) {
+
+ switch(code) {
+ case APPEND_DB:
+ retval = do_append(&sina);
+ break;
+ case ABORT:
+ cleanup();
+ close(0);
+ exit(0);
+ default:
+ retval = KFAILURE;
+ syslog(LOG_NOTICE,
+ "invalid command code on db update (0x%x)",
+ code);
+ }
+
+ } else {
+ retval = KFAILURE;
+ syslog(LOG_ERR,
+ "couldn't read command code on Kerberos update");
+ }
+
+ code = (u_char) retval;
+ if (code != KSUCCESS) {
+ (void) sprintf(msgbuf, "%s", krb_err_txt[code]);
+ send_packet(msgbuf, RCRYPT);
+ } else {
+ (void) sprintf(msgbuf, "Update complete.");
+ send_packet(msgbuf, RCRYPT);
+ }
+ cleanup();
+ close(0);
+ exit(0);
+}
+
+#define MAX_PRINCIPAL 10
+static Principal principal_data[MAX_PRINCIPAL];
+static C_Block key, master_key;
+static Key_schedule master_key_schedule;
+int
+do_append(sinp)
+ struct sockaddr_in *sinp;
+{
+ Principal default_princ;
+ char input_name[ANAME_SZ];
+ char input_instance[INST_SZ];
+ int j,n, more;
+ long mkeyversion;
+
+
+
+ /* get master key from MKEYFILE */
+ if (kdb_get_master_key(0, &master_key, master_key_schedule) != 0) {
+ syslog(LOG_ERR, "couldn't get master key");
+ return(KFAILURE);
+ }
+
+ mkeyversion = kdb_verify_master_key(&master_key, master_key_schedule, NULL);
+ if (mkeyversion < 0) {
+ syslog(LOG_ERR, "couldn't validate master key");
+ return(KFAILURE);
+ }
+
+ n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
+ &default_princ, 1, &more);
+
+ if (n != 1) {
+ syslog(LOG_ERR, "couldn't get default principal");
+ return(KFAILURE);
+ }
+
+ /*
+ * get principal name, instance, and password from network.
+ * convert password to key and store it
+ */
+
+ if (net_get_principal(input_name, input_instance, key) != 0) {
+ return(KFAILURE);
+ }
+
+
+ j = kerb_get_principal(
+ input_name,
+ input_instance,
+ principal_data,
+ MAX_PRINCIPAL,
+ &more
+ );
+
+ if (j != 0) {
+ /* already in database, no update */
+ syslog(LOG_NOTICE,
+ "attempt to add duplicate entry for principal %s.%s",
+ input_name, input_instance);
+ return(KDC_PR_N_UNIQUE);
+ }
+
+ /*
+ * set up principal's name, instance
+ */
+
+ strcpy(principal_data[0].name, input_name);
+ strcpy(principal_data[0].instance, input_instance);
+ principal_data[0].old = NULL;
+
+
+ /* and the expiration date and version #s */
+
+ principal_data[0].exp_date = default_princ.exp_date;
+ strcpy(principal_data[0].exp_date_txt, default_princ.exp_date_txt);
+ principal_data[0].max_life = default_princ.max_life;
+ principal_data[0].attributes = default_princ.attributes;
+ principal_data[0].kdc_key_ver = default_princ.kdc_key_ver;
+
+
+ /* and the key */
+
+ kdb_encrypt_key(&key, &key, &master_key, master_key_schedule,
+ ENCRYPT);
+ bcopy(key, &principal_data[0].key_low, 4);
+ bcopy(((long *) key) + 1, &principal_data[0].key_high,4);
+ bzero(key, sizeof(key));
+
+ principal_data[0].key_version = 1; /* 1st entry */
+
+ /* and write it to the database */
+
+ if (kerb_put_principal(&principal_data[0], 1)) {
+ syslog(LOG_INFO, "Kerberos update failure: put_principal failed");
+ return(KFAILURE);
+ }
+
+ syslog(LOG_NOTICE, "Kerberos update: wrote new record for %s.%s from %s",
+ principal_data[0].name,
+ principal_data[0].instance,
+ inet_ntoa(sinp->sin_addr)
+ );
+
+ return(KSUCCESS);
+
+}
+
+send_packet(msg,flag)
+ char *msg;
+ int flag;
+{
+ int len = strlen(msg);
+ msg[len++] = '\n';
+ msg[len] = '\0';
+ if (len > sizeof(msgbuf)) {
+ syslog(LOG_ERR, "send_packet: invalid msg size");
+ return;
+ }
+ if (flag == RCRYPT) {
+ if (des_write(0, msg, len) != len)
+ syslog(LOG_ERR, "couldn't write reply message");
+ } else if (flag == CLEAR) {
+ if (write(0, msg, len) != len)
+ syslog(LOG_ERR, "couldn't write reply message");
+ } else
+ syslog(LOG_ERR, "send_packet: invalid flag (%d)", flag);
+
+}
+
+net_get_principal(pname, iname, keyp)
+ char *pname, *iname;
+ C_Block *keyp;
+{
+ int cc;
+ static char password[255];
+
+ cc = des_read(0, pname, ANAME_SZ);
+ if (cc != ANAME_SZ) {
+ syslog(LOG_ERR, "couldn't get principal name");
+ return(-1);
+ }
+
+ cc = des_read(0, iname, INST_SZ);
+ if (cc != INST_SZ) {
+ syslog(LOG_ERR, "couldn't get instance name");
+ return(-1);
+ }
+
+ cc = des_read(0, password, 255);
+ if (cc != 255) {
+ syslog(LOG_ERR, "couldn't get password");
+ bzero(password, 255);
+ return(-1);
+ }
+
+ string_to_key(password, keyp);
+ bzero(password, 255);
+ return(0);
+}
+
+cleanup()
+{
+ bzero(master_key, sizeof(master_key));
+ bzero(key, sizeof(key));
+ bzero(master_key_schedule, sizeof(master_key_schedule));
+}
+
+void
+die()
+{
+ syslog(LOG_ERR, "remote end died (SIGPIPE)");
+ cleanup();
+ exit(1);
+}
--- /dev/null
+# $Id: Makefile,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $
+
+LIB= ss
+SRCS= ss_err.c data.c error.c execute_cmd.c help.c invocation.c list_rqs.c \
+ listen.c pager.c parse.c prompt.c request_tbl.c requests.c \
+ std_rqs.c
+CFLAGS+=-I. -I${.CURDIR} -I${.CURDIR}/../com_err
+LDADD+= ${COM_ERR}
+CLEANFILES+= ss_err.c ss_err.h std_rqs.c ss
+
+ss_err.h ss_err.c: ${.CURDIR}/ss_err.et
+ test -e ss_err.et || ln -s ${.CURDIR}/ss_err.et .
+ ${COMPILE_ET} ss_err.et
+ -test -h ss_err.et && rm ss_err.et
+
+std_rqs.c: ${.CURDIR}/std_rqs.ct
+ test -e std_rqs.ct || ln -s ${.CURDIR}/std_rqs.ct .
+ ${MK_CMDS} std_rqs.ct
+ -test -h std_rqs.ct && rm std_rqs.ct
+
+beforeinstall:
+ -cd ${.OBJDIR}; \
+ if [ -f ss_err.h ]; then \
+ cmp -s ss_err.h ${DESTDIR}/usr/include/ss/ss_err.h || \
+ install -c -o ${BINOWN} -g ${BINGRP} -m 444 ss_err.h \
+ ${DESTDIR}/usr/include/ss; \
+ else \
+ true; \
+ fi
+
+beforedepend:
+ ln -s . ss
+
+.include <bsd.lib.mk>
--- /dev/null
+/* $Id: data.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include "ss_internal.h"
+
+const static char copyright[] =
+ "Copyright 1987, 1988, 1989 by the Massachusetts Institute of Technology";
+
+ss_data **_ss_table = (ss_data **)NULL;
+char *_ss_pager_name = (char *)NULL;
--- /dev/null
+/* $Id: error.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Our standalone dpANS environment on the RT doesn't include any
+ * header files.
+ */
+#if defined(__STDC__) && !defined(ibm032)
+#include <stdarg.h>
+#define STDARG
+#else
+#include <varargs.h>
+#define ss_error ss_error_external
+#endif
+
+#include <kerberosIV/com_err.h>
+#include "ss_internal.h"
+
+#undef ss_error
+
+char *
+ss_name(sci_idx)
+ int sci_idx;
+{
+ register char *ret_val;
+ register ss_data *infop;
+
+ infop = ss_info(sci_idx);
+ if (infop->current_request == (char const *)NULL) {
+ ret_val = malloc((unsigned)
+ (strlen(infop->subsystem_name)+1)
+ * sizeof(char));
+ if (ret_val == (char *)NULL)
+ return((char *)NULL);
+ strcpy(ret_val, infop->subsystem_name);
+ return(ret_val);
+ }
+ else {
+ register char *cp;
+ register char const *cp1;
+ ret_val = malloc((unsigned)sizeof(char) *
+ (strlen(infop->subsystem_name)+
+ strlen(infop->current_request)+
+ 4));
+ cp = ret_val;
+ cp1 = infop->subsystem_name;
+ while (*cp1)
+ *cp++ = *cp1++;
+ *cp++ = ' ';
+ *cp++ = '(';
+ cp1 = infop->current_request;
+ while (*cp1)
+ *cp++ = *cp1++;
+ *cp++ = ')';
+ *cp = '\0';
+ return(ret_val);
+ }
+}
+
+#ifdef STDARG
+void
+ss_error (int sci_idx, long code, const char * fmt, ...)
+#else
+void
+ss_error (va_alist)
+ va_dcl
+#endif
+{
+ register char *whoami;
+ va_list pvar;
+#ifndef STDARG
+ int sci_idx;
+ long code;
+ char * fmt;
+ va_start (pvar);
+ sci_idx = va_arg (pvar, int);
+ code = va_arg (pvar, long);
+ fmt = va_arg (pvar, char *);
+#else
+ va_start (pvar, fmt);
+#endif
+ whoami = ss_name (sci_idx);
+ com_err_va (whoami, code, fmt, pvar);
+ free (whoami);
+ va_end(pvar);
+}
+
+void
+ss_perror (sci_idx, code, msg) /* for compatibility */
+ int sci_idx;
+ long code;
+ char const *msg;
+{
+ ss_error (sci_idx, code, "%s", msg);
+}
--- /dev/null
+/* $Id: execute_cmd.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ss_internal.h"
+
+#ifndef lint
+static char const rcsid[] =
+ "$Id: execute_cmd.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $";
+#endif
+
+/*
+ * get_request(tbl, idx)
+ *
+ * Function:
+ * Gets the idx'th request from the request table pointed to
+ * by tbl.
+ * Arguments:
+ * tbl (ss_request_table *)
+ * pointer to request table
+ * idx (int)
+ * index into table
+ * Returns:
+ * (ss_request_entry *)
+ * pointer to request table entry
+ * Notes:
+ * Has been replaced by a macro.
+ */
+
+#ifdef __SABER__
+/* sigh. saber won't deal with pointer-to-const-struct */
+static struct _ss_request_entry *
+get_request (tbl, idx)
+ ss_request_table * tbl;
+ int idx;
+{
+ struct _ss_request_table *tbl1 = (struct _ss_request_table *) tbl;
+ struct _ss_request_entry *e = (struct _ss_request_entry *) tbl1->requests;
+ return e + idx;
+}
+#else
+#define get_request(tbl,idx) ((tbl) -> requests + (idx))
+#endif
+
+/*
+ * check_request_table(rqtbl, argc, argv, sci_idx)
+ *
+ * Function:
+ * If the command string in argv[0] is in the request table, execute
+ * the commands and return error code 0. Otherwise, return error
+ * code ss_et_command_not_found.
+ * Arguments:
+ * rqtbl (ss_request_table *)
+ * pointer to request table
+ * argc (int)
+ * number of elements in argv[]
+ * argv (char *[])
+ * argument string array
+ * sci_idx (int)
+ * ss-internal index for subsystem control info structure
+ * Returns:
+ * (int)
+ * zero if command found, ss_et_command_not_found otherwise
+ * Notes:
+ */
+
+static int
+check_request_table (rqtbl, argc, argv, sci_idx)
+ register ss_request_table *rqtbl;
+ int argc;
+ char *argv[];
+ int sci_idx;
+{
+#ifdef __SABER__
+ struct _ss_request_entry *request;
+#else
+ register ss_request_entry *request;
+#endif
+ register ss_data *info;
+ register char const * const * name;
+ char *string = argv[0];
+ int i;
+
+ info = ss_info(sci_idx);
+ info->argc = argc;
+ info->argv = argv;
+ for (i = 0; (request = get_request(rqtbl, i))->command_names; i++) {
+ for (name = request->command_names; *name; name++)
+ if (!strcmp(*name, string)) {
+ info->current_request = request->command_names[0];
+ (request->function)(argc, (const char *const *) argv,
+ sci_idx,info->info_ptr);
+ info->current_request = (char *)NULL;
+ return(0);
+ }
+ }
+ return(SS_ET_COMMAND_NOT_FOUND);
+}
+
+/*
+ * really_execute_command(sci_idx, argc, argv)
+ *
+ * Function:
+ * Fills in the argc, argv values in the subsystem entry and
+ * call the appropriate routine.
+ * Arguments:
+ * sci_idx (int)
+ * ss-internal index for subsystem control info structure
+ * argc (int)
+ * number of arguments in argument list
+ * argv (char **[])
+ * pointer to parsed argument list (may be reallocated
+ * on abbrev expansion)
+ *
+ * Returns:
+ * (int)
+ * Zero if successful, ss_et_command_not_found otherwise.
+ * Notes:
+ */
+
+static int
+really_execute_command (sci_idx, argc, argv)
+ int sci_idx;
+ int argc;
+ char **argv[];
+{
+ register ss_request_table **rqtbl;
+ register ss_data *info;
+
+ info = ss_info(sci_idx);
+
+ for (rqtbl = info->rqt_tables; *rqtbl; rqtbl++) {
+ if (check_request_table (*rqtbl, argc, *argv, sci_idx) == 0)
+ return(0);
+ }
+ return(SS_ET_COMMAND_NOT_FOUND);
+}
+
+/*
+ * ss_execute_command(sci_idx, argv)
+ *
+ * Function:
+ * Executes a parsed command list within the subsystem.
+ * Arguments:
+ * sci_idx (int)
+ * ss-internal index for subsystem control info structure
+ * argv (char *[])
+ * parsed argument list
+ * Returns:
+ * (int)
+ * Zero if successful, ss_et_command_not_found otherwise.
+ * Notes:
+ */
+
+int
+ss_execute_command(sci_idx, argv)
+ int sci_idx;
+ register char *argv[];
+{
+ register int i, argc;
+ char **argp;
+
+ argc = 0;
+ for (argp = argv; *argp; argp++)
+ argc++;
+ argp = (char **)malloc((argc+1)*sizeof(char *));
+ for (i = 0; i <= argc; i++)
+ argp[i] = argv[i];
+ i = really_execute_command(sci_idx, argc, &argp);
+ free(argp);
+ return(i);
+}
+
+/*
+ * ss_execute_line(sci_idx, line_ptr)
+ *
+ * Function:
+ * Parses and executes a command line within a subsystem.
+ * Arguments:
+ * sci_idx (int)
+ * ss-internal index for subsystem control info structure
+ * line_ptr (char *)
+ * Pointer to command line to be parsed.
+ * Returns:
+ * (int)
+ * Error code.
+ * Notes:
+ */
+
+int
+ss_execute_line (sci_idx, line_ptr)
+ int sci_idx;
+ char *line_ptr;
+{
+ char **argv;
+ int argc;
+ int retval;
+
+ /* flush leading whitespace */
+ while (line_ptr[0] == ' ' || line_ptr[0] == '\t')
+ line_ptr++;
+
+ /* check if it should be sent to operating system for execution */
+ if (*line_ptr == '!') {
+ if (ss_info(sci_idx)->flags.escape_disabled)
+ return SS_ET_ESCAPE_DISABLED;
+ else {
+ line_ptr++;
+ system(line_ptr);
+ return 0;
+ }
+ }
+
+ /* parse it */
+ argv = ss_parse(sci_idx, line_ptr, &argc);
+ if (argc == 0)
+ return 0;
+
+ /* look it up in the request tables, execute if found */
+ retval = really_execute_command (sci_idx, argc, &argv);
+ free(argv);
+ return(retval);
+}
--- /dev/null
+/* $Id: help.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#ifndef NPOSIX
+#include <fcntl.h>
+#endif
+#include <sys/wait.h>
+#include "ss_internal.h"
+
+extern int errno;
+
+void
+ss_help (argc, argv, sci_idx, info_ptr)
+ int argc;
+ char const * const *argv;
+ int sci_idx;
+ pointer info_ptr;
+{
+ char buffer[MAXPATHLEN];
+ char const *request_name;
+ int code;
+ int fd, child;
+ register int idx;
+ register ss_data *info;
+
+ request_name = ss_current_request(sci_idx, &code);
+ if (code != 0) {
+ ss_perror(sci_idx, code, "");
+ return; /* no ss_abort_line, if invalid invocation */
+ }
+ if (argc == 1) {
+ ss_list_requests(argc, argv, sci_idx, info_ptr);
+ return;
+ }
+ else if (argc != 2) {
+ /* should do something better than this */
+ sprintf(buffer, "usage:\n\t%s [topic|command]\nor\t%s\n",
+ request_name, request_name);
+ ss_perror(sci_idx, 0, buffer);
+ return;
+ }
+ info = ss_info(sci_idx);
+ if (info->info_dirs == (char **)NULL) {
+ ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL);
+ return;
+ }
+ if (info->info_dirs[0] == (char *)NULL) {
+ ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL);
+ return;
+ }
+ for (idx = 0; info->info_dirs[idx] != (char *)NULL; idx++) {
+ (void) strcpy(buffer, info->info_dirs[idx]);
+ (void) strcat(buffer, "/");
+ (void) strcat(buffer, argv[1]);
+ (void) strcat(buffer, ".info");
+ if ((fd = open(&buffer[0], O_RDONLY, 0)) >= 0) goto got_it;
+ }
+ if ((fd = open(&buffer[0], O_RDONLY, 0)) < 0) {
+ char buf[MAXPATHLEN];
+ strcpy(buf, "No info found for ");
+ strcat(buf, argv[1]);
+ ss_perror(sci_idx, 0, buf);
+ return;
+ }
+got_it:
+ switch (child = fork()) {
+ case -1:
+ ss_perror(sci_idx, errno, "Can't fork for pager");
+ return;
+ case 0:
+ (void) dup2(fd, 0); /* put file on stdin */
+ ss_page_stdin();
+ default:
+ (void) close(fd); /* what can we do if it fails? */
+#ifndef NPOSIX
+ while (wait((int *)0) != child) ; /* do nothing if wrong pid */
+#else
+ while (wait((union wait *)0) != child) ; /* do nothing if wrong pid */
+#endif
+ }
+}
+
+#include <sys/types.h>
+#ifdef NPOSIX
+#include <sys/dir.h>
+#else
+#include <dirent.h>
+#endif /* NPOSIX */
+
+void
+ss_add_info_dir(sci_idx, info_dir, code_ptr)
+ int sci_idx;
+ char *info_dir;
+ int *code_ptr;
+{
+ register ss_data *info;
+ DIR *d;
+ int n_dirs;
+ register char **dirs;
+
+ info = ss_info(sci_idx);
+ if (info_dir == NULL && *info_dir) {
+ *code_ptr = SS_ET_NO_INFO_DIR;
+ return;
+ }
+ if ((d = opendir(info_dir)) == (DIR *)NULL) {
+ *code_ptr = errno;
+ return;
+ }
+ closedir(d);
+ dirs = info->info_dirs;
+ for (n_dirs = 0; dirs[n_dirs] != (char *)NULL; n_dirs++)
+ ; /* get number of non-NULL dir entries */
+ dirs = (char **)realloc((char *)dirs,
+ (unsigned)(n_dirs + 2)*sizeof(char *));
+ if (dirs == (char **)NULL) {
+ info->info_dirs = (char **)NULL;
+ *code_ptr = errno;
+ return;
+ }
+ info->info_dirs = dirs;
+ dirs[n_dirs + 1] = (char *)NULL;
+ dirs[n_dirs] = malloc((unsigned)strlen(info_dir)+1);
+ strcpy(dirs[n_dirs], info_dir);
+ *code_ptr = 0;
+}
+
+void
+ss_delete_info_dir(sci_idx, info_dir, code_ptr)
+ int sci_idx;
+ char *info_dir;
+ int *code_ptr;
+{
+ register char **i_d;
+ register char **info_dirs;
+
+ info_dirs = ss_info(sci_idx)->info_dirs;
+ for (i_d = info_dirs; *i_d; i_d++) {
+ if (!strcmp(*i_d, info_dir)) {
+ while (*i_d) {
+ *i_d = *(i_d+1);
+ i_d++;
+ }
+ *code_ptr = 0;
+ return;
+ }
+ }
+ *code_ptr = SS_ET_NO_INFO_DIR;
+}
--- /dev/null
+/* $Id: invocation.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdlib.h>
+#include "ss_internal.h"
+#define size sizeof(ss_data *)
+
+#ifndef lint
+static char const rcsid[] =
+ "$Id: invocation.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $";
+#endif
+
+int
+ss_create_invocation(subsystem_name, version_string, info_ptr,
+ request_table_ptr, code_ptr)
+ char *subsystem_name, *version_string;
+ char *info_ptr;
+ ss_request_table *request_table_ptr;
+ int *code_ptr;
+{
+ register int sci_idx;
+ register ss_data *new_table;
+ register ss_data **table;
+
+ *code_ptr = 0;
+ table = _ss_table;
+ new_table = (ss_data *) malloc(sizeof(ss_data));
+
+ if (table == (ss_data **) NULL) {
+ table = (ss_data **) malloc(2 * size);
+ table[0] = table[1] = (ss_data *)NULL;
+ }
+ initialize_ss_error_table ();
+
+ for (sci_idx = 1; table[sci_idx] != (ss_data *)NULL; sci_idx++)
+ ;
+ table = (ss_data **) realloc((char *)table,
+ ((unsigned)sci_idx+2)*size);
+ table[sci_idx+1] = (ss_data *) NULL;
+ table[sci_idx] = new_table;
+
+ new_table->subsystem_name = subsystem_name;
+ new_table->subsystem_version = version_string;
+ new_table->argv = (char **)NULL;
+ new_table->current_request = (char *)NULL;
+ new_table->info_dirs = (char **)malloc(sizeof(char *));
+ *new_table->info_dirs = (char *)NULL;
+ new_table->info_ptr = info_ptr;
+ new_table->prompt = malloc((unsigned)strlen(subsystem_name)+4);
+ strcpy(new_table->prompt, subsystem_name);
+ strcat(new_table->prompt, ": ");
+#ifdef silly
+ new_table->abbrev_info = ss_abbrev_initialize("/etc/passwd", code_ptr);
+#else
+ new_table->abbrev_info = NULL;
+#endif
+ new_table->flags.escape_disabled = 0;
+ new_table->flags.abbrevs_disabled = 0;
+ new_table->rqt_tables =
+ (ss_request_table **) calloc(2, sizeof(ss_request_table *));
+ *(new_table->rqt_tables) = request_table_ptr;
+ *(new_table->rqt_tables+1) = (ss_request_table *) NULL;
+ _ss_table = table;
+ return(sci_idx);
+}
+
+void
+ss_delete_invocation(sci_idx)
+ int sci_idx;
+{
+ register ss_data *t;
+ int ignored_code;
+
+ t = ss_info(sci_idx);
+ free(t->prompt);
+ free((char *)t->rqt_tables);
+ while(t->info_dirs[0] != (char *)NULL)
+ ss_delete_info_dir(sci_idx, t->info_dirs[0], &ignored_code);
+ free((char *)t->info_dirs);
+ free((char *)t);
+}
--- /dev/null
+/* $Id: list_rqs.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include "ss_internal.h"
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#ifdef lint /* "lint returns a value which is sometimes ignored" */
+#define DONT_USE(x) x=x;
+#else /* !lint */
+#define DONT_USE(x) ;
+#endif /* lint */
+
+static char const twentyfive_spaces[26] =
+ " ";
+static char const NL[2] = "\n";
+
+int
+ss_list_requests(argc, argv, sci_idx, info_ptr)
+ int argc;
+ char **argv;
+ int sci_idx;
+ pointer info_ptr;
+{
+ register ss_request_entry *entry;
+ register char const * const *name;
+ register int spacing;
+ register ss_request_table **table;
+
+ char buffer[BUFSIZ];
+ FILE *output;
+ int fd;
+#ifndef NPOSIX
+ struct sigaction nsig, osig;
+ sigset_t nmask, omask;
+ int waitb;
+#else
+ int (*func)();
+ int mask;
+ union wait waitb;
+#endif
+
+ DONT_USE(argc);
+ DONT_USE(argv);
+
+#ifndef NPOSIX
+ sigemptyset(&nmask);
+ sigaddset(&nmask, SIGINT);
+ sigprocmask(SIG_BLOCK, &nmask, &omask);
+
+ nsig.sa_handler = SIG_IGN;
+ sigemptyset(&nsig.sa_mask);
+ nsig.sa_flags = 0;
+ sigaction(SIGINT, &nsig, &osig);
+#else
+ mask = sigblock(sigmask(SIGINT));
+ func = signal(SIGINT, SIG_IGN);
+#endif
+ fd = ss_pager_create();
+ output = fdopen(fd, "w");
+#ifndef NPOSIX
+ sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
+#else
+ sigsetmask(mask);
+#endif
+
+ fprintf (output, "Available %s requests:\n\n",
+ ss_info (sci_idx) -> subsystem_name);
+
+ for (table = ss_info(sci_idx)->rqt_tables; *table; table++) {
+ entry = (*table)->requests;
+ for (; entry->command_names; entry++) {
+ spacing = -2;
+ buffer[0] = '\0';
+ if (entry->flags & SS_OPT_DONT_LIST)
+ continue;
+ for (name = entry->command_names; *name; name++) {
+ register int len = strlen(*name);
+ strncat(buffer, *name, len);
+ spacing += len + 2;
+ if (name[1]) {
+ strcat(buffer, ", ");
+ }
+ }
+ if (spacing > 23) {
+ strcat(buffer, NL);
+ fputs(buffer, output);
+ spacing = 0;
+ buffer[0] = '\0';
+ }
+ strncat(buffer, twentyfive_spaces, 25-spacing);
+ strcat(buffer, entry->info_string);
+ strcat(buffer, NL);
+ fputs(buffer, output);
+ }
+ }
+ fclose(output);
+#ifndef NO_FORK
+ wait(&waitb);
+#endif
+#ifndef NPOSIX
+ sigaction(SIGINT, &osig, (struct sigaction *)0);
+#else
+ (void) signal(SIGINT, func);
+#endif
+}
--- /dev/null
+/* $Id: listen.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Listener loop for subsystem library libss.a.
+ */
+
+#include "ss_internal.h"
+#include <stdio.h>
+#ifndef NPOSIX
+#include <string.h>
+#else
+#include <strings.h>
+#define memcpy(a, b, c) bcopy(b, a, c)
+#endif
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/param.h>
+#ifdef BSD
+#include <sgtty.h>
+#endif
+
+#ifndef lint
+static char const rcs_id[] =
+ "$Id: listen.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $";
+#endif
+
+#ifndef NPOSIX
+#define sigtype void
+#else
+#define sigtype int
+#endif
+
+static ss_data *current_info;
+static jmp_buf listen_jmpb;
+
+static sigtype
+print_prompt()
+{
+#ifdef BSD
+ /* put input into a reasonable mode */
+ struct sgttyb ttyb;
+ if (ioctl(fileno(stdin), TIOCGETP, &ttyb) != -1) {
+ if (ttyb.sg_flags & (CBREAK|RAW)) {
+ ttyb.sg_flags &= ~(CBREAK|RAW);
+ (void) ioctl(0, TIOCSETP, &ttyb);
+ }
+ }
+#endif
+ (void) fputs(current_info->prompt, stdout);
+ (void) fflush(stdout);
+}
+
+static sigtype
+listen_int_handler()
+{
+ putc('\n', stdout);
+ longjmp(listen_jmpb, 1);
+}
+
+static sigtype print_prompt();
+
+int
+ss_listen (sci_idx)
+ int sci_idx;
+{
+ register char *cp;
+ register ss_data *info;
+ char input[BUFSIZ];
+ char expanded_input[BUFSIZ];
+ char buffer[BUFSIZ];
+ char *end = buffer;
+ int code;
+ jmp_buf old_jmpb;
+ ss_data *old_info = current_info;
+#ifndef NPOSIX
+ struct sigaction isig, csig, nsig, osig;
+ sigset_t nmask, omask;
+#else
+ register sigtype (*sig_cont)();
+ sigtype (*sig_int)(), (*old_sig_cont)();
+ int mask;
+#endif
+
+ current_info = info = ss_info(sci_idx);
+ info->abort = 0;
+#ifndef NPOSIX
+ csig.sa_handler = (sigtype (*)())0;
+
+ sigemptyset(&nmask);
+ sigaddset(&nmask, SIGINT);
+ sigprocmask(SIG_BLOCK, &nmask, &omask);
+#else
+ sig_cont = (sigtype (*)())0;
+ mask = sigblock(sigmask(SIGINT));
+#endif
+
+ memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
+
+#ifndef NPOSIX
+ nsig.sa_handler = listen_int_handler;
+ sigemptyset(&nsig.sa_mask);
+ nsig.sa_flags = 0;
+ sigaction(SIGINT, &nsig, &isig);
+#else
+ sig_int = signal(SIGINT, listen_int_handler);
+#endif
+
+ setjmp(listen_jmpb);
+
+#ifndef NPOSIX
+ sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
+#else
+ (void) sigsetmask(mask);
+#endif
+ while(!info->abort) {
+ print_prompt();
+ *end = '\0';
+#ifndef NPOSIX
+ nsig.sa_handler = listen_int_handler; /* fgets is not signal-safe */
+ osig = csig;
+ sigaction(SIGCONT, &nsig, &csig);
+ if ((sigtype (*)())csig.sa_handler==(sigtype (*)())listen_int_handler)
+ csig = osig;
+#else
+ old_sig_cont = sig_cont;
+ sig_cont = signal(SIGCONT, print_prompt);
+#ifdef mips
+ /* The mips compiler breaks on determining the types, we help */
+ if ( (sigtype *) sig_cont == (sigtype *) print_prompt)
+ sig_cont = old_sig_cont;
+#else
+ if (sig_cont == print_prompt)
+ sig_cont = old_sig_cont;
+#endif
+#endif
+ if (fgets(input, BUFSIZ, stdin) != input) {
+ code = SS_ET_EOF;
+ goto egress;
+ }
+ cp = strchr(input, '\n');
+ if (cp) {
+ *cp = '\0';
+ if (cp == input)
+ continue;
+ }
+#ifndef NPOSIX
+ sigaction(SIGCONT, &csig, (struct sigaction *)0);
+#else
+ (void) signal(SIGCONT, sig_cont);
+#endif
+ for (end = input; *end; end++)
+ ;
+
+ code = ss_execute_line (sci_idx, input);
+ if (code == SS_ET_COMMAND_NOT_FOUND) {
+ register char *c = input;
+ while (*c == ' ' || *c == '\t')
+ c++;
+ cp = strchr (c, ' ');
+ if (cp)
+ *cp = '\0';
+ cp = strchr (c, '\t');
+ if (cp)
+ *cp = '\0';
+ ss_error (sci_idx, 0,
+ "Unknown request \"%s\". Type \"?\" for a request list.",
+ c);
+ }
+ }
+ code = 0;
+egress:
+#ifndef NPOSIX
+ sigaction(SIGINT, &isig, (struct sigaction *)0);
+#else
+ (void) signal(SIGINT, sig_int);
+#endif
+ memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf));
+ current_info = old_info;
+ return code;
+}
+
+void
+ss_abort_subsystem(sci_idx, code)
+ int sci_idx;
+{
+ ss_info(sci_idx)->abort = 1;
+ ss_info(sci_idx)->exit_status = code;
+
+}
+
+int
+ss_quit(argc, argv, sci_idx, infop)
+ int argc;
+ char **argv;
+ int sci_idx;
+ pointer infop;
+{
+ ss_abort_subsystem(sci_idx, 0);
+}
--- /dev/null
+/* $Id: pager.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Pager: Routines to create a "more" running out of a particular file
+ * descriptor.
+ */
+
+#include "ss_internal.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <signal.h>
+
+static char MORE[] = "more";
+extern char *_ss_pager_name;
+extern char *getenv();
+extern int errno;
+
+/*
+ * this needs a *lot* of work....
+ *
+ * run in same process
+ * handle SIGINT sensibly
+ * allow finer control -- put-page-break-here
+ */
+void ss_page_stdin();
+
+#ifndef NO_FORK
+int
+ss_pager_create()
+{
+ int filedes[2];
+
+ if (pipe(filedes) != 0)
+ return(-1);
+
+ switch(fork()) {
+ case -1:
+ return(-1);
+ case 0:
+ /*
+ * Child; dup read half to 0, close all but 0, 1, and 2
+ */
+ if (dup2(filedes[0], 0) == -1)
+ exit(1);
+ ss_page_stdin();
+ default:
+ /*
+ * Parent: close "read" side of pipe, return
+ * "write" side.
+ */
+ (void) close(filedes[0]);
+ return(filedes[1]);
+ }
+}
+#else /* don't fork */
+int
+ss_pager_create()
+{
+ int fd;
+ fd = open("/dev/tty", O_WRONLY, 0);
+ return fd;
+}
+#endif
+
+void
+ss_page_stdin()
+{
+ int i;
+#ifndef NPOSIX
+ struct sigaction sa;
+ sigset_t mask;
+#endif
+
+ for (i = 3; i < 32; i++)
+ (void) close(i);
+#ifndef NPOSIX
+ sa.sa_handler = SIG_DFL;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sigaction(SIGINT, &sa, (struct sigaction *)0);
+#else
+ (void) signal(SIGINT, SIG_DFL);
+#endif
+ {
+#ifndef NPOSIX
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+ sigprocmask(SIG_UNBLOCK, &mask, (sigset_t *)0);
+#else
+ register int mask = sigblock(0);
+ mask &= ~sigmask(SIGINT);
+ sigsetmask(mask);
+#endif
+ }
+ if (_ss_pager_name == (char *)NULL) {
+ if ((_ss_pager_name = getenv("PAGER")) == (char *)NULL)
+ _ss_pager_name = MORE;
+ }
+ (void) execlp(_ss_pager_name, _ss_pager_name, (char *) NULL);
+ {
+ /* minimal recovery if pager program isn't found */
+ char buf[80];
+ register int n;
+ while ((n = read(0, buf, 80)) > 0)
+ write(1, buf, n);
+ }
+ exit(errno);
+}
--- /dev/null
+/* $Id: parse.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "ss_internal.h"
+
+#ifndef lint
+static char const rcsid[] =
+ "$Id: parse.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $";
+#endif
+
+enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING };
+
+/*
+ * parse(line_ptr, argc_ptr)
+ *
+ * Function:
+ * Parses line, dividing at whitespace, into tokens, returns
+ * the "argc" and "argv" values.
+ * Arguments:
+ * line_ptr (char *)
+ * Pointer to text string to be parsed.
+ * argc_ptr (int *)
+ * Where to put the "argc" (number of tokens) value.
+ * Returns:
+ * argv (char **)
+ * Series of pointers to parsed tokens.
+ */
+
+#define NEW_ARGV(old,n) (char **)realloc((char *)old,\
+ (unsigned)(n+2)*sizeof(char*))
+
+char **
+ss_parse (sci_idx, line_ptr, argc_ptr)
+ int sci_idx;
+ register char *line_ptr;
+ int *argc_ptr;
+{
+ register char **argv, *cp;
+ register int argc;
+ register enum parse_mode parse_mode;
+
+ *argc_ptr = 0; /* In case of error return something sane */
+ argv = (char **) malloc (sizeof(char *));
+ if (argv == (char **)NULL) {
+ ss_error(sci_idx, errno, "Can't allocate storage");
+ return(argv);
+ }
+ *argv = (char *)NULL;
+
+ argc = 0;
+
+ parse_mode = WHITESPACE; /* flushing whitespace */
+ cp = line_ptr; /* cp is for output */
+ while (1) {
+#ifdef DEBUG
+ {
+ printf ("character `%c', mode %d\n", *line_ptr, parse_mode);
+ }
+#endif
+ while (parse_mode == WHITESPACE) {
+ if (*line_ptr == '\0')
+ goto end_of_line;
+ if (*line_ptr == ' ' || *line_ptr == '\t') {
+ line_ptr++;
+ continue;
+ }
+ if (*line_ptr == '"') {
+ /* go to quoted-string mode */
+ parse_mode = QUOTED_STRING;
+ cp = line_ptr++;
+ argv = NEW_ARGV (argv, argc);
+ argv[argc++] = cp;
+ argv[argc] = NULL;
+ }
+ else {
+ /* random-token mode */
+ parse_mode = TOKEN;
+ cp = line_ptr;
+ argv = NEW_ARGV (argv, argc);
+ argv[argc++] = line_ptr;
+ argv[argc] = NULL;
+ }
+ }
+ while (parse_mode == TOKEN) {
+ if (*line_ptr == '\0') {
+ *cp++ = '\0';
+ goto end_of_line;
+ }
+ else if (*line_ptr == ' ' || *line_ptr == '\t') {
+ *cp++ = '\0';
+ line_ptr++;
+ parse_mode = WHITESPACE;
+ }
+ else if (*line_ptr == '"') {
+ line_ptr++;
+ parse_mode = QUOTED_STRING;
+ }
+ else {
+ *cp++ = *line_ptr++;
+ }
+ }
+ while (parse_mode == QUOTED_STRING) {
+ if (*line_ptr == '\0') {
+ ss_error (sci_idx, 0,
+ "Unbalanced quotes in command line");
+ free (argv);
+ return NULL;
+ }
+ else if (*line_ptr == '"') {
+ if (*++line_ptr == '"') {
+ *cp++ = '"';
+ line_ptr++;
+ }
+ else {
+ parse_mode = TOKEN;
+ }
+ }
+ else {
+ *cp++ = *line_ptr++;
+ }
+ }
+ }
+end_of_line:
+ *argc_ptr = argc;
+#ifdef DEBUG
+ {
+ int i;
+ printf ("argc = %d\n", argc);
+ for (i = 0; i <= argc; i++)
+ printf ("\targv[%2d] = `%s'\n", i,
+ argv[i] ? argv[i] : "<NULL>");
+ }
+#endif
+ return(argv);
+}
--- /dev/null
+/* $Id: prompt.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * prompt.c: Routines for retrieving and setting a prompt.
+ */
+
+#include <stdio.h>
+#include "ss_internal.h"
+
+static const char rcsid[] =
+ "$Id: prompt.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $";
+
+int
+ss_set_prompt(sci_idx, new_prompt)
+ int sci_idx;
+ char *new_prompt;
+{
+ ss_info(sci_idx)->prompt = new_prompt;
+}
+
+char *
+ss_get_prompt(sci_idx)
+ int sci_idx;
+{
+ return(ss_info(sci_idx)->prompt);
+}
--- /dev/null
+/* $Id: request_tbl.c,v 1.1.1.1 1995/12/14 06:52:47 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include "ss_internal.h"
+
+#define ssrt ss_request_table /* for some readable code... */
+
+void
+ss_add_request_table(sci_idx, rqtbl_ptr, position, code_ptr)
+ int sci_idx;
+ ssrt *rqtbl_ptr;
+ int position; /* 1 -> becomes second... */
+ int *code_ptr;
+{
+ register ss_data *info;
+ register int i, size;
+
+ info = ss_info(sci_idx);
+ for (size=0; info->rqt_tables[size] != (ssrt *)NULL; size++)
+ ;
+ /* size == C subscript of NULL == #elements */
+ size += 2; /* new element, and NULL */
+ info->rqt_tables = (ssrt **)realloc((char *)info->rqt_tables,
+ (unsigned)size*sizeof(ssrt));
+ if (info->rqt_tables == (ssrt **)NULL) {
+ *code_ptr = errno;
+ return;
+ }
+ if (position > size - 2)
+ position = size - 2;
+
+ if (size > 1)
+ for (i = size - 2; i >= position; i--)
+ info->rqt_tables[i+1] = info->rqt_tables[i];
+
+ info->rqt_tables[position] = rqtbl_ptr;
+ info->rqt_tables[size-1] = (ssrt *)NULL;
+ *code_ptr = 0;
+}
+
+void
+ss_delete_request_table(sci_idx, rqtbl_ptr, code_ptr)
+ int sci_idx;
+ ssrt *rqtbl_ptr;
+ int *code_ptr;
+{
+ register ss_data *info;
+ register ssrt **rt1, **rt2;
+
+ *code_ptr = SS_ET_TABLE_NOT_FOUND;
+ info = ss_info(sci_idx);
+ rt1 = info->rqt_tables;
+ for (rt2 = rt1; *rt1; rt1++) {
+ if (*rt1 != rqtbl_ptr) {
+ *rt2++ = *rt1;
+ *code_ptr = 0;
+ }
+ }
+ *rt2 = (ssrt *)NULL;
+ return;
+}
--- /dev/null
+/* $Id: requests.c,v 1.1.1.1 1995/12/14 06:52:46 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988, 1989 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+/*
+ * Various minor routines...
+ */
+
+#include <stdio.h>
+#include "ss_internal.h"
+
+#define DECLARE(name) name(argc,argv,sci_idx)int argc,sci_idx;char **argv;
+
+/*
+ * ss_self_identify -- assigned by default to the "." request
+ */
+DECLARE(ss_self_identify)
+{
+ register ss_data *info = ss_info(sci_idx);
+ printf("%s version %s\n", info->subsystem_name,
+ info->subsystem_version);
+}
+
+/*
+ * ss_subsystem_name -- print name of subsystem
+ */
+DECLARE(ss_subsystem_name)
+{
+ printf("%s\n", ss_info(sci_idx)->subsystem_name);
+}
+
+/*
+ * ss_subsystem_version -- print version of subsystem
+ */
+DECLARE(ss_subsystem_version)
+{
+ printf("%s\n", ss_info(sci_idx)->subsystem_version);
+}
+
+/*
+ * ss_unimplemented -- routine not implemented (should be
+ * set up as (dont_list,dont_summarize))
+ */
+DECLARE(ss_unimplemented)
+{
+ ss_perror(sci_idx, SS_ET_UNIMPLEMENTED, "");
+}
--- /dev/null
+major=4
+minor=0
--- /dev/null
+ error_table ss
+
+ec SS_ET_SUBSYSTEM_ABORTED,
+ "Subsystem aborted"
+
+ec SS_ET_VERSION_MISMATCH,
+ "Version mismatch"
+
+ec SS_ET_NULL_INV,
+ "No current invocation"
+
+ec SS_ET_NO_INFO_DIR,
+ "No info directory"
+
+ec SS_ET_COMMAND_NOT_FOUND,
+ "Command not found"
+
+ec SS_ET_LINE_ABORTED,
+ "Command line aborted"
+
+ec SS_ET_EOF,
+ "End-of-file reached"
+
+ec SS_ET_PERMISSION_DENIED,
+ "Permission denied"
+
+ec SS_ET_TABLE_NOT_FOUND,
+ "Request table not found"
+
+ec SS_ET_NO_HELP_FILE,
+ "No info available"
+
+ec SS_ET_ESCAPE_DISABLED,
+ "Shell escapes are disabled"
+
+ec SS_ET_UNIMPLEMENTED,
+ "Sorry, this request is not yet implemented"
+
+ end
--- /dev/null
+/* $Id: ss_internal.h,v 1.1.1.1 1995/12/14 06:52:46 tholo Exp $ */
+
+/*-
+ * Copyright 1987, 1988 by the Student Information Processing Board
+ * of the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice
+ * appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation,
+ * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * M.I.T. and the M.I.T. S.I.P.B. make no representations about
+ * the suitability of this software for any purpose. It is
+ * provided "as is" without express or implied warranty.
+ */
+
+#ifndef _ss_ss_internal_h
+#define _ss_ss_internal_h __FILE__
+#include <stdio.h>
+#include <string.h>
+
+#ifdef __STDC__
+
+#define PROTOTYPE(p) p
+typedef void * pointer;
+
+#else
+
+#define const
+#define volatile
+#define PROTOTYPE(p) ()
+typedef char * pointer;
+
+#endif /* not __STDC__ */
+
+#include <ss/ss.h>
+
+#if defined(__GNUC__)
+#define LOCAL_ALLOC(x) __builtin_alloca(x)
+#define LOCAL_FREE(x)
+#else
+#if defined(vax)
+#define LOCAL_ALLOC(x) alloca(x)
+#define LOCAL_FREE(x)
+extern pointer alloca PROTOTYPE((unsigned));
+#else
+#if defined(__HIGHC__) /* Barf! */
+pragma on(alloca);
+#define LOCAL_ALLOC(x) alloca(x)
+#define LOCAL_FREE(x)
+extern pointer alloca PROTOTYPE((unsigned));
+#else
+/* no alloca? */
+#define LOCAL_ALLOC(x) malloc(x)
+#define LOCAL_FREE(x) free(x)
+#endif
+#endif
+#endif /* LOCAL_ALLOC stuff */
+
+typedef char BOOL;
+
+typedef struct _ss_abbrev_entry {
+ char *name; /* abbrev name */
+ char **abbrev; /* new tokens to insert */
+ int beginning_of_line : 1;
+} ss_abbrev_entry;
+
+typedef struct _ss_abbrev_list {
+ int n_abbrevs;
+ ss_abbrev_entry *first_abbrev;
+} ss_abbrev_list;
+
+typedef struct {
+/* char *path; */
+ ss_abbrev_list abbrevs[127];
+} ss_abbrev_info;
+
+typedef struct _ss_data { /* init values */
+ /* this subsystem */
+ char *subsystem_name;
+ char *subsystem_version;
+ /* current request info */
+ int argc;
+ char **argv; /* arg list */
+ char const *current_request; /* primary name */
+ /* info directory for 'help' */
+ char **info_dirs;
+ /* to be extracted by subroutines */
+ pointer info_ptr; /* (void *) NULL */
+ /* for ss_listen processing */
+ char *prompt;
+ ss_request_table **rqt_tables;
+ ss_abbrev_info *abbrev_info;
+ struct {
+ int escape_disabled : 1,
+ abbrevs_disabled : 1;
+ } flags;
+ /* to get out */
+ int abort; /* exit subsystem */
+ int exit_status;
+} ss_data;
+
+#define CURRENT_SS_VERSION 1
+
+#define ss_info(sci_idx) (_ss_table[sci_idx])
+#define ss_current_request(sci_idx,code_ptr) \
+ (*code_ptr=0,ss_info(sci_idx)->current_request)
+void ss_unknown_function();
+void ss_delete_info_dir();
+int ss_execute_line();
+char **ss_parse();
+ss_abbrev_info *ss_abbrev_initialize PROTOTYPE((char *, int *));
+void ss_page_stdin();
+
+extern ss_data **_ss_table;
+extern char *ss_et_msgs[];
+
+#if 0
+extern pointer malloc PROTOTYPE((unsigned));
+extern pointer realloc PROTOTYPE((pointer, unsigned));
+extern pointer calloc PROTOTYPE((unsigned, unsigned));
+#ifndef sun
+extern int exit PROTOTYPE((int));
+#endif
+#endif /* 0 */
+
+#endif /* _ss_internal_h */
--- /dev/null
+ command_table ss_std_requests;
+
+ request ss_self_identify, "Identify the subsystem.",
+ ".",
+ (dont_list, dont_summarize);
+
+ request ss_help, "Display info on command or topic.",
+ help;
+
+ unimplemented
+ ss_list_help,
+ "List topics for which help is available.",
+ list_help, lh;
+
+ request ss_list_requests, "List available commands.",
+ list_requests, lr, "?";
+
+ request ss_quit, "Leave the subsystem.",
+ quit, q;
+
+ unimplemented
+ ss_abbrev,
+ "Enable/disable abbreviation processing of request lines.",
+ abbrev, ab;
+
+ unimplemented
+ ss_execute,
+ "Execute a UNIX command line.",
+ execute, e;
+
+ unimplemented
+ ss_summarize_requests,
+ "Produce a list of the most commonly used requests.",
+ "?";
+
+ request ss_subsystem_name,
+ "Return the name of this subsystem.",
+ subsystem_name,
+ (dont_list);
+
+ request ss_subsystem_version,
+ "Return the version of this subsystem.",
+ subsystem_version,
+ (dont_list);
+
+ end;