--- /dev/null
+Changes up until now:
+
+ * Kerberos database format changed (but in a backwards compatible way).
+ Once you go forward, no going back.
+
+[tytso:19930304.2209EST]
+
+ Removed SERVER_MISMATCH error message. Fixed bug in
+ validate_tgs_request() to handle forwarded tickets correctly.
+
+[tytso:19930309.2201EST]
+
+ Function prototype for krb5_sname_to_principal changing to
+ include use of name type. This is an API Change.
+
+[tytso:19930316.0225EST]
+
+ (last week) --- fixed ASN.1 checksuming problem
+
+ Fixed get_cred() so that you don't get new credentials if the
+ second ticket matches.
+
--- /dev/null
+[tytso:19920921.1439EDT]
+
+Add debugging code to the free subroutines, such as
+krb5_free_keyblock() to catch cases when NULL is passed to them. This
+should be a compile-time option, of course...
+
+
--- /dev/null
+# make source-tree symlinks to generated source-files,
+# so that synctree-generated shadows of the source-tree will have access
+# to the generated files.
+# this should be run in the shadow-dir, after synctree completes.
+
+#attach krb5
+#synctree -s /mit/krb5/src -d .
+foreach f ( include/krb5/error_tables lib/error_tables kdc comerr ss)
+ ln -s /mit/krb5/build/@sys/${f}/*_err.[ch] ${f}
+ ls -ls ${f}/*_err.[ch]
+ end
--- /dev/null
+# This file containes the changes made to the kerberos code
+# for porting to various platforms:
+
+Date System File Changes
+10/?/91 all cr_auth_rply.c Added files to lib/krb425 so
+ cr_err_reply.c that the kdc could handle v4
+ cr_ticket.c AS and TGS requests.
+ create_ciph.c
+ month_sname.c
+ log.c
+ one.c
+ stime.c
+
+10/2/91 hpux9000 com_err/compile_et.c Added hpux to i386 to include
+ strcasecmp routine which is not
+ in the hpux stdc library.
+
+10/2/91 hpux9000 com_err/et_lex.lex.l Added hpux ifdef to use strrchr
+ instead of rindex.
+
+10/2/91 hpux9000 ss/cmd_tbl.l Added hpux ifdef to use strrchr
+ instead of rindex.
+
+10/2/91 hpux9000 ss/ss_internal.h Added hpux ifdef to use strrchr
+ instead of rindex, strchr instead of
+ index, and memcpy of bcopy.
+
+10/7/91 hpux9000 ss/listen.c ifndef hpux to "not" declare index().
+
+10/2/91 hpux9000 ss/mk_cmds.c Changed mk_cmds to use "ss.h" instead
+ of <ss.h> i.e.
+ fputs("#include <ss.h>\n\n", output_file); =>
+ fputs("#include \"ss.h\"\n\n", output_file);
+
+10/3/91 hpux9000 include/fake-stdlib.h ifndef hpux on declaration of strlen
+ usr2/krb5/isode-interim/include
+
+10/3/91 hpux9000 lib/os/gen_rname.c ifndef hpux on include of
+ kdc/do_as_req.c <arpa/inet.h>
+ kdc/do_tgs_req.c
+ kdc/kerberos_v4.c
+ kdc/network.c
+ slave/kpropd.c
+ appl/popper/pop_init.c
+ appl/user-user/client.c
+ appl/user-user/server.c
+ lib/krb425/mk_priv.c
+ lib/krb425/rd_priv.c
+ lib/krb425/mk_safe.c
+ lib/krb425/rd_safe.c
+
+ -- Where is the declaration of inet_ntoa() and related functions
+ on HPUX? --
+
+10/4/91 hpux9000 include/krb5/stock/config.h Added ifdef SYSV which
+ redefines random,srandom,
+ and utimes to rand,srand,
+ and utime
+
+ -- Are these functions sufficiently compatible? The changes
+ should be in osconf.h, not config.h (or maybe somewhere else). --
+
+10/4/91 hpux9000 lib/des425/des.h Added #include <krb5/asn1.h> to
+ get bzero() and bcopy() defines.
+
+ -- Wrong fix. --
+
+10/7/91 hpux9000 lib/os/strcasecmp.c Added routines strncasecmp() and
+ strcasecmp() into new file strcasecmp.c.
+ These routines are included if the
+ the variable NEED_STRCASECMP is defined.
+ For hpux this is defined into the
+ variable StandardDefines in
+ site.def.hp9000. The Imakefile file for
+ lib/os was also updated to build
+ strcasecmp.c
+
+ -- Maybe. Should we instead fix the library not to use
+ strcasecmp()? The only use appears to be in os/hst_realm.c. */
+
+10/7/91 hpux9000 appl/movemail.c Added #ifdef SYSV => to undefine
+ MAIL_USE_FLOCK since real system v uses
+ lockf or POSIX style file locks. Also
+ included <krb5/asn1.h> so that bcmp and
+ rindex are defined to something
+ available on this platform.
+
+ -- Do SYSV systems want to avoid locking files, or do they want to
+ use lockf/fcntl to lock files? <krb5/asn1.h> is the wrong file
+ to include. --
+
+10/7/91 hpux9000 appl/popper/popper.h Ifdef SANDIA to include asn1.h to
+ define a system dependant bzero and
+ index. Also defined a file_lock to
+ replace the system dependent flock().
+
+ appl/popper/pop_updt.c Use file_lock defined in popper.h
+ appl/popper/pop_dropcopy.c
+
+ -- Does lockf() work on POSIX, or do you need to use fcntl directly?
+ Including asn1.h is wrong. */
+
+
+10/7/91 hpux9000 slave/kprop.c Ifdef SANDIA to use file locking
+ routines in lib/os/lock_file.c, which
+ takes into account POSIX file locking
+ and does not blanketly use flock().
+
+ -- Already fixed in MIT source. --
+
+10/7/91 hpux9000 lib/krb425/des_sched.c Ifndef SANDIA to remove the
+ (BUG FIX) des_key_sched() routine from this
+ really file. It was a noop but is necessary
+ for the kdc to handle v4 kinits. By
+ removing, the "good" des_key_sched
+ in lib/des425/key_sched.c will now
+ be used.
+
+ -- Probably put off to post-beta. --
+
+11/12/91 All lib/krb/rd_req_dec.c: BUG fix reset tktauthent->ticket to
+ 0 after krb5_auth_to_rep call so
+ that if cleanup is done req->ticket
+ is not freed up.
+
+ -- Similar fix installed. --
+
+11/15/91 all krb4_rd_req.c Added file to lib/krb425 so
+ kdc would not use the krb_rd_req
+ routine in libkrb425.a. The rd_req
+ in libkrb425.a does not handle a
+ true version 4 mk_req.
+
+11/15/91 all kdc/kerberos_v4.c Ifdef SANDIA to call krb4_rd_req
+ instead of the rd_req in krb425.
+
+
+12/4/91 All lib/krb425/425data.c Setup the variables ky and
+ lib/krb425/krb4_rd_req.c serv_key in 425data.c so that
+ lib/krb425/set_key.c the krb_set_key routine which
+ was located there could be
+ replaced with the krb_set_key
+ routine in set_key.c. Set_key.c
+ which is used for lib425
+ krb_rd_req, uses a different
+ global service key than
+ krb4_rd_req, so we added the
+ setting of ky and serv_key there
+ also so that the same routine
+ could be used for krb4_rd_req
+ and (lib425) krb_rd_req.
+
+ -- ? --
+
+
+
+12/18/91 All lib/krb/getcredswopt.c Added new routines
+ krb5_get_credentials_wkdcopt
+ krb5_get_cred_from_kdc_wkdcopt
+ krb5_get_cred_via_tgt_wkdcopt
+
+ which allow applications to
+ implement forwarding/proxy and
+ other kdc options.
+
+ -- There is no such file in the archive. --
+
+12/18/91 All lib/krb/int-proto.h Added calls for new routine
+ krb5_get_cred_via_tgt_wkdcopt.
+
+12/18/91 All lib/krb/copy_addrs.c Added routine :
+ krb5_append_addresses() which
+ allows appending addresses to a
+ list of addresses. Used for
+ proxy and forwarding.
+
+ -- Modified version installed. --
+
+12/18/91 All lib/krb/copy_checksum.c Renamed copy_checksum.c to
+ copy_cksum.c so that it would
+ fit into the 14 character limit
+ of the archive program ar.
+
+ -- Should do this for beta 2. --
+
+12/18/91 All lib/krb/Imakefile Changed to add new name for
+ copy_checksum.c and to add the
+ file getcredswopt.c
+
+12/18/91 All appl/sample/sserver/sserver.c Added new checks for proxy
+ appl/sample/sclient/sclient.c and forwarded tickets.
+
+12/18/91 hpux lib/syslog.c Ifdefed out the syslog routines
+ for hpux and set vsyslog to
+ simply call hpuxs syslog library
+ routine.
+
+ -- Shouldn't this change go into a config file? --
+
+1/29/92 ALL lib/krb/copy_auth.c BUG fix : check for input
+ reference ptr == 0, if so
+ return 0. If not done suns
+ core dump.
+
+ -- Is this needed? I've never had a NULL pointer core dump in this
+ code. --
+
+2/13/92 ALL lib/os/an_to_ln.c For Sandia if /etc/aname does
+ (sandia only) not exist then use the "other"
+ krb5_aname_to_localname as if
+ USE_DBM_LNAME was not defined.
+
+2/18/92 ALL lib/krb/copy_data.c Modified so that the structure
+ assignment is not necessary.
+ Also added some null pointer,
+ and zero length checks.
+
+ -- Is this needed? When will this function be called with a zero
+ length krb5_data structure? --
+
+3/17/92 unicos and lib/asn1/asn1glue.h Changed xmalloc define so
+ sysvimp that if 0 len is passed
+ at least 1 byte is malloc'd.
+
+ -- asn.1 source is changed so that malloc is not called when
+ the size is 0, but NULL is returned unconditionally; this
+ fix is not needed. --
+
+4/20/92 ALL include/krb5/error_tables/krb5_err.h Added error
+ lib/error_tables/krb5_err.et KRB5KDC_ERR_KEY_EXPIRED
+ include/krb5/errors.h to explain expired
+ passwords
+
+ -- This is a protocol change. Can we do it? --
+
+5/3/92 ALL lib/asn.1/adat2kadat.c Bug fix which allows passing
+ of ticket authoriztion info.
+
+ -- Simpler fix installed ("rv->next" should have been "rv"). --
+
+5/4/92 ALL lib/os/read_pwd.c Added better signal catching
+ facilities. SunOS would core
+ dump on SIGQUIT signals when
+ in krb5_read_password().
+
+ -- What's wrong with that? Dumping core is standard procedure
+ for SIGQUIT. --
--- /dev/null
+integrate new DES implementation (after beta)
+
+eliminate ISODE dependence (after beta)
+
+look at sandia changes (contact gmachin@somnet.sandia.gov):
+
+ admin server
+
+ BSD applications
+
+ kdc/v4 changes
+
+specific coding items:
+----------------------
+
+new protocol revision
+
+principal type change (krb5_data ** -> struct)
+
+merge local changes into latest telnet
+
+telnet client address checking (hard to get hold of the addr?)
+
+generalize walk realm tree, add to API
+
+uuserver adds a ticket to the credentials cache each time it runs,
+even if the client is using the same ticket.
+
+other XXX stuff in code
+
+
+KDC bulletproofing (after beta)
+
+KDC statistic gathering (after beta)
+
+admin server (after beta)
+
+applications
+ nfs
+ discuss (?)
+ X11
+
+realm "quality" code and/or hooks (tytso) (after beta?)
+
+alloca/tempalloc (after beta)
+
+test suites (after beta)
+
+KDC transited field comma quoting
+
+verify that memcpy/memcmp is in use for principal names
+Make sure that all comparisons of principal components (realms, etc.)
+use memcmp instead of strcmp --- principal components can have nulls
+in them! (Don't blame me, blame OSI!)
+ --> kdc realm transiting
+
+code boiling between scc_ and fcc_ (after beta)
+
+remove 32 bit dependencies (esp. in md4 and md5) (after beta)
+
+documentation issues:
+--------------------
+
+manual pages (programs, library)
+
+Manual pages for appl/bsd need to be fixed!!!!
+
+what we depend on in the system (kprop, kdc: sockets; etc)
+
+build/installation doc:
+ document expected "warnings", how to build it, configuration options
+ picking up ss, com_err, makedepend, imake separately
+ unifdef: ftp.uu.net:/bsd-sources/pgrm/unifdef/
+
+
+operation doc
+ interrealm gotchas
+
+RFC
+ DES bit ordering
+ ap_rep vs. subsession keys
+ assign "no meaning" #s for others?
+ byte-wise comparison for principal names
+ DER, "Zulu" format timestamps
+
+API doc (tytso maintaining)
+
+bug list
+
+testing issues:
+--------------
+
+mprof/mnemosyne
+
+error paths
+
+DCE interoperability
+
+
+
+
+----------------------------------------------------------------
+
+library name problems: with shared libraries cryptoconf.o can't be
+replaced. Change docs to require static linking.
+
+
+----------------------------------------------------------------
+
+
+Document new functions:
+
+krb5_free_address
+krb5_append_addresses
+krb5_gc_via_2tgt
+
+--------------------------------------------------------------
+
+Bad comment message in KRB5-aux.h (KRB5-types.c should be KRB5_tables.c)
--- /dev/null
+ignore telnet.90.09.14
+ignore *.TXT
+link arpa
+ignore old-telnet
--- /dev/null
+#define OPTS_FORWARD_CREDS 0x00000002
+#define OPTS_FORWARDABLE_CREDS 0x00000001
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Id$
+ *
+ * Copyright 1989,1990 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * 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 the field bits for Kerberos protocol
+ * version 5.
+ */
+
+
+#ifndef KRB5_FIELDBITS__
+#define KRB5_FIELDBITS__
+
+/* kdc_options for kdc_request */
+/* options is 32 bits; each host is responsible to put the 4 bytes
+ representing these bits into net order before transmission */
+/* #define KDC_OPT_RESERVED 0x80000000 */
+#define KDC_OPT_FORWARDABLE 0x40000000
+#define KDC_OPT_FORWARDED 0x20000000
+#define KDC_OPT_PROXIABLE 0x10000000
+#define KDC_OPT_PROXY 0x08000000
+#define KDC_OPT_ALLOW_POSTDATE 0x04000000
+#define KDC_OPT_POSTDATED 0x02000000
+/* #define KDC_OPT_UNUSED 0x01000000 */
+#define KDC_OPT_RENEWABLE 0x00800000
+/* #define KDC_OPT_UNUSED 0x00400000 */
+/* #define KDC_OPT_RESERVED 0x00200000 */
+/* #define KDC_OPT_RESERVED 0x00100000 */
+/* #define KDC_OPT_RESERVED 0x00080000 */
+/* #define KDC_OPT_RESERVED 0x00040000 */
+/* #define KDC_OPT_RESERVED 0x00020000 */
+/* #define KDC_OPT_RESERVED 0x00010000 */
+/* #define KDC_OPT_RESERVED 0x00008000 */
+/* #define KDC_OPT_RESERVED 0x00004000 */
+/* #define KDC_OPT_RESERVED 0x00002000 */
+/* #define KDC_OPT_RESERVED 0x00001000 */
+/* #define KDC_OPT_RESERVED 0x00000800 */
+/* #define KDC_OPT_RESERVED 0x00000400 */
+/* #define KDC_OPT_RESERVED 0x00000200 */
+/* #define KDC_OPT_RESERVED 0x00000100 */
+/* #define KDC_OPT_RESERVED 0x00000080 */
+/* #define KDC_OPT_RESERVED 0x00000040 */
+/* #define KDC_OPT_RESERVED 0x00000020 */
+#define KDC_OPT_RENEWABLE_OK 0x00000010
+#define KDC_OPT_ENC_TKT_IN_SKEY 0x00000008
+/* #define KDC_OPT_UNUSED 0x00000004 */
+#define KDC_OPT_RENEW 0x00000002
+#define KDC_OPT_VALIDATE 0x00000001
+
+/* fields common which can be masked and copied */
+/* Old mask = KDC_OPT_FORWARDABLE | KDC_OPT_FORWARDED | KDC_OPT_PROXIABLE |
+ KDC_OPT_PROXY | KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED |
+ KDC_OPT_RENEWABLE */
+/*
+#define KDC_TKT_COMMON_MASK 0x7e800000
+*/
+/* New mask = KDC_OPT_FORWARDABLE | KDC_OPT_PROXIABLE |
+ KDC_OPT_ALLOW_POSTDATE | KDC_OPT_RENEWABLE */
+
+#define KDC_TKT_COMMON_MASK 0x54800000
+
+/* definitions for ap_options fields */
+/* ap_options are 32 bits; each host is responsible to put the 4 bytes
+ representing these bits into net order before transmission */
+#define AP_OPTS_RESERVED 0x80000000
+#define AP_OPTS_USE_SESSION_KEY 0x40000000
+#define AP_OPTS_MUTUAL_REQUIRED 0x20000000
+#define AP_OPTS_FORWARD_CREDS 0x10000000
+#define AP_OPTS_FORWARDABLE_CREDS 0x08000000
+/* #define AP_OPTS_RESERVED 0x04000000 */
+/* #define AP_OPTS_RESERVED 0x02000000 */
+/* #define AP_OPTS_RESERVED 0x01000000 */
+/* #define AP_OPTS_RESERVED 0x00800000 */
+/* #define AP_OPTS_RESERVED 0x00400000 */
+/* #define AP_OPTS_RESERVED 0x00200000 */
+/* #define AP_OPTS_RESERVED 0x00100000 */
+/* #define AP_OPTS_RESERVED 0x00080000 */
+/* #define AP_OPTS_RESERVED 0x00040000 */
+/* #define AP_OPTS_RESERVED 0x00020000 */
+/* #define AP_OPTS_RESERVED 0x00010000 */
+/* #define AP_OPTS_RESERVED 0x00008000 */
+/* #define AP_OPTS_RESERVED 0x00004000 */
+/* #define AP_OPTS_RESERVED 0x00002000 */
+/* #define AP_OPTS_RESERVED 0x00001000 */
+/* #define AP_OPTS_RESERVED 0x00000800 */
+/* #define AP_OPTS_RESERVED 0x00000400 */
+/* #define AP_OPTS_RESERVED 0x00000200 */
+/* #define AP_OPTS_RESERVED 0x00000100 */
+/* #define AP_OPTS_RESERVED 0x00000080 */
+/* #define AP_OPTS_RESERVED 0x00000040 */
+/* #define AP_OPTS_RESERVED 0x00000020 */
+/* #define AP_OPTS_RESERVED 0x00000010 */
+/* #define AP_OPTS_RESERVED 0x00000008 */
+/* #define AP_OPTS_RESERVED 0x00000004 */
+/* #define AP_OPTS_RESERVED 0x00000002 */
+/* #define AP_OPTS_RESERVED 0x00000001 */
+
+/* definitions for ad_type fields. */
+#define AD_TYPE_RESERVED 0x8000
+#define AD_TYPE_EXTERNAL 0x4000
+#define AD_TYPE_REGISTERED 0x2000
+
+#define AD_TYPE_FIELD_TYPE_MASK 0x1fff
+
+/* Ticket flags */
+/* flags are 32 bits; each host is responsible to put the 4 bytes
+ representing these bits into net order before transmission */
+/* #define TKT_FLG_RESERVED 0x80000000 */
+#define TKT_FLG_FORWARDABLE 0x40000000
+#define TKT_FLG_FORWARDED 0x20000000
+#define TKT_FLG_PROXIABLE 0x10000000
+#define TKT_FLG_PROXY 0x08000000
+#define TKT_FLG_MAY_POSTDATE 0x04000000
+#define TKT_FLG_POSTDATED 0x02000000
+#define TKT_FLG_INVALID 0x01000000
+#define TKT_FLG_RENEWABLE 0x00800000
+#define TKT_FLG_INITIAL 0x00400000
+#define TKT_FLG_PRE_AUTH 0x00200000
+#define TKT_FLG_HW_AUTH 0x00100000
+/* #define TKT_FLG_RESERVED 0x00080000 */
+/* #define TKT_FLG_RESERVED 0x00040000 */
+/* #define TKT_FLG_RESERVED 0x00020000 */
+/* #define TKT_FLG_RESERVED 0x00010000 */
+/* #define TKT_FLG_RESERVED 0x00008000 */
+/* #define TKT_FLG_RESERVED 0x00004000 */
+/* #define TKT_FLG_RESERVED 0x00002000 */
+/* #define TKT_FLG_RESERVED 0x00001000 */
+/* #define TKT_FLG_RESERVED 0x00000800 */
+/* #define TKT_FLG_RESERVED 0x00000400 */
+/* #define TKT_FLG_RESERVED 0x00000200 */
+/* #define TKT_FLG_RESERVED 0x00000100 */
+/* #define TKT_FLG_RESERVED 0x00000080 */
+/* #define TKT_FLG_RESERVED 0x00000040 */
+/* #define TKT_FLG_RESERVED 0x00000020 */
+/* #define TKT_FLG_RESERVED 0x00000010 */
+/* #define TKT_FLG_RESERVED 0x00000008 */
+/* #define TKT_FLG_RESERVED 0x00000004 */
+/* #define TKT_FLG_RESERVED 0x00000002 */
+/* #define TKT_FLG_RESERVED 0x00000001 */
+
+/* definitions for lr_type fields. */
+#define LR_TYPE_THIS_SERVER_ONLY 0x8000
+
+#define LR_TYPE_INTERPRETATION_MASK 0x7fff
+
+/* definitions for ad_type fields. */
+#define AD_TYPE_EXTERNAL 0x4000
+#define AD_TYPE_REGISTERED 0x2000
+
+#define AD_TYPE_FIELD_TYPE_MASK 0x1fff
+#define AD_TYPE_INTERNAL_MASK 0x3fff
+
+/* definitions for msec direction bit for KRB_SAFE, KRB_PRIV */
+#define MSEC_DIRBIT 0x8000
+#define MSEC_VAL_MASK 0x7fff
+
+#endif /* KRB5_FIELDBITS__ */
+
+
--- /dev/null
+/*
+ * $Source$
+ * $Id$
+ */
+
+#ifndef lint
+static char *rcsid_forward_c =
+ "$Id$";
+#endif /* lint */
+#define LIBC_SCCS
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE 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.
+ */
+
+
+/* General-purpose forwarding routines. These routines may be put into */
+/* libkrb5.a to allow widespread use */
+
+#ifdef KERBEROS
+#include <stdio.h>
+#include <pwd.h>
+#include <netdb.h>
+
+#include <krb5/krb5.h>
+#include <krb5/asn1.h>
+#include <krb5/crc-32.h>
+#include <krb5/los-proto.h>
+#include <krb5/ext-proto.h>
+
+#define TGTNAME "krbtgt" /* Else #include <krb5/kdb.h> */
+#define KRB5_DEFAULT_LIFE 60*60*8 /* 8 hours */
+/* helper function: convert flags to necessary KDC options */
+#define flags2options(flags) (flags & KDC_TKT_COMMON_MASK)
+
+
+
+/* Get a TGT for use at the remote host */
+krb5_error_code
+get_for_creds(etype, sumtype, rhost, client, enc_key, forwardable, outbuf)
+ const krb5_enctype etype;
+ const krb5_cksumtype sumtype;
+ char *rhost;
+ krb5_principal client;
+ krb5_keyblock *enc_key;
+ int forwardable; /* Should forwarded TGT also be forwardable? */
+ krb5_data *outbuf;
+{
+ struct hostent *hp;
+ krb5_address **addrs;
+ krb5_error_code retval;
+ krb5_data *scratch;
+ krb5_kdc_rep *dec_rep;
+ krb5_error *err_reply;
+ krb5_response tgsrep;
+ krb5_creds creds, tgt;
+ krb5_ccache cc;
+ krb5_flags kdcoptions;
+ krb5_timestamp now;
+ char *remote_host;
+ char **hrealms;
+ int i;
+
+ if (!rhost || !(hp = gethostbyname(rhost)))
+ return KRB5_ERR_BAD_HOSTNAME;
+
+ remote_host = malloc(strlen(hp->h_name)+1);
+ if (!remote_host)
+ return ENOMEM;
+ strcpy(remote_host, hp->h_name);
+
+ if (retval = krb5_get_host_realm(remote_host, &hrealms)) {
+ free(remote_host);
+ return retval;
+ }
+ if (!hrealms[0]) {
+ free(remote_host);
+ xfree(hrealms);
+ return KRB5_ERR_HOST_REALM_UNKNOWN;
+ }
+
+ /* Count elements */
+ for(i=0; hp->h_addr_list[i]; i++);
+
+ addrs = (krb5_address **) malloc ((i+1)*sizeof(*addrs));
+ if (!addrs)
+ return ENOMEM;
+
+ for(i=0; hp->h_addr_list[i]; i++) {
+ addrs[i] = (krb5_address *) malloc(sizeof(krb5_address));
+ if (addrs[i]) {
+ addrs[i]->addrtype = hp->h_addrtype;
+ addrs[i]->length = hp->h_length;
+ addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
+ if (!addrs[i]->contents) {
+ krb5_free_addresses(addrs);
+ return ENOMEM;
+ }
+ else
+ memcpy ((char *)addrs[i]->contents, hp->h_addr_list[i],
+ addrs[i]->length);
+ }
+ else {
+ return ENOMEM;
+ }
+ }
+ addrs[i] = 0;
+
+ memset((char *)&creds, 0, sizeof(creds));
+ if (retval = krb5_copy_principal(client, &creds.client))
+ return retval;
+
+ if (retval = krb5_build_principal_ext(&creds.server,
+ strlen(hrealms[0]),
+ hrealms[0],
+ sizeof(TGTNAME) - 1,
+ TGTNAME,
+ client->realm.length,
+ client->realm.data,
+ 0))
+ return retval;
+
+ creds.times.starttime = 0;
+ if (retval = krb5_timeofday(&now)) {
+ return retval;
+ }
+ creds.times.endtime = now + KRB5_DEFAULT_LIFE;
+ creds.times.renew_till = 0;
+
+ if (retval = krb5_cc_default(&cc)) {
+ return retval;
+ }
+
+ /* fetch tgt directly from cache */
+ if (retval = krb5_cc_retrieve_cred (cc,
+ KRB5_TC_MATCH_SRV_NAMEONLY,
+ &creds,
+ &tgt)) {
+ return retval;
+ }
+
+ /* tgt->client must be equal to creds.client */
+ if (!krb5_principal_compare(tgt.client, creds.client))
+ return KRB5_PRINC_NOMATCH;
+
+ if (!tgt.ticket.length)
+ return(KRB5_NO_TKT_SUPPLIED);
+
+ kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED;
+
+ if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */
+ kdcoptions &= ~(KDC_OPT_FORWARDABLE);
+
+ if (retval = krb5_send_tgs(kdcoptions, &creds.times, etype, sumtype,
+ creds.server,
+ addrs,
+ creds.authdata,
+ 0, /* no padata */
+ 0, /* no second ticket */
+ &tgt, &tgsrep))
+ return retval;
+
+#undef cleanup
+#define cleanup() free(tgsrep.response.data)
+
+ switch (tgsrep.message_type) {
+ case KRB5_TGS_REP:
+ break;
+ case KRB5_ERROR:
+ default:
+ if (!krb5_is_krb_error(&tgsrep.response)) {
+ retval = KRB5KRB_AP_ERR_MSG_TYPE;
+ } else
+ retval = decode_krb5_error(&tgsrep.response, &err_reply);
+ if (retval) {
+ cleanup();
+ return retval; /* neither proper reply nor error! */
+ }
+
+ retval = err_reply->error + ERROR_TABLE_BASE_krb5;
+
+ krb5_free_error(err_reply);
+ cleanup();
+ return retval;
+ }
+ retval = krb5_decode_kdc_rep(&tgsrep.response,
+ &tgt.keyblock,
+ etype, /* enctype */
+ &dec_rep);
+
+ cleanup();
+ if (retval)
+ return retval;
+#undef cleanup
+#define cleanup() {\
+ memset((char *)dec_rep->enc_part2->session->contents, 0,\
+ dec_rep->enc_part2->session->length);\
+ krb5_free_kdc_rep(dec_rep); }
+
+ if (dec_rep->msg_type != KRB5_TGS_REP) {
+ retval = KRB5KRB_AP_ERR_MSG_TYPE;
+ cleanup();
+ return retval;
+ }
+
+ /* now it's decrypted and ready for prime time */
+
+ if (!krb5_principal_compare(dec_rep->client, tgt.client)) {
+ cleanup();
+ return KRB5_KDCREP_MODIFIED;
+ }
+
+ if (retval = mk_cred(dec_rep,
+ etype,
+ enc_key,
+ 0,
+ 0,
+ outbuf))
+ return retval;
+
+ krb5_free_kdc_rep(dec_rep);
+
+ return retval;
+#undef cleanup
+}
+
+
+
+/* Create asn.1 encoded KRB-CRED message from the kdc reply. */
+krb5_error_code
+mk_cred(dec_rep, etype, key, sender_addr, recv_addr, outbuf)
+krb5_kdc_rep *dec_rep;
+krb5_enctype etype;
+krb5_keyblock *key;
+krb5_address *sender_addr;
+krb5_address *recv_addr;
+krb5_data *outbuf;
+{
+ krb5_error_code retval;
+ krb5_encrypt_block eblock;
+ krb5_cred ret_cred;
+ krb5_cred_enc_part cred_enc_part;
+ krb5_data *scratch;
+
+ if (!valid_etype(etype))
+ return KRB5_PROG_ETYPE_NOSUPP;
+
+ ret_cred.tickets = (krb5_ticket **) calloc(2, sizeof(*ret_cred.tickets));
+ if (!ret_cred.tickets)
+ return ENOMEM;
+ ret_cred.tickets[0] = dec_rep->ticket;
+ ret_cred.tickets[1] = 0;
+
+ ret_cred.enc_part.etype = etype;
+ ret_cred.enc_part.kvno = 0;
+
+ cred_enc_part.creds = (krb5_cred_enc_struct **)
+ calloc(2, sizeof(*cred_enc_part.creds));
+ if (!cred_enc_part.creds) {
+ krb5_free_tickets(ret_cred.tickets);
+ return ENOMEM;
+ }
+ cred_enc_part.creds[0] = (krb5_cred_enc_struct *)
+ malloc(sizeof(*cred_enc_part.creds[0]));
+ if (!cred_enc_part.creds[0]) {
+ krb5_free_tickets(ret_cred.tickets);
+ krb5_free_cred_enc_part(cred_enc_part);
+ return ENOMEM;
+ }
+ cred_enc_part.creds[0]->session = dec_rep->enc_part2->session;
+ cred_enc_part.creds[0]->nonce = 0;
+
+ if (retval = krb5_us_timeofday(&cred_enc_part.creds[0]->timestamp,
+ &cred_enc_part.creds[0]->usec))
+ return retval;
+
+ cred_enc_part.creds[0]->s_address = (krb5_address *)sender_addr;
+ cred_enc_part.creds[0]->r_address = (krb5_address *)recv_addr;
+ cred_enc_part.creds[0]->client = dec_rep->client;
+ cred_enc_part.creds[0]->server = dec_rep->enc_part2->server;
+ cred_enc_part.creds[0]->flags = dec_rep->enc_part2->flags;
+ cred_enc_part.creds[0]->times = dec_rep->enc_part2->times;
+ cred_enc_part.creds[0]->caddrs = dec_rep->enc_part2->caddrs;
+
+ cred_enc_part.creds[1] = 0;
+
+ /* start by encoding to-be-encrypted part of the message */
+
+ if (retval = encode_krb5_enc_cred_part(&cred_enc_part, &scratch))
+ return retval;
+
+#define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); krb5_free_data(scratch); }
+
+ /* put together an eblock for this encryption */
+
+ krb5_use_cstype(&eblock, etype);
+ ret_cred.enc_part.ciphertext.length = krb5_encrypt_size(scratch->length,
+ eblock.crypto_entry);
+ /* add padding area, and zero it */
+ if (!(scratch->data = realloc(scratch->data,
+ ret_cred.enc_part.ciphertext.length))) {
+ /* may destroy scratch->data */
+ xfree(scratch);
+ return ENOMEM;
+ }
+ memset(scratch->data + scratch->length, 0,
+ ret_cred.enc_part.ciphertext.length - scratch->length);
+ if (!(ret_cred.enc_part.ciphertext.data =
+ malloc(ret_cred.enc_part.ciphertext.length))) {
+ retval = ENOMEM;
+ goto clean_scratch;
+ }
+
+#define cleanup_encpart() {\
+ (void) memset(ret_cred.enc_part.ciphertext.data, 0, \
+ ret_cred.enc_part.ciphertext.length); \
+ free(ret_cred.enc_part.ciphertext.data); \
+ ret_cred.enc_part.ciphertext.length = 0; \
+ ret_cred.enc_part.ciphertext.data = 0;}
+
+ /* do any necessary key pre-processing */
+ if (retval = krb5_process_key(&eblock, key)) {
+ goto clean_encpart;
+ }
+
+#define cleanup_prockey() {(void) krb5_finish_key(&eblock);}
+
+ /* call the encryption routine */
+ if (retval = krb5_encrypt((krb5_pointer) scratch->data,
+ (krb5_pointer)
+ ret_cred.enc_part.ciphertext.data,
+ scratch->length, &eblock,
+ 0)) {
+ goto clean_prockey;
+ }
+
+ /* private message is now assembled-- do some cleanup */
+ cleanup_scratch();
+
+ if (retval = krb5_finish_key(&eblock)) {
+ cleanup_encpart();
+ return retval;
+ }
+ /* encode private message */
+ if (retval = encode_krb5_cred(&ret_cred, &scratch)) {
+ cleanup_encpart();
+ return retval;
+ }
+
+ cleanup_encpart();
+
+ *outbuf = *scratch;
+ xfree(scratch);
+ return 0;
+
+ clean_prockey:
+ cleanup_prockey();
+ clean_encpart:
+ cleanup_encpart();
+ clean_scratch:
+ cleanup_scratch();
+
+ return retval;
+#undef cleanup_prockey
+#undef cleanup_encpart
+#undef cleanup_scratch
+}
+
+
+
+/* Decode, decrypt and store the forwarded creds in the local ccache. */
+krb5_error_code
+rd_and_store_for_creds(inbuf, ticket, lusername)
+ krb5_data *inbuf;
+ krb5_ticket *ticket;
+ char *lusername;
+{
+ krb5_encrypt_block eblock;
+ krb5_creds creds;
+ krb5_error_code retval;
+ char ccname[35];
+ krb5_ccache ccache = NULL;
+ struct passwd *pwd;
+
+ if (retval = rd_cred(inbuf, ticket->enc_part2->session,
+ &creds, 0, 0)) {
+ return(retval);
+ }
+
+ if (!(pwd = (struct passwd *) getpwnam(lusername))) {
+ return -1;
+ }
+
+ sprintf(ccname, "FILE:/tmp/krb5cc_%d", pwd->pw_uid);
+
+ if (retval = krb5_cc_resolve(ccname, &ccache)) {
+ return(retval);
+ }
+
+ if (retval = krb5_cc_initialize(ccache,
+ ticket->enc_part2->client)) {
+ return(retval);
+ }
+
+ if (retval = krb5_cc_store_cred(ccache, &creds)) {
+ return(retval);
+ }
+
+ if (retval = chown(ccname+5, pwd->pw_uid, -1)) {
+ return(retval);
+ }
+
+ return retval;
+}
+
+
+
+extern krb5_deltat krb5_clockskew;
+#define in_clock_skew(date) (abs((date)-currenttime) < krb5_clockskew)
+
+/* Decode the KRB-CRED message, and return creds */
+krb5_error_code
+rd_cred(inbuf, key, creds, sender_addr, recv_addr)
+const krb5_data *inbuf;
+const krb5_keyblock *key;
+krb5_creds *creds; /* Filled in */
+const krb5_address *sender_addr; /* optional */
+const krb5_address *recv_addr; /* optional */
+{
+ krb5_error_code retval;
+ krb5_encrypt_block eblock;
+ krb5_cred *credmsg;
+ krb5_cred_enc_part *credmsg_enc_part;
+ krb5_data *scratch;
+ krb5_timestamp currenttime;
+
+ if (!krb5_is_krb_cred(inbuf))
+ return KRB5KRB_AP_ERR_MSG_TYPE;
+
+ /* decode private message */
+ if (retval = decode_krb5_cred(inbuf, &credmsg)) {
+ return retval;
+ }
+
+#define cleanup_credmsg() {(void)xfree(credmsg->enc_part.ciphertext.data); (void)xfree(credmsg);}
+
+ if (!(scratch = (krb5_data *) malloc(sizeof(*scratch)))) {
+ cleanup_credmsg();
+ return ENOMEM;
+ }
+
+#define cleanup_scratch() {(void)memset(scratch->data, 0, scratch->length); (void)xfree(scratch->data);}
+
+ if (retval = encode_krb5_ticket(credmsg->tickets[0], &scratch)) {
+ cleanup_credmsg();
+ cleanup_scratch();
+ return(retval);
+ }
+
+ creds->ticket = *scratch;
+ if (!(creds->ticket.data = malloc(scratch->length))) {
+ xfree(creds->ticket.data);
+ return ENOMEM;
+ }
+ memcpy((char *)creds->ticket.data, (char *) scratch->data, scratch->length);
+
+ cleanup_scratch();
+
+ if (!valid_etype(credmsg->enc_part.etype)) {
+ cleanup_credmsg();
+ return KRB5_PROG_ETYPE_NOSUPP;
+ }
+
+ /* put together an eblock for this decryption */
+
+ krb5_use_cstype(&eblock, credmsg->enc_part.etype);
+ scratch->length = credmsg->enc_part.ciphertext.length;
+
+ if (!(scratch->data = malloc(scratch->length))) {
+ cleanup_credmsg();
+ return ENOMEM;
+ }
+
+ /* do any necessary key pre-processing */
+ if (retval = krb5_process_key(&eblock, key)) {
+ cleanup_credmsg();
+ cleanup_scratch();
+ return retval;
+ }
+
+#define cleanup_prockey() {(void) krb5_finish_key(&eblock);}
+
+ /* call the decryption routine */
+ if (retval = krb5_decrypt((krb5_pointer) credmsg->enc_part.ciphertext.data,
+ (krb5_pointer) scratch->data,
+ scratch->length, &eblock,
+ 0)) {
+ cleanup_credmsg();
+ cleanup_scratch();
+ cleanup_prockey();
+ return retval;
+ }
+
+ /* cred message is now decrypted -- do some cleanup */
+
+ cleanup_credmsg();
+
+ if (retval = krb5_finish_key(&eblock)) {
+ cleanup_scratch();
+ return retval;
+ }
+
+ /* now decode the decrypted stuff */
+ if (retval = decode_krb5_enc_cred_part(scratch, &credmsg_enc_part)) {
+ cleanup_scratch();
+ return retval;
+ }
+ cleanup_scratch();
+
+#define cleanup_mesg() {(void)xfree(credmsg_enc_part);}
+
+ if (retval = krb5_timeofday(¤ttime)) {
+ cleanup_mesg();
+ return retval;
+ }
+ if (!in_clock_skew(credmsg_enc_part->creds[0]->timestamp)) {
+ cleanup_mesg();
+ return KRB5KRB_AP_ERR_SKEW;
+ }
+
+ if (sender_addr && credmsg_enc_part->creds[0]->s_address &&
+ !krb5_address_compare(sender_addr,
+ credmsg_enc_part->creds[0]->s_address)) {
+ cleanup_mesg();
+ return KRB5KRB_AP_ERR_BADADDR;
+ }
+ if (recv_addr && credmsg_enc_part->creds[0]->r_address &&
+ !krb5_address_compare(recv_addr,
+ credmsg_enc_part->creds[0]->r_address)) {
+ cleanup_mesg();
+ return KRB5KRB_AP_ERR_BADADDR;
+ }
+
+ if (credmsg_enc_part->creds[0]->r_address) {
+ krb5_address **our_addrs;
+
+ if (retval = krb5_os_localaddr(&our_addrs)) {
+ cleanup_mesg();
+ return retval;
+ }
+ if (!krb5_address_search(credmsg_enc_part->creds[0]->r_address,
+ our_addrs)) {
+ krb5_free_addresses(our_addrs);
+ cleanup_mesg();
+ return KRB5KRB_AP_ERR_BADADDR;
+ }
+ krb5_free_addresses(our_addrs);
+ }
+
+ if (retval = krb5_copy_principal(credmsg_enc_part->creds[0]->client,
+ &creds->client)) {
+ return(retval);
+ }
+
+ if (retval = krb5_copy_principal(credmsg_enc_part->creds[0]->server,
+ &creds->server)) {
+ return(retval);
+ }
+
+ if (retval =
+ krb5_copy_keyblock_contents(credmsg_enc_part->creds[0]->session,
+ &creds->keyblock)) {
+ return(retval);
+ }
+
+#undef clean
+#define clean() {\
+ memset((char *)creds->keyblock.contents, 0, creds->keyblock.length);}
+
+ creds->times = credmsg_enc_part->creds[0]->times;
+ creds->is_skey = FALSE;
+ creds->ticket_flags = credmsg_enc_part->creds[0]->flags;
+
+ if (retval = krb5_copy_addresses(credmsg_enc_part->creds[0]->caddrs,
+ &creds->addresses)) {
+ clean();
+ return(retval);
+ }
+
+ creds->second_ticket.length = 0;
+
+ creds->authdata = 0;
+
+ cleanup_mesg();
+ return 0;
+#undef clean
+#undef cleanup_credmsg
+#undef cleanup_scratch
+#undef cleanup_prockey
+#undef cleanup_mesg
+}
+
+#endif /* KERBEROS */
--- /dev/null
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setenv.c 5.2 (Berkeley) 6/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <stdio.h>
+
+/*
+ * setenv --
+ * Set the value of the environmental variable "name" to be
+ * "value". If rewrite is set, replace any current value.
+ */
+setenv(name, value, rewrite)
+ register char *name, *value;
+ int rewrite;
+{
+ extern char **environ;
+ static int alloced; /* if allocated space before */
+ register char *C;
+ int l_value, offset;
+ char *malloc(), *realloc(), *_findenv();
+
+ if (*value == '=') /* no `=' in value */
+ ++value;
+ l_value = strlen(value);
+ if ((C = _findenv(name, &offset))) { /* find if already exists */
+ if (!rewrite)
+ return(0);
+ if (strlen(C) >= l_value) { /* old larger; copy over */
+ while (*C++ = *value++);
+ return(0);
+ }
+ }
+ else { /* create new slot */
+ register int cnt;
+ register char **P;
+
+ for (P = environ, cnt = 0; *P; ++P, ++cnt);
+ if (alloced) { /* just increase size */
+ environ = (char **)realloc((char *)environ,
+ (u_int)(sizeof(char *) * (cnt + 2)));
+ if (!environ)
+ return(-1);
+ }
+ else { /* get new space */
+ alloced = 1; /* copy old entries into it */
+ P = (char **)malloc((u_int)(sizeof(char *) *
+ (cnt + 2)));
+ if (!P)
+ return(-1);
+ bcopy(environ, P, cnt * sizeof(char *));
+ environ = P;
+ }
+ environ[cnt + 1] = NULL;
+ offset = cnt;
+ }
+ for (C = name; *C && *C != '='; ++C); /* no `=' in name */
+ if (!(environ[offset] = /* name + `=' + value */
+ malloc((u_int)((int)(C - name) + l_value + 2))))
+ return(-1);
+ for (C = environ[offset]; (*C = *name++) && *C != '='; ++C);
+ for (*C++ = '='; *C++ = *value++;);
+ return(0);
+}
+
+/*
+ * unsetenv(name) --
+ * Delete environmental variable "name".
+ */
+void
+unsetenv(name)
+ char *name;
+{
+ extern char **environ;
+ register char **P;
+ int offset;
+ char *_findenv();
+
+ while (_findenv(name, &offset)) /* if set multiple times */
+ for (P = &environ[offset];; ++P)
+ if (!(*P = *(P + 1)))
+ break;
+}
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getenv.c 5.5 (Berkeley) 6/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * getenv --
+ * Returns ptr to value associated with name, if any, else NULL.
+ */
+char *
+getenv(name)
+ char *name;
+{
+ int offset;
+ char *_findenv();
+
+ return(_findenv(name, &offset));
+}
+
+/*
+ * _findenv --
+ * Returns pointer to value associated with name, if any, else NULL.
+ * Sets offset to be the offset of the name/value combination in the
+ * environmental array, for use by setenv(3) and unsetenv(3).
+ * Explicitly removes '=' in argument name.
+ *
+ * This routine *should* be a static; don't use it.
+ */
+char *
+_findenv(name, offset)
+ register char *name;
+ int *offset;
+{
+ extern char **environ;
+ register int len;
+ register char **P, *C;
+
+ for (C = name, len = 0; *C && *C != '='; ++C, ++len);
+ for (P = environ; *P; ++P)
+ if (!strncmp(*P, name, len))
+ if (*(C = *P + len) == '=') {
+ *offset = P - environ;
+ return(++C);
+ }
+ return(NULL);
+}
--- /dev/null
+ignore README
+ignore pop3.rfc1081
+ignore pop3e.rfc1082
+ignore orig-makefiles
+ignore syslog_levels
--- /dev/null
+@(#)README 1.6 7/13/90
+
+
+The Post Office Protocol Server: Installation Guide
+
+
+
+Introduction
+
+The Post Office Protocol server runs on a variety of Unix[1] computers
+to manage electronic mail for Macintosh and MS-DOS computers. The
+server was developed at the University of California at Berkeley and
+conforms fully to the specifications in RFC 1081[2] and RFC 1082[3].
+The Berkeley server also has extensions to send electronic mail on
+behalf of a client.
+
+This guide explains how to install the POP server on your Unix
+computer. It assumes that you are not only familiar with Unix but also
+capable of performing Unix system administration.
+
+
+How to Obtain the Server
+
+The POP server is available via anonymous ftp from lilac.Berkeley.EDU
+(128.32.136.12). It is in two files in the pub directory: a compressed
+tar file popper.tar.Z and a Macintosh StuffIt archive in BinHex format
+called MacPOP.sit.hqx.
+
+
+Contents of the Distribution
+
+The distribution contains the following:
+
++ All of the C source necessary to create the server program.
+
++ A visual representation of how the POP system works.
+
++ Reprints of RFC 1081 and RFC 1082.
+
++ A HyperCard stack POP client implementation using MacTCP.
+
++ A man page for the popper daemon.
+
++ This guide.
+
+
+Compatibility
+
+The Berkeley POP server has been successfully tested on the following
+Unix operating systems:
+
++ Berkeley Systems Distribution 4.3
+
++ Sun Microsystems Operating System versions 3.5 and 4.0
+
++ Ultrix version 2.3
+
+The following POP clients operate correctly with the Berkeley POP server:
+
++ The Berkeley HyperMail HyperCard stack for the Apple Macintosh
+ (distributed with the server).
+
++ The Stanford University Macintosh Internet Protocol MacMH program.
+
++ The Stanford University Personal Computer Internet Protocol MH
+ program.
+
++ The mh version 6.0 programs for Unix.
+
+
+Support
+
+The Berkeley POP server is not officially supported and is without any
+warranty, explicit or implied. However, we are interested in your
+experiences using the server. Bugs, comments and suggestions should be
+sent electronically to netinfo@garnet.Berkeley.EDU.
+
+
+Operational Characteristics
+
+The POP Transaction Cycle
+
+The Berkeley POP server is a single program (called popper) that is
+launched by inetd when it gets a service request on the POP TCP port.
+(The official port number specified in RFC 1081 for POP version 3 is
+port 110. However, some POP3 clients attempt to contact the server at
+port 109, the POP version 2 port. Unless you are running both POP2 and
+POP3 servers, you can simply define both ports for use by the POP3
+server. This is explained in the installation instructions later on.)
+The popper program initializes and verifies that the peer IP address is
+registered in the local domain, logging a warning message when a
+connection is made to a client whose IP address does not have a
+canonical name. For systems using BSD 4.3 bind, it also checks to see
+if a cannonical name lookup for the client returns the same peer IP
+address, logging a warning message if it does not. The the server
+enters the authorization state, during which the client must correctly
+identify itself by providing a valid Unix userid and password on the
+server's host machine. No other exchanges are allowed during this
+state (other than a request to quit.) If authentication fails, a
+warning message is logged and the session ends. Once the user is
+identified, popper changes its user and group ids to match that of the
+user and enters the transaction state. The server makes a temporary
+copy of the user's maildrop (ordinarily in /usr/spool/mail) which is
+used for all subsequent transactions. These include the bulk of POP
+commands to retrieve mail, delete mail, undelete mail, and so forth. A
+Berkeley extension also allows the user to submit a mail parcel to the
+server who mails it using the sendmail program (this extension is
+supported in the HyperMail client distributed with the server). When
+the client quits, the server enters the final update state during which
+the network connection is terminated and the user's maildrop is updated
+with the (possibly) modified temporary maildrop.
+
+
+Logging
+
+The POP server uses syslog to keep a record of its activities. On
+systems with BSD 4.3 syslogging, the server logs (by default) to the
+"local0" facility at priority "notice" for all messages except
+debugging which is logged at priority "debug". The default log file is
+/usr/spool/mqueue/POPlog. These can be changed, if desired. On
+systems with 4.2 syslogging all messages are logged to the local log
+file, usually /usr/spool/mqueue/syslog.
+
+
+Debugging
+
+The popper program will log debugging information when the -d parameter
+is specified after its invocation in the inetd.conf file. Care should
+be exercised in using this option since it generates considerable
+output in the syslog file. Alternatively, the "-t <file-name>" option
+will place debugging information into file "<file-name>" using fprintf
+instead of syslog.
+
+For SunOS version 3.5, the popper program is launched by inetd from
+/etc/servers. This file does not allow you to specify command line
+arguments. Therefore, if you want to enable debugging, you can specify
+a shell script in /etc/servers to be launched instead of popper and in
+this script call popper with the desired arguments.
+
+
+Installation
+
+1. Examine this file for the latest information, warnings, etc.
+
+2. Check the Makefile for conformity with your system.
+
+3. Issue the make command in the directory containing the popper
+ source.
+
+4. Issue the make install command in the directory containing the
+ popper source to copy the program to /usr/etc.
+
+5. Enable syslogging:
+
+ + For systems with 4.3 syslogging:
+
+ Add the following line to the /etc/syslog.conf file:
+
+ local0.notice;local0.debug /usr/spool/mqueue/POPlog
+
+ Create the empty file /usr/spool/mqueue/POPlog.
+
+ Kill and restart the syslogd daemon.
+
+ + For systems with 4.2 syslogging:
+
+ Be sure that you are logging messages of priority 7 and higher.
+ For example:
+
+ 7/usr/spool/mqueue/syslog
+ 9/dev/null
+
+6. Update /etc/services:
+
+ Add the following line to the /etc/services file:
+
+ pop 110/tcp
+
+ Note: This is the official port number for version 3 of the
+ Post Office Protocol as defined in RFC 1081. However, some
+ POP3 clients use port 109, the port number for the previous
+ version (2) of POP. Therefore you may also want to add the
+ following line to the /etc/services file:
+
+ pop2 109/tcp
+
+ For Sun systems running yp, also do the following:
+
+ + Change to the /var/yp directory.
+
+ + Issue the make services command.
+
+7. Update the inetd daemon configuration. Include the second line ONLY if you
+ are running the server at both ports.
+
+ + On BSD 4.3 and SunOS 4.0 systems, add the following line to the
+ /etc/inetd.conf file:
+
+ pop stream tcp nowait root /usr/etc/popper popper
+ pop2 stream tcp nowait root /usr/etc/popper popper
+
+ + On Ultrix systems, add the following line to the
+ /etc/inetd.conf file:
+
+ pop stream tcp nowait /usr/etc/popper popper
+ pop2 stream tcp nowait /usr/etc/popper popper
+
+ + On SunOS 3.5 systems, add the following line to the
+ /etc/servers file:
+
+ pop tcp /usr/etc/popper
+ pop2 tcp /usr/etc/popper
+
+ Kill and restart the inetd daemon.
+
+You can confirm that the POP server is running on Unix by telneting to
+port 110 (or 109 if you set it up that way). For example:
+
+%telnet myhost 110
+Trying...
+Connected to myhost.berkeley.edu.
+Escape character is '^]'.
++OK UCB Pop server (version 1.6) at myhost starting.
+quit
+Connection closed by foreign host.
+
+
+Release Notes
+
+1.7 Extensive re-write of the maildrop processing code contributed by
+ Viktor Dukhovni <viktor@math.princeton.edu> that greatly reduces the
+ possibility that the maildrop can be corrupted as the result of
+ simultaneous access by two or more processes.
+
+ Added "pop_dropcopy" module to create a temporary maildrop from
+ the existing, standard maildrop as root before the setuid and
+ setgid for the user is done. This allows the temporary maildrop
+ to be created in a mail spool area that is not world read-writable.
+
+ This version does *not* send the sendmail "From " delimiter line
+ in response to a TOP or RETR command.
+
+ Encased all debugging code in #ifdef DEBUG constructs. This code can
+ be included by specifying the DEGUG compiler flag. Note: You still
+ need to use the -d or -t option to obtain debugging output.
+
+1.6 Corrects a bug that causes the server to crash on SunOS
+ 4.0 systems.
+
+ Uses varargs and vsprintf (if available) in pop_log and
+ pop_msg. This is enabled by the "HAVE_VSPRINTF"
+ compiler flag.
+
+ For systems with BSD 4.3 bind, performs a cannonical
+ name lookup and searches the returned address(es) for
+ the client's address, logging a warning message if it
+ is not located. This is enabled by the "BIND43"
+ comiler flag.
+
+ Removed all the includes from popper.h and distributed
+ them throughout the porgrams files, as needed.
+
+ Reformatted the source to convert tabs to spaces and
+ shorten lines for display on 80-column terminals.
+
+1.5 Creates the temporary maildrop with mode "600" and
+ immediately unlinks it.
+
+ Uses client's IP address in lieu of a canonical name if
+ the latter cannot be obtained.
+
+ Added "-t <file-name>" option. The presence of this
+ option causes debugging output to be placed in the file
+ "file-name" using fprintf instead of the system log
+ file using syslog.
+
+ Corrected maildrop parsing problem.
+
+1.4 Copies user's mail into a temporary maildrop on which
+ all subsequent activity is performed.
+
+ Added "pop_log" function and replaced "syslog" calls
+ throughout the code with it.
+
+1.3 Corrected updating of Status: header line.
+
+ Added strncasecmp for systems that do not have one.
+ Used strncasecmp in all appropriate places. This is
+ enabled by the STRNCASECMP compiler flag.
+
+1.2 Support for version 4.2 syslogging added. This is
+ enabled by the SYSLOG42 compiler flag.
+
+1.1 Several bugs fixed.
+
+
+Credits
+
+The POP server was written by Edward Moy and Austin Shelton with
+contributions from Robert Campbell (U.C. Berkeley) and Viktor Dukhovni
+(Princeton University). Edward Moy wrote the HyperMail stack and drew
+the POP operation diagram. This installation guide was written by
+Austin Shelton.
+
+
+Footnotes
+
+[1] Copyright (c) 1990 Regents of the University of California.
+ All rights reserved. The Berkeley software License Agreement
+ specifies the terms and conditions for redistribution. Unix is
+ a registered trademark of AT&T corporation. HyperCard and
+ Macintosh are registered trademarks of Apple Corporation.
+
+[2] M. Rose, Post Office Protocol - Version 3. RFC 1081, NIC,
+ November 1988.
+
+[3] M. Rose, Post Office Protocol - Version 3 Extended Service
+ Offerings. RFC 1082, NIC, November 1988.
--- /dev/null
+CSRCS = pop_dele.c pop_dropcopy.c pop_dropinfo.c \
+ pop_get_command.c pop_get_subcommand.c pop_init.c \
+ pop_last.c pop_list.c pop_log.c pop_lower.c \
+ pop_msg.c pop_parse.c pop_pass.c pop_quit.c \
+ pop_rset.c pop_send.c pop_stat.c pop_updt.c \
+ pop_user.c pop_xtnd.c pop_xmit.c popper.c
+
+OBJS = pop_dele.o pop_dropcopy.o pop_dropinfo.o \
+ pop_get_command.o pop_get_subcommand.o pop_init.o \
+ pop_last.o pop_list.o pop_log.o pop_lower.o \
+ pop_msg.o pop_parse.o pop_pass.o pop_quit.o \
+ pop_rset.o pop_send.o pop_stat.o pop_updt.o \
+ pop_user.o pop_xtnd.o pop_xmit.o popper.o
+
+SP_SRCS = pop_enter.c
+SP_OBJS = pop_enter.o
+
+DOCS = README pop3.rfc1081 pop3e.rfc1082 popper.8
+
+INCLUDES = popper.h version.h
+
+SRCS = ${CSRCS} ${INCLUDES}
+
+SCCS = /usr/ucb/sccs
+
+REL =
+
+MAKEFILE = Makefile
+
+# Options are:
+# BIND43 - If you are using BSD 4.3 domain
+# name service.
+# DEBUG - Include the debugging code. Note: You
+# still have to use the -d or -t flag to
+# enable debugging.
+# HAVE_VSPRINTF - If the vsprintf functions are available
+# on your system.
+# SYSLOG42 - For BSD 4.2 syslog (default is BSD 4.3
+# syslog).
+# STRNCASECMP - If you do not have strncasecmp()
+# KERBEROS - If you want authentication vis Kerberos
+# (tm)
+
+CFLAGS = -O -DBIND43 -DKERBEROS_PASSWD_HACK
+
+TARGET = popper
+
+TAR = ${TARGET}.tar
+
+INSTALLDIR = /usr/etc
+
+MANPAGE = popper.8
+
+CATPAGE = popper.0
+
+MANDIR = /usr/local/man/cat8
+
+LIBS = -lkrb -ldes
+
+all: ${TARGET} spop
+
+spop: ${SP_OBJS}
+ cc ${SP_OBJS} -o spop ${LIBS}
+
+${TARGET}: ${OBJS}
+ cc ${OBJS} -o ${TARGET} ${LIBS}
+
+tar: ${SRCS} ${DOCS} ${MAKEFILE}
+ rm -f ${TAR} *.Z*
+ tar -cvf ${TAR} ${SRCS} ${DOCS} ${MAKEFILE}
+ compress ${TAR}
+ uuencode ${TAR}.Z ${TAR}.Z > ${TAR}.Z.uuencoded
+ split -300 ${TAR}.Z.uuencoded
+ mv xaa ${TAR}.Z.uuencoded.xaa
+ mv xab ${TAR}.Z.uuencoded.xab
+ mv xac ${TAR}.Z.uuencoded.xac
+ mv xad ${TAR}.Z.uuencoded.xad
+ mv xae ${TAR}.Z.uuencoded.xae
+
+clean:
+ rm -f core *.o *.Z*
+ ${SCCS} clean
+
+install: ${TARGET}
+ install -c -m 700 -o root -g staff ${TARGET} ${INSTALLDIR}
+
+installman:
+ rm -f ${CATPAGE}
+ nroff -man ${MANPAGE} > ${CATPAGE}
+ install -c -m 644 -o root -g staff ${CATPAGE} ${MANDIR}
+
+edit:
+ ${SCCS} edit ${REL} ${SRCS}
+
+admin:
+ ${SCCS} admin -ft"Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n" ${SRCS}
+
+sources: ${SRCS}
+
+${SRCS}:
+ ${SCCS} get ${REL} $@ -p | expand -4 > $@
+
+${DOCS}:
+ ${SCCS} get README -p | expand -4 > README
+ ${SCCS} get popper.8 -p | expand -4 > popper.8
+
+${OBJS}: popper.h version.h
--- /dev/null
+
+
+
+
+
+
+Network Working Group M. Rose
+Request for Comments: 1081 TWG
+ November 1988
+
+ Post Office Protocol - Version 3
+
+
+Status of this Memo
+
+ This memo suggests a simple method for workstations to dynamically
+ access mail from a mailbox server. This RFC specifies a proposed
+ protocol for the Internet community, and requests discussion and
+ suggestions for improvements. Distribution of this memo is
+ unlimited.
+
+ This memo is based on RFC 918 (since revised as RFC 937). Although
+ similar in form to the original Post Office Protocol (POP) proposed
+ for the Internet community, the protocol discussed in this memo is
+ similar in spirit to the ideas investigated by the MZnet project at
+ the University of California, Irvine.
+
+ Further, substantial work was done on examining POP in a PC-based
+ environment. This work, which resulted in additional functionality
+ in this protocol, was performed by the ACIS Networking Systems Group
+ at Stanford University. The author gratefully acknowledges their
+ interest.
+
+Introduction
+
+ On certain types of smaller nodes in the Internet it is often
+ impractical to maintain a message transport system (MTS). For
+ example, a workstation may not have sufficient resources (cycles,
+ disk space) in order to permit a SMTP server and associated local
+ mail delivery system to be kept resident and continuously running.
+ Similarly, it may be expensive (or impossible) to keep a personal
+ computer interconnected to an IP-style network for long amounts of
+ time (the node is lacking the resource known as "connectivity").
+
+ Despite this, it is often very useful to be able to manage mail on
+ these smaller nodes, and they often support a user agent (UA) to aid
+ the tasks of mail handling. To solve this problem, a node which can
+ support an MTS entity offers a maildrop service to these less endowed
+ nodes. The Post Office Protocol - Version 3 (POP3) is intended to
+ permit a workstation to dynamically access a maildrop on a server
+ host in a useful fashion. Usually, this means that the POP3 is used
+ to allow a workstation to retrieve mail that the server is holding
+ for it.
+
+
+
+
+Rose [Page 1]
+\f
+RFC 1081 POP3 November 1988
+
+
+ For the remainder of this memo, the term "client host" refers to a
+ host making use of the POP3 service, while the term "server host"
+ refers to a host which offers the POP3 service.
+
+A Short Digression
+
+ This memo does not specify how a client host enters mail into the
+ transport system, although a method consistent with the philosophy of
+ this memo is presented here:
+
+ When the user agent on a client host wishes to enter a message
+ into the transport system, it establishes an SMTP connection to
+ its relay host (this relay host could be, but need not be, the
+ POP3 server host for the client host).
+
+ If this method is followed, then the client host appears to the MTS
+ as a user agent, and should NOT be regarded as a "trusted" MTS entity
+ in any sense whatsoever. This concept, along with the role of the
+ POP3 as a part of a split-UA model is discussed later in this memo.
+
+ Initially, the server host starts the POP3 service by listening on
+ TCP port 110. When a client host wishes to make use of the service,
+ it establishes a TCP connection with the server host. When the
+ connection is established, the POP3 server sends a greeting. The
+ client and POP3 server then exchange commands and responses
+ (respectively) until the connection is closed or aborted.
+
+ Commands in the POP3 consist of a keyword possibly followed by an
+ argument. All commands are terminated by a CRLF pair.
+
+ Responses in the POP3 consist of a success indicator and a keyword
+ possibly followed by additional information. All responses are
+ terminated by a CRLF pair. There are currently two success
+ indicators: positive ("+OK") and negative ("-ERR").
+
+ Responses to certain commands are multi-line. In these cases, which
+ are clearly indicated below, after sending the first line of the
+ response and a CRLF, any additional lines are sent, each terminated
+ by a CRLF pair. When all lines of the response have been sent, a
+ final line is sent, consisting of a termination octet (decimal code
+ 046, ".") and a CRLF pair. If any line of the multi-line response
+ begins with the termination octet, the line is "byte-stuffed" by
+ pre-pending the termination octet to that line of the response.
+ Hence a multi-line response is terminated with the five octets
+ "CRLF.CRLF". When examining a multi-line response, the client checks
+ to see if the line begins with the termination octet. If so and if
+ octets other than CRLF follow, the the first octet of the line (the
+ termination octet) is stripped away. If so and if CRLF immediately
+
+
+
+Rose [Page 2]
+\f
+RFC 1081 POP3 November 1988
+
+
+ follows the termination character, then the response from the POP
+ server is ended and the line containing ".CRLF" is not considered
+ part of the multi-line response.
+
+ A POP3 session progresses through a number of states during its
+ lifetime. Once the TCP connection has been opened and the POP3
+ server has sent the greeting, the session enters the AUTHORIZATION
+ state. In this state, the client must identify itself to the POP3
+ server. Once the client has successfully done this, the server
+ acquires resources associated with the client's maildrop, and the
+ session enters the TRANSACTION state. In this state, the client
+ requests actions on the part of the POP3 server. When the client has
+ finished its transactions, the session enters the UPDATE state. In
+ this state, the POP3 server releases any resources acquired during
+ the TRANSACTION state and says goodbye. The TCP connection is then
+ closed.
+
+The AUTHORIZATION State
+
+ Once the TCP connection has been opened by a POP3 client, the POP3
+ server issues a one line greeting. This can be any string terminated
+ by CRLF. An example might be:
+
+ S. +OK dewey POP3 server ready (Comments to: PostMaster@UDEL.EDU)
+
+ Note that this greeting is a POP3 reply. The POP3 server should
+ always give a positive response as the greeting.
+
+ The POP3 session is now in the AUTHORIZATION state. The client must
+ now issue the USER command. If the POP3 server responds with a
+ positive success indicator ("+OK"), then the client may issue either
+ the PASS command to complete the authorization, or the QUIT command
+ to terminate the POP3 session. If the POP3 server responds with a
+ negative success indicator ("-ERR") to the USER command, then the
+ client may either issue a new USER command or may issue the QUIT
+ command.
+
+ When the client issues the PASS command, the POP3 server uses the
+ argument pair from the USER and PASS commands to determine if the
+ client should be given access to the appropriate maildrop. If so,
+ the POP3 server then acquires an exclusive-access lock on the
+ maildrop. If the lock is successfully acquired, the POP3 server
+ parses the maildrop into individual messages (read note below),
+ determines the last message (if any) present in the maildrop that was
+ referenced by the RETR command, and responds with a positive success
+ indicator. The POP3 session now enters the TRANSACTION state. If
+ the lock can not be acquired or the client should is denied access to
+ the appropriate maildrop or the maildrop can't be parsed for some
+
+
+
+Rose [Page 3]
+\f
+RFC 1081 POP3 November 1988
+
+
+ reason, the POP3 server responds with a negative success indicator.
+ (If a lock was acquired but the POP3 server intends to respond with a
+ negative success indicator, the POP3 server must release the lock
+ prior to rejecting the command.) At this point, the client may
+ either issue a new USER command and start again, or the client may
+ issue the QUIT command.
+
+ NOTE: Minimal implementations of the POP3 need only be
+ able to break a maildrop into its component messages;
+ they need NOT be able to parse individual messages.
+ More advanced implementations may wish to have this
+ capability, for reasons discussed later.
+
+ After the POP3 server has parsed the maildrop into individual
+ messages, it assigns a message-id to each message, and notes the size
+ of the message in octets. The first message in the maildrop is
+ assigned a message-id of "1", the second is assigned "2", and so on,
+ so that the n'th message in a maildrop is assigned a message-id of
+ "n". In POP3 commands and responses, all message-id's and message
+ sizes are expressed in base-10 (i.e., decimal).
+
+ It sets the "highest number accessed" to be that of the last message
+ referenced by the RETR command.
+
+ Here are summaries for the three POP3 commands discussed thus far:
+
+ USER name
+ Arguments: a server specific user-id (required)
+ Restrictions: may only be given in the AUTHORIZATION
+ state after the POP3 greeting or after an
+ unsuccessful USER or PASS command
+ Possible Responses:
+ +OK name is welcome here
+ -ERR never heard of name
+ Examples:
+ C: USER mrose
+ S: +OK mrose is a real hoopy frood
+ ...
+ C: USER frated
+ S: -ERR sorry, frated doesn't get his mail here
+
+ PASS string
+ Arguments: a server/user-id specific password (required)
+ Restrictions: may only be given in the AUTHORIZATION
+ state after a successful USER command
+ Possible Responses:
+ +OK maildrop locked and ready
+ -ERR invalid password
+
+
+
+Rose [Page 4]
+\f
+RFC 1081 POP3 November 1988
+
+
+ -ERR unable to lock maildrop
+ Examples:
+ C: USER mrose
+ S: +OK mrose is a real hoopy frood
+ C: PASS secret
+ S: +OK mrose's maildrop has 2 messages
+ (320 octets)
+ ...
+ C: USER mrose
+ S: +OK mrose is a real hoopy frood
+ C: PASS secret
+ S: -ERR unable to lock mrose's maildrop, file
+ already locked
+
+ QUIT
+ Arguments: none
+ Restrictions: none
+ Possible Responses:
+ +OK
+ Examples:
+ C: QUIT
+ S: +OK dewey POP3 server signing off
+
+
+The TRANSACTION State
+
+ Once the client has successfully identified itself to the POP3 server
+ and the POP3 server has locked and burst the appropriate maildrop,
+ the POP3 session is now in the TRANSACTION state. The client may now
+ issue any of the following POP3 commands repeatedly. After each
+ command, the POP3 server issues a response. Eventually, the client
+ issues the QUIT command and the POP3 session enters the UPDATE state.
+
+ Here are the POP3 commands valid in the TRANSACTION state:
+
+ STAT
+ Arguments: none
+ Restrictions: may only be given in the TRANSACTION state.
+ Discussion:
+
+ The POP3 server issues a positive response with a line
+ containing information for the maildrop. This line is
+ called a "drop listing" for that maildrop.
+
+ In order to simplify parsing, all POP3 servers are
+ required to use a certain format for drop listings.
+ The first octets present must indicate the number of
+ messages in the maildrop. Following this is the size
+
+
+
+Rose [Page 5]
+\f
+RFC 1081 POP3 November 1988
+
+
+ of the maildrop in octets. This memo makes no
+ requirement on what follows the maildrop size.
+ Minimal implementations should just end that line of
+ the response with a CRLF pair. More advanced
+ implementations may include other information.
+
+ NOTE: This memo STRONGLY discourages
+ implementations from supplying additional
+ information in the drop listing. Other,
+ optional, facilities are discussed later on
+ which permit the client to parse the messages
+ in the maildrop.
+
+ Note that messages marked as deleted are not counted in
+ either total.
+
+ Possible Responses:
+ +OK nn mm
+ Examples:
+ C: STAT
+ S: +OK 2 320
+
+ LIST [msg]
+ Arguments: a message-id (optionally) If a message-id is
+ given, it may NOT refer to a message marked as
+ deleted.
+ Restrictions: may only be given in the TRANSACTION state.
+ Discussion:
+
+ If an argument was given and the POP3 server issues a
+ positive response with a line containing information
+ for that message. This line is called a "scan listing"
+ for that message.
+
+ If no argument was given and the POP3 server issues a
+ positive response, then the response given is
+ multi-line. After the initial +OK, for each message
+ in the maildrop, the POP3 server responds with a line
+ containing information for that message. This line
+ is called a "scan listing" for that message.
+
+ In order to simplify parsing, all POP3 servers are
+ required to use a certain format for scan listings.
+ The first octets present must be the message-id of
+ the message. Following the message-id is the size of
+ the message in octets. This memo makes no requirement
+ on what follows the message size in the scan listing.
+ Minimal implementations should just end that line of
+
+
+
+Rose [Page 6]
+\f
+RFC 1081 POP3 November 1988
+
+
+ the response with a CRLF pair. More advanced
+ implementations may include other information, as
+ parsed from the message.
+
+ NOTE: This memo STRONGLY discourages
+ implementations from supplying additional
+ information in the scan listing. Other, optional,
+ facilities are discussed later on which permit
+ the client to parse the messages in the maildrop.
+
+ Note that messages marked as deleted are not listed.
+
+ Possible Responses:
+ +OK scan listing follows
+ -ERR no such message
+ Examples:
+ C: LIST
+ S: +OK 2 messages (320 octets)
+ S: 1 120
+ S: 2 200
+ S: .
+ ...
+ C: LIST 2
+ S: +OK 2 200
+ ...
+ C: LIST 3
+ S: -ERR no such message, only 2 messages in
+ maildrop
+
+ RETR msg
+ Arguments: a message-id (required) This message-id may
+ NOT refer to a message marked as deleted.
+ Restrictions: may only be given in the TRANSACTION state.
+ Discussion:
+
+ If the POP3 server issues a positive response, then the
+ response given is multi-line. After the initial +OK,
+ the POP3 server sends the message corresponding to the
+ given message-id, being careful to byte-stuff the
+ termination character (as with all multi-line
+ responses).
+
+ If the number associated with this message is higher
+ than the "highest number accessed" in the maildrop, the
+ POP3 server updates the "highest number accessed" to
+ the number associated with this message.
+
+
+
+
+
+Rose [Page 7]
+\f
+RFC 1081 POP3 November 1988
+
+
+ Possible Responses:
+ +OK message follows
+ -ERR no such message
+ Examples:
+ C: RETR 1
+ S: +OK 120 octets
+ S: <the POP3 server sends the entire message here>
+ S: .
+
+ DELE msg
+ Arguments: a message-id (required) This message-id
+ may NOT refer to a message marked as deleted.
+ Restrictions: may only be given in the TRANSACTION state.
+ Discussion:
+
+ The POP3 server marks the message as deleted. Any
+ future reference to the message-id associated with the
+ message in a POP3 command generates an error. The POP3
+ server does not actually delete the message until the
+ POP3 session enters the UPDATE state.
+
+ If the number associated with this message is higher
+ than the "highest number accessed" in the maildrop,
+ the POP3 server updates the "highest number accessed"
+ to the number associated with this message.
+
+ Possible Responses:
+ +OK message deleted
+ -ERR no such message
+ Examples:
+ C: DELE 1
+ S: +OK message 1 deleted
+ ...
+ C: DELE 2
+ S: -ERR message 2 already deleted
+
+ NOOP
+ Arguments: none
+ Restrictions: may only be given in the TRANSACTION state.
+ Discussion:
+
+ The POP3 server does nothing, it merely replies with a
+ positive response.
+
+ Possible Responses:
+ +OK
+
+
+
+
+
+Rose [Page 8]
+\f
+RFC 1081 POP3 November 1988
+
+
+ Examples:
+ C: NOOP
+ S: +OK
+
+ LAST
+ Arguments: none
+ Restrictions: may only be issued in the TRANSACTION state.
+ Discussion:
+
+ The POP3 server issues a positive response with a line
+ containing the highest message number which accessed.
+ Zero is returned in case no message in the maildrop has
+ been accessed during previous transactions. A client
+ may thereafter infer that messages, if any, numbered
+ greater than the response to the LAST command are
+ messages not yet accessed by the client.
+
+ Possible Response:
+ +OK nn
+
+ Examples:
+ C: STAT
+ S: +OK 4 320
+ C: LAST
+ S: +OK 1
+ C: RETR 3
+ S: +OK 120 octets
+ S: <the POP3 server sends the entire message
+ here>
+ S: .
+ C: LAST
+ S: +OK 3
+ C: DELE 2
+ S: +OK message 2 deleted
+ C: LAST
+ S: +OK 3
+ C: RSET
+ S: +OK
+ C: LAST
+ S: +OK 1
+
+ RSET
+ Arguments: none
+ Restrictions: may only be given in the TRANSACTION
+ state.
+ Discussion:
+
+ If any messages have been marked as deleted by the POP3
+
+
+
+Rose [Page 9]
+\f
+RFC 1081 POP3 November 1988
+
+
+ server, they are unmarked. The POP3 server then
+ replies with a positive response. In addition, the
+ "highest number accessed" is also reset to the value
+ determined at the beginning of the POP3 session.
+
+ Possible Responses:
+ +OK
+ Examples:
+ C: RSET
+ S: +OK maildrop has 2 messages (320 octets)
+
+
+
+The UPDATE State
+
+ When the client issues the QUIT command from the TRANSACTION state,
+ the POP3 session enters the UPDATE state. (Note that if the client
+ issues the QUIT command from the AUTHORIZATION state, the POP3
+ session terminates but does NOT enter the UPDATE state.)
+
+ QUIT
+ Arguments: none
+ Restrictions: none
+ Discussion:
+
+ The POP3 server removes all messages marked as deleted
+ from the maildrop. It then releases the
+ exclusive-access lock on the maildrop and replies as
+ to the success of
+ these operations. The TCP connection is then closed.
+
+ Possible Responses:
+ +OK
+ Examples:
+ C: QUIT
+ S: +OK dewey POP3 server signing off (maildrop
+ empty)
+ ...
+ C: QUIT
+ S: +OK dewey POP3 server signing off (2 messages
+ left)
+ ...
+
+
+Optional POP3 Commands
+
+ The POP3 commands discussed above must be supported by all minimal
+ implementations of POP3 servers.
+
+
+
+Rose [Page 10]
+\f
+RFC 1081 POP3 November 1988
+
+
+ The optional POP3 commands described below permit a POP3 client
+ greater freedom in message handling, while preserving a simple POP3
+ server implementation.
+
+ NOTE: This memo STRONGLY encourages implementations to
+ support these commands in lieu of developing augmented
+ drop and scan listings. In short, the philosophy of
+ this memo is to put intelligence in the part of the
+ POP3 client and not the POP3 server.
+
+ TOP msg n
+ Arguments: a message-id (required) and a number. This
+ message-id may NOT refer to a message marked as
+ deleted.
+ Restrictions: may only be given in the TRANSACTION state.
+ Discussion:
+
+ If the POP3 server issues a positive response, then
+ the response given is multi-line. After the initial
+ +OK, the POP3 server sends the headers of the message,
+ the blank line separating the headers from the body,
+ and then the number of lines indicated message's body,
+ being careful to byte-stuff the termination character
+ (as with all multi-line responses).
+
+ Note that if the number of lines requested by the POP3
+ client is greater than than the number of lines in the
+ body, then the POP3 server sends the entire message.
+
+ Possible Responses:
+ +OK top of message follows
+ -ERR no such message
+ Examples:
+ C: TOP 10
+ S: +OK
+ S: <the POP3 server sends the headers of the
+ message, a blank line, and the first 10 lines
+ of the body of the message>
+ S: .
+ ...
+ C: TOP 100
+ S: -ERR no such message
+
+ RPOP user
+ Arguments: a client specific user-id (required)
+ Restrictions: may only be given in the AUTHORIZATION
+ state after a successful USER command; in addition,
+ may only be given if the client used a reserved
+
+
+
+Rose [Page 11]
+\f
+RFC 1081 POP3 November 1988
+
+
+ (privileged) TCP port to connect to the server.
+ Discussion:
+
+ The RPOP command may be used instead of the PASS
+ command to authenticate access to the maildrop. In
+ order for this command to be successful, the POP3
+ client must use a reserved TCP port (port < 1024) to
+ connect tothe server. The POP3 server uses the
+ argument pair from the USER and RPOP commands to
+ determine if the client should be given access to
+ the appropriate maildrop. Unlike the PASS command
+ however, the POP3 server considers if the remote user
+ specified by the RPOP command who resides on the POP3
+ client host is allowed to access the maildrop for the
+ user specified by the USER command (e.g., on Berkeley
+ UNIX, the .rhosts mechanism is used). With the
+ exception of this differing in authentication, this
+ command is identical to the PASS command.
+
+ Note that the use of this feature has allowed much wider
+ penetration into numerous hosts on local networks (and
+ sometimes remote networks) by those who gain illegal
+ access to computers by guessing passwords or otherwise
+ breaking into the system.
+
+ Possible Responses:
+ +OK maildrop locked and ready
+ -ERR permission denied
+ Examples:
+ C: USER mrose
+ S: +OK mrose is a real hoopy frood
+ C: RPOP mrose
+ S: +OK mrose's maildrop has 2 messages (320
+ octets)
+
+ Minimal POP3 Commands:
+ USER name valid in the AUTHORIZATION state
+ PASS string
+ QUIT
+
+ STAT valid in the TRANSACTION state
+ LIST [msg]
+ RETR msg
+ DELE msg
+ NOOP
+ LAST
+ RSET
+
+
+
+
+Rose [Page 12]
+\f
+RFC 1081 POP3 November 1988
+
+
+ QUIT valid in the UPDATE state
+
+ Optional POP3 Commands:
+ RPOP user valid in the AUTHORIZATION state
+
+ TOP msg n valid in the TRANSACTION state
+
+ POP3 Replies:
+ +OK
+ -ERR
+
+ Note that with the exception of the STAT command, the reply given
+ by the POP3 server to any command is significant only to "+OK"
+ and "-ERR". Any text occurring after this reply may be ignored
+ by the client.
+
+Example POP3 Session
+
+ S: <wait for connection on TCP port 110>
+ ...
+ C: <open connection>
+ S: +OK dewey POP3 server ready (Comments to: PostMaster@UDEL.EDU)
+ C: USER mrose
+ S: +OK mrose is a real hoopy frood
+ C: PASS secret
+ S: +OK mrose's maildrop has 2 messages (320 octets)
+ C: STAT
+ S: +OK 2 320
+ C: LIST
+ S: +OK 2 messages (320 octets)
+ S: 1 120
+ S: 2 200
+ S: .
+ C: RETR 1
+ S: +OK 120 octets
+ S: <the POP3 server sends message 1>
+ S: .
+ C: DELE 1
+ S: +OK message 1 deleted
+ C: RETR 2
+ S: +OK 200 octets
+ S: <the POP3 server sends message 2>
+ S: .
+ C: DELE 2
+ S: +OK message 2 deleted
+ C: QUIT
+
+
+
+
+
+Rose [Page 13]
+\f
+RFC 1081 POP3 November 1988
+
+
+ S: +OK dewey POP3 server signing off (maildrop empty)
+ C: <close connection>
+ S: <wait for next connection>
+
+Message Format
+
+ All messages transmitted during a POP3 session are assumed to conform
+ to the standard for the format of Internet text messages [RFC822].
+
+ It is important to note that the byte count for a message on the
+ server host may differ from the octet count assigned to that message
+ due to local conventions for designating end-of-line. Usually,
+ during the AUTHORIZATION state of the POP3 session, the POP3 client
+ can calculate the size of each message in octets when it parses the
+ maildrop into messages. For example, if the POP3 server host
+ internally represents end-of-line as a single character, then the
+ POP3 server simply counts each occurrence of this character in a
+ message as two octets. Note that lines in the message which start
+ with the termination octet need not be counted twice, since the POP3
+ client will remove all byte-stuffed termination characters when it
+ receives a multi-line response.
+
+The POP and the Split-UA model
+
+ The underlying paradigm in which the POP3 functions is that of a
+ split-UA model. The POP3 client host, being a remote PC based
+ workstation, acts solely as a client to the message transport system.
+ It does not provide delivery/authentication services to others.
+ Hence, it is acting as a UA, on behalf of the person using the
+ workstation. Furthermore, the workstation uses SMTP to enter mail
+ into the MTS.
+
+ In this sense, we have two UA functions which interface to the
+ message transport system: Posting (SMTP) and Retrieval (POP3). The
+ entity which supports this type of environment is called a split-UA
+ (since the user agent is split between two hosts which must
+ interoperate to provide these functions).
+
+ ASIDE: Others might term this a remote-UA instead.
+ There are arguments supporting the use of both terms.
+
+ This memo has explicitly referenced TCP as the underlying transport
+ agent for the POP3. This need not be the case. In the MZnet split-
+ UA, for example, personal micro-computer systems are used which do
+ not have IP-style networking capability. To connect to the POP3
+ server host, a PC establishes a terminal connection using some simple
+ protocol (PhoneNet). A program on the PC drives the connection,
+ first establishing a login session as a normal user. The login shell
+
+
+
+Rose [Page 14]
+\f
+RFC 1081 POP3 November 1988
+
+
+ for this pseudo-user is a program which drives the other half of the
+ terminal protocol and communicates with one of two servers. Although
+ MZnet can support several PCs, a single pseudo-user login is present
+ on the server host. The user-id and password for this pseudo-user
+ login is known to all members of MZnet. Hence, the first action of
+ the login shell, after starting the terminal protocol, is to demand a
+ USER/PASS authorization pair from the PC. This second level of
+ authorization is used to ascertain who is interacting with the MTS.
+ Although the server host is deemed to support a "trusted" MTS entity,
+ PCs in MZnet are not. Naturally, the USER/PASS authorization pair
+ for a PC is known only to the owner of the PC (in theory, at least).
+
+ After successfully verifying the identity of the client, a modified
+ SMTP server is started, and the PC posts mail with the server host.
+ After the QUIT command is given to the SMTP server and it terminates,
+ a modified POP3 server is started, and the PC retrieves mail from the
+ server host. After the QUIT command is given to the POP3 server and
+ it terminates, the login shell for the pseudo-user terminates the
+ terminal protocol and logs the job out. The PC then closes the
+ terminal connection to the server host.
+
+ The SMTP server used by MZnet is modified in the sense that it knows
+ that it's talking to a user agent and not a "trusted" entity in the
+ message transport system. Hence, it does performs the validation
+ activities normally performed by an entity in the MTS when it accepts
+ a message from a UA.
+
+ The POP3 server used by MZnet is modified in the sense that it does
+ not require a USER/PASS combination before entering the TRANSACTION
+ state. The reason for this (of course) is that the PC has already
+ identified itself during the second-level authorization step
+ described above.
+
+ NOTE: Truth in advertising laws require that the author
+ of this memo state that MZnet has not actually been
+ fully implemented. The concepts presented and proven
+ by the project led to the notion of the MZnet
+ split-slot model. This notion has inspired the
+ split-UA concept described in this memo, led to the
+ author's interest in the POP, and heavily influenced
+ the the description of the POP3 herein.
+
+ In fact, some UAs present in the Internet already support the notion
+ of posting directly to an SMTP server and retrieving mail directly
+ from a POP server, even if the POP server and client resided on the
+ same host!
+
+ ASIDE: this discussion raises an issue which this memo
+
+
+
+Rose [Page 15]
+\f
+RFC 1081 POP3 November 1988
+
+
+ purposedly avoids: how does SMTP know that it's talking
+ to a "trusted" MTS entity?
+
+References
+
+ [MZnet] Stefferud, E., J. Sweet, and T. Domae, "MZnet: Mail
+ Service for Personal Micro-Computer Systems",
+ Proceedings, IFIP 6.5 International Conference on
+ Computer Message Systems, Nottingham, U.K., May 1984.
+
+ [RFC821] Postel, J., "Simple Mail Transfer Protocol",
+ USC/Information Sciences Institute, August 1982.
+
+ [RFC822] Crocker, D., "Standard for the Format of ARPA-Internet
+ Text Messages", University of Delaware, August 1982.
+
+ [RFC937] Butler, M., J. Postel, D. Chase, J. Goldberger, and J.
+ Reynolds, "Post Office Protocol - Version 2", RFC 937,
+ USC/Information Sciences Institute, February 1985.
+
+ [RFC1010] Reynolds, J., and J. Postel, "Assigned Numbers", RFC
+ 1010, USC/Information Sciences Institute, May 1987.
+
+Author's Address:
+
+
+ Marshall Rose
+ The Wollongong Group
+ 1129 San Antonio Rd.
+ Palo Alto, California 94303
+
+ Phone: (415) 962-7100
+
+ Email: MRose@TWG.COM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Rose [Page 16]
--- /dev/null
+
+
+
+
+
+
+Network Working Group M. Rose
+Request for Comments: 1082 TWG
+ November 1988
+
+
+
+ Post Office Protocol - Version 3
+ Extended Service Offerings
+
+Status of This Memo
+
+ This memo suggests a simple method for workstations to dynamically
+ access mail from a discussion group server, as an extension to an
+ earlier memo which dealt with dynamically accessing mail from a
+ mailbox server using the Post Office Protocol - Version 3 (POP3).
+ This RFC specifies a proposed protocol for the Internet community,
+ and requests discussion and suggestions for improvements. All of the
+ extensions described in this memo to the POP3 are OPTIONAL.
+ Distribution of this memo is unlimited.
+
+Introduction and Motivation
+
+ It is assumed that the reader is familiar with RFC 1081 that
+ discusses the Post Office Protocol - Version 3 (POP3) [RFC1081].
+ This memo describes extensions to the POP3 which enhance the service
+ it offers to clients. This additional service permits a client host
+ to access discussion group mail, which is often kept in a separate
+ spool area, using the general POP3 facilities.
+
+ The next section describes the evolution of discussion groups and the
+ technologies currently used to implement them. To summarize:
+
+ o An exploder is used to map from a single address to
+ a list of addresses which subscribe to the list, and redirects
+ any subsequent error reports associated with the delivery of
+ each message. This has two primary advantages:
+ - Subscribers need know only a single address
+ - Responsible parties get the error reports and not
+ the subscribers
+
+
+
+
+
+
+
+
+
+
+
+
+Rose [Page 1]
+\f
+RFC 1082 POP3 Extended Service November 1988
+
+
+ o Typically, each subscription address is not a person's private
+ maildrop, but a system-wide maildrop, which can be accessed
+ by more than one user. This has several advantages:
+ - Only a single copy of each message need traverse the
+ net for a given site (which may contain several local
+ hosts). This conserves bandwidth and cycles.
+ - Only a single copy of each message need reside on each
+ subscribing host. This conserves disk space.
+ - The private maildrop for each user is not cluttered
+ with discussion group mail.
+
+ Despite this optimization of resources, further economy can be
+ achieved at sites with more than one host. Typically, sites with
+ more than one host either:
+
+ 1. Replicate discussion group mail on each host. This
+ results in literally gigabytes of disk space committed to
+ unnecessarily store redundant information.
+
+ 2. Keep discussion group mail on one host and give all users a
+ login on that host (in addition to any other logins they may
+ have). This is usually a gross inconvenience for users who
+ work on other hosts, or a burden to users who are forced to
+ work on that host.
+
+ As discussed in [RFC1081], the problem of giving workstations dynamic
+ access to mail from a mailbox server has been explored in great
+ detail (originally there was [RFC918], this prompted the author to
+ write [RFC1081], independently of this [RFC918] was upgraded to
+ [RFC937]). A natural solution to the problem outlined above is to
+ keep discussion group mail on a mailbox server at each site and
+ permit different hosts at that site to employ the POP3 to access
+ discussion group mail. If implemented properly, this avoids the
+ problems of both strategies outlined above.
+
+ ASIDE: It might be noted that a good distributed filesystem
+ could also solve this problem. Sadly, "good"
+ distributed filesystems, which do not suffer
+ unacceptable response time for interactive use, are
+ few and far between these days!
+
+ Given this motivation, now let's consider discussion groups, both in
+ general and from the point of view of a user agent. Following this,
+ extensions to the POP3 defined in [RFC1081] are presented. Finally,
+ some additional policy details are discussed along with some initial
+ experiences.
+
+
+
+
+
+Rose [Page 2]
+\f
+RFC 1082 POP3 Extended Service November 1988
+
+
+What's in a Discussion Group
+
+ Since mailers and user agents first crawled out of the primordial
+ ARPAnet, the value of discussion groups have been appreciated,
+ (though their implementation has not always been well-understood).
+
+ Described simply, a discussion group is composed of a number of
+ subscribers with a common interest. These subscribers post mail to a
+ single address, known as a distribution address. From this
+ distribution address, a copy of the message is sent to each
+ subscriber. Each group has a moderator, which is the person that
+ administrates the group. The moderator can usually be reached at a
+ special address, known as a request address. Usually, the
+ responsibilities of the moderator are quite simple, since the mail
+ system handles the distribution to subscribers automatically. In
+ some cases, the interest group, instead of being distributed directly
+ to its subscribers, is put into a digest format by the moderator and
+ then sent to the subscribers. Although this requires more work on
+ the part of the moderator, such groups tend to be better organized.
+
+ Unfortunately, there are a few problems with the scheme outlined
+ above. First, if two users on the same host subscribe to the same
+ interest group, two copies of the message get delivered. This is
+ wasteful of both processor and disk resources.
+
+ Second, some of these groups carry a lot of traffic. Although
+ subscription to an group does indicate interest on the part of a
+ subscriber, it is usually not interesting to get 50 messages or so
+ delivered to the user's private maildrop each day, interspersed with
+ personal mail, that is likely to be of a much more important and
+ timely nature.
+
+ Third, if a subscriber on the distribution list for a group becomes
+ "bad" somehow, the originator of the message and not the moderator of
+ the group is notified. It is not uncommon for a large list to have
+ 10 or so bogus addresses present. This results in the originator
+ being flooded with "error messages" from mailers across the Internet
+ stating that a given address on the list was bad. Needless to say,
+ the originator usually could not care less if the bogus addresses got
+ a copy of the message or not. The originator is merely interested in
+ posting a message to the group at large. Furthermore, the moderator
+ of the group does care if there are bogus addresses on the list, but
+ ironically does not receive notification.
+
+ There are various approaches which can be used to solve some or all
+ of these problems. Usually these involve placing an exploder agent
+ at the distribution source of the discussion group, which expands the
+ name of the group into the list of subscription addresses for the
+
+
+
+Rose [Page 3]
+\f
+RFC 1082 POP3 Extended Service November 1988
+
+
+ group. In the process, the exploder will also change the address
+ that receives error notifications to be the request address or other
+ responsible party.
+
+ A complementary approach, used in order to cut down on resource
+ utilization of all kinds, replaces all the subscribers at a single
+ host (or group of hosts under a single administration) with a single
+ address at that host. This address maps to a file on the host,
+ usually in a spool area, which all users can access. (Advanced
+ implementations can also implement private discussion groups this
+ way, in which a single copy of each message is kept, but is
+ accessible to only a select number of users on the host.)
+
+ The two approaches can be combined to avoid all of the problems
+ described above.
+
+ Finally, a third approach can be taken, which can be used to aid user
+ agents processing mail for the discussion group: In order to speed
+ querying of the maildrop which contains the local host's copy of the
+ discussion group, two other items are usually associated with the
+ discussion group, on a local basis. These are the maxima and the
+ last-date. Each time a message is received for the group on the
+ local host, the maxima is increased by at least one. Furthermore,
+ when a new maxima is generated, the current date is determined. This
+ is called the last date. As the message is entered into the local
+ maildrop, it is given the current maxima and last-date. This permits
+ the user agent to quickly determine if new messages are present in
+ the maildrop.
+
+ NOTE: The maxima may be characterized as a monotonically
+ increasing quanity. Although sucessive values of the
+ maxima need not be consecutive, any maxima assigned
+ is always greater than any previously assigned value.
+
+Definition of Terms
+
+ To formalize these notions somewhat, consider the following 7
+ parameters which describe a given discussion group from the
+ perspective of the user agent (the syntax given is from [RFC822]):
+
+
+
+
+
+
+
+
+
+
+
+
+Rose [Page 4]
+\f
+RFC 1082 POP3 Extended Service November 1988
+
+
+ NAME Meaning: the name of the discussion group
+ Syntax: TOKEN (ALPHA *[ ALPHA / DIGIT / "-" ])
+ (case-insensitive recognition)
+ Example: unix-wizards
+
+ ALIASES Meaning: alternates names for the group, which
+ are locally meaningful; these are
+ typically used to shorten user typein
+ Syntax: TOKEN (case-insensitive recognition)
+ Example: uwiz
+
+ ADDRESS Meaning: the primary source of the group
+ Syntax: 822 address
+ Example: Unix-Wizards@BRL.MIL
+
+ REQUEST Meaning: the primary moderator of the group
+ Syntax: 822 address
+ Example: Unix-Wizards-Request@BRL.MIL
+
+ FLAGS Meaning: locally meaningful flags associated
+ with the discussion group; this memo
+ leaves interpretation of this
+ parameter to each POP3 implementation
+ Syntax: octal number
+ Example: 01
+
+ MAXIMA Meaning: the magic cookie associated with the
+ last message locally received for the
+ group; it is the property of the magic
+ cookie that it's value NEVER
+ decreases, and increases by at least
+ one each time a message is locally
+ received
+ Syntax: decimal number
+ Example: 1004
+
+ LASTDATE Meaning: the date that the last message was
+ locally received
+ Syntax: 822 date
+ Example: Thu, 19 Dec 85 10:26:48 -0800
+
+ Note that the last two values are locally determined for the maildrop
+ associated with the discussion group and with each message in that
+ maildrop. Note however that the last message in the maildrop have a
+ different MAXIMA and LASTDATE than the discussion group. This often
+ occurs when the maildrop has been archived.
+
+
+
+
+
+Rose [Page 5]
+\f
+RFC 1082 POP3 Extended Service November 1988
+
+
+ Finally, some local systems provide mechanisms for automatically
+ archiving discussion group mail. In some cases, a two-level archive
+ scheme is used: current mail is kept in the standard maildrop,
+ recent mail is kept in an archive maildrop, and older mail is kept
+ off-line. With this scheme, in addition to having a "standard"
+ maildrop for each discussion group, an "archive" maildrop may also be
+ available. This permits a user agent to examine the most recent
+ archive using the same mechanisms as those used on the current mail.
+
+The XTND Command
+
+ The following commands are valid only in the TRANSACTION state of the
+ POP3. This implies that the POP3 server has already opened the
+ user's maildrop (which may be empty). This maildrop is called the
+ "default maildrop". The phrase "closes the current maildrop" has two
+ meanings, depending on whether the current maildrop is the default
+ maildrop or is a maildrop associated with a discussion group.
+
+ In the former context, when the current maildrop is closed any
+ messages marked as deleted are removed from the maildrop currently in
+ use. The exclusive-access lock on the maildrop is then released
+ along with any implementation-specific resources (e.g., file-
+ descriptors).
+
+ In the latter context, a maildrop associated with a discussion group
+ is considered to be read-only to the POP3 client. In this case, the
+ phrase "closes the current maildrop" merely means that any
+ implementation-specific resources are released. (Hence, the POP3
+ command DELE is a no-op.)
+
+ All the new facilities are introduced via a single POP3 command,
+ XTND. All positive reponses to the XTND command are multi-line.
+
+ The most common multi-line response to the commands contains a
+ "discussion group listing" which presents the name of the discussion
+ group along with it's maxima. In order to simplify parsing all POP3
+ servers are required to use a certain format for discussion group
+ listings:
+
+ NAME SP MAXIMA
+
+ This memo makes no requirement on what follows the maxima in the
+ listing. Minimal implementations should just end that line of the
+ response with a CRLF pair. More advanced implementations may include
+ other information, as parsed from the message.
+
+ NOTE: This memo STRONGLY discourages implementations from
+ supplying additional information in the listing.
+
+
+
+Rose [Page 6]
+\f
+RFC 1082 POP3 Extended Service November 1988
+
+
+ XTND BBOARDS [name]
+ Arguments: the name of a discussion group (optionally)
+ Restrictions: may only be given in the TRANSACTION state.
+ Discussion:
+
+ If an argument was given, the POP3 server closes the current
+ maildrop. The POP3 server then validates the argument as the name of
+ a discussion group. If this is successful, it opens the maildrop
+ associated with the group, and returns a multi-line response
+ containing the discussion group listing. If the discussion group
+ named is not valid, or the associated archive maildrop is not
+ readable by the user, then an error response is returned.
+
+ If no argument was given, the POP3 server issues a multi-line
+ response. After the initial +OK, for each discussion group known,
+ the POP3 server responds with a line containing the listing for that
+ discussion group. Note that only world-readable discussion groups
+ are included in the multi-line response.
+
+ In order to aid user agents, this memo requires an extension to the
+ scan listing when an "XTND BBOARDS" command has been given.
+ Normally, a scan listing, as generated by the LIST, takes the form:
+
+ MSGNO SIZE
+
+ where MSGNO is the number of the message being listed and SIZE is the
+ size of the message in octets. When reading a maildrop accessed via
+ "XTND BBOARDS", the scan listing takes the form
+
+ MSGNO SIZE MAXIMA
+
+ where MAXIMA is the maxima that was assigned to the message when it
+ was placed in the BBoard.
+
+ Possible Responses:
+ +OK XTND
+ -ERR no such bboard
+ Examples:
+ C: XTND BBOARDS
+ S: +OK XTND
+ S: system 10
+ S: mh-users 100
+ S: .
+ C: XTND BBOARDS system
+ S: + OK XTND
+ S: system 10
+ S: .
+
+
+
+
+Rose [Page 7]
+\f
+RFC 1082 POP3 Extended Service November 1988
+
+
+ XTND ARCHIVE name
+ Arguments: the name of a discussion group (required)
+ Restrictions: may only be given in the TRANSACTION state.
+ Discussion:
+
+ The POP3 server closes the current maildrop. The POP3 server then
+ validates the argument as the name of a discussion group. If this is
+ successful, it opens the archive maildrop associated with the group,
+ and returns a multi-line response containing the discussion group
+ listing. If the discussion group named is not valid, or the
+ associated archive maildrop is not readable by the user, then an
+ error response is returned.
+
+ In addition, the scan listing generated by the LIST command is
+ augmented (as described above).
+
+ Possible Responses:
+ +OK XTND
+ -ERR no such bboard Examples:
+ C: XTND ARCHIVE system
+ S: + OK XTND
+ S: system 3
+ S: .
+
+ XTND X-BBOARDS name
+ Arguments: the name of a discussion group (required)
+ Restrictions: may only be given in the TRANSACTION state.
+ Discussion:
+
+ The POP3 server validates the argument as the name of a
+ discussion group. If this is unsuccessful, then an error
+ response is returned. Otherwise a multi-line response is
+ returned. The first 14 lines of this response (after the
+ initial +OK) are defined in this memo. Minimal implementations
+ need not include other information (and may omit certain
+ information, outputing a bare CRLF pair). More advanced
+ implementations may include other information.
+
+ Line Information (refer to "Definition of Terms")
+ ---- -----------
+ 1 NAME
+ 2 ALIASES, separated by SP
+ 3 system-specific: maildrop
+ 4 system-specific: archive maildrop
+ 5 system-specific: information
+ 6 system-specific: maildrop map
+ 7 system-specific: encrypted password
+ 8 system-specific: local leaders, separated by SP
+
+
+
+Rose [Page 8]
+\f
+RFC 1082 POP3 Extended Service November 1988
+
+
+ 9 ADDRESS
+ 10 REQUEST
+ 11 system-specific: incoming feed
+ 12 system-specific: outgoing feeds
+ 13 FLAGS SP MAXIMA
+ 14 LASTDATE
+
+ Most of this information is entirely too specific to the UCI Version
+ of the Rand MH Message Handling System [MRose85]. Nevertheless,
+ lines 1, 2, 9, 10, 13, and 14 are of general interest, regardless of
+ the implementation.
+
+ Possible Responses:
+ +OK XTND
+ -ERR no such bboard
+ Examples:
+ C: XTND X-BBOARDS system
+ S: + OK XTND
+ S: system
+ S: local general
+ S: /usr/bboards/system.mbox
+ S: /usr/bboards/archive/system.mbox
+ S: /usr/bboards/.system.cnt
+ S: /usr/bboards/.system.map
+ S: *
+ S: mother
+ S: system@nrtc.northrop.com
+ S: system-request@nrtc.northrop.com
+ S:
+ S: dist-system@nrtc-gremlin.northrop.com
+ S: 01 10
+ S: Thu, 19 Dec 85 00:08:49 -0800
+ S: .
+
+Policy Notes
+
+ Depending on the particular entity administrating the POP3 service
+ host, two additional policies might be implemented:
+
+ 1. Private Discussion Groups
+
+ In the general case, discussion groups are world-readable, any user,
+ once logged in (via a terminal, terminal server, or POP3, etc.), is
+ able to read the maildrop for each discussion group known to the POP3
+ service host. Nevertheless, it is desirable, usually for privacy
+ reasons, to implement private discussion groups as well.
+
+ Support of this is consistent with the extensions outlined in this
+
+
+
+Rose [Page 9]
+\f
+RFC 1082 POP3 Extended Service November 1988
+
+
+ memo. Once the AUTHORIZATION state has successfully concluded, the
+ POP3 server grants the user access to exactly those discussion groups
+ the POP3 service host permits the authenticated user to access. As a
+ "security" feature, discussion groups associated with unreadable
+ maildrops should not be listed in a positive response to the XTND
+ BBOARDS command.
+
+ 2. Anonymous POP3 Users
+
+ In order to minimize the authentication problem, a policy permitting
+ "anonymous" access to the world-readable maildrops for discussion
+ groups on the POP3 server may be implemented.
+
+ Support of this is consistent with the extensions outlined in this
+ memo. The POP3 server can be modified to accept a USER command for a
+ well-known pseudonym (i.e., "anonymous") which is valid with any PASS
+ command. As a "security" feature, it is advisable to limit this kind
+ of access to only hosts at the local site, or to hosts named in an
+ access list.
+
+Experiences and Conclusions
+
+ All of the facilities described in this memo and in [RFC1081] have
+ been implemented in MH #6.1. Initial experiences have been, on the
+ whole, very positive.
+
+ After the first implementation, some performance tuning was required.
+ This consisted primarily of caching the datastructures which describe
+ discussion groups in the POP3 server. A second optimization
+ pertained to the client: the program most commonly used to read
+ BBoards in MH was modified to retrieve messages only when needed.
+ Two schemes are used:
+
+ o If only the headers (and the first few lines of the body) of
+ the message are required (e.g., for a scan listing), then only
+ these are retrieved. The resulting output is then cached, on
+ a per-message basis.
+
+ o If the entire message is required, then it is retrieved intact,
+ and cached locally.
+
+ With these optimizations, response time is quite adequate when the
+ POP3 server and client are connected via a high-speed local area
+ network. In fact, the author uses this mechanism to access certain
+ private discussion groups over the Internet. In this case, response
+ is still good. When a 9.6Kbps modem is inserted in the path,
+ response went from good to almost tolerable (fortunately the author
+ only reads a few discussion groups in this fashion).
+
+
+
+Rose [Page 10]
+\f
+RFC 1082 POP3 Extended Service November 1988
+
+
+ To conclude: the POP3 is a good thing, not only for personal mail but
+ for discussion group mail as well.
+
+
+References
+
+ [RFC1081] Rose, M., "Post Office Protocol - Verison 3 (POP3)", RFC
+ 1081, TWG, November 1988.
+
+ [MRose85] Rose, M., and J. Romine, "The Rand MH Message Handling
+ System: User's Manual", University of California, Irvine,
+ November 1985.
+
+ [RFC822] Crocker, D., "Standard for the Format of ARPA-Internet
+ Text Messages", RFC 822, University of Delaware, August
+ 1982.
+
+ [RFC918] Reynolds, J., "Post Office Protocol", RFC 918,
+ USC/Information Sciences Institute, October 1984.
+
+ [RFC937] Butler, M., J. Postel, D. Chase, J. Goldberger, and J.
+ Reynolds, "Post Office Protocol - Version 2", RFC 937,
+ USC/Information Sciences Institute, February 1985.
+
+Author's Address:
+
+
+ Marshall Rose
+ The Wollongong Group
+ 1129 San Antonio Rd.
+ Palo Alto, California 94303
+
+ Phone: (415) 962-7100
+
+ Email: MRose@TWG.COM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Rose [Page 11]
+\f
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_dele.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include "popper.h"
+
+/*
+ * dele: Delete a message from the POP maildrop
+ */
+pop_dele (p)
+POP * p;
+{
+ MsgInfoList * mp; /* Pointer to message info list */
+ int msg_num;
+
+ /* Convert the message number parameter to an integer */
+ msg_num = atoi(p->pop_parm[1]);
+
+ /* Is requested message out of range? */
+ if ((msg_num < 1) || (msg_num > p->msg_count))
+ return (pop_msg (p,POP_FAILURE,"Message %d does not exist.",msg_num));
+
+ /* Get a pointer to the message in the message list */
+ mp = &(p->mlp[msg_num-1]);
+
+ /* Is the message already flagged for deletion? */
+ if (mp->del_flag)
+ return (pop_msg (p,POP_FAILURE,"Message %d has already been deleted.",
+ msg_num));
+
+ /* Flag the message for deletion */
+ mp->del_flag = TRUE;
+
+#ifdef DEBUG
+ if(p->debug)
+ pop_log(p,POP_DEBUG,"Deleting message %u at offset %u of length %u\n",
+ mp->number,mp->offset,mp->length);
+#endif DEBUG
+
+ /* Update the messages_deleted and bytes_deleted counters */
+ p->msgs_deleted++;
+ p->bytes_deleted += mp->length;
+
+ /* Update the last-message-accessed number if it is lower than
+ the deleted message */
+ if (p->last_msg < msg_num) p->last_msg = msg_num;
+
+ return (pop_msg (p,POP_SUCCESS,"Message %d has been deleted.",msg_num));
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_dropcopy.c 1.2 7/13/90";
+#endif not lint
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include "popper.h"
+
+extern int errno;
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+#define LOCK_RETRY 3
+#define LOCK_WAIT 5
+
+/*
+ * dropcopy: Make a temporary copy of the user's mail drop and
+ * save a stream pointer for it.
+ */
+
+pop_dropcopy(p)
+POP * p;
+{
+ int mfd; /* File descriptor for
+ the user's maildrop */
+ int dfd; /* File descriptor for
+ the SERVER maildrop */
+ char buffer[BUFSIZ]; /* Read buffer */
+ long offset; /* Old/New boundary */
+ int nchar; /* Bytes written/read */
+ int locked; /* if drop is loced */
+ int retry = 0; /* times to retry lock */
+
+ /* Create a temporary maildrop into which to copy the updated maildrop */
+ (void)sprintf(p->temp_drop,POP_DROP,p->user);
+
+#ifdef DEBUG
+ if(p->debug)
+ pop_log(p,POP_DEBUG,"Creating temporary maildrop '%s'",
+ p->temp_drop);
+#endif DEBUG
+
+ /* Open for append, this solves the crash recovery problem */
+ if ((dfd = open(p->temp_drop,O_RDWR|O_APPEND|O_CREAT,0666)) == -1){
+ pop_log(p,POP_ERROR,
+ "%s: (%s) unable to create temporary maildrop: %s",
+ p->client, p->temp_drop,
+ (errno < sys_nerr) ? sys_errlist[errno] : "") ;
+ return (POP_FAILURE);
+ }
+
+ /* Lock the temporary maildrop. Try a few times if it doesn't succeed. */
+
+ locked = 1;
+ while(locked) {
+ if ( flock (dfd, LOCK_EX|LOCK_NB) == -1 )
+ switch(errno) {
+ case EWOULDBLOCK:
+ if(retry++ < LOCK_RETRY) {
+ sleep(LOCK_WAIT);
+ continue;
+ }
+ pop_log(p, POP_PRIORITY, "%s: (%s) maildrop locked",
+ p->client, p->temp_drop);
+ return pop_msg(p,POP_FAILURE,
+ "Maildrop for %s is busy. Please try again in a few moments.",
+ p->user);
+ /* NOTREACHED */
+
+ default:
+ pop_log(p, POP_PRIORITY, "%s: (%s) flock: %s", p->client,
+ p->temp_drop,
+ (errno < sys_nerr) ? sys_errlist[errno] : "");
+ return pop_msg(p,POP_FAILURE,"flock: '%s': %s", p->temp_drop,
+ (errno < sys_nerr) ? sys_errlist[errno] : "");
+ /* NOTREACHED */
+ }
+ else
+ locked = 0;
+ }
+
+ /* May have grown or shrunk between open and lock! */
+ offset = lseek(dfd,0,L_XTND);
+
+ /* Open the user's maildrop, If this fails, no harm in assuming empty */
+ if ((mfd = open(p->drop_name,O_RDWR)) > 0) {
+
+ /* Lock the maildrop */
+ if (flock (mfd,LOCK_EX) == -1) {
+ (void)close(mfd) ;
+ pop_log(p, POP_PRIORITY, "%s: (%s) flock: %s", p->client,
+ p->drop_name,(errno < sys_nerr) ? sys_errlist[errno] : "");
+ return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop,
+ (errno < sys_nerr) ? sys_errlist[errno] : "");
+ }
+
+ /* Copy the actual mail drop into the temporary mail drop */
+ while ( (nchar=read(mfd,buffer,BUFSIZ)) > 0 )
+ if ( nchar != write(dfd,buffer,nchar) ) {
+ nchar = -1 ;
+ break ;
+ }
+
+ if ( nchar != 0 ) {
+ /* Error adding new mail. Truncate to original size,
+ and leave the maildrop as is. The user will not
+ see the new mail until the error goes away.
+ Should let them process the current backlog, in case
+ the error is a quota problem requiring deletions! */
+ (void)ftruncate(dfd,(int)offset) ;
+ } else {
+ /* Mail transferred! Zero the mail drop NOW, that we
+ do not have to do gymnastics to figure out what's new
+ and what is old later */
+ (void)ftruncate(mfd,0) ;
+ }
+
+ /* Close the actual mail drop */
+ (void)close (mfd);
+ }
+
+ /* Acquire a stream pointer for the temporary maildrop */
+ if ( (p->drop = fdopen(dfd,"a+")) == NULL ) {
+ (void)close(dfd) ;
+ pop_log(p, POP_PRIORITY, "%s: (%s) fdopen: %s", p->client,
+ p->temp_drop, (errno < sys_nerr) ? sys_errlist[errno] : "");
+ return pop_msg(p,POP_FAILURE,"Cannot assign stream for %s",
+ p->temp_drop);
+ }
+
+ rewind (p->drop);
+
+#ifdef DEBUG
+ if (!p->debug)
+ unlink (p->temp_drop);
+#endif DEBUG
+
+ return(POP_SUCCESS);
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/*
+ * compatibility with mail files stored with mh (tom)
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_dropinfo.c 1.4 8/16/90";
+#endif not lint
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include "popper.h"
+
+extern int errno;
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+/*
+ * dropinfo: Extract information about the POP maildrop and store
+ * it for use by the other POP routines.
+ */
+
+pop_dropinfo(p)
+POP * p;
+{
+ char buffer[BUFSIZ]; /* Read buffer */
+ MsgInfoList * mp; /* Pointer to message
+ info list */
+ register int msg_num; /* Current message
+ counter */
+ int nchar; /* Bytes written/read */
+ int end; /* eom */
+
+ /* Initialize maildrop status variables in the POP parameter block */
+ p->msg_count = 0;
+ p->msgs_deleted = 0;
+ p->last_msg = 0;
+ p->bytes_deleted = 0;
+ p->drop_size = 0;
+ end = 1;
+
+ /* Allocate memory for message information structures */
+ p->msg_count = ALLOC_MSGS;
+ p->mlp = (MsgInfoList *)calloc((unsigned)p->msg_count,sizeof(MsgInfoList));
+ if (p->mlp == NULL){
+ (void)fclose (p->drop);
+ p->msg_count = 0;
+ pop_log(p, POP_ERROR, "%s: (%s) no memory.", p->client, p->user);
+ return pop_msg (p,POP_FAILURE,
+ "Can't build message list for '%s': Out of memory", p->user);
+ }
+
+ rewind (p->drop);
+
+ /* Scan the file, loading the message information list with
+ information about each message */
+
+ for (msg_num = p->drop_size = 0, mp = p->mlp - 1;
+ fgets(buffer,MAXMSGLINELEN,p->drop);) {
+
+ nchar = strlen(buffer);
+ if((strncmp(buffer,"\001\001\001\001",4) == 0) && (end == 0)) {
+ end = 1;
+ continue;
+ }
+
+ if (is_msg_boundary(buffer)) {
+ end = 0;
+ if (++msg_num > p->msg_count) {
+ p->mlp=(MsgInfoList *) realloc(p->mlp,
+ (p->msg_count+=ALLOC_MSGS)*sizeof(MsgInfoList));
+ if (p->mlp == NULL){
+ (void)fclose (p->drop);
+ p->msg_count = 0;
+ pop_log(p, POP_ERROR, "%s: (%s) no memory.",
+ p->client, p->user);
+ return pop_msg (p,POP_FAILURE,
+ "Can't build message list for '%s': Out of memory",
+ p->user);
+ }
+ mp = p->mlp + msg_num - 2;
+ }
+#ifdef DEBUG
+ if(p->debug)
+ pop_log(p,POP_DEBUG,
+ "Msg %d at offset %d is %d octets long and has %u lines.",
+ mp->number,mp->offset,mp->length,mp->lines);
+#endif DEBUG
+ ++mp;
+ mp->number = msg_num;
+ mp->length = 0;
+ mp->lines = 0;
+ mp->offset = ftell(p->drop) - nchar;
+ mp->del_flag = FALSE;
+ mp->retr_flag = FALSE;
+#ifdef DEBUG
+ if(p->debug)
+ pop_log(p,POP_DEBUG, "Msg %d being added to list", mp->number);
+#endif DEBUG
+ }
+ mp->length += nchar;
+ p->drop_size += nchar;
+ mp->lines++;
+ }
+ p->msg_count = msg_num;
+
+#ifdef DEBUG
+ if(p->debug && msg_num > 0) {
+ register i;
+ for (i = 0, mp = p->mlp; i < p->msg_count; i++, mp++)
+ pop_log(p,POP_DEBUG,
+ "Msg %d at offset %d is %d octets long and has %u lines.",
+ mp->number,mp->offset,mp->length,mp->lines);
+ }
+#endif DEBUG
+
+ return(POP_SUCCESS);
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_get_command.c 1.9 8/16/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <strings.h>
+#include "popper.h"
+
+/*
+ * get_command: Extract the command from an input line form a POP client
+ */
+
+static state_table states[] = {
+ auth1, "user", 1, 1, pop_user, {auth1, auth2},
+ auth2, "pass", 1, 1, pop_pass, {auth1, trans},
+#ifdef RPOP
+ auth2, "rpop", 1, 1, pop_rpop, {auth1, trans},
+#endif RPOP
+ auth1, "quit", 0, 0, pop_quit, {halt, halt},
+ auth2, "quit", 0, 0, pop_quit, {halt, halt},
+ trans, "stat", 0, 0, pop_stat, {trans, trans},
+ trans, "list", 0, 1, pop_list, {trans, trans},
+ trans, "retr", 1, 1, pop_send, {trans, trans},
+ trans, "dele", 1, 1, pop_dele, {trans, trans},
+ trans, "noop", 0, 0, NULL, {trans, trans},
+ trans, "rset", 0, 0, pop_rset, {trans, trans},
+ trans, "top", 2, 2, pop_send, {trans, trans},
+ trans, "last", 0, 0, pop_last, {trans, trans},
+ trans, "xtnd", 1, 99, pop_xtnd, {trans, trans},
+ trans, "quit", 0, 0, pop_updt, {halt, halt},
+ (state) 0, NULL, 0, 0, NULL, {halt, halt},
+};
+
+state_table *pop_get_command(p,mp)
+POP * p;
+register char * mp; /* Pointer to unparsed line
+ received from the client */
+{
+ state_table * s;
+ char buf[MAXMSGLINELEN];
+
+ /* Save a copy of the original client line */
+#ifdef DEBUG
+ if(p->debug) strcpy (buf,mp);
+#endif DEBUG
+
+ /* Parse the message into the parameter array */
+ if ((p->parm_count = pop_parse(p,mp)) < 0) return(NULL);
+
+ /* Do not log cleartext passwords */
+#ifdef DEBUG
+ if(p->debug){
+ if(strcmp(p->pop_command,"pass") == 0)
+ pop_log(p,POP_DEBUG,"Received: \"%s xxxxxxxxx\"",p->pop_command);
+ else {
+ /* Remove trailing <LF> */
+ buf[strlen(buf)-2] = '\0';
+ pop_log(p,POP_DEBUG,"Received: \"%s\"",buf);
+ }
+ }
+#endif DEBUG
+
+ /* Search for the POP command in the command/state table */
+ for (s = states; s->command; s++) {
+
+ /* Is this a valid command for the current operating state? */
+ if (strcmp(s->command,p->pop_command) == 0
+ && s->ValidCurrentState == p->CurrentState) {
+
+ /* Were too few parameters passed to the command? */
+ if (p->parm_count < s->min_parms)
+ return((state_table *)pop_msg(p,POP_FAILURE,
+ "Too few arguments for the %s command.",p->pop_command));
+
+ /* Were too many parameters passed to the command? */
+ if (p->parm_count > s->max_parms)
+ return((state_table *)pop_msg(p,POP_FAILURE,
+ "Too many arguments for the %s command.",p->pop_command));
+
+ /* Return a pointer to the entry for this command in
+ the command/state table */
+ return (s);
+ }
+ }
+ /* The client command was not located in the command/state table */
+ return((state_table *)pop_msg(p,POP_FAILURE,
+ "Unknown command: \"%s\".",p->pop_command));
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_get_subcommand.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <strings.h>
+#include "popper.h"
+
+/*
+ * get_subcommand: Extract a POP XTND subcommand from a client input line
+ */
+
+static xtnd_table subcommands[] = {
+ "xmit", 0, 0, pop_xmit,
+ NULL
+};
+
+xtnd_table *pop_get_subcommand(p)
+POP * p;
+{
+ xtnd_table * s;
+
+ /* Search for the POP command in the command/state table */
+ for (s = subcommands; s->subcommand; s++) {
+
+ if (strcmp(s->subcommand,p->pop_subcommand) == 0) {
+
+ /* Were too few parameters passed to the subcommand? */
+ if ((p->parm_count-1) < s->min_parms)
+ return((xtnd_table *)pop_msg(p,POP_FAILURE,
+ "Too few arguments for the %s %s command.",
+ p->pop_command,p->pop_subcommand));
+
+ /* Were too many parameters passed to the subcommand? */
+ if ((p->parm_count-1) > s->max_parms)
+ return((xtnd_table *)pop_msg(p,POP_FAILURE,
+ "Too many arguments for the %s %s command.",
+ p->pop_command,p->pop_subcommand));
+
+ /* Return a pointer to the entry for this subcommand
+ in the XTND command table */
+ return (s);
+ }
+ }
+ /* The client subcommand was not located in the XTND command table */
+ return((xtnd_table *)pop_msg(p,POP_FAILURE,
+ "Unknown command: \"%s %s\".",p->pop_command,p->pop_subcommand));
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_last.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "popper.h"
+
+/*
+ * last: Display the last message touched in a POP session
+ */
+
+int pop_last (p)
+POP * p;
+{
+ return (pop_msg(p,POP_SUCCESS,"%u is the last message seen.",p->last_msg));
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_list.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "popper.h"
+
+/*
+ * list: List the contents of a POP maildrop
+ */
+
+int pop_list (p)
+POP * p;
+{
+ MsgInfoList * mp; /* Pointer to message info list */
+ register int i;
+ register int msg_num;
+
+ /* Was a message number provided? */
+ if (p->parm_count > 0) {
+ msg_num = atoi(p->pop_parm[1]);
+
+ /* Is requested message out of range? */
+ if ((msg_num < 1) || (msg_num > p->msg_count))
+ return (pop_msg (p,POP_FAILURE,
+ "Message %d does not exist.",msg_num));
+
+ /* Get a pointer to the message in the message list */
+ mp = &p->mlp[msg_num-1];
+
+ /* Is the message already flagged for deletion? */
+ if (mp->del_flag)
+ return (pop_msg (p,POP_FAILURE,
+ "Message %d has been deleted.",msg_num));
+
+ /* Display message information */
+ return (pop_msg(p,POP_SUCCESS,"%u %u",msg_num,mp->length));
+ }
+
+ /* Display the entire list of messages */
+ pop_msg(p,POP_SUCCESS,
+ "%u messages (%u octets)",
+ p->msg_count-p->msgs_deleted,p->drop_size-p->bytes_deleted);
+
+ /* Loop through the message information list. Skip deleted messages */
+ for (i = p->msg_count, mp = p->mlp; i > 0; i--, mp++) {
+ if (!mp->del_flag)
+ (void)fprintf(p->output,"%u %u\r\n",mp->number,mp->length);
+ }
+
+ /* "." signals the end of a multi-line transmission */
+ (void)fprintf(p->output,".\r\n");
+ (void)fflush(p->output);
+
+ return(POP_SUCCESS);
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_log.c 1.7 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <varargs.h>
+#include "popper.h"
+
+/*
+ * log: Make a log entry
+ */
+
+static char msgbuf[MAXLINELEN];
+
+pop_log(va_alist)
+va_dcl
+{
+ va_list ap;
+ POP * p;
+ int stat;
+ char * format;
+
+ va_start(ap);
+ p = va_arg(ap,POP *);
+ stat = va_arg(ap,int);
+ format = va_arg(ap,char *);
+ va_end(ap);
+
+#ifdef HAVE_VSPRINTF
+ vsprintf(msgbuf,format,ap);
+#else
+ (void)sprintf (msgbuf,format,((int *)ap)[0],((int *)ap)[1],((int *)ap)[2],
+ ((int *)ap)[3],((int *)ap)[4],((int *)ap)[5]);
+#endif HAVE_VSPRINTF
+
+ if (p->debug && p->trace) {
+ (void)fprintf(p->trace,"%s\n",msgbuf);
+ (void)fflush(p->trace);
+ }
+ else {
+ syslog (stat,"%s",msgbuf);
+ }
+
+ return(stat);
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_lower.c 1.6 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+
+/*
+ * lower: Convert a string to lowercase
+ */
+
+pop_lower (buf)
+char * buf;
+{
+ char * mp;
+
+ for (mp = buf; *mp; mp++)
+ if (isupper(*mp) && isupper(*mp)) *mp = (char)tolower((int)*mp);
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_msg.c 1.7 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <strings.h>
+#include <varargs.h>
+#include "popper.h"
+
+/*
+ * msg: Send a formatted line to the POP client
+ */
+
+pop_msg(va_alist)
+va_dcl
+{
+ POP * p;
+ int stat; /* POP status indicator */
+ char * format; /* Format string for the message */
+ va_list ap;
+ register char * mp;
+ char message[MAXLINELEN];
+
+ va_start(ap);
+ p = va_arg(ap, POP *);
+ stat = va_arg(ap, int);
+ format = va_arg(ap, char *);
+ va_end(ap);
+
+ /* Point to the message buffer */
+ mp = message;
+
+ /* Format the POP status code at the beginning of the message */
+ if (stat == POP_SUCCESS)
+ (void)sprintf (mp,"%s ",POP_OK);
+ else
+ (void)sprintf (mp,"%s ",POP_ERR);
+
+ /* Point past the POP status indicator in the message message */
+ mp += strlen(mp);
+
+ /* Append the message (formatted, if necessary) */
+ if (format)
+#ifdef HAVE_VSPRINTF
+ vsprintf(mp,format,ap);
+#else
+ (void)sprintf(mp,format,((int *)ap)[0],((int *)ap)[1],((int *)ap)[2],
+ ((int *)ap)[3],((int *)ap)[4]);
+#endif HAVE_VSPRINTF
+
+ /* Log the message if debugging is turned on */
+#ifdef DEBUG
+ if (p->debug && stat == POP_SUCCESS)
+ pop_log(p,POP_DEBUG,"%s",message);
+#endif DEBUG
+
+ /* Append the <CR><LF> */
+ (void)strcat(message, "\r\n");
+
+ /* Send the message to the client */
+ (void)fputs(message,p->output);
+ (void)fflush(p->output);
+
+ return(stat);
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_parse.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include "popper.h"
+
+/*
+ * parse: Parse a raw input line from a POP client
+ * into null-delimited tokens
+ */
+
+pop_parse(p,buf)
+POP * p;
+char * buf; /* Pointer to a message containing
+ the line from the client */
+{
+ char * mp;
+ register int i;
+
+ /* Loop through the POP command array */
+ for (mp = buf, i = 0; ; i++) {
+
+ /* Skip leading spaces and tabs in the message */
+ while (isspace(*mp))mp++;
+
+ /* Are we at the end of the message? */
+ if (*mp == 0) break;
+
+ /* Have we already obtained the maximum allowable parameters? */
+ if (i >= MAXPARMCOUNT) {
+ pop_msg(p,POP_FAILURE,"Too many arguments supplied.");
+ return(-1);
+ }
+
+ /* Point to the start of the token */
+ p->pop_parm[i] = mp;
+
+ /* Search for the first space character (end of the token) */
+ while (!isspace(*mp) && *mp) mp++;
+
+ /* Delimit the token with a null */
+ if (*mp) *mp++ = 0;
+ }
+
+ /* Were any parameters passed at all? */
+ if (i == 0) return (-1);
+
+ /* Convert the first token (POP command) to lower case */
+ pop_lower(p->pop_command);
+
+ /* Return the number of tokens extracted minus the command itself */
+ return (i-1);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_quit.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "popper.h"
+
+/*
+ * quit: Terminate a POP session
+ */
+
+int pop_quit (p)
+POP * p;
+{
+ /* Release the message information list */
+ if (p->mlp) free ((char *)p->mlp);
+
+ return(POP_SUCCESS);
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_rset.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "popper.h"
+
+/*
+ * rset: Unflag all messages flagged for deletion in a POP maildrop
+ */
+
+int pop_rset (p)
+POP * p;
+{
+ MsgInfoList * mp; /* Pointer to the message info list */
+ register int i;
+
+ /* Unmark all the messages */
+ for (i = p->msg_count, mp = p->mlp; i > 0; i--, mp++)
+ mp->del_flag = FALSE;
+
+ /* Reset the messages-deleted and bytes-deleted counters */
+ p->msgs_deleted = 0;
+ p->bytes_deleted = 0;
+
+ /* Reset the last-message-access flag */
+ p->last_msg = 0;
+
+ return (pop_msg(p,POP_SUCCESS,"Maildrop has %u messages (%u octets)",
+ p->msg_count,p->drop_size));
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/*
+ * mh compatibility (tom)
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_send.c 1.7 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <strings.h>
+#include "popper.h"
+
+/*
+ * send: Send the header and a specified number of lines
+ * from a mail message to a POP client.
+ */
+
+pop_send(p)
+POP * p;
+{
+ MsgInfoList * mp; /* Pointer to message info list */
+ register int msg_num;
+ register int msg_lines;
+ char buffer[MAXMSGLINELEN];
+
+ /* Convert the first parameter into an integer */
+ msg_num = atoi(p->pop_parm[1]);
+
+ /* Is requested message out of range? */
+ if ((msg_num < 1) || (msg_num > p->msg_count))
+ return (pop_msg (p,POP_FAILURE,"Message %d does not exist.",msg_num));
+
+ /* Get a pointer to the message in the message list */
+ mp = &p->mlp[msg_num-1];
+
+ /* Is the message flagged for deletion? */
+ if (mp->del_flag)
+ return (pop_msg (p,POP_FAILURE,
+ "Message %d has been deleted.",msg_num));
+
+ /* If this is a TOP command, get the number of lines to send */
+ if (strcmp(p->pop_command,"top") == 0) {
+ /* Convert the second parameter into an integer */
+ msg_lines = atoi(p->pop_parm[2]);
+ }
+ else {
+ /* Assume that a RETR (retrieve) command was issued */
+ msg_lines = -1;
+ /* Flag the message as retreived */
+ mp->retr_flag = TRUE;
+ }
+
+ /* Display the number of bytes in the message */
+ pop_msg(p,POP_SUCCESS,"%u octets",mp->length);
+
+ /* Position to the start of the message */
+ (void)fseek(p->drop,mp->offset,0);
+
+ /* Skip the first line (the sendmail "From" line) */
+ (void)fgets (buffer,MAXMSGLINELEN,p->drop);
+
+ /* Send the header of the message followed by a blank line */
+ while (fgets(buffer,MAXMSGLINELEN,p->drop)) {
+ pop_sendline (p,buffer);
+ /* A single newline (blank line) signals the
+ end of the header. sendline() converts this to a NULL,
+ so that's what we look for. */
+ if (*buffer == 0) break;
+ }
+ /* Send the message body */
+ while (fgets(buffer,MAXMSGLINELEN,p->drop)) {
+ /* Look for the start of the next message */
+ if (is_msg_boundary(buffer)) break;
+ /* Decrement the lines sent (for a TOP command) */
+ if (msg_lines >= 0 && msg_lines-- == 0) break;
+ pop_sendline(p,buffer);
+ }
+ /* "." signals the end of a multi-line transmission */
+ (void)fputs(".\r\n",p->output);
+ (void)fflush(p->output);
+
+ return(POP_SUCCESS);
+}
+
+/*
+ * sendline: Send a line of a multi-line response to a client.
+ */
+pop_sendline(p,buffer)
+POP * p;
+char * buffer;
+{
+ char * bp;
+
+ /* Byte stuff lines that begin with the temirnation octet */
+ if (*buffer == POP_TERMINATE) (void)fputc(POP_TERMINATE,p->output);
+
+ /* Look for a <NL> in the buffer */
+ if (bp = index(buffer,NEWLINE)) *bp = 0;
+
+ /* Send the line to the client */
+ (void)fputs(buffer,p->output);
+
+#ifdef DEBUG
+ if(p->debug)pop_log(p,POP_DEBUG,"Sending line \"%s\"",buffer);
+#endif DEBUG
+
+ /* Put a <CR><NL> if a newline was removed from the buffer */
+ if (bp) (void)fputs ("\r\n",p->output);
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_stat.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "popper.h"
+
+/*
+ * stat: Display the status of a POP maildrop to its client
+ */
+
+int pop_stat (p)
+POP * p;
+{
+ return (pop_msg (p,POP_SUCCESS,
+ "%u %u",p->msg_count-p->msgs_deleted,p->drop_size-p->bytes_deleted));
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/*
+ * code for mh compatibility (tom)
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_updt.c 1.9 8/16/90";
+#endif not lint
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <strings.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include "popper.h"
+
+extern int errno;
+
+static char standard_error[] =
+ "Error updating primary drop. Mailbox unchanged.";
+
+/*
+ * updt: Apply changes to a user's POP maildrop
+ */
+
+int pop_updt (p)
+POP * p;
+{
+ FILE * md; /* Stream pointer for
+ the user's maildrop */
+ int mfd; /* File descriptor for
+ above */
+ char buffer[BUFSIZ]; /* Read buffer */
+
+ MsgInfoList * mp; /* Pointer to message
+ info list */
+ register int msg_num; /* Current message
+ counter */
+ register int status_written; /* Status header field
+ written */
+ int nchar; /* Bytes read/written */
+
+ long offset; /* New mail offset */
+
+ int begun; /* Sanity check */
+
+#ifdef DEBUG
+ if (p->debug) {
+ pop_log(p,POP_DEBUG,"Performing maildrop update...");
+ pop_log(p,POP_DEBUG,"Checking to see if all messages were deleted");
+ }
+#endif DEBUG
+
+ if (p->msgs_deleted == p->msg_count) {
+ /* Truncate before close, to avoid race condition, DO NOT UNLINK!
+ Another process may have opened, and not yet tried to lock */
+ (void)ftruncate ((int)fileno(p->drop),0);
+ (void)fclose(p->drop) ;
+ return (POP_SUCCESS);
+ }
+
+#ifdef DEBUG
+ if (p->debug)
+ pop_log(p,POP_DEBUG,"Opening mail drop \"%s\"",p->drop_name);
+#endif DEBUG
+
+ /* Open the user's real maildrop */
+ if (((mfd = open(p->drop_name,O_RDWR|O_CREAT,0666)) == -1 ) ||
+ ((md = fdopen(mfd,"r+")) == NULL)) {
+ return pop_msg(p,POP_FAILURE,"%s %s",
+ p->drop_name, sys_errlist[errno]);
+ }
+
+ /* Lock the user's real mail drop */
+ if ( flock(mfd,LOCK_EX) == -1 ) {
+ (void)fclose(md) ;
+ return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop,
+ (errno < sys_nerr) ? sys_errlist[errno] : "");
+ }
+
+ /* Go to the right places */
+ offset = lseek((int)fileno(p->drop),0,L_XTND) ;
+
+ /* Append any messages that may have arrived during the session
+ to the temporary maildrop */
+ while ((nchar=read(mfd,buffer,BUFSIZ)) > 0)
+ if ( nchar != write((int)fileno(p->drop),buffer,nchar) ) {
+ nchar = -1;
+ break ;
+ }
+ if ( nchar != 0 ) {
+ (void)fclose(md) ;
+ (void)ftruncate((int)fileno(p->drop),(int)offset) ;
+ (void)fclose(p->drop) ;
+ return pop_msg(p,POP_FAILURE,standard_error);
+ }
+
+ rewind(md);
+ (void)ftruncate(mfd,0) ;
+
+ /* Synch stdio and the kernel for the POP drop */
+ rewind(p->drop);
+ (void)lseek((int)fileno(p->drop),0,L_SET);
+
+ /* Transfer messages not flagged for deletion from the temporary
+ maildrop to the new maildrop */
+#ifdef DEBUG
+ if (p->debug)
+ pop_log(p,POP_DEBUG,"Creating new maildrop \"%s\" from \"%s\"",
+ p->drop_name,p->temp_drop);
+#endif DEBUG
+
+ for (msg_num = 0; msg_num < p->msg_count; ++msg_num) {
+
+ int doing_body;
+
+ /* Get a pointer to the message information list */
+ mp = &p->mlp[msg_num];
+
+ if (mp->del_flag) {
+#ifdef DEBUG
+ if(p->debug)
+ pop_log(p,POP_DEBUG,
+ "Message %d flagged for deletion.",mp->number);
+#endif DEBUG
+ continue;
+ }
+
+ (void)fseek(p->drop,mp->offset,0);
+
+#ifdef DEBUG
+ if(p->debug)
+ pop_log(p,POP_DEBUG,"Copying message %d.",mp->number);
+#endif DEBUG
+
+ begun = 0;
+
+ for(status_written = doing_body = 0 ;
+ fgets(buffer,MAXMSGLINELEN,p->drop);) {
+
+ if (doing_body == 0) { /* Header */
+
+ /* panic, I'm tired and can't think contorted. */
+ if(is_msg_boundary(buffer) && begun) {
+ pop_log(p, POP_ERROR,
+ "%s: mailbox detonation has begun!", p->user);
+ (void)ftruncate(mfd,0);
+ (void)fclose(md);
+ (void)fclose(p->drop);
+ return(pop_msg(p, POP_FAILURE, "Unable to close mailbox door. Contact the postmaster to repair it."));
+ }
+
+ begun = 1;
+
+ /* Update the message status */
+ if (strncasecmp(buffer,"Status:",7) == 0) {
+ if (mp->retr_flag)
+ (void)fputs("Status: RO\n",md);
+ else
+ (void)fputs(buffer, md);
+ status_written++;
+ continue;
+ }
+ /* A blank line signals the end of the header. */
+ if (*buffer == '\n') {
+ doing_body = 1;
+
+#ifndef NOSTATUS
+ if (status_written == 0) {
+ if (mp->retr_flag)
+ (void)fputs("Status: RO\n\n",md);
+ else
+ (void)fputs("Status: U\n\n",md);
+ }
+ else
+#endif /* NOSTATUS */
+ (void)fputs ("\n", md);
+ continue;
+ }
+ /* Save another header line */
+ (void)fputs (buffer, md);
+ }
+ else { /* Body */
+ if (strncmp(buffer,"\001\001\001\001",4) == 0) {
+ (void)fputs (buffer, md);
+ break;
+ }
+ if(is_msg_boundary(buffer))
+ break;
+ (void)fputs (buffer, md);
+ }
+ }
+ }
+
+ /* flush and check for errors now! The new mail will writen
+ without stdio, since we need not separate messages */
+
+ (void)fflush(md) ;
+ if (ferror(md)) {
+ (void)ftruncate(mfd,0) ;
+ (void)fclose(md) ;
+ (void)fclose(p->drop) ;
+ return pop_msg(p,POP_FAILURE,standard_error);
+ }
+
+ /* Go to start of new mail if any */
+ (void)lseek((int)fileno(p->drop),offset,L_SET);
+
+ while((nchar=read((int)fileno(p->drop),buffer,BUFSIZ)) > 0)
+ if ( nchar != write(mfd,buffer,nchar) ) {
+ nchar = -1;
+ break ;
+ }
+ if ( nchar != 0 ) {
+ (void)ftruncate(mfd,0) ;
+ (void)fclose(md) ;
+ (void)fclose(p->drop) ;
+ return pop_msg(p,POP_FAILURE,standard_error);
+ }
+
+ /* Close the maildrop and empty temporary maildrop */
+ (void)fclose(md);
+ (void)ftruncate((int)fileno(p->drop),0);
+ (void)fclose(p->drop);
+
+ return(pop_quit(p));
+}
+
+
+
+
+is_msg_boundary(line)
+ char *line;
+{
+ if(strncmp(line, "\001\001\001\001", 4) == 0)
+ return(1);
+
+ if(strncmp(line, "From ", 5) != 0)
+ return(0);
+
+ line += 5;
+ while((*line != ' ') && (*line != '\0'))
+ ++line;
+
+ if(*line++ != ' ')
+ return(0);
+
+ if(strlen(line) < 28)
+ return(0);
+
+ /* Tue */
+ line += 3;
+ if(*line++ != ' ')
+ return(0);
+
+ /* Jan */
+ line += 3;
+ if(*line++ != ' ')
+ return(0);
+
+ /* 22 */
+ line += 2;
+ if(*line++ != ' ')
+ return(0);
+
+ /* 18:21:34 */
+ line += 2;
+ if(*line++ != ':')
+ return(0);
+
+ line += 2;
+ if(*line++ != ':')
+ return(0);
+
+ line += 2;
+ if(*line++ != ' ')
+ return(0);
+
+ return(1);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_user.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <strings.h>
+#include "popper.h"
+
+/*
+ * user: Prompt for the user name at the start of a POP session
+ */
+
+int pop_user (p)
+POP * p;
+{
+#ifndef KERBEROS
+ /* Save the user name */
+ (void)strcpy(p->user, p->pop_parm[1]);
+#endif /* KERBEROS */
+
+ /* Tell the user that the password is required */
+ return (pop_msg(p,POP_SUCCESS,"Password required for %s.",p->user));
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_xmit.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include "popper.h"
+
+/*
+ * xmit: POP XTND function to receive a message from
+ * a client and send it in the mail
+ */
+
+pop_xmit (p)
+POP * p;
+{
+ FILE * tmp; /* File descriptor for
+ temporary file */
+ char buffer[MAXLINELEN]; /* Read buffer */
+ char temp_xmit[MAXDROPLEN]; /* Name of the temporary
+ filedrop */
+ union wait stat;
+ int id, pid;
+
+ /* Create a temporary file into which to copy the user's message */
+ (void)mktemp((char *)strcpy(temp_xmit,POP_TMPXMIT));
+#ifdef DEBUG
+ if(p->debug)
+ pop_log(p,POP_DEBUG,
+ "Creating temporary file for sending a mail message \"%s\"\n",
+ temp_xmit);
+#endif DEBUG
+ if ((tmp = fopen(temp_xmit,"w+")) == NULL)
+ return (pop_msg(p,POP_FAILURE,
+ "Unable to create temporary message file \"%s\", errno = %d",
+ temp_xmit,errno));
+
+ /* Tell the client to start sending the message */
+ pop_msg(p,POP_SUCCESS,"Start sending the message.");
+
+ /* Receive the message */
+#ifdef DEBUG
+ if(p->debug)pop_log(p,POP_DEBUG,"Receiving mail message");
+#endif DEBUG
+ while (fgets(buffer,MAXLINELEN,p->input)){
+ /* Look for initial period */
+#ifdef DEBUG
+ if(p->debug)pop_log(p,POP_DEBUG,"Receiving: \"%s\"",buffer);
+#endif DEBUG
+ if (*buffer == '.') {
+ /* Exit on end of message */
+ if (strcmp(buffer,".\r\n") == 0) break;
+ }
+ (void)fputs (buffer,tmp);
+ }
+ (void)fclose (tmp);
+
+#ifdef DEBUG
+ if(p->debug)pop_log(p,POP_DEBUG,"Forking for \"%s\"",MAIL_COMMAND);
+#endif DEBUG
+ /* Send the message */
+ switch (pid = fork()) {
+ case 0:
+ (void)fclose (p->input);
+ (void)fclose (p->output);
+ (void)close(0);
+ if (open(temp_xmit,O_RDONLY,0) < 0) (void)_exit(1);
+ (void)execl (MAIL_COMMAND,"send-mail","-t","-oem",NULLCP);
+ (void)_exit(1);
+ case -1:
+#ifdef DEBUG
+ if (!p->debug) (void)unlink (temp_xmit);
+#endif DEBUG
+ return (pop_msg(p,POP_FAILURE,
+ "Unable to execute \"%s\"",MAIL_COMMAND));
+ default:
+ while((id = wait(&stat)) >=0 && id != pid);
+ if (!p->debug) (void)unlink (temp_xmit);
+ if (stat.w_retcode)
+ return (pop_msg(p,POP_FAILURE,"Unable to send message"));
+ return (pop_msg (p,POP_SUCCESS,"Message sent successfully"));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+static char SccsId[] = "@(#)pop_xtnd.c 1.5 7/13/90";
+#endif not lint
+
+#include <stdio.h>
+#include <sys/types.h>
+#include "popper.h"
+
+/*
+ * xtnd: Handle extensions to the POP protocol suite
+ */
+
+extern xtnd_table * pop_get_subcommand();
+
+int pop_xtnd (p)
+POP * p;
+{
+ xtnd_table * x;
+
+ /* Convert the XTND subcommand to lower case */
+ pop_lower(p->pop_subcommand);
+
+ /* Search for the subcommand in the XTND command table */
+ if ((x = pop_get_subcommand(p)) == NULL) return(POP_FAILURE);
+
+ /* Call the function associated with this subcommand */
+ if (x->function) return((*x->function)(p));
+
+ /* Otherwise assume NOOP */
+ return (pop_msg(p,POP_SUCCESS,NULL));
+}
--- /dev/null
+.\" Copyright (c) 1980 Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms are permitted
+.\" provided that this notice is preserved and that due credit is given
+.\" to the University of California at Berkeley. The name of the University
+.\" may not be used to endorse or promote products derived from this
+.\" software without specific prior written permission. This software
+.\" is provided ``as is'' without express or implied warranty.
+.\"
+.\" @(#)popper.8 1.3 (CCS) 9/15/90 Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n
+.\"
+.TH popper 8 "August 1990"
+.UC 6
+.ad
+.SH NAME
+popper \- pop 3 server
+.SH SYNOPSIS
+.B /usr/etc/popper
+[ -d ]
+[ -t trace-file]
+.SH DESCRIPTION
+.I Popper
+is an implementation of the Post Office Protocol server that runs on a
+variety of Unix computers to manage electronic mail for Macintosh
+and MS-DOS computers. The server was developed at the University of
+California at Berkeley and conforms fully to the specifications in RFC
+1081 and RFC 1082. The Berkeley server also has extensions to
+send electronic mail on behalf of a client.
+.PP
+The
+.B \-d
+flag sets the socket to debugging and turns on debugging. All debugging
+information is saved using syslog(8). The
+.B \-t trace\-file
+flag turns on debugging and saves the trace information in
+.I trace\-file
+using fprintf(s).
+.SH HOW TO OBTAIN THE SERVER
+.PP
+The POP server is available via anonymous ftp from lilac.Berkeley.EDU
+(128.32.136.12). It is in two files in the pub directory: a compressed
+tar file popper.tar.Z and a Macintosh StuffIt archive in BinHex format
+called MacPOP.sit.hqx.
+.SH THE POP TRANSACTION CYCLE
+.PP
+The Berkeley POP server is a single program (called popper) that is
+launched by inetd when it gets a service request on the POP TCP port.
+(The official port number specified in RFC 1081 for POP version 3 is
+port 110. However, some POP3 clients attempt to contact the server at
+port 109, the POP version 2 port. Unless you are running both POP2 and
+POP3 servers, you can simply define both ports for use by the POP3
+server. This is explained in the installation instructions later on.)
+The popper program initializes and verifies that the peer IP address is
+registered in the local domain, logging a warning message when a
+connection is made to a client whose IP address does not have a
+canonical name. For systems using BSD 4.3 bind, it also checks to see
+if a cannonical name lookup for the client returns the same peer IP
+address, logging a warning message if it does not. The the server
+enters the authorization state, during which the client must correctly
+identify itself by providing a valid Unix userid and password on the
+server's host machine. No other exchanges are allowed during this
+state (other than a request to quit.) If authentication fails, a
+warning message is logged and the session ends. Once the user is
+identified, popper changes its user and group ids to match that of the
+user and enters the transaction state. The server makes a temporary
+copy of the user's maildrop (ordinarily in /usr/spool/mail) which is
+used for all subsequent transactions. These include the bulk of POP
+commands to retrieve mail, delete mail, undelete mail, and so forth. A
+Berkeley extension also allows the user to submit a mail parcel to the
+server who mails it using the sendmail program (this extension is
+supported in the HyperMail client distributed with the server). When
+the client quits, the server enters the final update state during which
+the network connection is terminated and the user's maildrop is updated
+with the (possibly) modified temporary maildrop.
+.SH LOGGING
+.PP
+The POP server uses syslog to keep a record of its activities. On
+systems with BSD 4.3 syslogging, the server logs (by default) to the
+"local0" facility at priority "notice" for all messages except
+debugging which is logged at priority "debug". The default log file is
+/usr/spool/mqueue/POPlog. These can be changed, if desired. On
+systems with 4.2 syslogging all messages are logged to the local log
+file, usually /usr/spool/mqueue/syslog.
+.SH DEBUGGING
+.PP
+The popper program will log debugging information when the -d parameter
+is specified after its invocation in the inetd.conf file. Care should
+be exercised in using this option since it generates considerable
+output in the syslog file. Alternatively, the "-t <file-name>" option
+will place debugging information into file "<file-name>" using fprintf
+instead of syslog.
+.PP
+For SunOS version 3.5, the popper program is launched by inetd from
+/etc/servers. This file does not allow you to specify command line
+arguments. Therefore, if you want to enable debugging, you can specify
+a shell script in /etc/servers to be launched instead of popper and in
+this script call popper with the desired arguments.
+.PP
+You can confirm that the POP server is running on Unix by telneting to
+port 110 (or 109 if you set it up that way). For example:
+.PP
+.nf
+%telnet myhost 110
+Trying...
+Connected to myhost.berkeley.edu.
+Escape character is '^]'.
++OK UCB Pop server (version 1.6) at myhost starting.
+quit
+Connection closed by foreign host.
+.fi
+.SH VERSION 1.7 RELEASE NOTES
+Extensive re-write of the maildrop processing code contributed by
+Viktor Dukhovni <viktor@math.princeton.edu> that greatly reduces the
+possibility that the maildrop can be corrupted as the result of
+simultaneous access by two or more processes.
+.PP
+Added "pop_dropcopy" module to create a temporary maildrop from
+the existing, standard maildrop as root before the setuid and
+setgid for the user is done. This allows the temporary maildrop
+to be created in a mail spool area that is not world read-writable.
+.PP
+This version does *not* send the sendmail "From " delimiter line
+in response to a TOP or RETR command.
+.PP
+Encased all debugging code in #ifdef DEBUG constructs. This code can
+be included by specifying the DEGUG compiler flag. Note: You still
+need to use the -d or -t option to obtain debugging output.
+.SH FILES
+.nf
+/usr/spool/mail mail files
+/etc/inetd.conf pop program invocation
+/etc/syslog.conf logging specifications
+.fi
+.SH "SEE ALSO"
+inetd(8),
+RFC1081,
+RFC1082
+.SH AUTHORS
+Bob Campbell, Edward Moy, Austin Shelton, Marshall T Rose, and cast of
+thousands at Rand, UDel, UCI, and elsewhere.
+Kerberos authentication added by Tom Coppeto - MIT Network Services.
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ * static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+ * static char SccsId[] = "@(#)popper.h 1.10 7/13/90";
+ *
+ */
+
+/* LINTLIBRARY */
+
+/*
+ * Header file for the POP programs
+ */
+
+#include <syslog.h>
+#include "version.h"
+
+#define NULLCP ((char *) 0)
+#define SPACE 32
+#define TAB 9
+#define TRUE 1
+#define FALSE 0
+#define NEWLINE '\n'
+
+#define MAXHOSTNAMELEN 256
+#define MAXUSERNAMELEN 65
+#define MAXDROPLEN 296 /* was 65: kerberos name + max path size - tom */
+#define MAXLINELEN 1024
+#define MAXMSGLINELEN 1024
+#define MAXCMDLEN 4
+#define MAXPARMCOUNT 5
+#define MAXPARMLEN 10
+#define ALLOC_MSGS 20
+#define MAIL_COMMAND "/usr/lib/sendmail"
+
+#define POP_FACILITY LOG_LOCAL0
+#define POP_ERROR LOG_ERR
+#define POP_WARNING LOG_WARNING
+#define POP_PRIORITY LOG_NOTICE
+#define POP_INFO LOG_INFO
+#define POP_DEBUG LOG_DEBUG
+#define POP_LOGOPTS 0
+#define POP_MAILDIR "/usr/spool/pop"
+#define POP_PASSFILE "/usr/spool/pop/POP"
+#define POP_DROP "/usr/spool/pop/.%s.temp"
+#define POP_TMPXMIT "/tmp/xmitXXXXXX"
+#define POP_OK "+OK"
+#define POP_ERR "-ERR"
+#define POP_SUCCESS 1
+#define POP_FAILURE 0
+#define POP_TERMINATE '.'
+
+extern int errno;
+extern int sys_nerr;
+extern char * sys_errlist[];
+extern char * sys_siglist[];
+
+#define pop_command pop_parm[0] /* POP command is first token */
+#define pop_subcommand pop_parm[1] /* POP XTND subcommand is the
+ second token */
+
+typedef enum { /* POP processing states */
+ auth1, /* Authorization: waiting for
+ USER command */
+ auth2, /* Authorization: waiting for
+ PASS command */
+ trans, /* Transaction */
+ update, /* Update: session ended,
+ process maildrop changes */
+ halt, /* (Halt): stop processing
+ and exit */
+ error /* (Error): something really
+ bad happened */
+} state;
+
+typedef struct { /* State information for
+ each POP command */
+ state ValidCurrentState; /* The operating state of
+ the command */
+ char * command; /* The POP command */
+ int min_parms; /* Minimum number of parms
+ for the command */
+ int max_parms; /* Maximum number of parms
+ for the command */
+ int (*function) (); /* The function that process
+ the command */
+ state result[2]; /* The resulting state after
+ command processing */
+#define success_state result[0] /* State when a command
+ succeeds */
+} state_table;
+
+typedef struct { /* Table of extensions */
+ char * subcommand; /* The POP XTND subcommand */
+ int min_parms; /* Minimum number of parms for
+ the subcommand */
+ int max_parms; /* Maximum number of parms for
+ the subcommand */
+ int (*function) (); /* The function that processes
+ the subcommand */
+} xtnd_table;
+
+typedef struct { /* Message information */
+ int number; /* Message number relative to
+ the beginning of list */
+ long length; /* Length of message in
+ bytes */
+ int lines; /* Number of (null-terminated) lines in the message */
+ long offset; /* Offset from beginning of
+ file */
+ int del_flag; /* Flag indicating if message
+ is marked for deletion */
+ int retr_flag; /* Flag indicating if message
+ was retrieved */
+} MsgInfoList;
+
+typedef struct { /* POP parameter block */
+ int debug; /* Debugging requested */
+ char * myname; /* The name of this POP
+ daemon program */
+ char myhost[MAXHOSTNAMELEN]; /* The name of our host
+ computer */
+ char * client; /* Canonical name of client
+ computer */
+ char * ipaddr; /* Dotted-notation format of
+ client IP address */
+ unsigned short ipport; /* Client port for privileged
+ operations */
+ char user[MAXUSERNAMELEN]; /* Name of the POP user */
+ state CurrentState; /* The current POP operational state */
+ MsgInfoList * mlp; /* Message information list */
+ int msg_count; /* Number of messages in
+ the maildrop */
+ int msgs_deleted; /* Number of messages flagged
+ for deletion */
+ int last_msg; /* Last message touched by
+ the user */
+ long bytes_deleted; /* Number of maildrop bytes
+ flagged for deletion */
+ char drop_name[MAXDROPLEN]; /* The name of the user's
+ maildrop */
+ char temp_drop[MAXDROPLEN]; /* The name of the user's
+ temporary maildrop */
+ long drop_size; /* Size of the maildrop in
+ bytes */
+ FILE * drop; /* (Temporary) mail drop */
+ FILE * input; /* Input TCP/IP communication
+ stream */
+ FILE * output; /* Output TCP/IP communication stream */
+ FILE * trace; /* Debugging trace file */
+ char * pop_parm[MAXPARMCOUNT]; /* Parse POP parameter list */
+ int parm_count; /* Number of parameters in
+ parsed list */
+} POP;
+
+extern int pop_dele();
+extern int pop_last();
+extern int pop_list();
+extern int pop_pass();
+extern int pop_quit();
+extern int pop_rset();
+extern int pop_send();
+extern int pop_stat();
+extern int pop_updt();
+extern int pop_user();
+extern int pop_xtnd();
+extern int pop_xmit();
+
--- /dev/null
+debug - debugging information
+info - logs connections
+notice - errors (ie: locked maildrop, broken pipe)
+warning - authentication/authorization errors
+error - bigger errors (ie: no resources)
--- /dev/null
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ * static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
+ * static char SccsId[] = "@(#)version.h 1.11 9/15/90";
+ *
+ */
+
+/*
+ * Current version of this POP implementation
+ */
+
+#define VERSION "1.7"
--- /dev/null
+ignore */*.0
--- /dev/null
+all:
+ cd libtelnet; make CC="${CC}" TELNET_OPSYS=$(TELNET_OPSYS)
+ cd telnet; make CC="${CC}" TELNET_OPSYS=$(TELNET_OPSYS)
+ cd telnetd; make CC="${CC}" TELNET_OPSYS=$(TELNET_OPSYS)
+
+clean::
+ cd libtelnet; make CC="${CC}" TELNET_OPSYS=$(TELNET_OPSYS) clean
+ cd telnet; make CC="${CC}" TELNET_OPSYS=$(TELNET_OPSYS) clean
+ cd telnetd; make CC="${CC}" TELNET_OPSYS=$(TELNET_OPSYS) clean
+
+install::
+ cd libtelnet; make CC="${CC}" DESTDIR=$(DESTDIR) \
+ TELNET_OPSYS=$(TELNET_OPSYS) install
+ cd telnet; make CC="${CC}" DESTDIR=$(DESTDIR) \
+ TELNET_OPSYS=$(TELNET_OPSYS) install
+ cd telnetd; make CC="${CC}" DESTDIR=$(DESTDIR) \
+ TELNET_OPSYS=$(TELNET_OPSYS) install
+
+SUBDIRS=libtelnet telnet telnetd
+
+MakefileSubdirs($(SUBDIRS))
+
+depend:
+ @echo "We don't calculate dependencies below this point."
--- /dev/null
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted provided
+# that: (1) source distributions retain this entire copyright notice and
+# comment, and (2) distributions including binaries display the following
+# acknowledgement: ``This product includes software developed by the
+# University of California, Berkeley and its contributors'' in the
+# documentation or other materials provided with the distribution and in
+# all advertising materials mentioning features or use of this software.
+# 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+# @(#)Makefile 5.5 (Berkeley) 3/1/91
+#
+
+#
+# Everything happens in ../Makefile.config and Makefile.generic
+#
+
+all:
+ @-if [ -f ../Config.local ]; \
+ then \
+ echo make -f ../Config.local WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)"; \
+ make -f ../Config.local WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)"; \
+ else \
+ echo make -f ../Config.generic WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)" $(TELNET_OPSYS); \
+ make -f ../Config.generic WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)" $(TELNET_OPSYS); \
+ fi
+
+Makefiles::
+ @echo "Do nothing!"
+
+.DEFAULT:
+ @-if [ -f ../Config.local ]; \
+ then \
+ echo make -f ../Config.local WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ make -f ../Config.local WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ else \
+ echo make -f ../Config.generic WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ make -f ../Config.generic WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ fi
+
--- /dev/null
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)gettytab.c 5.1 (Berkeley) 4/29/85";
+#endif not lint
+
+#include <ctype.h>
+
+#define TABBUFSIZ 512
+
+static char *tbuf;
+int hopcount; /* detect infinite loops in termcap, init 0 */
+char *skip();
+char *getstr();
+char *decode();
+
+/*
+ * Get an entry for terminal name in buffer bp,
+ * from the termcap file. Parse is very rudimentary;
+ * we just notice escaped newlines.
+ */
+getent(bp, name)
+ char *bp, *name;
+{
+ register char *cp;
+ register int c;
+ register int i = 0, cnt = 0;
+ char ibuf[TABBUFSIZ];
+ char *cp2;
+ int tf;
+
+ tbuf = bp;
+ tf = open("/etc/gettytab", 0);
+ if (tf < 0)
+ return (-1);
+ for (;;) {
+ cp = bp;
+ for (;;) {
+ if (i == cnt) {
+ cnt = read(tf, ibuf, TABBUFSIZ);
+ if (cnt <= 0) {
+ close(tf);
+ return (0);
+ }
+ i = 0;
+ }
+ c = ibuf[i++];
+ if (c == '\n') {
+ if (cp > bp && cp[-1] == '\\'){
+ cp--;
+ continue;
+ }
+ break;
+ }
+ if (cp >= bp+TABBUFSIZ) {
+ write(2,"Gettytab entry too long\n", 24);
+ break;
+ } else
+ *cp++ = c;
+ }
+ *cp = 0;
+
+ /*
+ * The real work for the match.
+ */
+ if (namatch(name)) {
+ close(tf);
+ return(nchktc());
+ }
+ }
+}
+
+/*
+ * tnchktc: check the last entry, see if it's tc=xxx. If so,
+ * recursively find xxx and append that entry (minus the names)
+ * to take the place of the tc=xxx entry. This allows termcap
+ * entries to say "like an HP2621 but doesn't turn on the labels".
+ * Note that this works because of the left to right scan.
+ */
+#define MAXHOP 32
+nchktc()
+{
+ register char *p, *q;
+ char tcname[16]; /* name of similar terminal */
+ char tcbuf[TABBUFSIZ];
+ char *holdtbuf = tbuf;
+ int l;
+
+ p = tbuf + strlen(tbuf) - 2; /* before the last colon */
+ while (*--p != ':')
+ if (p<tbuf) {
+ write(2, "Bad gettytab entry\n", 19);
+ return (0);
+ }
+ p++;
+ /* p now points to beginning of last field */
+ if (p[0] != 't' || p[1] != 'c')
+ return(1);
+ strcpy(tcname,p+3);
+ q = tcname;
+ while (q && *q != ':')
+ q++;
+ *q = 0;
+ if (++hopcount > MAXHOP) {
+ write(2, "Getty: infinite tc= loop\n", 25);
+ return (0);
+ }
+ if (getent(tcbuf, tcname) != 1)
+ return(0);
+ for (q=tcbuf; *q != ':'; q++)
+ ;
+ l = p - holdtbuf + strlen(q);
+ if (l > TABBUFSIZ) {
+ write(2, "Gettytab entry too long\n", 24);
+ q[TABBUFSIZ - (p-tbuf)] = 0;
+ }
+ strcpy(p, q+1);
+ tbuf = holdtbuf;
+ return(1);
+}
+
+/*
+ * Tnamatch deals with name matching. The first field of the termcap
+ * entry is a sequence of names separated by |'s, so we compare
+ * against each such name. The normal : terminator after the last
+ * name (before the first field) stops us.
+ */
+namatch(np)
+ char *np;
+{
+ register char *Np, *Bp;
+
+ Bp = tbuf;
+ if (*Bp == '#')
+ return(0);
+ for (;;) {
+ for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
+ continue;
+ if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
+ return (1);
+ while (*Bp && *Bp != ':' && *Bp != '|')
+ Bp++;
+ if (*Bp == 0 || *Bp == ':')
+ return (0);
+ Bp++;
+ }
+}
+
+/*
+ * Skip to the next field. Notice that this is very dumb, not
+ * knowing about \: escapes or any such. If necessary, :'s can be put
+ * into the termcap file in octal.
+ */
+static char *
+skip(bp)
+ register char *bp;
+{
+
+ while (*bp && *bp != ':')
+ bp++;
+ if (*bp == ':')
+ bp++;
+ return (bp);
+}
+
+/*
+ * Return the (numeric) option id.
+ * Numeric options look like
+ * li#80
+ * i.e. the option string is separated from the numeric value by
+ * a # character. If the option is not found we return -1.
+ * Note that we handle octal numbers beginning with 0.
+ */
+long
+getnum(id)
+ char *id;
+{
+ register long i, base;
+ register char *bp = tbuf;
+
+ for (;;) {
+ bp = skip(bp);
+ if (*bp == 0)
+ return (-1);
+ if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
+ continue;
+ if (*bp == '@')
+ return(-1);
+ if (*bp != '#')
+ continue;
+ bp++;
+ base = 10;
+ if (*bp == '0')
+ base = 8;
+ i = 0;
+ while (isdigit(*bp))
+ i *= base, i += *bp++ - '0';
+ return (i);
+ }
+}
+
+/*
+ * Handle a flag option.
+ * Flag options are given "naked", i.e. followed by a : or the end
+ * of the buffer. Return 1 if we find the option, or 0 if it is
+ * not given.
+ */
+getflag(id)
+ char *id;
+{
+ register char *bp = tbuf;
+
+ for (;;) {
+ bp = skip(bp);
+ if (!*bp)
+ return (-1);
+ if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
+ if (!*bp || *bp == ':')
+ return (1);
+ else if (*bp == '!')
+ return (0);
+ else if (*bp == '@')
+ return(-1);
+ }
+ }
+}
+
+/*
+ * Get a string valued option.
+ * These are given as
+ * cl=^Z
+ * Much decoding is done on the strings, and the strings are
+ * placed in area, which is a ref parameter which is updated.
+ * No checking on area overflow.
+ */
+char *
+getstr(id, area)
+ char *id, **area;
+{
+ register char *bp = tbuf;
+
+ for (;;) {
+ bp = skip(bp);
+ if (!*bp)
+ return (0);
+ if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
+ continue;
+ if (*bp == '@')
+ return(0);
+ if (*bp != '=')
+ continue;
+ bp++;
+ return (decode(bp, area));
+ }
+}
+
+/*
+ * Tdecode does the grung work to decode the
+ * string capability escapes.
+ */
+static char *
+decode(str, area)
+ register char *str;
+ char **area;
+{
+ register char *cp;
+ register int c;
+ register char *dp;
+ int i;
+
+ cp = *area;
+ while ((c = *str++) && c != ':') {
+ switch (c) {
+
+ case '^':
+ c = *str++ & 037;
+ break;
+
+ case '\\':
+ dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
+ c = *str++;
+nextc:
+ if (*dp++ == c) {
+ c = *dp++;
+ break;
+ }
+ dp++;
+ if (*dp)
+ goto nextc;
+ if (isdigit(c)) {
+ c -= '0', i = 2;
+ do
+ c <<= 3, c |= *str++ - '0';
+ while (--i && isdigit(*str));
+ }
+ break;
+ }
+ *cp++ = c;
+ }
+ *cp++ = 0;
+ str = *area;
+ *area = cp;
+ return (str);
+}
--- /dev/null
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ * @(#)gettytab.h 5.2 (Berkeley) 1/7/86
+ */
+
+/*
+ * Getty description definitions.
+ */
+struct gettystrs {
+ char *field; /* name to lookup in gettytab */
+ char *defalt; /* value we find by looking in defaults */
+ char *value; /* value that we find there */
+};
+
+struct gettynums {
+ char *field; /* name to lookup */
+ long defalt; /* number we find in defaults */
+ long value; /* number we find there */
+ int set; /* we actually got this one */
+};
+
+struct gettyflags {
+ char *field; /* name to lookup */
+ char invrt; /* name existing in gettytab --> false */
+ char defalt; /* true/false in defaults */
+ char value; /* true/false flag */
+ char set; /* we found it */
+};
+
+/*
+ * String values.
+ */
+#define NX gettystrs[0].value
+#define CL gettystrs[1].value
+#define IM gettystrs[2].value
+#define LM gettystrs[3].value
+#define ER gettystrs[4].value
+#define KL gettystrs[5].value
+#define ET gettystrs[6].value
+#define PC gettystrs[7].value
+#define TT gettystrs[8].value
+#define EV gettystrs[9].value
+#define LO gettystrs[10].value
+#define HN gettystrs[11].value
+#define HE gettystrs[12].value
+#define IN gettystrs[13].value
+#define QU gettystrs[14].value
+#define XN gettystrs[15].value
+#define XF gettystrs[16].value
+#define BK gettystrs[17].value
+#define SU gettystrs[18].value
+#define DS gettystrs[19].value
+#define RP gettystrs[20].value
+#define FL gettystrs[21].value
+#define WE gettystrs[22].value
+#define LN gettystrs[23].value
+
+/*
+ * Numeric definitions.
+ */
+#define IS gettynums[0].value
+#define OS gettynums[1].value
+#define SP gettynums[2].value
+#define ND gettynums[3].value
+#define CD gettynums[4].value
+#define TD gettynums[5].value
+#define FD gettynums[6].value
+#define BD gettynums[7].value
+#define TO gettynums[8].value
+#define F0 gettynums[9].value
+#define F0set gettynums[9].set
+#define F1 gettynums[10].value
+#define F1set gettynums[10].set
+#define F2 gettynums[11].value
+#define F2set gettynums[11].set
+#define PF gettynums[12].value
+
+/*
+ * Boolean values.
+ */
+#define HT gettyflags[0].value
+#define NL gettyflags[1].value
+#define EP gettyflags[2].value
+#define EPset gettyflags[2].set
+#define OP gettyflags[3].value
+#define OPset gettyflags[2].set
+#define AP gettyflags[4].value
+#define APset gettyflags[2].set
+#define EC gettyflags[5].value
+#define CO gettyflags[6].value
+#define CB gettyflags[7].value
+#define CK gettyflags[8].value
+#define CE gettyflags[9].value
+#define PE gettyflags[10].value
+#define RW gettyflags[11].value
+#define XC gettyflags[12].value
+#define LC gettyflags[13].value
+#define UC gettyflags[14].value
+#define IG gettyflags[15].value
+#define PS gettyflags[16].value
+#define HC gettyflags[17].value
+#define UB gettyflags[18].value
+#define AB gettyflags[19].value
+#define DX gettyflags[20].value
+#define RM gettyflags[21].value
+
+int getent();
+long getnum();
+int getflag();
+char *getstr();
+
+extern struct gettyflags gettyflags[];
+extern struct gettynums gettynums[];
+extern struct gettystrs gettystrs[];
+extern int hopcount;
--- /dev/null
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted provided
+# that: (1) source distributions retain this entire copyright notice and
+# comment, and (2) distributions including binaries display the following
+# acknowledgement: ``This product includes software developed by the
+# University of California, Berkeley and its contributors'' in the
+# documentation or other materials provided with the distribution and in
+# all advertising materials mentioning features or use of this software.
+# 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+# @(#)Makefile 5.5 (Berkeley) 3/1/91
+#
+
+#
+# Everything happens in ../Makefile.config and Makefile.generic
+#
+
+all:
+ @-if [ -f ../Config.local ]; \
+ then \
+ echo make -f ../Config.local WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)"; \
+ make -f ../Config.local WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)"; \
+ else \
+ echo make -f ../Config.generic WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)" $(TELNET_OPSYS); \
+ make -f ../Config.generic WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)" $(TELNET_OPSYS); \
+ fi
+
+.DEFAULT:
+ @-if [ -f ../Config.local ]; \
+ then \
+ echo make -f ../Config.local WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ make -f ../Config.local WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ else \
+ echo make -f ../Config.generic WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ make -f ../Config.generic WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ fi
+
--- /dev/null
+#
+# Copyright (c) 1991 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted provided
+# that: (1) source distributions retain this entire copyright notice and
+# comment, and (2) distributions including binaries display the following
+# acknowledgement: ``This product includes software developed by the
+# University of California, Berkeley and its contributors'' in the
+# documentation or other materials provided with the distribution and in
+# all advertising materials mentioning features or use of this software.
+# 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+# @(#)Makefile 5.5 (Berkeley) 3/1/91
+#
+
+#
+# Everything happens in ../Makefile.config and Makefile.generic
+#
+
+all:
+ @-if [ -f ../Config.local ]; \
+ then \
+ echo make -f ../Config.local WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)"; \
+ make -f ../Config.local WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)"; \
+ else \
+ echo make -f ../Config.generic WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)" $(TELNET_OPSYS); \
+ make -f ../Config.generic WHAT="" CC="${CC}" \
+ KLIB="$(KLIB)" DEPKLIB="$(DEPKLIB)" $(TELNET_OPSYS); \
+ fi
+
+.DEFAULT:
+ @-if [ -f ../Config.local ]; \
+ then \
+ echo make -f ../Config.local WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ make -f ../Config.local WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ else \
+ echo make -f ../Config.generic WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ make -f ../Config.generic WHAT=$@ CC="${CC}" \
+ DESTDIR=$(DESTDIR) DEST=$(DEST) $(TELNET_OPSYS); \
+ fi
+
--- /dev/null
+all::
+
+Krb5InstallManPage(krb.conf,$(FILE_MANDIR),$(FILE_MANSUFFIX))
+Krb5InstallManPage(krb.realms,$(FILE_MANDIR),$(FILE_MANSUFFIX))
+
+depend::
--- /dev/null
+***************
+*** 1,119 ****
+! /**/# $Source$
+! /**/# $Author$
+! /**/# $Id$
+! /**/#
+!
+! /**/###########################################################################
+! /**/# Imake rules for building libraries, programs, scripts, and data files
+! /**/# rules: $XConsortium: Imake.rules,v 1.67 89/12/18 17:14:15 jim Exp $
+
+ /*
+ * MACHINE-INDEPENDENT RULES; DO NOT MODIFY
+ *
+! * Warning, when defining rules: make sure you don't include both a trailing
+ * backslash and double ampersand backslash or else you will get an extra
+ * backslash in the Makefile.
+ *
+! * These macros are defined for the various templates and Imakefiles (for a
+! * list of the applicable make variables, see the template files):
+ *
+! * SaberProgramTarget (program,srclist,objlist,locallibs,syslibs)
+! * RemoveTargetProgram (program)
+! * BuildIncludes (srclist,dstdir)
+! * NormalProgramTarget (program,objects,deplibs,locallibs,syslibs)
+! * SimpleProgramTarget (program)
+! * ComplexProgramTarget (program)
+! * ComplexProgramTarget_1 (program,locallib,syslib)
+! * ComplexProgramTarget_2 (program,locallib,syslib)
+! * ComplexProgramTarget_3 (program,locallib,syslib)
+! * ServerTarget (server,subdirs,objects,libs,syslibs)
+! * InstallLibrary (libname,dest)
+! * InstallSharedLibrary (libname,rev,dest)
+! * InstallLibraryAlias (libname,alias,dest)
+! * InstallLintLibrary (libname,dest)
+! * InstallManPageLong (file,destdir,dest)
+! * InstallManPage (file,dest)
+! * InstallNonExec (file,dest)
+! * InstallProgram (program,dest)
+! * InstallProgramWithFlags (program,dest,flags)
+! * InstallScript (program,dest)
+! * LinkFileList (step,list,dir,sub)
+! * InstallMultipleDestFlags (step,list,dest,flags)
+! * InstallMultipleDest (step,list,dest)
+! * InstallMultiple (list,dest)
+! * InstallMultipleFlags (list,dest,flags)
+! * InstallMultipleMan (list,dest)
+! * InstallAppDefaults (class)
+! * DependDependency ()
+! * DependTarget ()
+! * CleanTarget ()
+! * TagsTarget ()
+! * ImakeDependency (target)
+! * BuildMakefileTarget (imakefile,imakeflags)
+! * MakefileTarget ()
+! * NormalLibraryObjectRule ()
+! * ProfiledLibraryObjectRule ()
+! * DebuggedLibraryObjectRule ()
+! * DebuggedAndProfiledLibraryObjectRule ()
+! * SharedLibraryObjectRule ()
+! * SharedAndDebuggedLibraryObjectRule ()
+! * SpecialObjectRule (objs,depends,options)
+! * SpecialProfiledObjectRule (objs,depends,options)
+! * SpecialDebuggedObjectRule (objs,depends,options)
+! * SpecialDebuggedAndProfiledObjectRule (objs,depends,options)
+! * NormalLibraryTarget (libname,objlist)
+! * NormalSharedLibraryTarget (libname,rev,solist,salist)
+! * NormalLibraryTarget2 (libname,objlist1,objlist2)
+! * ProfiledLibraryTarget (libname,objlist)
+! * DebuggedLibraryTarget (libname,objlist)
+! * AliasedLibraryTarget (libname,alias)
+! * NormalRelocatableTarget (objname,objlist)
+! * ProfiledRelocatableTarget (objname,objlist)
+! * DebuggedRelocatableTarget (objname,objlist)
+! * LintLibraryTarget (libname,srclist)
+! * NormalLintTarget (srclist)
+! * LintTarget ()
+! * MakeSubincludesForBuild (step,dir,srclist)
+! * NamedTargetSubdirs (name,dirs,verb,flags,subname)
+! * MakeSubdirs (dirs)
+! * NamedMakeSubdirs (name,dirs)
+! * DependSubdirs (dirs)
+! * InstallSubdirs (dirs)
+! * InstallManSubdirs (dirs)
+! * NamedIncludesSubdirs (name,dirs)
+! * IncludesSubdirs (dirs)
+! * NamedCleanSubdirs (name,dirs)
+! * CleanSubdirs (dirs)
+! * NamedTagSubdirs (name,dirs)
+! * TagSubdirs (dirs)
+! * MakeLintSubdirs (dirs,target,subtarget)
+! * LintSubdirs (dirs)
+! * MakeLintLibSubdirs (dirs)
+! * MakeMakeSubdirs (dirs,target)
+! * MakeNsubdirMakefiles ()
+! * MakefileSubdirs (dirs)
+! * CppScriptTarget (dst,src,defs,deplist)
+! * MakeScriptFromCpp (name,defs)
+! * MakeDirectories (step,dirs)
+! * MakeFonts ()
+! * InstallFonts (dest)
+! * InstallFontAliases (dest)
+! * FontTarget (basename)
+! * CompressedFontTarget (basename)
+! * AllTarget (depends)
+! * DoRanlib (flags,files)
+! *
+! *
+! * The general linking for building programs is:
+ *
+! * program-objects programlibs syslibs EXTRA_LIBRARIES systemlibs \
+! * EXTRA_LOAD_FLAGS
+ *
+! * where programlibs is LOCAL_LIBRARIES for ComplexProgramTarget
+! * and EXTRA comes with syslibs from the LDLIBS
+ */
+
+
+
+ /*
+ * SaberProgramTarget - generate rules to make Saber-C read in sources and
+--- 1,150 ----
+! XCOMM -------------------------------------------------------------------------
+! XCOMM Imake rules for building libraries, programs, scripts, and data files
+! XCOMM rules: $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+ /*
+ * MACHINE-INDEPENDENT RULES; DO NOT MODIFY
+ *
+! * Warning, when defining rules: make sure you do not include both a trailing
+ * backslash and double ampersand backslash or else you will get an extra
+ * backslash in the Makefile.
+ *
+! * The following macros are defined for the various templates and Imakefiles
+! * (for a list of the applicable make variables, see the template files):
+ *
+! * SaberProgramTarget (program,srclist,objlist,locallibs,syslibs)
+! * RemoveTargetProgram (program)
+! * MakeDir (dir)
+! * BuildIncludes (srclist,dstsubdir,dstupdir)
+! * NormalProgramTarget (program,objects,deplibs,locallibs,syslibs)
+! * SetUIDProgramTarget (program,objects,deplibs,locallibs,syslibs)
+! * SingleProgramTarget (program,objects,locallibs,syslibs)
+! * SimpleProgramTarget (program)
+! * ComplexProgramTarget (program)
+! * ComplexProgramTarget_1 (program,locallib,syslib)
+! * ComplexProgramTarget_2 (program,locallib,syslib)
+! * ComplexProgramTarget_3 (program,locallib,syslib)
+! * ServerTarget (server,subdirs,objects,libs,syslibs)
+! * RanLibrary (args)
+! * InstallLibrary (libname,dest)
+! * MergeIntoInstalledLibrary (tolib,fromlib)
+! * InstallLibraryAlias (libname,alias,dest)
+! * InstallLintLibrary (libname,dest)
+! * InstallManPageLong (file,destdir,dest)
+! * InstallManPage (file,destdir)
+! * InstallManPageAliases (file,destdir,aliases)
+! * InstallNamedNonExec (srcname,dstname,dest)
+! * InstallNonExecFile (file,dest)
+! * InstallNonExec (file,dest)
+! * InstallProgramWithFlags (program,dest,flags)
+! * InstallProgram (program,dest)
+! * InstallScript (program,dest)
+! * InstallNamedProg (srcname,dstname,dest)
+! * LinkFileList (step,list,dir,sub)
+! * InstallMultipleDestFlags (step,list,dest,flags)
+! * InstallMultipleDest (step,list,dest)
+! * InstallMultiple (list,dest)
+! * InstallMultipleFlags (list,dest,flags)
+! * InstallMultipleMan (list,dest)
+! * InstallAppDefaults (class)
+! * InstallAppDefaultsLong (file,class)
+! * DependDependency ()
+! * DependTarget ()
+! * DependTarget3 (srcs1,srcs2,srcs3)
+! * CleanTarget ()
+! * TagsTarget ()
+! * ImakeDependency (target)
+! * BuildMakefileTarget (notused,imakeflags)
+! * MakefileTarget ()
+! * LibMkdir (dir)
+! * LibCleanDir (dir)
+! * ObjectCompile (options)
+! * NormalLibObjCompile (options)
+! * NormalSharedLibObjCompile (options)
+! * LibObjCompile (dir,options)
+! * DebuggedLibObjCompile (options)
+! * ProfiledLibObjCompile (options)
+! * SharedLibObjCompile (options)
+! * NormalLibraryObjectRule ()
+! * NormalFortranObjectRule ()
+! * ObjectFromSpecialSource (dst,src,flags)
+! * SpecialObjectRule (objs,depends,options)
+! * NormalLibraryTarget (libname,objlist)
+! * NormalLibraryTarget2 (libname,objlist1,objlist2)
+! * NormalLibraryTarget3 (libname,objlist1,objlist2,objlist3)
+! * NormalDepLibraryTarget (libname,deplist,objlist)
+! * SubdirLibraryRule (objlist)
+! * ProfiledLibraryTarget (libname,objlist)
+! * DebuggedLibraryTarget (libname,objlist)
+! * AliasedLibraryTarget (libname,alias)
+! * NormalRelocatableTarget (objname,objlist)
+! * ProfiledRelocatableTarget (objname,objlist)
+! * DebuggedRelocatableTarget (objname,objlist)
+! * LintLibraryTarget (libname,srclist)
+! * NormalLintTarget (srclist)
+! * LintTarget ()
+! * LinkSourceFile (src,dir)
+! * LinkFile (tofile,fromfile)
+! * MakeSubincludesForBuild (step,dir,srclist)
+! * NamedTargetSubdirs (name,dirs,verb,flags,subname)
+! * NamedMakeSubdirs (name,dirs)
+! * MakeSubdirs (dirs)
+! * DependSubdirs (dirs)
+! * ForceSubdirs (dirs)
+! * InstallSubdirs (dirs)
+! * InstallManSubdirs (dirs)
+! * IncludesSubdirs (dirs)
+! * NamedCleanSubdirs (name,dirs)
+! * CleanSubdirs (dirs)
+! * NamedTagSubdirs (name,dirs)
+! * TagSubdirs (dirs)
+! * MakeLintSubdirs (dirs,target,subtarget)
+! * LintSubdirs (dirs)
+! * MakeLintLibSubdirs (dirs)
+! * MakeMakeSubdirs (dirs,target)
+! * MakeNsubdirMakefiles ()
+! * MakefileSubdirs (dirs)
+! * CppScriptTarget (dst,src,defs,deplist)
+! * MakeScriptFromCpp (name,defs)
+! * CppFileTarget (dst,src,defs,deplist)
+! * MakeDirectories (step,dirs)
+! * MakeFontsDir (deplist)
+! * MakeFonts ()
+! * InstallFontObjs (objs,dest)
+! * InstallFonts (dest)
+! * InstallFontAliases (dest)
+! * FontSrc (basename)
+! * FontBaseObj (basename)
+! * InstallFontScale (dest)
+! * UncompressedFontTarget (basename)
+! * UncompressedFontTarget (basename)
+! * CompressedFontTarget (basename)
+! * FontTarget (basename)
+! * FontObj (basename)
+! * AllTarget (depends)
+! *
+! *
+! * The following are in Imake.tmpl:
+! *
+! * Concat (a,b)
+! * Concat3 (a,b,c)
+ *
+! *
+! * The following are in specific <os>Lib.rules:
+ *
+! * SharedLibraryTarget (libname,rev,solist,down,up)
+! * SharedLibraryDataTarget (libname,rev,salist)
+! * InstallSharedLibrary (libname,rev,dest)
+! * InstallSharedLibraryData (libname,rev,dest)
+! *
+ */
+
++ #define NullParameter
+
++ /* if [ -d ] or [ ! -d ] causes make to fail, define this as - */
++ #ifndef DirFailPrefix
++ #define DirFailPrefix
++ #endif
+
+ /*
+ * SaberProgramTarget - generate rules to make Saber-C read in sources and
--- /dev/null
+/*
+ * generic imake template
+ */
+
+/**/# $Source$
+/**/# $Author$
+/**/# $Id$
+/**/#
+
+/**/###########################################################################
+/**/# Makefile generated from IMAKE_TEMPLATE and INCLUDE_IMAKEFILE
+/**/# $XConsortium: Imake.tmpl,v 1.77 89/12/18 17:01:37 jim Exp $
+/**/#
+/**/# Platform-specific parameters may be set in the appropriate .cf
+/**/# configuration files. Site-wide parameters may be set in the file
+/**/# site.def. Full rebuilds are recommended if any parameters are changed.
+/**/#
+/**/# If your C preprocessor doesn't define any unique symbols, you'll need
+/**/# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+/**/# "make Makefile", "make Makefiles", or "make World").
+/**/#
+/**/# If you absolutely can't get imake to work, you'll need to set the
+/**/# variables at the top of each Makefile as well as the dependencies at the
+/**/# bottom (makedepend will do this automatically).
+/**/#
+
+
+#define YES 1
+#define NO 0
+
+
+/*
+ * To add support for another platform:
+ *
+ * 1. Identify a machine-specific cpp symbol. If your preprocessor
+ * doesn't have any built in, you'll need to add the symbol to the
+ * cpp_argv table in config/imake.c and rebuild imake with the
+ * BOOTSTRAPCFLAGS variable set (see the macII for an example).
+ *
+ * [ignore this for now...no makedepend with Kerberos V5 (yet...)]
+ * 2. Add all machine-specific cpp symbols (either defined by you or by
+ * the preprocessor or compiler) to the predefs table in
+ * config/makedepend/main.c.
+ *
+ * 3. But a new #ifdef block below that defines MacroIncludeFile and
+ * MacroFile for your new platform and then #undefs the machine-
+ * specific preprocessor symbols (to avoid problems with file names).
+ *
+ * 4. Create a .cf file with the name given by MacroFile. See
+ * existing .cf files for examples of what to put there.
+ */
+
+#define MacroIncludeFile <vaxbsd.cf>
+#define MacroFile vaxbsd.cf
+#undef vax
+#define VaxArchitecture
+
+
+#ifndef MacroIncludeFile
+/**/# WARNING: Imake.tmpl not configured; guessing at definitions!!!
+/**/# This might mean that BOOTSTRAPCFLAGS wasn't set when building imake.
+#define MacroIncludeFile <generic.cf>
+#define MacroFile generic.cf
+#endif
+
+/*****************************************************************************
+ * *
+ * DO NOT MODIFY BELOW THIS LINE *
+ * *
+ *****************************************************************************/
+
+
+/**/###########################################################################
+/**/# platform-specific configuration parameters - edit MacroFile to change
+#include MacroIncludeFile
+
+/**/###########################################################################
+/**/# site-specific configuration parameters - edit site.def to change
+#include <site.def>
+
+/*
+ * defaults for various generic parameters; set in site.def if needed
+ */
+
+#ifndef SystemV
+#ifdef SYSV
+#define SystemV YES /* need system 5 style */
+#else
+#define SystemV NO /* bsd */
+#endif
+#endif
+#ifndef OSMajorVersion
+#define OSMajorVersion 0
+#endif
+#ifndef OSMinorVersion
+#define OSMinorVersion 0
+#endif
+#ifndef UnalignedReferencesAllowed
+#define UnalignedReferencesAllowed NO /* if arbitrary deref is okay */
+#endif
+#ifndef ExecableScripts
+#ifdef SYSV
+#define ExecableScripts NO
+#else
+#define ExecableScripts YES /* kernel exec() can handle #! */
+#endif
+#endif
+
+#ifndef BourneShell /* to force shell in makefile */
+#define BourneShell /bin/sh
+#endif
+#ifndef ConstructMFLAGS
+#if SystemV
+#define ConstructMFLAGS YES /* build MFLAGS from MAKEFLAGS */
+#else
+#define ConstructMFLAGS NO /* build MFLAGS from MAKEFLAGS */
+#endif
+#endif
+
+#ifndef HasLargeTmp
+#define HasLargeTmp NO /* be paranoid */
+#endif
+#ifndef HasSockets
+#if SystemV
+#define HasSockets NO /* not yet... */
+#else
+#define HasSockets YES /* bsd does have them */
+#endif
+#endif
+#ifndef HasVFork
+#if SystemV
+#define HasVFork NO /* not yet... */
+#else
+#define HasVFork YES
+#endif
+#endif
+#ifndef HasPutenv
+#define HasPutenv NO /* assume not */
+#endif
+#ifndef HasVoidSignalReturn
+#if SystemV
+#define HasVoidSignalReturn YES
+#else
+#define HasVoidSignalReturn NO /* may or may not be true */
+#endif
+#endif
+#ifndef HasBsearch
+#if SystemV
+#define HasBsearch YES
+#else
+#define HasBsearch NO /* stupid systems */
+#endif
+#endif
+#ifndef HasSaberC
+#define HasSaberC NO /* for people unclear on the concept */
+#endif
+#ifndef HasFortran
+#define HasFortran NO
+#endif
+#ifndef HasNdbm
+#define HasNdbm NO
+#endif
+#ifndef HasDESLibrary
+#define HasDESLibrary NO /* if you have any DES library */
+#endif
+#ifndef NeedFunctionPrototypes
+#define NeedFunctionPrototypes NO
+#endif
+#ifndef NeedWidePrototypes
+#define NeedWidePrototypes YES /* mix and match ANSI-C, non-ANSI */
+#endif
+
+#ifndef HasSunOSSharedLibraries
+#define HasSunOSSharedLibraries NO
+#endif
+
+#ifndef SharedCodeDef
+#if HasSunOSSharedLibraries
+#define SharedCodeDef -DSHAREDCODE
+#else
+#define SharedCodeDef /**/
+#endif
+#endif
+#ifndef SharedLibraryDef
+#if HasSunOSSharedLibraries
+#define SharedLibraryDef -DSUNSHLIB /* eventually will be SVR4SHLIB... */
+#ifndef HasSharedLibraries
+#define HasSharedLibraries YES
+#endif
+#else
+#define SharedLibraryDef /**/
+#ifndef HasSharedLibraries
+#define HasSharedLibraries NO
+#endif
+#endif
+#else
+#ifndef HasSharedLibraries
+#define HasSharedLibraries NO
+#endif
+#endif
+
+#ifndef StripInstalledPrograms
+#define StripInstalledPrograms NO /* leave symbol table just in case */
+#endif
+
+#ifndef DestDir
+#define DestDir /* as nothing */
+#endif
+#ifndef UsrLibDir /* if changed under SunOS with shared */
+#define UsrLibDir $(DESTDIR)/usr/lib /* libs, then need to run ldconfig */
+#endif /* as root */
+#ifndef IncRoot
+#define IncRoot $(DESTDIR)/usr/include
+#endif
+#ifndef UNCOMPRESSPATH
+#define UNCOMPRESSPATH /usr/ucb/uncompress
+#endif
+#ifndef OptimizedCDebugFlags
+#define OptimizedCDebugFlags -O
+#endif
+#ifndef DebuggableCDebugFlags
+#define DebuggableCDebugFlags -g
+#endif
+#ifndef NoOpCDebugFlags
+#define NoOpCDebugFlags /* as nothing */
+#endif
+#ifndef DefaultCDebugFlags
+#define DefaultCDebugFlags OptimizedCDebugFlags
+#endif
+#ifndef LibraryCDebugFlags
+#define LibraryCDebugFlags OptimizedCDebugFlags
+#endif
+#ifndef DefaultCCOptions
+#define DefaultCCOptions /* as nothing: this is for floating point, etc. */
+#endif
+#ifndef LibraryCCOptions
+#define LibraryCCOptions DefaultCCOptions
+#endif
+#ifndef ServerCCOptions
+#define ServerCCOptions DefaultCCOptions
+#endif
+#ifndef PexCDebugFlags
+#define PexCDebugFlags -g
+#endif
+#ifndef InstPgmFlags
+#define InstPgmFlags
+#endif
+#ifndef InstScrFlags
+#define InstScrFlags
+#endif
+#ifndef InstBinFlags
+#define InstBinFlags -m 0755
+#endif
+#ifndef InstUidFlags
+#define InstUidFlags -m 4755
+#endif
+#ifndef InstLibFlags
+#define InstLibFlags -m 0664
+#endif
+#ifndef InstIncFlags
+#define InstIncFlags -m 0444
+#endif
+#ifndef InstManFlags
+#define InstManFlags -m 0444
+#endif
+#ifndef InstDatFlags
+#define InstDatFlags -m 0444
+#endif
+#ifndef InstKmemFlags
+#define InstKmemFlags InstUidFlags /* put -g kmem -m 2755 in site.def... */
+#endif
+#ifndef ArCmd
+#if HasLargeTmp
+#define ArCmd ar cq /* use /tmp for temp files */
+#else
+#define ArCmd ar clq /* use local dir for temp files */
+#endif
+#endif
+#ifndef BootstrapCFlags
+#define BootstrapCFlags /**/
+#endif
+#ifndef CcCmd
+#define CcCmd cc
+#endif
+#ifndef HasGcc
+#define HasGcc NO
+#endif
+#ifndef ServerCcCmd
+#define ServerCcCmd CcCmd
+#endif
+#ifndef LibraryCcCmd
+#define LibraryCcCmd CcCmd
+#endif
+#if HasFortran
+#ifndef FortranCmd /* for xgks */
+#define FortranCmd f77
+#endif
+#ifndef FortranFlags
+#define FortranFlags /**/
+#endif
+#ifndef FortranDebugFlags
+#define FortranDebugFlags /**/ /* for -O or -g */
+#endif
+#endif
+#ifndef AsCmd
+#define AsCmd as
+#endif
+#ifndef CompressCmd
+#define CompressCmd compress
+#endif
+#ifndef CppCmd
+#define CppCmd /lib/cpp
+#endif
+#ifndef PreProcessCmd
+#define PreProcessCmd CcCmd -E
+#endif
+#ifndef InstallCmd
+#if SystemV
+#define InstallCmd $(SCRIPTSRC)/bsdinst.sh /* hack should be in project */
+#else
+#define InstallCmd install
+#endif
+#endif
+#ifndef LdCmd
+#define LdCmd ld
+#endif
+#ifndef LintCmd
+#define LintCmd lint
+#endif
+#ifndef LintLibFlag
+#if SystemV
+#define LintLibFlag -o
+#else
+#define LintLibFlag -C
+#endif
+#endif
+#ifndef LintOpts
+#if SystemV
+#define LintOpts -ax
+#else
+#define LintOpts -axz
+#endif
+#endif
+#ifndef CpCmd
+#define CpCmd cp -p
+#endif
+#ifndef LnCmd
+#if SystemV
+#define LnCmd ln /* or even cp */
+#else
+#define LnCmd ln -s
+#endif
+#endif
+#ifndef MakeCmd
+#define MakeCmd make
+#endif
+#ifndef MvCmd
+#define MvCmd mv
+#endif
+#if !defined(RanlibCmd) && !SystemV
+#define RanlibCmd ranlib
+#endif
+#ifndef RanlibInstFlags
+#define RanlibInstFlags /**/
+#endif
+#ifndef RmCmd
+#define RmCmd rm -f
+#endif
+#ifndef StandardCppDefines
+#if SystemV
+#define StandardCppDefines -DSYSV
+#else
+#define StandardCppDefines /**/
+#endif
+#endif
+#ifndef StandardIncludes
+#define StandardIncludes /**/ /* for platform-specifics */
+#endif
+#ifndef StandardDefines
+#if SystemV
+#define StandardDefines -DSYSV
+#else
+#define StandardDefines /**/
+#endif
+#endif
+#ifndef SaberDefines
+#define SaberDefines /**/
+#endif
+#ifndef NdbmDefines
+#if HasNdbm
+#define NdbmDefines -DNDBM
+#else
+#define NdbmDefines /**/
+#endif
+#endif
+#ifndef ExtraLibraries
+#define ExtraLibraries /**/
+#endif
+#ifndef ExtraLoadFlags
+#define ExtraLoadFlags /**/
+#endif
+#ifndef LdCombineFlags
+#define LdCombineFlags -X -r
+#endif
+#ifndef LdLibLocations
+#define LdLibLocations /**/
+#endif
+#ifndef CompatibilityFlags
+#define CompatibilityFlags /**/
+#endif
+#ifndef TagsCmd
+#define TagsCmd ctags
+#endif
+#ifndef EtagsCmd
+#define EtagsCmd etags
+#endif
+#ifndef LoaderLibPrefix
+#define LoaderLibPrefix /**/ /* cray does -l libX11.a */
+#endif
+#ifndef TOPDIR
+#define TOPDIR .
+#endif
+#ifndef CURDIR
+#define CURDIR .
+#endif
+#ifndef FilesToClean
+#define FilesToClean *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+#endif
+#ifndef STDCTopIncludes
+#define STDCTopIncludes /**/
+#endif
+#ifndef MakeDependFlags
+#define MakeDependFlags /**/
+#endif
+
+#ifdef SourceTop
+ SRCDIR = SourceTop/CURDIR/
+ VPATH = SourceTop/CURDIR
+ SRCTOP = SourceTop
+ SRCINCLUDE = -I/**/SourceTop/CURDIR
+#endif
+ SHELL = BourneShell
+
+ TOP = TOPDIR
+ CURRENT_DIR = CURDIR
+
+ AR = ArCmd
+ BOOTSTRAPCFLAGS = BootstrapCFlags /* set if cpp doesn't have uniq sym */
+ CC = CcCmd
+#if HasFortran
+ FC = FortranCmd
+ FDEBUGFLAGS = FortranDebugFlags
+ FCFLAGS = FortranFlags $(FDEBUGFLAGS)
+#endif
+ COMPRESS = CompressCmd
+ CPP = CppCmd $(STD_CPP_DEFINES) /* simple filters */
+ PREPROCESSCMD = PreProcessCmd $(STD_CPP_DEFINES) /* prefered; mdep */
+ INSTALL = InstallCmd
+ LD = LdCmd
+ LDLOCATIONS = LdLibLocations
+ LINT = LintCmd
+ LINTLIBFLAG = LintLibFlag
+ LINTOPTS = LintOpts
+ LN = LnCmd
+ MAKE = MakeCmd
+ MV = MvCmd
+ CP = CpCmd
+#ifdef RanlibCmd
+ RANLIB = RanlibCmd
+#else
+ RANLIB = \:
+#endif
+ RANLIBINSTFLAGS = RanlibInstFlags
+ RM = RmCmd
+ STD_INCLUDES = StandardIncludes
+ STD_CPP_DEFINES = StandardCppDefines
+ STD_DEFINES = StandardDefines
+ SABER_DEFINES = SaberDefines
+ EXTRA_LOAD_FLAGS = ExtraLoadFlags
+ EXTRA_LIBRARIES = ExtraLibraries
+ TAGS = TagsCmd
+ ETAGS = EtagsCmd
+STDC_TOP_INCLUDES = STDCTopIncludes
+
+#if ConstructMFLAGS
+ MFLAGS = -$(MAKEFLAGS)
+#endif
+#if HasSharedLibraries
+ SHAREDCODEDEF = SharedCodeDef
+ SHLIBDEF = SharedLibraryDef
+#endif
+#if !HasVoidSignalReturn
+ SIGNAL_DEFINES = -DSIGNALRETURNSINT
+#endif
+#if StripInstalledPrograms
+ INSTPGMFLAGS = InstPgmFlags -s /* install flags for stripping */
+#else
+ INSTPGMFLAGS = InstPgmFlags /* install flags without stripping */
+#endif
+ INSTSCRFLAGS = InstScrFlags /* install flags without stripping */
+ INSTBINFLAGS = InstBinFlags /* install flags for programs */
+ INSTUIDFLAGS = InstUidFlags /* install flags for setuid programs */
+ INSTLIBFLAGS = InstLibFlags /* install flags for libraries */
+ INSTINCFLAGS = InstIncFlags /* install flags for headers */
+ INSTMANFLAGS = InstManFlags /* install flags for man pages */
+ INSTDATFLAGS = InstDatFlags /* install flags for data files */
+ INSTKMEMFLAGS = InstKmemFlags /* install flags for /dev/kmem progs */
+
+ DESTDIR = DestDir /* root of install */
+#ifdef UseInstalled
+ TOP_INCLUDES = -I$(INCROOT) /* def: for alternative /usr/include */
+#else
+ TOP_INCLUDES = -I$(TOP) /* def: for builds within tree */
+#endif
+ CDEBUGFLAGS = DefaultCDebugFlags
+ CCOPTIONS = DefaultCCOptions /* to distinguish from param flags */
+ COMPATFLAGS = CompatibilityFlags
+/*
+ * STD_INCLUDES contains system-specific includes
+ * TOP_INCLUDES specifies how to get to /usr/include or its build substitute
+ * EXTRA_INCLUDES contains project-specific includes set in project incfiles
+ * INCLUDES contains client-specific includes set in Imakefile
+ */
+ ALLINCLUDES = $(INCLUDES) $(STD_INCLUDES) $(TOP_INCLUDES) $(EXTRA_INCLUDES)
+ ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(DEFINES) $(COMPATFLAGS)
+ CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+ LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+ LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+ LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LDLOCATIONS)
+ LDCOMBINEFLAGS = LdCombineFlags
+ MDFLAGS = MakeDependFlags
+
+ MACROFILE = MacroFile
+ RM_CMD = $(RM) FilesToClean
+
+ IMAKE_DEFINES = /* leave blank, for command line use only */
+#ifdef UseInstalled
+ IRULESRC = $(CONFIGDIR) /* used in rules file */
+ IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+#else
+ IRULESRC = $(CONFIGSRC)
+#ifdef UseImakeInstalled
+ IMAKE_CMD = $(IMAKE) -I$(NEWTOP)$(IRULESRC) $(IMAKE_DEFINES)
+#else
+ IMAKE_CMD = $(NEWTOP)$(IMAKE) -I$(NEWTOP)$(IRULESRC) $(IMAKE_DEFINES)
+#endif
+#endif
+ ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+ $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+ $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+
+/*
+ * get project-specific configuration and rules
+ */
+
+#include <Project.tmpl>
+
+
+
+#include <Imake.rules>
+
+/**/###########################################################################
+/**/# start of Imakefile
+#include INCLUDE_IMAKEFILE
+
+/**/###########################################################################
+/**/# common rules for all Makefiles - do not edit
+/*
+ * These need to be here so that rules in Imakefile occur first; the blank
+ * all is to make sure that an empty Imakefile doesn't default to make clean.
+ */
+emptyrule::
+
+CleanTarget()
+
+#ifndef IHaveSpecialMakefileTarget
+MakefileTarget()
+#endif
+
+TagsTarget()
+#ifdef MakefileAdditions
+MakefileAdditions()
+#endif
+
+#if HasSaberC
+saber:
+ /**/#load $(ALLDEFINES) $(SABER_DEFINES) $(SRCS)
+ /**/#setopt load_flags $(ALLDEFINES) $(SABER_DEFINES)
+
+osaber:
+ /**/#load $(ALLDEFINES) $(OBJS)
+#endif
+
+
+#ifdef IHaveSubdirs
+/**/###########################################################################
+/**/# rules for building in SUBDIRS - do not edit
+
+InstallSubdirs($(SUBDIRS))
+InstallManSubdirs($(SUBDIRS))
+CleanSubdirs($(SUBDIRS))
+TagSubdirs($(SUBDIRS))
+MakefileSubdirs($(SUBDIRS))
+IncludesSubdirs($(SUBDIRS))
+DependSubdirs($(SUBDIRS))
+
+#else
+/**/###########################################################################
+/**/# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+ @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+ @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+#endif /* if subdirectory rules are needed */
+
+/**/###########################################################################
+/**/# dependencies generated by makedepend
--- /dev/null
+#
+# WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+#
+# This is NOT an automatically generated Makefile! It is hand-crafted as a
+# bootstrap, may need editing for your system. The BOOTSTRAPCFLAGS variable
+# may be given at the top of the build tree for systems that do not define
+# any machine-specific preprocessor symbols.
+#
+
+BOOTSTRAPCFLAGS =
+ CDEBUGFLAGS = -O
+ CFLAGS = $(BOOTSTRAPCFLAGS) $(CDEBUGFLAGS)
+ SHELL = /bin/sh
+ RM = rm -f
+ MAKE = make
+ RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a \
+ tags TAGS make.log
+ NPROC = 1
+
+imake::
+ @echo "making imake with BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS)"
+
+imake:: ccimake imake.c
+ $(CC) -o imake $(CFLAGS) imake.c `./ccimake`
+
+ccimake: ccimake.c
+ $(CC) -o ccimake $(CFLAGS) ccimake.c
+
+relink:
+ $(RM) imake
+ $(MAKE) $(MFLAGS) imake
+
+clean:
+ $(RM) ccimake imake
+ $(RM_CMD) \#*
+
+depend:
+
+
+# for manual use
+
+Makefile: imake
+ imake -DNEWTOP=../
+
+tags:
+
+install:
+
+install.man:
+
+Makefiles:
--- /dev/null
+/*
+ * $XConsortium: ccimake.c,v 1.12 89/10/16 12:09:23 jim Exp $
+ *
+ * Warning: This file must be kept as simple as posible so that it can
+ * compile without any special flags on all systems. Do not touch it unless
+ * you *really* know what you're doing. Make changes in imakemdep.h, not here.
+ */
+
+#define CCIMAKE /* only get imake_ccflags definitions */
+#include "imakemdep.h" /* things to set when porting imake */
+
+#ifndef imake_ccflags
+#define imake_ccflags "-O"
+#endif
+
+main()
+{
+ write(1, imake_ccflags, sizeof(imake_ccflags) - 1);
+ exit(0);
+}
+
--- /dev/null
+.\" macros ripped off from Rosenthal and Lemke's paper
+.\" refer -e -n -p vis.refs -s vis.nr | eqn | pic | psroff -ms
+.\.EQ
+.\delim $$
+.\.EN
+.ds CH
+.de Ip
+.IP \(bu 3
+..
+.de Qp
+.nr PS -2
+.nr VS -2
+.QP
+..
+.de Qe
+.nr PS +2
+.nr VS +2
+..
+.de RQ
+.br
+.di
+.nr NF 0
+.if \\n(dn-\\n(.t .nr NF 1
+.if \\n(TC .nr NF 1
+.if !\\n(NF .if \\n(TB .nr TB 0
+.nf
+.rs
+.nr TC 5
+.in 0
+.ls 1
+.if !\\n(TB \{\
+. ev
+. br
+. ev 2
+. KK
+.\}
+.ls
+.ce 0
+.if !\\n(TB .rm KK
+.if \\n(TB .da KJ
+.if \\n(TB \!.KD \\n(dn
+.if \\n(TB .KK
+.if \\n(TB .di
+.nr TC \\n(TB
+.if \\n(KN .fi
+.in
+.ev
+..
+.\" These macros should select a typewriter font if you have one.
+.de LS
+.LP
+.KS
+.LD
+.ft L
+.ta .6i 1.2i 1.8i 2.4i 3i 3.6i 4.2i
+..
+.de LE
+.ft P
+.DE
+.KE
+..
+.de Ls
+.nr PS -4
+.nr VS -6
+.LS
+..
+.de Le
+.LE
+.nr PS +4
+.nr VS +6
+.LP
+..
+.nr PO 1.25i
+.TL
+Configuration Management in the X Window System
+.AU
+Jim Fulton
+.AI
+X Consortium
+MIT Laboratory for Computer Science
+545 Technology Square
+Cambridge, MA 02139
+.AB
+The X Window System\(dg has become an industry standard for network window
+technology in part because of the
+portability of the sample implementation from MIT. Although many systems are
+designed to reuse source code across different platforms, X is
+unusual in its
+portability across software build environments. This paper describes several
+mechanisms used in the MIT release of the X Window System to obtain such
+flexibility, and summarizes some of the lessons learned in trying to support
+X on a number of different platforms.
+.AE
+.NH 1
+Introduction
+.LP
+The X Window System\f(d is a portable, network transparent window system
+originally developed at MIT. It is intended for use on raster display
+devices ranging from simple monochrome frame buffers to deep,
+true color graphics processors. Because of its client/server architecture,
+the non-proprietary nature of its background, and the portability of the
+sample implementation from MIT, the X Window System has rapidly grown to
+become an industry standard. This portability is the result of several
+factors: a system architecture that isolates operating system and
+device-specifics at several levels; a slow, but machine-independent, graphics
+package that may be used for an initial port and to handle cases that
+the underlying graphics hardware does not support; and the use of a few,
+higher-level tools for managing the build process itself.
+.FS
+\(dg X Window System is a trademark of MIT; DECnet is a trademark of
+Digital Equipment Corporation; UNIX is a registered trademark of AT&T.
+.sp
+Copyright \(co\ 1989 by the Massachusetts Institute of Technology.
+.sp
+Permission to use, copy, modify, and distribute this
+document 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
+the software described herein for any purpose. It is provided "as is"
+without express or implied warranty.
+.FE
+.NH 2
+Summary of X Window System Architecture
+.LP
+The X Window System is the result of a combined effort between MIT Project
+Athena and the MIT Laboratory for Computer Science. Since its inception
+in 1984, X has been redesigned three times, culminating in Version 11 which
+has since become an industry standard (see [Scheifler 88] for a more detailed
+history). X uses the client/server model of
+limiting interactions with the physical display hardware to a single program
+(the \fIserver\fP) and providing a way for applications (the \fIclients\fP)
+to send messages (known as \fIrequests\fP) to the server to ask it to perform
+graphics operations on the client's behalf. These messages are sent along
+a reliable, sequenced, duplex byte stream using whatever underlying transport
+mechanisms the operating system provides. If connections
+using network virtual circuits (such as TCP/IP or DECnet) are supported,
+clients may be run
+on any remote machine (including ones of differing architectures) while still
+displaying on the local server.
+.LP
+The details of how the client establishes and maintains connections with the
+server are typically hidden in a subroutine package (known as a \fIlanguage
+binding\fP) which provides a function call interface to the X protocol. Higher
+level toolkits and user interface management systems are then built on top of
+the binding library, as shown in Figure 1 for the C programming language.
+Since only the underlying
+operating system networking interface of the binding (shown in \fIitalics\fP)
+need be changed when
+porting to a new platform, well-written applications can simply be recompiled.
+.sp 1
+.DS C
+.TS
+box tab (/) ;
+cB s s s
+_ lB lB lB
+cBe | le le le
+_ s lB lB
+cB s | lB lB
+_ s s lB
+cB s s | lB
+_ s s s
+cB s s s
+_ lB lB _
+cI s s s .
+application///
+///
+UIMS///
+///
+widgets///
+///
+toolkit///
+///
+Xlib///
+///
+os
+.TE
+.sp 1
+\fBFigure 1:\fP architecture of a typical C language client program
+.DE
+.sp 1
+.LP
+The server takes care of clipping of graphics output and routing keyboard and
+pointer input
+to the appropriate applications. Unlike many previous window systems,
+moving and resizing of windows are handled outside the server
+by special X applications called
+\fIwindow managers\fP. Different user interface policies can be selected
+simply by running a different window manager.
+.LP
+The MIT sample server can be divided into three sections: a device-independent
+layer called \fIdiX\fP for managing the various shared resources (windows,
+pixmaps, colormaps, fonts, cursors, etc.), an operating system layer called
+\fIos\fP for performing machine-specific operations (managing
+connections to clients, dealing with timers, reading color and font name
+databases, and memory allocation), and a device-specific
+layer called \fIddX\fP for drawing on the display and getting input from the
+keyboard and pointer. Only the \fIos\fP and \fIddX\fP portions of the server
+need to be changed when porting X to a new device.
+.LP
+Although this is still
+a substantial amount of work, a collection of pixel-oriented drawing packages
+that only require device-specific routines (refered to as \fIspans\fP)
+to read and write rows of pixels are provided
+to allow initial ports of X to be done in a very short time. A server
+developer can then concentrate on replacing those operations that can be
+implemented more efficiently by the hardware. Figure 2 shows the relative
+layering of the various packages within the sample server from MIT. The
+\fImi\fP library provides highly portable, machine-independent routines that
+may be used on a wide variety of displays. The \fImfb\fP and \fIcfb\fP
+libraries contain versions of the graphics routines for monochrome and
+color frame buffers, respectively. Finally, the \fIsnf\fP library can be
+used to read fonts stored in Server Natural Format. Typically, only the
+sections printed in \fIitalics\fP need be changed when moving to a new
+platform.
+.sp 1
+.DS C
+.TS
+allbox tab (/) ;
+cB s s s s
+cI s s s cI
+cB cB cB cB cB
+cI s s s cB .
+diX
+ddX/os
+mi/mfb/cfb/snf/\^
+spans/\^
+.TE
+.sp 1
+\fBFigure 2:\fP architecture of the MIT sample server
+.DE
+.sp 1
+.LP
+By splitting out the device-specific code (by separating clients from servers
+and \fIdiX\fP from \fIddX\fP) and then providing portable utility libraries
+(\fImi\fP, \fImfb\fP, \fIcfb\fP, and \fIcfb\fP) that may be used to
+implement the non-portable portions
+of the system, much of the code can be reused across many platforms, ranging
+from personal computers to supercomputers.
+.NH 1
+Configuring the Software Build Process
+.LP
+In practice, porting X to a new platform typically requires adding support
+in the operating system-specific networking routines and mixing together
+pieces of machine-independent and device-specific code to access the
+input and output hardware. Although this approach is very portable, it
+increases the complexity of the build process as different implementations
+require different subsets. One solution is to litter the
+source code with machine-specific compiler directives controlling which
+modules areas get built on a given platform. However, this rapidly leads to
+sources that are hard to understand and even harder to maintain.
+.LP
+A more serious problem with this approach is that it requires
+configuration information to be replicated in almost every module. In
+addition to being highly prone to error, modifying or adding a new
+configuration becomes extremely difficult. In contrast, collecting the
+various options and parameters in a single location makes it possible for
+someone to reconfigure the system without having to
+understand how all of the modules fit together.
+.LP
+Although sophisticated software management systems are very useful, they
+tend to be found only on specific platforms. Since the configuration system
+must be working before a build can begin, the MIT releases try to adhere to
+the following principles:
+.RS .5in
+.Ip
+Use existing tools to do the build (e.g. \fImake\fP) where possible; writing
+complicated new tools simply adds to the amount of software that has to be
+bootstrapped.
+.Ip
+Keep it simple. Every platform has a different set of extensions and bugs.
+Plan for the least common denominator by only using
+the core features of known tools; don't rely on vendor-specific features.
+.Ip
+Providing sample implementations of simple tools that are not available on
+all platforms (e.g. a BSD-compatible \fIinstall\fP script for System V) is
+very useful.
+.Ip
+Machine-dependencies should be centralized to make reconfiguration easy.
+.Ip
+Site-wide options (e.g. default parameters such as directory names,
+file permissions, and enabling particular features) should be stored in
+only one location.
+.Ip
+Rebuilding within the source tree without losing any of the configuration
+information must be simple.
+.Ip
+It should be possible to configure external software without requiring
+access to the source tree.
+.RE
+.LP
+One approach is to add certain programming constructs (particularly
+conditionals and iterators) to the utility used to actually build the
+software (usually \fImake\fP; see [Lord 88]). Although this an attractive
+solution, limits on time and personnel made implementing and maintaining
+such a system impractical for X.
+.LP
+The MIT releases of X employ a less ambitious approach that uses existing tools
+(particularly \fImake\fP and \fIcpp\fP). \fIMakefiles\fP
+are generated automatically by a small,
+very simple program named \fIimake\fP (written by Todd Brunhoff of Tektronix)
+that combines a template listing variables and rules
+that are common to all
+\fIMakefiles\fP, a machine- and a site-specific configuration file,
+a set of rule functions written as \fIcpp\fP macros,
+and simple specifications of targets and sources called \fIImakefiles\fP.
+Since the descriptions of the inputs and outputs of the build are separated
+from the commands that implement them, machine dependencies such as the
+following can be controlled from a single location:
+.RS .5in
+.Ip
+Some versions of \fImake\fP require that the variable SHELL to be set to the
+name of the shell that should be used to execute \fImake\fP commands.
+.Ip
+The names of various special \fImake\fP variables (e.g. MFLAGS vs. MAKEFLAGS)
+differ between versions.
+.Ip
+Special directives to control interaction with source code maintenance systems
+are required by some versions of \fImake\fP.
+.Ip
+Rules for building targets (e.g. \fIranlib\fP,
+lint options, executable shell scripts, selecting alternate compilers)
+differ among platforms.
+.Ip
+Some systems require special compiler options (e.g. increased internal
+table sizes, floating point options) for even simple programs.
+.Ip
+Some systems require extra libraries when linking programs.
+.Ip
+Not all systems need to compile all sources.
+.Ip
+Configuration parameters may need to be passed to some (such as -DDNETCONN
+to compile in DECnet support) or all (such as -DSYSV to select System V code)
+programs as preprocessor symbols.
+.Ip
+Almost all systems organize header files differently, making
+static dependencies in \fIMakefiles\fP impossible to generate.
+.RE
+.LP
+By using the C preprocessor, \fIimake\fP provides a familiar set of interfaces
+to conditionals, macros, and symbolic constants. Common operations, such as
+compiling programs, creating libraries, creating shell scripts, and
+managing subdirectories, can be described in a concise, simple way.
+Figure 3 shows the \fIImakefile\fP used to build a manual page browser
+named \fIxman\fP (written by Chris Peterson program of the MIT X Consortium,
+based on an implementation for X10 by Barry Shein):
+.sp 1
+.KF
+.RS 1in
+.nf
+.ft L
+DEFINES = -DHELPFILE=\e"$(LIBDIR)$(PATHSEP)xman.help\e"
+LOCAL_LIBRARIES = $(XAWLIB) $(XMULIB) $(XTOOLLIB) $(XLIB)
+SRCS = ScrollByL.c handler.c man.c pages.c buttons.c help.c menu.c search.c \e
+ globals.c main.c misc.c tkfuncs.c
+OBJS = ScrollByL.o handler.o man.o pages.o buttons.o help.o menu.o search.o \e
+ globals.o main.o misc.o tkfuncs.o
+INCLUDES = -I$(TOOLKITSRC) -I$(TOP)
+
+ComplexProgramTarget (xman)
+InstallNonExec (xman.help, $(LIBDIR))
+
+.ft P
+.fi
+.RE
+.DS C
+.sp 1
+\fBFigure 3:\fP \fIImakefile\fP used by a typical client program
+.DE
+.KE
+.sp 1
+.LP
+This application requires the name of the directory in which its help file is
+installed (which is a configuration parameter), several libraries, and
+various X header files. The macro
+\fIComplexProgramTarget\fP generates the appropriate rules to build
+the program, install it, compute dependencies, and remove old versions of
+the program and its object files. The \fIInstallNonExec\fP macro generates
+rules to install \fIxman\fP's help file with appropriate permissions.
+.NH 1
+Generating Makefiles
+.LP
+Although \fIimake\fP is a fairly powerful tool, it is a very simple program.
+All of the real work is performed by the template, rule, and configuration
+files. The version currently used at MIT (which differs somewhat from the
+version supplied in the last release of X)
+uses symbolic constants for all configuration
+parameters so that they may be overridden or used by other parameters.
+General build issues (such as the command to execute to run the compiler)
+are isolated from X issues (such as where should application default files be
+installed) by splitting the template as shown in Figure 4.
+.KF
+.sp 1
+.DS C
+.TS
+box tab (%) ;
+l s s
+l _ l
+l | l | l
+l _ l
+l _ l
+l | l | l
+l _ l
+l _ l
+l | l | l
+l _ l
+l _ l
+l | l | l
+l _ l
+l _ l
+l | l | l
+l _ l .
+Imake.tmpl
+ %
+%#include "\fImachine\fP.cf"%
+ %
+ %
+%#include "site.def"%
+ %
+ %
+%#include "Project.tmpl"%
+ %
+ %
+%#include "Imake.rules"%
+ %
+ %
+%#include "./Imakefile"%
+ %
+.TE
+.sp 1
+\fBFigure 4:\fP structure of \fIimake\fP template used by X
+.DE
+.sp 1
+.KE
+.LP
+This template instructs \fIimake\fP to perform the following steps when
+creating a \fIMakefile\fP:
+.RS .5in
+.IP 1.
+Using conditionals, \fIImake.tmpl\fP determines the machine for which the
+build is being configured and includes a machine-specific configuration file
+(usually named \fImachine\fP.cf). Using the C preprocessor to define various
+symbols, this configuration file sets the major and minor version
+numbers of the operating system, the names of any servers
+to build, and any special programs (such as alternate compilers)
+or options (usually to increase internal table sizes) that
+need to be used during the build. Defaults are provided for
+all parameters, so .cf files need only describe how this particular
+platform differs from ``generic'' UNIX System V or BSD UNIX.
+Unlike previous versions of the \fIimake\fP configuration files,
+when new parameters are added, only the systems which are
+effected by them need to be updated.
+.IP 2.
+Next, a site-specific file (named \fIsite.def\fP) is included so
+that parameters from the .cf files may be overridden or
+defaults for other options provided. This is typically used
+by a site administrator to set the names of the various
+directories into which the software should be installed.
+Again, all of the standard \fIcpp\fP constructs may be used.
+.IP 3.
+A project-specific file (named \fIProject.tmpl\fP) is
+included to set various parameters used by the particular
+software package being configured. By separating the
+project parameters (such as directories, options, etc.)
+from build parameters (such as compilers, utilities, etc.),
+the master template and the .cf files can be shared among various development
+efforts.
+.IP 4.
+A file containing the set of \fIcpp\fP rules (named \fIImake.rules\fP)
+is included. This is where the various macro functions used
+in the master template and the per-directory description
+files (named \fIImakefile\fP) are defined. These rules typically
+make very heavy use of the \fImake\fP variables defined in
+\fIImake.tmpl\fP so that a build's configuration may be changed without
+having to edit this file.
+.IP 5.
+The \fIImakefile\fP describing the input files and output targets
+for the current directory is included. This file is supplied
+by the programmer instead of a \fIMakefile\fP. The functions that
+it invokes are translated by \fIcpp\fP into series of \fImake\fP
+rules and targets.
+.IP 6.
+Finally, \fImake\fP rules for recreating the \fIMakefile\fP and managing
+subdirectories are appended, and the result is written out as the
+new \fIMakefile\fP.
+.RE
+.LP
+\fIImake\fP, along with a separate tool (named \fImakedepend\fP, also
+written by
+Brunhoff) that generates \fIMakefile\fP dependencies
+between object files and the source files used to build them, allows
+properly configured \fIMakefiles\fP to be regenerated quickly and correctly.
+By isolating the machine- and site-specifics from the programmer,
+\fIimake\fP is much like a well-developed text formatter: both allow
+the writer to concentrate on the content, rather than the production, of a
+document.
+.NH 1
+How X uses \fIimake\fP
+.LP
+Development of X at MIT is currently done on more than half a dozen
+different platforms, each of which is running a different operating system.
+A common source pool is shared across those machines that support
+symbolic links and NFS by creating trees of links pointing
+back to the master sources (similar to the object trees of [Harrison 88]).
+Editing and source code control is done in the master sources and builds are
+done in the link trees.
+.LP
+.ne 4
+A full build is done by creating a fresh link tree and invoking a
+simple, stub top-level \fIMakefile\fP which:
+.RS .5in
+.IP 1.
+compiles \fIimake\fP.
+.IP 2.
+builds the real top-level \fIMakefile\fP.
+.IP 3.
+builds the rest of the \fIMakefiles\fP using the new top-level \fIMakefile\fP.
+.IP 4.
+removes any object files left over from the previous build.
+.IP 5.
+builds the header file tree, and
+computes and appends the list of dependencies between object files and sources
+to the appropriate \fIMakefiles\fP.
+.IP 6.
+and finally, compiles all of the sources.
+.RE
+.LP
+If the build completes successfully, programs, libraries, data files, and
+manual pages may then be installed. By keeping object files out of the master
+source tree, backups and releases can be done easily and efficiently. By
+substituting local copies of particular files for the appropriate links,
+developers can work without disturbing others.
+.NH 1
+Limitations
+.LP
+Although the system described here is very useful, it isn't perfect.
+Differences
+between utilities on various systems places a restriction on how well
+existing tools can be used. One of the reasons why \fIimake\fP is a program
+instead of a trivial invocation of the C preprocessor is that some \fIcpp\fP's
+collapse tabs into spaces while others do not. Since \fImake\fP uses
+tabs to separate commands from targets, \fIimake\fP must sometimes reformat
+the output from \fIcpp\fP so that a valid \fIMakefile\fP is generated.
+.LP
+Since \fIcpp\fP only provides global
+scoping of symbolic constants, parameters
+are visible to the whole configuration system. For larger projects, this
+approach will probably prove unwieldy both to the people trying to maintain
+them and to the preprocessors that keep the entire symbol table in memory.
+.LP
+The macro facility provided by \fIcpp\fP is convenient because it is available
+on every platform and it is familar to most people. However, a better
+language with real programming constructs might provide a better interface.
+The notions of describing one platform in terms of another and providing
+private configuration parameters map intriguingly well into the models used
+in object management systems.
+.NH 1
+Summary and Observations
+.LP
+The sample implementation of the X Window System from MIT takes advantage
+of a system architecture that goes to great lengths to isolate
+device-dependencies. By selectively using portable versions of
+the device-specific functions, a developer moving X to a new platform can
+quickly get an initial port up and running very quickly.
+.LP
+To manage the various combinations of modules and to cope with the
+differing requirements of every platform and site, X uses a
+utility named \fIimake\fP
+to separate the description of sources and targets from the
+details of how the software is actually built. Using as few external
+tools as possible, this mechanism allows support for new platforms to be
+added with relatively little effort.
+.LP
+Although the approaches taken by MIT will not work for everyone, several of
+its experiences may be useful in other projects:
+.RS .5in
+.Ip
+Even if portability isn't a goal now, it probably will become one sooner
+than expected.
+.Ip
+Just as in other areas, it frequently pays to periodically stand back
+from a problem and see whether or not a simple tool will help. With
+luck and the right amount of abstracting it may even solve several
+problems at once.
+.Ip
+Be wary of anything that requires manual intervention.
+.Ip
+And finally, there is no such thing as portable software, only software that
+has been ported.
+.RE
+.NH 1
+References
+.LP
+.IP "\[Harrison 88\]"
+.br
+``Rtools: Tools for Software Management in a Distributed Computing
+Environment,'' Helen E. Harrison, Stephen P. Schaefer, Terry S. Yoo,
+\fIProceedings of the Usenix Association Summer Conference\fP,
+June 1988, 85-94.
+.IP "\[Lord 88\]"
+.br
+``Tools and Policies for the Hierarchical Management of Source Code
+Development,'' Thomas Lord, \fIProceedings of the Usenix Association
+Summer Conference\fP, June 1988, 95-106.
+.IP "\[Scheifler 88\]"
+.br
+\fIX Window System: C Library and Protocol Reference\fP, Robert Scheifler,
+James Gettys, and Ron Newman, Digital Press, Bedford, MA, 1988.
+
+
+.\
+.\XXX - Xos.h:
+.\ o 12 character file names
+.\ o isolate system calls
+.\ o avoid tricky coding
+.\ o index vs. strchr
+.\ o bcopy
+.\ o test on as wide a range of systems as possible
+.\
--- /dev/null
+/* Rules to generate an AIX 3 shared library. */
+
+/* Generate a null rule for libfoo.a so that "make libfoo.a" will work
+ on all systems to bring libfoo.a up to date (BSD systems would run
+ ranlib). */
+
+#define IBMSharedLibraryTarget(tdeps,libname,ldeps) @@\
+lib/**/libname.a:: @@\
+libname.o: tdeps @@\
+ $(RM) libname.o @@\
+ ld -o libname.o lib/**/libname.a -H512 -T512 -bM\:SRE -bE\:$(SRCDIR)exports.libname ldeps -lc @@\
+ $(RM) shared/lib/**/libname.a @@\
+ $(ARADD) shared/lib/**/libname.a libname.o @@\
+clean:: @@\
+ $(RM) lib/**/libname.a shared/lib/**/libname.a libname.o
+
+#define RanlibLibraryTarget(libname,deps) @@\
+AllTarget(lib/**/libname.a) @@\
+IBMSharedLibraryTarget(foo/**/libname,libname,deps)
+
+#define AdditiveLibraryTarget(libname,objlist,deps) @@\
+AllTarget(lib/**/libname.a) @@\
+AllTarget(libname.o) @@\
+AllTarget(foo/**/libname) @@\
+DependTarget() @@\
+ @@\
+foo/**/libname: objlist @@\
+ $(ARADD) lib/**/libname.a objlist @@\
+ $(TOUCH) foo/**/libname @@\
+IBMSharedLibraryTarget(lib/**/libname.a,libname,deps) @@\
+clean:: @@\
+ $(RM_CMD) foo/**/libname
+
+
+#define SharedLibraryTarget(libname,ldeps) @@\
+IBMSharedLibraryTarget(lib/**/libname.a,libname,ldeps)
+
--- /dev/null
+.TH IMAKE 1 "Release 4" "X Version 11"
+.SH NAME
+imake \- C preprocessor interface to the make utility
+.SH SYNOPSIS
+\fBimake \fP[-D\fIdefine\fP] [-I\fIdir\fP] [-T\fItemplate\fP]
+[-f \fIfilename\fP] [-s \fIfilename\fP] [-e] [-v]
+.SH DESCRIPTION
+.I Imake
+is used to
+generate \fIMakefiles\fP from a template, a set of \fIcpp\fP macro functions,
+and a per-directory input file called an \fIImakefile\fP. This allows machine
+dependencies (such has compiler options, alternate command names, and special
+\fImake\fP rules) to be kept separate from the descriptions of the
+various items to be built.
+.SH OPTIONS
+The following command line options may be passed to \fIimake\fP:
+.TP 8
+.B \-D\fIdefine\fP
+This option is passed directly to \fIcpp\fP. It is typically used to set
+directory-specific variables. For example, the X Window System uses this
+flag to set \fITOPDIR\fP to the name of the directory containing the top
+of the core distribution and \fICURDIR\fP to the name of the current
+directory, relative to the top.
+.TP 8
+.B \-I\fIdirectory\fP
+This option is passed directly to \fIcpp\fP. It is typically used to
+indicate the directory in which the \fIimake\fP template and configuration
+files may be found.
+.TP 8
+.B \-T\fItemplate\fP
+This option specifies the name of the master template file (which is usually
+located in the directory specified with \fI\-I\fP) used by \fIcpp\fP.
+The default is \fIImake.tmpl\fP.
+.TP 8
+.B \-f \fIfilename\fP
+This option specifies the name of the per-directory input file. The default
+is \fIImakefile\fP.
+.TP 8
+.B \-s \fIfilename\fP
+This option specifies the name of the \fImake\fP description file to be
+generated but \fImake\fP should not be invoked.
+If the \fIfilename\fP is a dash (-), the
+output is written to \fIstdout\fP. The default is to generate, but
+not execute, a \fIMakefile\fP.
+.TP 8
+.B \-e
+This option indicates the \fIimake\fP should execute the generated
+\fIMakefile\fP. The default is to leave this to the user.
+.TP 8
+.B \-v
+This option indicates that \fIimake\fP should print the \fIcpp\fP command line
+that it is using to generate the \fIMakefile\fP.
+.SH "HOW IT WORKS"
+\fIImake\fP invokes \fIcpp\fP with any \fI\-I\fP or \fI-D\fP flags passed
+on the command line and passes it the following 3 lines:
+.sp
+.nf
+ #define IMAKE_TEMPLATE "Imake.tmpl"
+ #define INCLUDE_IMAKEFILE "Imakefile"
+ #include IMAKE_TEMPLATE
+.fi
+.sp
+where \fIImake.tmpl\fP and \fIImakefile\fP may be overridden by the
+\fI\-T\fP and \fI\-f\fP command options, respectively. If the
+\fIImakefile\fP contains any lines beginning with a '#' character
+that is not followed by a \fIcpp\fP directive (\fB#include\fP,
+\fB#define\fP, \fB#undef\fP, \fB#ifdef\fP, \fB#else\fP, \fB#endif\fP,
+or \fB#if\fP), \fIimake\fP will make a temporary \fImakefile\fP in
+which the '#' lines are prepended with the string ``/**/'' (so that
+\fIcpp\fP will copy the line into the \fIMakefile\fP as a comment).
+.PP
+The \fIImakefile\fP reads in file containing machine-dependent parameters
+(specified as \fIcpp\fP symbols), a site-specific parameters file, a file
+containing \fIcpp\fP macro functions for generating \fImake\fP rules, and
+finally the \fIImakefile\fP (specified by INCLUDE_IMAKEFILE) in the current
+directory. The \fIImakefile\fP uses the macro functions to indicate what
+targets should be built; \fIimake\fP takes care of generating the appropriate
+rules.
+.PP
+The rules file (usually named \fIImake.rules\fP in the configuration
+directory) contains a variety of \fIcpp\fP macro functions that are
+configured according to the current platform. \fIImake\fP replaces
+any occurrences of the string ``@@'' with a newline to allow macros that
+generate more than one line of \fImake\fP rules.
+For example, the macro
+.ta .8i 1.6i 5i
+.nf
+
+#define program_target(program, objlist) @@\e
+program: objlist @@\e
+ $(CC) -o $@ objlist $(LDFLAGS)
+
+.fi
+when called with
+.I "program_target(foo, foo1.o foo2.o)"
+will expand to
+.nf
+
+foo: foo1.o foo2.o
+ $(CC) -o $@ foo1.o foo2.o $(LDFLAGS)
+
+.fi
+.PP
+On systems whose \fIcpp\fP reduces multiple tabs and spaces to a single
+space, \fIimake\fP attempts to put back any necessary tabs (\fImake\fP is
+very picky about the difference between tabs and spaces). For this reason,
+colons (:) in command lines must be preceded by a backslash (\\).
+.SH "USE WITH THE X WINDOW SYSTEM"
+The X Window System uses \fIimake\fP extensively, for both full builds within
+the source tree and external software. As mentioned above, two special
+variables, \fITOPDIR\fP and \fICURDIR\fP set to make referencing files
+using relative path names easier. For example, the following command is
+generated automatically to build the \fIMakefile\fP in the directory
+\fIlib/X/\fP (relative to the top of the sources):
+.sp
+.nf
+ % ../.././config/imake -I../.././config \\
+ -DTOPDIR=../../. -DCURDIR=./lib/X
+.fi
+.sp
+When building X programs outside the source tree, a special symbol
+\fIUseInstalled\fP is defined and \fITOPDIR\fP and
+\fICURDIR\fP are omitted. If the configuration files have been
+properly installed, the script \fIxmkmf(1)\fP may be used to specify
+the proper options:
+.sp
+.nf
+ % xmkmf
+.fi
+.sp
+The command \fImake Makefiles\fP can then be used to generate \fIMakefiles\fP
+in any subdirectories.
+.SH FILES
+.ta 3i
+/usr/tmp/tmp-imake.\fInnnnnn\fP temporary input file for cpp
+.br
+/usr/tmp/tmp-make.\fInnnnnn\fP temporary input file for make
+.br
+/lib/cpp default C preprocessor
+.DT
+.SH "SEE ALSO"
+make(1)
+.br
+S. I. Feldman
+.I
+Make \- A Program for Maintaining Computer Programs
+.SH "ENVIRONMENT VARIABLES"
+The following environment variables may be set, however their use is not
+recommended as they introduce dependencies that are not readily apparent
+when \fIimake\fP is run:
+.TP 5
+.B IMAKEINCLUDE
+If defined, this should be a valid include argument for the
+C preprocessor. E.g. ``-I/usr/include/local''.
+Actually, any valid
+.I cpp
+argument will work here.
+.TP 5
+.B IMAKECPP
+If defined, this should be a valid path to a preprocessor program.
+E.g. ``/usr/local/cpp''.
+By default,
+.I imake
+will use /lib/cpp.
+.TP 5
+.B IMAKEMAKE
+If defined, this should be a valid path to a make program.
+E.g. ``/usr/local/make''.
+By default,
+.I imake
+will use whatever
+.I make
+program is found using
+.I execvp(3).
+.SH "BUGS"
+Comments should be preceded by ``/**/#'' to protect them from \fIcpp\fP.
+.SH "AUTHOR"
+Todd Brunhoff, Tektronix and MIT Project Athena; Jim Fulton, MIT X Consortium
+
--- /dev/null
+/*
+ * $XConsortium: imakemdep.h,v 1.10 89/12/18 16:56:38 jim Exp $
+ *
+ * This file contains machine-dependent constants for the imake utility. When
+ * porting imake, read each of the steps below and add in any necessary
+ * definitions. Do *not* edit ccimake.c or imake.c!
+ */
+
+#ifdef CCIMAKE
+/*
+ * Step 1: imake_ccflags
+ * Define any special flags that will be needed to get imake.c to compile.
+ * These will be passed to the compile along with the contents of the
+ * make variable BOOTSTRAPCFLAGS.
+ */
+#ifdef hpux
+#define imake_ccflags "-Wc,-Nd4000,-Ns3000 -DSYSV"
+#endif
+
+#ifdef macII
+#define imake_ccflags "-DSYSV"
+#endif
+
+#ifdef stellar
+#define imake_ccflags "-DSYSV"
+#endif
+
+#ifdef att
+#define imake_ccflags "-DSYSV -DUSG"
+#endif
+
+#ifdef CRAY
+#define imake_ccflags "-DSYSV -DUSG"
+#endif
+
+#ifdef aix
+#define imake_ccflags "-Daix -DSYSV"
+#endif
+
+#ifdef umips
+#ifdef SYSTYPE_SYSV
+#define imake_ccflags "-DSYSV -I../../lib/X/mips -I/usr/include/bsd ../../lib/X/mips/mipssysvc.c -lbsd"
+#endif
+#endif
+
+#else /* not CCIMAKE */
+#ifndef MAKEDEPEND
+/*
+ * Step 2: dup2
+ * If your OS doesn't have a dup2() system call to duplicate one file
+ * descriptor onto another, define such a mechanism here (if you don't
+ * already fall under the existing category(ies).
+ */
+#if defined(SYSV) && !defined(CRAY)
+#define dup2(fd1,fd2) ((fd1 == fd2) ? fd1 : (close(fd2), \
+ fcntl(fd1, F_DUPFD, fd2)))
+#endif
+
+
+/*
+ * Step 3: FIXUP_CPP_WHITESPACE
+ * If your cpp collapses tabs macro expansions into a single space and
+ * replaces escaped newlines with a space, define this symbol. This will
+ * cause imake to attempt to patch up the generated Makefile by looking
+ * for lines that have colons in them (this is why the rules file escapes
+ * all colons). One way to tell if you need this is to see whether or not
+ * your Makefiles have no tabs in them and lots of @@ strings.
+ */
+#if defined(sun) || defined(SYSV)
+#define FIXUP_CPP_WHITESPACE
+#endif
+
+
+/*
+ * Step 4: DEFAULT_CPP
+ * If the C preprocessor does not live in /lib/cpp, set this symbol to
+ * the appropriate location.
+ */
+#ifdef apollo
+#define DEFAULT_CPP "/usr/lib/cpp"
+#endif
+
+
+/*
+ * Step 5: cpp_argv
+ * The following table contains the cpp flags that should be passed to
+ * cpp whenever a Makefile is being generated. If your preprocessor
+ * doesn't predefine any unique symbols, choose one and add it to the
+ * end of this table. Then, do the following:
+ *
+ * a. Use this symbol at the top of Imake.tmpl when setting MacroFile.
+ * b. Put this symbol in the definition of BootstrapCFlags in your
+ * <platform>.cf file.
+ * c. When doing a make World, always add "BOOTSTRAPCFLAGS=-Dsymbol"
+ * to the end of the command line.
+ *
+ * Note that you may define more than one symbols (useful for platforms
+ * that support multiple operating systems).
+ */
+
+#define ARGUMENTS 50 /* number of arguments in various arrays */
+char *cpp_argv[ARGUMENTS] = {
+ "cpp", /* replaced by the actual cpp program to exec */
+ "-I.", /* add current directory to include path */
+#ifdef unix
+ "-Uunix", /* remove unix symbol so that filename unix.c okay */
+#endif
+#ifdef M4330
+ "-DM4330", /* Tektronix */
+#endif
+#ifdef M4310
+ "-DM4310", /* Tektronix */
+#endif
+#ifdef macII
+ "-DmacII", /* Apple A/UX */
+#endif
+#ifdef att
+ "-Datt", /* AT&T products */
+#endif
+#ifdef aix
+ "-Daix", /* AIX instead of AOS */
+#ifndef ibm
+#define ibm /* allow BOOTSTRAPCFLAGS="-Daix" */
+#endif
+#endif
+#ifdef ibm
+ "-Dibm", /* IBM PS/2 and RT under both AOS and AIX */
+#endif
+};
+#else /* else MAKEDEPEND */
+/*
+ * Step 6: predefs
+ * If your compiler and/or preprocessor define any specific symbols, add
+ * them to the the following table. The definition of struct symtab is
+ * in util/makedepend/main.c.
+ */
+struct symtab predefs[] = {
+#ifdef apollo
+ {"apollo", "1"},
+#endif
+#ifdef ibm032
+ {"ibm032", "1"},
+#endif
+#ifdef ibm
+ {"ibm", "1"},
+#endif
+#ifdef aix
+ {"aix", "1"},
+#endif
+#ifdef sun
+ {"sun", "1"},
+#endif
+#ifdef hpux
+ {"hpux", "1"},
+#endif
+#ifdef vax
+ {"vax", "1"},
+#endif
+#ifdef VMS
+ {"VMS", "1"},
+#endif
+#ifdef cray
+ {"cray", "1"},
+#endif
+#ifdef CRAY
+ {"CRAY", "1"},
+#endif
+#ifdef att
+ {"att", "1"},
+#endif
+#ifdef mips
+ {"mips", "1"},
+#endif
+#ifdef ultrix
+ {"ultrix", "1"},
+#endif
+#ifdef stellar
+ {"stellar", "1"},
+#endif
+#ifdef mc68000
+ {"mc68000", "1"},
+#endif
+#ifdef mc68020
+ {"mc68020", "1"},
+#endif
+#ifdef __GNUC__
+ {"__GNUC__", "1"},
+#endif
+#ifdef __STDC__
+ {"__STDC__", "1"},
+#endif
+#ifdef __HIGHC__
+ {"__HIGHC__", "1"},
+#endif
+#ifdef CMU
+ {"CMU", "1"},
+#endif
+ /* add any additional symbols before this line */
+ {NULL, NULL}
+};
+
+#endif /* MAKEDEPEND */
+#endif /* CCIMAKE */
--- /dev/null
+copy syslog.h
+link kerberosIV
--- /dev/null
+/*
+ * generic #include file for BSD libc functions which have no other logical
+ * home.
+ */
+#ifndef __BSDLIB__
+#define __BSDLIB__
+#ifdef __STDC__
+/* compat-4.3 */
+extern char *ecvt (double , int , int *, int *);
+extern char *fcvt (double , int , int *, int *);
+extern char *gcvt (double , int , char *);
+
+/* compat-4.1 */
+extern int getpw (int , char []);
+extern int nice (int );
+extern int pause (void );
+extern int srand (unsigned );
+extern int rand (void );
+extern long tell (int );
+extern int utime (char *, const int []);
+extern int vlimit (int , int );
+
+
+/* compat-sys5 */
+extern int getopt (int , const char * const *, const char *);
+#ifdef FILE
+/* XXX depends on stdio #define of FILE */
+extern FILE *tmpfile (void);
+#endif
+
+
+extern char *tmpnam (char *);
+extern char *tempnam (const char *, const char *);
+
+
+/* other random stuff-- some goes into stdlib.h? */
+int abort (void );
+int alarm (int );
+int atoi (const char *);
+long atol (const char *);
+
+int setkey (const char *);
+int encrypt (char *, int );
+char *crypt (const char *, const char *);
+
+int ffs (long );
+
+char *getenv (const char *);
+int setenv (const char *, const char *, int );
+void unsetenv (const char *);
+
+char *getlogin (void );
+char *getpass (const char *);
+char *getwd (char *);
+
+char *getusershell (void );
+int endusershell (void );
+int setusershell (void );
+
+int initgroups (const char *, int );
+
+struct qelem {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+ char q_data[1];
+};
+
+int insque (struct qelem *, struct qelem *);
+int remque (struct qelem *);
+
+int isatty (int );
+
+int mkstemp (char *);
+char *mktemp (char *);
+
+int qsort (char *, int, int, int (*)(char *, char *));
+
+int srandom (unsigned );
+char *initstate (unsigned , char *, int );
+char *setstate (char *);
+long random (void );
+
+char *re_comp (const char *);
+int re_exec (const char *);
+int backref (int , const char *);
+int cclass (const char *, int , int );
+
+int setegid (int );
+int seteuid (int );
+int setgid (int );
+int setrgid (int );
+int setruid (int );
+int setuid (int );
+
+int sleep (unsigned );
+
+int swab (char *, char *, int );
+
+int system (const char *);
+
+char *ttyname (int );
+int ttyslot (void );
+
+unsigned ualarm (unsigned , unsigned );
+int usleep (unsigned );
+#else /* STDC */
+/* compat-4.3 */
+extern char *ecvt ();
+extern char *fcvt ();
+extern char *gcvt ();
+
+/* compat-4.1 */
+extern int getpw ();
+extern int nice ();
+extern int pause ();
+extern int srand ();
+extern int rand ();
+extern long tell ();
+extern int utime ();
+extern int vlimit ();
+
+/* compat-sys5 */
+extern int getopt ();
+#ifdef FILE
+/* XXX depends on stdio #define of FILE */
+extern FILE *tmpfile ();
+#endif
+extern char *tmpnam ();
+extern char *tempnam ();
+
+/* other random stuff-- some goes into stdlib.h? */
+int abort ();
+int alarm ();
+int atoi ();
+long atol ();
+
+int setkey ();
+int encrypt ();
+char *crypt ();
+
+int ffs ();
+
+char *getenv ();
+int setenv ();
+void unsetenv ();
+
+char *getlogin ();
+char *getpass ();
+char *getwd ();
+
+char *getusershell ();
+int endusershell ();
+int setusershell ();
+
+int initgroups ();
+
+int insque ();
+int remque ();
+
+int isatty ();
+
+int mkstemp ();
+char *mktemp ();
+
+int qsort ();
+
+int srandom ();
+char *initstate ();
+char *setstate ();
+long random ();
+
+char *re_comp ();
+int re_exec ();
+int backref ();
+int cclass ();
+
+int setegid ();
+int seteuid ();
+int setgid ();
+int setrgid ();
+int setruid ();
+int setuid ();
+
+int sleep ();
+
+int swab ();
+
+int system ();
+
+char *ttyname ();
+int ttyslot ();
+
+unsigned ualarm ();
+int usleep ();
+#endif /* STDC */
+
+#endif /* __BSDLIB__ */
--- /dev/null
+/*
+ * #include file for bstring(3) & sys5 version functions
+ * home.
+ */
+#ifndef __BSTRING__
+#define __BSTRING__
+#ifdef __STDC__
+/* compat-sys5 */
+/* these are in <string.h> */
+extern int bcmp (const char *, const char *, int );
+extern int bcopy (const char *, char *, int );
+extern int bzero (char *, int );
+#else /* STDC */
+/* compat-sys5 */
+extern char *memccpy ();
+extern char *memchr ();
+extern int memcmp ();
+extern char *memcpy ();
+extern char *memset ();
+
+extern int bcmp ();
+extern int bcopy ();
+extern int bzero ();
+
+#endif /* STDC */
+#endif /* __BSTRING__ */
--- /dev/null
+/*
+ * 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
+
+#ifdef __STDC__
+#ifndef __HIGHC__ /* gives us STDC but not stdarg */
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+/* ANSI C -- use prototypes etc */
+void com_err (const char *, long, const char *, ...);
+char const *error_message (long);
+void (*com_err_hook) (const char *, long, const char *, va_list);
+void (*set_com_err_hook (void (*) (const char *, long, const char *, va_list)))
+ (const char *, long, const char *, va_list);
+void (*reset_com_err_hook ()) (const char *, long, const char *, va_list);
+#else
+/* no prototypes */
+void com_err ();
+char *error_message ();
+void (*com_err_hook) ();
+void (*set_com_err_hook ()) ();
+void (*reset_com_err_hook ()) ();
+#endif
+
+#define __COM_ERR_H
+#endif /* ! defined(__COM_ERR_H) */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1987, 1988, 1989 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Include file for address comparison macros.
+ */
+
+#include <mit-copyright.h>
+
+#ifndef ADDR_COMP_DEFS
+#define ADDR_COMP_DEFS
+
+/*
+** Look boys and girls, a big kludge
+** We need to compare the two internet addresses in network byte order, not
+** local byte order. This is a *really really slow way of doing that*
+** But.....
+** .....it works
+** so we run with it
+**
+** long_less_than gets fed two (u_char *)'s....
+*/
+
+#define u_char_comp(x,y) \
+ (((x)>(y))?(1):(((x)==(y))?(0):(-1)))
+
+#define long_less_than(x,y) \
+ (u_char_comp((x)[0],(y)[0])?u_char_comp((x)[0],(y)[0]): \
+ (u_char_comp((x)[1],(y)[1])?u_char_comp((x)[1],(y)[1]): \
+ (u_char_comp((x)[2],(y)[2])?u_char_comp((x)[2],(y)[2]): \
+ (u_char_comp((x)[3],(y)[3])))))
+
+#endif /* ADDR_COMP_DEFS */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * 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 administration server.
+ */
+
+#include <mit-copyright.h>
+
+#ifndef ADMIN_SERVER_DEFS
+#define ADMIN_SERVER_DEFS
+
+#define PW_SRV_VERSION 2 /* version number */
+
+#define INSTALL_NEW_PW (1<<0) /*
+ * ver, cmd, name, password,
+ * old_pass, crypt_pass, uid
+ */
+
+#define ADMIN_NEW_PW (2<<1) /*
+ * ver, cmd, name, passwd,
+ * old_pass
+ * (grot), crypt_pass (grot)
+ */
+
+#define ADMIN_SET_KDC_PASSWORD (3<<1) /* ditto */
+#define ADMIN_ADD_NEW_KEY (4<<1) /* ditto */
+#define ADMIN_ADD_NEW_KEY_ATTR (5<<1) /*
+ * ver, cmd, name, passwd,
+ * inst, attr (grot)
+ */
+#define INSTALL_REPLY (1<<1) /* ver, cmd, name, password */
+#define RETRY_LIMIT 1
+#define TIME_OUT 30
+#define USER_TIMEOUT 90
+#define MAX_KPW_LEN 40
+
+#define KADM "changepw" /* service name */
+
+#endif /* ADMIN_SERVER_DEFS */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1989 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Machine-type definitions: Sun 386i using SunOS (~BSD)
+ */
+
+#include <mit-copyright.h>
+
+#define BITS32
+#define BIG
+#define LSBFIRST
+#define BSDUNIX
+
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Description.
+ */
+
+#include <mit-copyright.h>
+
+#define BSDUNIX
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define DES_SHIFT_SHIFT
+/*
+ * As of SR10, the C compiler claims to be __STDC__, but doesn't support
+ * const. Sigh.
+ */
+#define const
+
+
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Machine-type definitions: IBM 032 (RT/PC)
+ */
+
+#include <mit-copyright.h>
+
+#define BSDUNIX
+#define IBMWS
+#define IBMWSASM
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define MUSTALIGN
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Machine-type definitions: 68000 with BSD Unix, e.g. SUN
+ */
+
+#include <mit-copyright.h>
+
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define BSDUNIX
+
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Machine-type definitions: SPARC with BSD Unix, e.g. SUN-4
+ */
+
+#include <mit-copyright.h>
+
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define BSDUNIX
+#define MUSTALIGN
+
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1989 by the Regents of the University of California
+ *
+ * Machine Description : TAHOE.
+ */
+
+#include <mit-copyright.h>
+
+#define TAHOE
+#define BSDUNIX
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define MUSTALIGN
+#define NOASM
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Machine-type definitions: VAX
+ */
+
+#include <mit-copyright.h>
+
+#define VAX
+#define BITS32
+#define BIG
+#define LSBFIRST
+#define BSDUNIX
+
+#ifndef __STDC__
+#ifndef NOASM
+#define VAXASM
+#endif /* no assembly */
+#endif /* standard C */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Machine-type definitions: IBM 370
+ */
+
+#include <mit-copyright.h>
+
+/* What else? */
+#define BIG
+#define NONASCII
+#define SHORTNAMES
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Machine-type definitions: IBM PC 8086
+ */
+
+#include <mit-copyright.h>
+
+#define IBMPC
+#define BITS16
+#define CROSSMSDOS
+#define LSBFIRST
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1989 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Machine-type definitions: Pyramid
+ */
+
+#include <mit-copyright.h>
+
+#define BITS32
+#define BIG
+#define MSBFIRST
+#define BSDUNIX
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Machine-type definitions: DECstation 3100 (MIPS R2000)
+ */
+
+#include <mit-copyright.h>
+
+#define MIPS2
+#define BITS32
+#define BIG
+#define LSBFIRST
+#define BSDUNIX
+#define MUSTALIGN
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Configuration info for operating system, hardware description,
+ * language implementation, C library, etc.
+ *
+ * This file should be included in (almost) every file in the Kerberos
+ * sources, and probably should *not* be needed outside of those
+ * sources. (How do we deal with /usr/include/des.h and
+ * /usr/include/krb.h?)
+ */
+
+#ifndef _CONF_H_
+
+#include <mit-copyright.h>
+
+#include "osconf.h"
+
+#ifdef SHORTNAMES
+#include "names.h"
+#endif
+
+/*
+ * Language implementation-specific definitions
+ */
+
+/* special cases */
+#ifdef __HIGHC__
+/* broken implementation of ANSI C */
+#undef __STDC__
+#endif
+
+#ifndef __STDC__
+#define const
+#define volatile
+#define signed
+typedef char *pointer; /* pointer to generic data */
+#define PROTOTYPE(p) ()
+#else
+typedef void *pointer;
+#define PROTOTYPE(p) p
+#endif
+
+/* Does your compiler understand "void"? */
+#ifdef notdef
+#define void int
+#endif
+
+/*
+ * A few checks to see that necessary definitions are included.
+ */
+
+/* byte order */
+
+#ifndef MSBFIRST
+#ifndef LSBFIRST
+/* #error byte order not defined */
+Error: byte order not defined.
+#endif
+#endif
+
+/* machine size */
+#ifndef BITS16
+#ifndef BITS32
+Error: how big is this machine anyways?
+#endif
+#endif
+
+/* end of checks */
+
+#endif /* _CONF_H_ */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * 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 Data Encryption Standard library.
+ */
+
+/* only do the whole thing once */
+#ifndef DES_DEFS
+#define DES_DEFS
+
+#include <mit-copyright.h>
+
+typedef unsigned char des_cblock[8]; /* crypto-block size */
+/* Key schedule */
+typedef struct des_ks_struct { des_cblock _; } des_key_schedule[16];
+
+#define DES_KEY_SZ (sizeof(des_cblock))
+#define DES_ENCRYPT 1
+#define DES_DECRYPT 0
+
+#ifndef 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 key_sched des_key_sched
+#define cbc_encrypt des_cbc_encrypt
+#define cbc_cksum des_cbc_cksum
+#define C_Block_print des_cblock_print
+#define quad_cksum des_quad_cksum
+typedef struct des_ks_struct bit_64;
+#endif
+
+#define des_cblock_print(x) des_cblock_print_file(x, stdout)
+
+#endif /* DES_DEFS */
--- /dev/null
+This file is obsolete and should not be used any more.
+Use "conf.h" instead.
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Known breakage in the version of Metaware's High C compiler that
+ * we've got available....
+ */
+
+#include <mit-copyright.h>
+
+#define const
+/*#define volatile*/
+
+/*
+ * Some builtin functions we can take advantage of for inlining....
+ */
+
+#define abs _abs
+/* the _max and _min builtins accept any number of arguments */
+#undef MAX
+#define MAX(x,y) _max(x,y)
+#undef MIN
+#define MIN(x,y) _min(x,y)
+/*
+ * I'm not sure if 65535 is a limit for this builtin, but it's
+ * reasonable for a string length. Or is it?
+ */
+/*#define strlen(s) _find_char(s,65535,0)*/
+#define bzero(ptr,len) _fill_char(ptr,len,'\0')
+#define bcmp(b1,b2,len) _compare(b1,b2,len)
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Definitions for Kerberos administration server & client
+ */
+
+#ifndef KADM_DEFS
+#define KADM_DEFS
+
+#include <mit-copyright.h>
+/*
+ * kadm.h
+ * Header file for the fourth attempt at an admin server
+ * Doug Church, December 28, 1989, MIT Project Athena
+ */
+
+/* for those broken Unixes without this defined... should be in sys/param.h */
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <krb.h>
+#include <des.h>
+
+/* 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_char fields[FLDSZ]; /* The active fields in this struct */
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+ unsigned long key_low;
+ unsigned long key_high;
+ unsigned long exp_date;
+ unsigned short attributes;
+ unsigned char 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
+
+extern long kdb_get_master_key(); /* XXX should be in krb_db.h */
+extern long kdb_verify_master_key(); /* XXX ditto */
+
+extern long krb_mk_priv(), krb_rd_priv(); /* XXX should be in krb.h */
+extern void krb_set_tkt_string(); /* XXX ditto */
+
+extern unsigned long quad_cksum(); /* XXX should be in des.h */
+
+/* XXX This doesn't belong here!!! */
+char *malloc(), *realloc();
+#ifdef POSIX
+typedef void sigtype;
+#else
+typedef int sigtype;
+#endif
+
+#endif KADM_DEFS
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * 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.
+ */
+
+#include <mit-copyright.h>
+
+#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 MKEYFILE "/.k"
+#define K_LOGFIL "/kerberos/kpropd.log"
+#define KS_LOGFIL "/kerberos/kerberos_slave.log"
+#define KRB_ACL "/kerberos/kerberos.acl"
+#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
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * 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.
+ */
+
+#include <mit-copyright.h>
+
+#ifndef KLOG_DEFS
+#define KLOG_DEFS
+
+#define KRBLOG "/kerberos/kerberos.log" /* master server */
+#define KRBSLAVELOG "/kerberos/kerberos_slave.log" /* master server */
+#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
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * 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 library.
+ */
+
+/* Only one time, please */
+#ifndef KRB_DEFS
+#define KRB_DEFS
+
+#include <mit-copyright.h>
+
+/* Need some defs from des.h */
+#include <des.h>
+
+/* Text describing error codes */
+#define MAX_KRB_ERRORS 256
+extern char *krb_err_txt[MAX_KRB_ERRORS];
+
+/* These are not defined for at least SunOS 3.3 and Ultrix 2.2 */
+#if defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)
+#define FD_ZERO(p) ((p)->fds_bits[0] = 0)
+#define FD_SET(n, p) ((p)->fds_bits[0] |= (1 << (n)))
+#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1 << (n)))
+#endif /* ULTRIX022 || SunOS */
+
+/* General definitions */
+#define KSUCCESS 0
+#define KFAILURE 255
+
+#ifdef NO_UIDGID_T
+typedef unsigned short uid_t;
+typedef unsigned short gid_t;
+#endif /* NO_UIDGID_T */
+
+/*
+ * 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.
+ */
+
+#ifdef notdef
+this is server - only, does not belong here;
+#define KRBLOG "/kerberos/kerberos.log"
+are these used anyplace '?';
+#define VX_KRB_HSTFILE "/etc/krbhst"
+#define PC_KRB_HSTFILE "\\kerberos\\krbhst"
+#endif
+
+#define KRB_CONF "/etc/krb.conf"
+#define KRB_RLM_TRANS "/etc/krb.realms"
+#define KRB_MASTER "kerberos"
+#define KRB_HOST KRB_MASTER
+#define KRB_REALM "ATHENA.MIT.EDU"
+
+/* 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 */
+#define DEFAULT_TKT_LIFE 96 /* default lifetime for krb_mk_req
+ & co., 8 hrs */
+#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 */
+ unsigned long 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
+
+/* Definitions for cl_get_tgt */
+#ifdef PC
+#define CL_GTGT_INIT_FILE "\\kerberos\\k_in_tkts"
+#else
+#define CL_GTGT_INIT_FILE "/etc/k_in_tkts"
+#endif /* PC */
+
+/* Parameters for rd_ap_req */
+/* Maximum alloable clock skew in seconds */
+#define CLOCK_SKEW 5*60
+/* Filename for readservkey */
+#define KEYFILE "/etc/srvtab"
+
+/* 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 */
+ unsigned long checksum; /* Data checksum (opt) */
+ C_Block session; /* Session Key */
+ int life; /* Life of ticket */
+ unsigned long time_sec; /* Time ticket issued */
+ unsigned long 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 */
+ C_Block session; /* Session key */
+ int lifetime; /* Lifetime */
+ int kvno; /* Key version number */
+ KTEXT_ST ticket_st; /* The ticket itself */
+ long 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 */
+ unsigned long app_length; /* length of appl data */
+ unsigned long hash; /* hash to lookup replay */
+ int swap; /* swap bytes? */
+ long 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 */
+#ifdef PC
+#define TKT_FILE "\\kerberos\\ticket.ses"
+#else
+#define TKT_FILE tkt_string()
+#define TKT_ROOT "/tmp/tkt"
+#endif /* PC */
+
+/* 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_long 0-->3, 1-->2, 2-->1, 3-->0
+ * u_short 0-->1, 1-->0
+ */
+
+#define swap_u_16(x) {\
+ unsigned long _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) {\
+ unsigned long _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) {\
+ unsigned long _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) {\
+ unsigned long _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) {\
+ unsigned long _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) {\
+ unsigned short _krb_swap_sh_tmp; \
+ swab((char *) &x, ( &_krb_swap_sh_tmp) ,2); \
+ x = (unsigned short) _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 */
+
+#ifndef PC
+char *tkt_string();
+#endif /* PC */
+
+#ifdef OLDNAMES
+#define krb_mk_req mk_ap_req
+#define krb_rd_req rd_ap_req
+#define krb_kntoln an_to_ln
+#define krb_set_key set_serv_key
+#define krb_get_cred get_credentials
+#define krb_mk_priv mk_private_msg
+#define krb_rd_priv rd_private_msg
+#define krb_mk_safe mk_safe_msg
+#define krb_rd_safe rd_safe_msg
+#define krb_mk_err mk_appl_err_msg
+#define krb_rd_err rd_appl_err_msg
+#define krb_ck_repl check_replay
+#define krb_get_pw_in_tkt get_in_tkt
+#define krb_get_svc_in_tkt get_svc_in_tkt
+#define krb_get_pw_tkt get_pw_tkt
+#define krb_realmofhost krb_getrealm
+#define krb_get_phost get_phost
+#define krb_get_krbhst get_krbhst
+#define krb_get_lrealm get_krbrlm
+#endif /* OLDNAMES */
+
+/* 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 */
+
+#endif /* KRB_DEFS */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * spm Project Athena 8/85
+ *
+ * This file defines data structures for the kerberos
+ * authentication/authorization database.
+ *
+ * They MUST correspond to those defined in *.rel
+ */
+
+#include <mit-copyright.h>
+
+#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 ""
+#define DBM_FILE "/kerberos/principal"
+
+/* 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];
+
+ unsigned long key_low;
+ unsigned long key_high;
+ unsigned long exp_date;
+ char exp_date_txt[DATE_SZ];
+ unsigned long mod_date;
+ char mod_date_txt[DATE_SZ];
+ unsigned short attributes;
+ unsigned char max_life;
+ unsigned char kdc_key_ver;
+ unsigned char 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 {
+ long cpu;
+ long elapsed;
+ long dio;
+ long pfault;
+ long t_stamp;
+ long n_retrieve;
+ long n_replace;
+ long n_append;
+ long n_get_stat;
+ long n_put_stat;
+}
+ DB_stat;
+
+/* Dba defines the structure of a database administrator */
+
+typedef struct {
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+ unsigned short attributes;
+ unsigned long exp_date;
+ char exp_date_txt[DATE_SZ];
+ char *old; /*
+ * cast to (Dba *); not in db, ptr to
+ * old vals
+ */
+}
+ Dba;
+
+extern int kerb_get_principal();
+extern int kerb_put_principal();
+extern int kerb_db_get_stat();
+extern int kerb_db_put_stat();
+extern int kerb_get_dba();
+extern int kerb_db_get_dba();
+
+#endif /* KRB_DB_DEFS */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Comparison macros to emulate LSBFIRST comparison results of network
+ * byte-order quantities
+ */
+
+#include <mit-copyright.h>
+#ifndef LSB_ADDR_COMP_DEFS
+#define LSB_ADDR_COMP_DEFS
+
+#include "osconf.h"
+
+#ifdef LSBFIRST
+#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))
+#else
+/* MSBFIRST */
+#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])))
+
+#endif /* LSBFIRST */
+
+#endif /* LSB_ADDR_COMP_DEFS */
--- /dev/null
+/*
+ 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.
+
+ */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Athena configuration.
+ */
+
+#include <mit-copyright.h>
+
+#ifdef tahoe
+#include "conf-bsdtahoe.h"
+#else /* !tahoe */
+#ifdef vax
+#include "conf-bsdvax.h"
+#else /* !vax */
+#if defined(mips) && defined(ultrix)
+#include "conf-ultmips2.h"
+#else /* !Ultrix MIPS-2 */
+#ifdef ibm032
+#include "conf-bsdibm032.h"
+#else /* !ibm032 */
+#ifdef apollo
+#include "conf-bsdapollo.h"
+#else /* !apollo */
+#ifdef sun
+#ifdef sparc
+#include "conf-bsdsparc.h"
+#else /* sun but not sparc */
+#ifdef i386
+#include "conf-bsd386i.h"
+#else /* sun but not (sparc or 386i) */
+#include "conf-bsdm68k.h"
+#endif /* i386 */
+#endif /* sparc */
+#else /* !sun */
+#ifdef pyr
+#include "conf-pyr.h"
+#endif /* pyr */
+#endif /* sun */
+#endif /* apollo */
+#endif /* ibm032 */
+#endif /* mips */
+#endif /* vax */
+#endif /* tahoe */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Include file for password server
+ */
+
+#include <mit-copyright.h>
+
+#ifndef PASSWD_SERVER_DEFS
+#define PASSWD_SERVER_DEFS
+
+#define PW_SRV_VERSION 2 /* version number */
+#define RETRY_LIMIT 1
+#define TIME_OUT 30
+#define USER_TIMEOUT 90
+#define MAX_KPW_LEN 40 /* hey, seems like a good number */
+
+#define INSTALL_NEW_PW (1<<0) /*
+ * ver, cmd, name, password, old_pass,
+ * crypt_pass, uid
+ */
+
+#define INSTALL_REPLY (1<<1) /* ver, cmd, name, password */
+
+#endif /* PASSWD_SERVER_DEFS */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Definitions for principal names.
+ */
+
+#include <mit-copyright.h>
+
+#ifndef PRINCIPAL_DEFS
+#define PRINCIPAL_DEFS
+
+#define NAME_LEN 39
+#define INSTANCE_LEN 39
+
+#endif /* PRINCIPAL_DEFS */
--- /dev/null
+
+/*
+ * $Source$
+ * $Author$
+ * $Header$
+ *
+ * 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.
+ */
+
+#include <mit-copyright.h>
+
+#include <krb_conf.h>
+
+#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();
+KTEXT pkt_cipher();
+
+/* 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
+ignore README.encryption
+copy error_tables
+link stock
+ignore config.h
+ignore osconf.h
--- /dev/null
+ignore KRB5-types.h
--- /dev/null
+/*
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE 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.
+ *
+ * @(#)syslog.h 7.10 (Berkeley) 6/27/88
+ */
+
+/*
+ * RCS Info
+ * $Header$
+ * $Locker$
+ */
+
+/*
+ * Facility codes
+ */
+
+#define LOG_KERN (0<<3) /* kernel messages */
+#define LOG_USER (1<<3) /* random user-level messages */
+#define LOG_MAIL (2<<3) /* mail system */
+#define LOG_DAEMON (3<<3) /* system daemons */
+#define LOG_AUTH (4<<3) /* security/authorization messages */
+#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
+#define LOG_LPR (6<<3) /* line printer subsystem */
+#define LOG_NEWS (7<<3) /* network news subsystem */
+#define LOG_UUCP (8<<3) /* UUCP subsystem */
+ /* other codes through 15 reserved for system use */
+#define LOG_LOCAL0 (16<<3) /* reserved for local use */
+#define LOG_LOCAL1 (17<<3) /* reserved for local use */
+#define LOG_LOCAL2 (18<<3) /* reserved for local use */
+#define LOG_LOCAL3 (19<<3) /* reserved for local use */
+#define LOG_LOCAL4 (20<<3) /* reserved for local use */
+#define LOG_LOCAL5 (21<<3) /* reserved for local use */
+#define LOG_LOCAL6 (22<<3) /* reserved for local use */
+#define LOG_LOCAL7 (23<<3) /* reserved for local use */
+
+#define LOG_NFACILITIES 24 /* maximum number of facilities */
+#define LOG_FACMASK 0x03f8 /* mask to extract facility part */
+
+#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) /* facility of pri */
+
+/*
+ * Priorities (these are ordered)
+ */
+
+#define LOG_EMERG 0 /* system is unusable */
+#define LOG_ALERT 1 /* action must be taken immediately */
+#define LOG_CRIT 2 /* critical conditions */
+#define LOG_ERR 3 /* error conditions */
+#define LOG_WARNING 4 /* warning conditions */
+#define LOG_NOTICE 5 /* normal but signification condition */
+#define LOG_INFO 6 /* informational */
+#define LOG_DEBUG 7 /* debug-level messages */
+
+#define LOG_PRIMASK 0x0007 /* mask to extract priority part (internal) */
+#define LOG_PRI(p) ((p) & LOG_PRIMASK) /* extract priority */
+
+#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
+
+#ifdef KERNEL
+#define LOG_PRINTF -1 /* pseudo-priority to indicate use of printf */
+#endif
+
+/*
+ * arguments to setlogmask.
+ */
+#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */
+#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */
+
+/*
+ * Option flags for openlog.
+ *
+ * LOG_ODELAY no longer does anything; LOG_NDELAY is the
+ * inverse of what it used to be.
+ */
+#define LOG_PID 0x01 /* log the pid with each message */
+#define LOG_CONS 0x02 /* log on the console if errors in sending */
+#define LOG_ODELAY 0x04 /* delay open until syslog() is called */
+#define LOG_NDELAY 0x08 /* don't delay open */
+#define LOG_NOWAIT 0x10 /* if forking to log on console, don't wait() */
+
+#ifndef KERNEL
+#if defined(__STDC__) || defined(KRB5_PROVIDE_PROTOTYPES)
+extern void syslog (int , const char *, ... );
+#ifdef va_start
+/* XXX depending on #define of va_start in <stdarg.h> */
+extern void vsyslog (int , const char *, va_list );
+#endif
+extern void openlog (const char *, int , int );
+extern void closelog (void );
+extern int setlogmask (int );
+#else /* STDC */
+extern void syslog ();
+extern void vsyslog ();
+extern void openlog ();
+extern void closelog ();
+extern int setlogmask ();
+#endif /* STDC */
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE 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.
+ *
+ * @(#)syslog.h 7.10 (Berkeley) 6/27/88
+ */
+
+/*
+ * RCS Info
+ * $Header$
+ * $Locker$
+ */
+
+/*
+ * Facility codes
+ */
+
+#define LOG_KERN (0<<3) /* kernel messages */
+#define LOG_USER (1<<3) /* random user-level messages */
+#define LOG_MAIL (2<<3) /* mail system */
+#define LOG_DAEMON (3<<3) /* system daemons */
+#define LOG_AUTH (4<<3) /* security/authorization messages */
+#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
+#define LOG_LPR (6<<3) /* line printer subsystem */
+#define LOG_NEWS (7<<3) /* network news subsystem */
+#define LOG_UUCP (8<<3) /* UUCP subsystem */
+ /* other codes through 15 reserved for system use */
+#define LOG_LOCAL0 (16<<3) /* reserved for local use */
+#define LOG_LOCAL1 (17<<3) /* reserved for local use */
+#define LOG_LOCAL2 (18<<3) /* reserved for local use */
+#define LOG_LOCAL3 (19<<3) /* reserved for local use */
+#define LOG_LOCAL4 (20<<3) /* reserved for local use */
+#define LOG_LOCAL5 (21<<3) /* reserved for local use */
+#define LOG_LOCAL6 (22<<3) /* reserved for local use */
+#define LOG_LOCAL7 (23<<3) /* reserved for local use */
+
+#define LOG_NFACILITIES 24 /* maximum number of facilities */
+#define LOG_FACMASK 0x03f8 /* mask to extract facility part */
+
+#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) /* facility of pri */
+
+/*
+ * Priorities (these are ordered)
+ */
+
+#define LOG_EMERG 0 /* system is unusable */
+#define LOG_ALERT 1 /* action must be taken immediately */
+#define LOG_CRIT 2 /* critical conditions */
+#define LOG_ERR 3 /* error conditions */
+#define LOG_WARNING 4 /* warning conditions */
+#define LOG_NOTICE 5 /* normal but signification condition */
+#define LOG_INFO 6 /* informational */
+#define LOG_DEBUG 7 /* debug-level messages */
+
+#define LOG_PRIMASK 0x0007 /* mask to extract priority part (internal) */
+#define LOG_PRI(p) ((p) & LOG_PRIMASK) /* extract priority */
+
+#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri))
+
+#ifdef KERNEL
+#define LOG_PRINTF -1 /* pseudo-priority to indicate use of printf */
+#endif
+
+/*
+ * arguments to setlogmask.
+ */
+#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */
+#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */
+
+/*
+ * Option flags for openlog.
+ *
+ * LOG_ODELAY no longer does anything; LOG_NDELAY is the
+ * inverse of what it used to be.
+ */
+#define LOG_PID 0x01 /* log the pid with each message */
+#define LOG_CONS 0x02 /* log on the console if errors in sending */
+#define LOG_ODELAY 0x04 /* delay open until syslog() is called */
+#define LOG_NDELAY 0x08 /* don't delay open */
+#define LOG_NOWAIT 0x10 /* if forking to log on console, don't wait() */
+
+#ifndef KERNEL
+#if defined(__STDC__) || defined(KRB5_PROVIDE_PROTOTYPES)
+extern void syslog (int , const char *, ... );
+#ifdef va_start
+/* XXX depending on #define of va_start in <stdarg.h> */
+extern void vsyslog (int , const char *, va_list );
+#endif
+extern void openlog (const char *, int , int );
+extern void closelog (void );
+extern int setlogmask (int );
+#else /* STDC */
+extern void syslog ();
+extern void vsyslog ();
+extern void openlog ();
+extern void closelog ();
+extern int setlogmask ();
+#endif /* STDC */
+
+#endif
--- /dev/null
+# Administrator Access Control List
+# Format:
+# Name Privileges Comments
+# Where Privileges is a string containing one or more of
+# "a" Add New Principals
+# "c" Change Passwords
+# "d" Delete Current Principals
+# "i" Inquire About Existing Principals
+# "m" Modify Existing Principals
+# "*" All Privileges
+#jqsample/admin@realm *
+#tomjones/admin@realm acim # Note - May Not Delete
--- /dev/null
+ignore rtest.c
+ignore rtscript
+ignore .saberinit
+ignore don.log
+ignore rtest.good
--- /dev/null
+suppress 223
+suppress 285
+suppress 33 on v4_klog
+suppress 34 on v4_klog
+suppress 36 on sendto
+suppress 35
+suppress 287 on usage
+suppress 287 on rcsid_kerberos_c
+suppress 287 on sin
+suppress 349 on krb_err_txt
+suppress 349 on krbONE
+suppress 349 on _ctype_
+suppress 340
+suppress 341
+suppress 346
+suppress 226 on error
+load -G main.o kdc5_err.o kdc_util.o network.o policy.o -I../include
+load -G do_as_req.o do_tgs_req.o extern.o -I../include
+make SRCS=dispatch.c saber
+load -G kerberos_v4.c -DBACKWARD_COMPAT -DVARARGS -I../include/kerberosIV -I../include -I../include/stdc-incl
+cd /site/Don/krb5/kdc
+load -G ../lib/kdb/libkdb.a ../lib/libkrb5.a
+load -G ../lib/des/libdes.a ../lib/os-4.3/libos.a ../lib/crc-32/libcrc32.a
+load -G /mit/isode/isode-6.0/@sys/lib/libisode.a
+load -G -lkrb -ldes -lcom_err
+setopt load_flags -I/mit/krb5/vax-cc/include
+link
+unload /site/Don/krb5/lib/kdb/libkdb.a(decrypt_key.o)
+cd /site/Don/krb5/lib/kdb
+make SRCS=decrypt_key.c saber
+unload /site/Don/krb5/lib/des/libdes.a(enc_dec.o)
+unload /site/Don/krb5/lib/des/libdes.a(new_rn_key.o)
+cd /site/Don/krb5/lib/des
+make SRCS=enc_dec.c saber
+make SRCS=new_rn_key.c saber
+run
--- /dev/null
+This document describes the protocols & procedures necessary to allow
+a large krb4 site like MIT to migrate smoothly to krb5.
+
+The problem we have to solve is that v4 clients don't know about the v5
+string-to-key function, which incorporates the user's name, instance, and realm
+into his private key, along with his password.
+It happens that our solution also solves a related problem: the v5 str2key
+function prevents a site from changing its realm-name, as when the company gets
+bought by another.
+
+PROTOCOLS:
+
+The compatibilty kdc will mark v5-style entries with an attribute bit.
+
+the v5 get_in_tkt clients (kinit, login, etc) all will be able to perform
+v4 str2key; this will allow users with v4 passwords to gain v5 tickets.
+When a user's entry contains a v5-style password, and he uses v5 kinit,
+the kinit protocol will have the kdc send a cleartext realm-unique string
+(initially null) along with the (password+realm)-encrypted tgt.
+When such a user runs v4 kinit, he loses.
+
+Mapping the realm-name to a realm-id string happens in a kdc-configuration file,
+possibly in the first line of krb.conf .
+
+These things will not happen until we deploy a kpasswd that can replace
+v4-style passwords with v5-style ones.
+It would be nice to provide a "convert" flag, that allows you to upgrade
+without having to change your password's text.
+
+PROCEDURES:
+
+Initially, administrators should deploy the v5 kdc (with its built-in
+v4 compatibility), a v4 kadmin server, and a v5 kadmin server.
+The v5 kadmin server will at this time continue to use the v4 str2key function,
+so all of the passwords in the database will be v4 compatible.
+
+the compatibility versions of the get_in_tkt clients (kinit, login, etc)
+should be deployed when most of the campus' software can handle v5.
+When a v4 user runs v5 kinit, he gets v5 tickets unawares.
+Vice-versa, the user loses.
+
+The users are then weaned from v4 in three (two?) steps:
+ first, we change kpasswd to convert v4-style passwords to v5-style,
+ once the site converts most of its various clients and daemons to v5 krb.
+ the kdc now needs to be able to send a non-null realm-id string to kinit.
+
+ second, we turn off the v4 kadmin server (simultaneous with 1 or 3?).
+
+ third, but optionally, we turn off the v4-compatibility glue in the kdc.
+
+Every user who runs the converting kpasswd becomes unable to run v4 clients
+thereafter; we assume that a user who converts has continued access to
+other v5 clients. the conversion code can warn him.
+
+We continue to run the v4 kadmin because users of v4 kpasswd may not yet have
+ready access to v5 clients.
+
+Note that the database's conversion commences gradually with the deployment
+of the converting kpasswd, so this deployment doesn't have to be instantaneous.
--- /dev/null
+# Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+#
+# 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 Geer Zolot Associates not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. Geer Zolot Associates makes no
+# representations about the suitability of this software for any
+# purpose. It is provided "as is" without express or implied warranty.
+#
+# $Id$
+
+KRB5TOP = /ua/software/build/sun4/krb5.src.B2/src
+
+# Library sources
+SRCS = conv_creds.c conv_princ.c conv_tkt.c conv_tkt_skey.c \
+ encode.c misc.c globals.c sendmsg.c krb524_err.et
+OBJS = conv_creds.o conv_princ.o conv_tkt.o conv_tkt_skey.o \
+ encode.o misc.o globals.o sendmsg.o krb524_err.o
+
+GENS = krb524_err.c krb524_err.h
+
+# Server stuff.
+LDFLAGS= -L. -L/usr/local/lib
+LIBS = -lkrb524 -lkdb5 -lkrb5 -lkrb -lcrypto /usr/local/lib/libdes.a \
+ -lisode -lcom_err
+
+CL_LIBS = -lkrb524 -lkrb5 -lcrypto -lisode -lkrb -lcom_err
+
+CC = gcc
+CFLAGS = -g -DUSE_MASTER -I. -I/usr/local/include
+
+all: libkrb524.a krb524d test k524init
+
+libkrb524.a: $(OBJS)
+ ar cru libkrb524.a $(OBJS)
+ ranlib libkrb524.a
+
+test: libkrb524.a test.o
+ $(CC) -o test $(LDFLAGS) test.o $(LIBS)
+
+krb524d: libkrb524.a krb524d.o
+ $(CC) -o krb524d krb524d.o $(LDFLAGS) $(LIBS)
+
+k524init: libkrb524.a k524init.o
+ $(CC) -o k524init $(LDFLAGS) k524init.o $(CL_LIBS)
+
+krb524d.o: krb524d.c
+ $(CC) -c $(CFLAGS) -I$(KRB5TOP)/include $*.c
+
+test.o: test.c
+ $(CC) -c $(CFLAGS) -I$(KRB5TOP)/include $*.c
+
+depend: $(GENS)
+ makedepend -- $(CFLAGS) -I$(KRB5TOP)/include -- $(SRCS) \
+ test.c krb524d.c
+
+clean:
+ -rm -f libkrb524.a $(OBJS) $(GENS) core *~ *.bak #*
+ -rm -f test krb524d k524init test.o krb524d.o k524init.o
+
+krb524_err.c krb524_err.h: krb524_err.et
+ compile_et krb524_err.et
+
+.SUFFIXES: .et
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
--- /dev/null
+Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+
+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 Geer Zolot Associates not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. Geer Zolot Associates makes no
+representations about the suitability of this software for any
+purpose. It is provided "as is" without express or implied warranty.
+
+$Id$
+
+Kerberos V5 to Kerberos V4 Credentials Converting Service, ALPHA RELEASE
+========================================================================
+
+krb524 is a service that converts Kerberos V5 credentials into
+Kerberos V4 credentials suitable for use with applications that for
+whatever reason do not use V5 directly. The service consists of a
+server that has access to the secret key of the Kerberos service for
+which credentials will be converted, and a library for use by client
+programs that wish to use the server.
+
+The protocol is simple. Suppose that a client C wishes to obtain V4
+credentials for a V5 service S by using the krb524 server. The
+notation {C,S}_n represents a Vn service ticket for S for use by C.
+
+(1) C obtains V5 credentials, including a ticket {C,S}_5, for S by the
+normal V5 means.
+
+(2) C transmits {C,S}_5 to KRB524.
+
+(3) KRB524 converts {C,S}_5 into {C,S}_4.
+
+(4) KRB524 transmits {C,S}_4 to C.
+
+(5) C creates a V4 credentials strucuture from the plaintext
+information in the V5 credential and {C,S}_4.
+
+Steps (2) through (4) are encapsulated in a single function call in
+the krb524 library.
+
+Obviously, not all V5 credentials can be completely converted to V4
+credentials, since the former is a superset of the latter. The
+precise semantics of the conversion function are still undecided.
+UTSL.
+
+Programs contained in this release
+======================================================================
+
+krb524d [-m[aster]] [-k[eytab]]
+
+The krb524 server. It accepts UDP requests on the krb524 service
+port, specified in /etc/services, or on port 4444 by default. (A
+request for an official port assignment is underway.) The -m argument
+causes krb524d to access the KDC master database directly; the -k
+argument causes krb524d to use the default keytab (and therefore only
+be able to convert tickets for services in the keytab). Only one of
+-m or -k can be specified.
+
+test -remote server client service
+
+A test program that obtains a V5 credential for {client,service},
+converts it to a V4 credential, and prints out the entire contents of
+both versions. It prompts for service's secret key, which it needs to
+decrypt both tickets in order to print them out. Enter it as an eight
+digit ASCII hex number.
+
+k524init [-n] [-p principal]
+
+Convert a V5 credential into a V4 credential and store it in a V4
+ticket file. The client is 'principal', or krbtgt at the V5 ccache's
+default principal's realm if not specified. The -n argument causes
+the new ticket to be added to the existing ticket file; otherwise, the
+ticket file is initialized.
+
+Using libkrb524.a
+======================================================================
+
+To use libkrb524.a, #include <krb524.h>, link against libkrb524.a,
+call krb524_init_ets() at the beginning of your program, and call one
+of the following two functions:
+
+int krb524_convert_creds_addr(krb5_creds *v5creds, CREDENTIALS *v4creds,
+ struct sockaddr *saddr)
+
+int krb524_convert_creds_kdc(krb5_creds *v5creds, CREDENTIALS *v4creds)
+
+Both convert the V5 credential in v5creds into a V4 credential in
+v4creds. One assumes krb524d is running on the KDC, the other uses an
+explicit host. You only need to specify the address for saddr; the
+port is filled in automatically.
+
+Unresolved issues / Bugs
+======================================================================
+
+o krb524d requires access to the secret key of any service to be
+converted. Should krb524d run on the KDC or on individual server
+machines? The latter is more paranoid, since it prevents bugs in
+krb524d from provided unauthorized access to the master database.
+However, it also requires the client to provide the address of the
+server to be used. The client will usually have this information
+(since presumably it will be sending the converted V4 credentials to
+the same server) but it may not be in a convenient form. It seems
+"cleaner" to have krb524d run on the KDC.
+
+o Even if krb524d uses keytabs on server machines, it needs to be more
+flexible. You only want to run one krb524d per host, so it has to be
+able to scan multiple keytabs. This might get logistically messy.
+
+o This code is of alpha quality. Bugs, omissions, memory leaks, and
+perhaps security holes still remain. Do not use it (yet) in a
+production environment.
--- /dev/null
+$Id$
+
+Kerberos V5 to Kerberos V4 Credentials Converting Service, ALPHA RELEASE
+========================================================================
+
+This is the ALPHA RELEASE of krb524. Treat it accordingly.
+
+Soon, krb524 will be integrated into the standard MIT Kerberos 5
+distribution. krb524's existence as a distinct distribution is
+temporary.
+
+If you have any questions, contact
+
+Barry Jaspan, bjaspan@gza.com
+Geer Zolot Associates
+(617) 374-3700
+
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <krb5/krb5.h>
+#include <krb.h>
+
+#include "krb524.h"
+
+int krb524_convert_creds_addr(krb5_creds *v5creds, CREDENTIALS *v4creds,
+ struct sockaddr *saddr)
+{
+ int ret;
+
+ if (ret = krb524_convert_creds_plain(v5creds, v4creds))
+ return ret;
+
+ return krb524_convert_tkt(v5creds->server, &v5creds->ticket,
+ &v4creds->ticket_st,
+ &v4creds->kvno,
+ saddr);
+}
+
+int krb524_convert_creds_kdc(krb5_creds *v5creds, CREDENTIALS *v4creds)
+{
+ struct sockaddr_in *addrs;
+ int ret, naddrs;
+
+ if (ret = krb5_locate_kdc(&v5creds->server->realm, &addrs, &naddrs))
+ return ret;
+ if (naddrs == 0)
+ ret = KRB5_KDC_UNREACH;
+ else {
+ addrs[0].sin_port = 0; /* use krb524 default port */
+ ret = krb524_convert_creds_addr(v5creds, v4creds,
+ (struct sockaddr *) &addrs[0]);
+ }
+
+ free(addrs);
+ return ret;
+}
+
+int krb524_convert_creds_plain(krb5_creds *v5creds, CREDENTIALS *v4creds)
+{
+ unsigned long addr;
+ krb5_data *comp;
+ int ret;
+
+ bzero((char *) v4creds, sizeof(CREDENTIALS));
+
+ if (ret = krb524_convert_princs(v5creds->client, v5creds->server,
+ v4creds->pname, v4creds->pinst,
+ v4creds->realm, v4creds->service,
+ v4creds->instance))
+ return ret;
+
+ /* Check keytype too */
+ if (v5creds->keyblock.length != sizeof(C_Block)) {
+ if (krb524_debug)
+ fprintf(stderr, "v5 session keyblock length %d != "
+ "C_Block size %d\n", v5creds->keyblock.length,
+ sizeof(C_Block));
+ return KRB524_BADKEY;
+ } else
+ bcopy((char *) v5creds->keyblock.contents, v4creds->session,
+ sizeof(C_Block));
+
+ /* V4 has no concept of authtime or renew_till, so ignore them */
+ /* V4 lifetime is 1 byte, in 5 minute increments */
+ v4creds->lifetime = 0xff &
+ ((v5creds->times.endtime - v5creds->times.starttime) / 300);
+ v4creds->issue_date = v5creds->times.starttime;
+
+ /* XXX perhaps we should use the addr of the client host if */
+ /* v5creds contains more than one addr. Q: Does V4 support */
+ /* non-INET addresses? */
+ if (!v5creds->addresses || !v5creds->addresses[0] ||
+ v5creds->addresses[0]->addrtype != ADDRTYPE_INET ||
+ v5creds->addresses[0]->length != sizeof(addr)) {
+ if (krb524_debug)
+ fprintf(stderr, "Invalid v5creds address information.\n");
+ return KRB524_BADADDR;
+ } else
+ bcopy(v5creds->addresses[0]->contents, (char *) &addr,
+ sizeof(addr));
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+#include <stdio.h>
+#include <krb5/krb5.h>
+#include <krb.h>
+
+#include "krb524.h"
+
+int krb524_convert_princs(krb5_principal client, krb5_principal
+ server, char *pname, char *pinst, char
+ *prealm, char *sname, char *sinst)
+{
+ char dummy[REALM_SZ];
+ int ret;
+
+ if (ret = krb5_524_conv_principal(client, pname, pinst, prealm))
+ return ret;
+
+ return krb5_524_conv_principal(server, sname, sinst, dummy);
+}
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <krb5/krb5.h>
+#include <krb.h>
+
+#include "krb524.h"
+
+/*
+ * krb524_convert_tkt. Open a network connection to krb524d, send it
+ * the V5 ticket, receive the V4 ticket in response.
+ */
+int krb524_convert_tkt(krb5_principal server, krb5_data *v5tkt,
+ KTEXT_ST *v4tkt,
+ int *kvno,
+ struct sockaddr_in *saddr)
+{
+ char *p;
+ krb5_data reply;
+ struct servent *serv;
+ int ret, status;
+
+ reply.data = NULL;
+
+ if (saddr->sin_port == 0) {
+ serv = getservbyname(KRB524_SERVICE, "udp");
+ if (serv)
+ saddr->sin_port = serv->s_port;
+ else
+ saddr->sin_port = htons(KRB524_PORT);
+ }
+
+ if (ret = krb524_send_message(saddr, v5tkt, &reply))
+ goto fail;
+
+ p = reply.data;
+ status = ntohl(*((krb5_error_code *) p));
+ p += sizeof(krb5_error_code);
+ reply.length -= sizeof(krb5_error_code);
+ if (status) {
+ ret = status;
+ goto fail;
+ }
+ *kvno = ntohl(*((krb5_error_code *) p));
+ p += sizeof(int);
+ reply.length -= sizeof(int);
+ ret = decode_v4tkt(v4tkt, p, &reply.length);
+
+fail:
+ if (ret) {
+ if (reply.data)
+ free(reply.data);
+ reply.data = NULL;
+ reply.length = 0;
+ }
+
+ return ret;
+}
+
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+#include <stdio.h>
+#include <krb5/krb5.h>
+#include <krb.h>
+
+#include "krb524.h"
+
+/*
+ * Convert a v5 ticket for server to a v4 ticket, using service key
+ * skey for both.
+ */
+int krb524_convert_tkt_skey(krb5_ticket *v5tkt, KTEXT_ST *v4tkt,
+ krb5_keyblock *skey)
+{
+ char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
+ char sname[ANAME_SZ], sinst[INST_SZ];
+ krb5_enc_tkt_part *v5etkt;
+ krb5_data *comp;
+ int ret, lifetime;
+
+ v5tkt->enc_part2 = NULL;
+ if (ret = krb5_decrypt_tkt_part(skey, v5tkt)) {
+ krb5_free_ticket(v5tkt);
+ return ret;
+ }
+ v5etkt = v5tkt->enc_part2;
+
+ if (ret = krb524_convert_princs(v5etkt->client, v5tkt->server,
+ pname, pinst, prealm, sname,
+ sinst)) {
+ krb5_free_enc_tkt_part(v5etkt);
+ v5tkt->enc_part2 = NULL;
+ return ret;
+ }
+
+ if (v5etkt->session->keytype != KEYTYPE_DES ||
+ v5etkt->session->length != sizeof(C_Block)) {
+ if (krb524_debug)
+ fprintf(stderr, "v5 session keyblock type %d length %d != "
+ "C_Block size %d\n", v5etkt->session->keytype,
+ v5etkt->session->length,
+ sizeof(C_Block));
+ krb5_free_enc_tkt_part(v5etkt);
+ v5tkt->enc_part2 = NULL;
+ return KRB524_BADKEY;
+ }
+
+ /* V4 has no concept of authtime or renew_till, so ignore them */
+ /* V4 lifetime is 1 byte, in 5 minute increments */
+ if (v5etkt->times.starttime == 0)
+ v5etkt->times.starttime = v5etkt->times.authtime;
+ lifetime = 0xff &
+ ((v5etkt->times.endtime - v5etkt->times.authtime) / 300);
+
+ /* XXX perhaps we should use the addr of the client host if */
+ /* v5creds contains more than one addr. Q: Does V4 support */
+ /* non-INET addresses? */
+ if (!v5etkt->caddrs || !v5etkt->caddrs[0] ||
+ v5etkt->caddrs[0]->addrtype != ADDRTYPE_INET) {
+ if (krb524_debug)
+ fprintf(stderr, "Invalid v5creds address information.\n");
+ krb5_free_enc_tkt_part(v5etkt);
+ v5tkt->enc_part2 = NULL;
+ return KRB524_BADADDR;
+ }
+
+ if (krb524_debug)
+ printf("startime = %ld, authtime = %ld, lifetime = %ld\n",
+ (long) v5etkt->times.starttime,
+ (long) v5etkt->times.authtime,
+ (long) lifetime);
+
+ /* XXX are there V5 flags we should map to V4 equivalents? */
+ ret = krb_create_ticket(v4tkt,
+ 0, /* flags */
+ pname,
+ pinst,
+ krb5_princ_realm(v5etkt->client),
+ *((unsigned long *)v5etkt->caddrs[0]->contents),
+ v5etkt->session->contents,
+ lifetime,
+ /* issue_data */
+ v5etkt->times.starttime,
+ sname,
+ sinst,
+ skey->contents);
+
+ krb5_free_enc_tkt_part(v5etkt);
+ v5tkt->enc_part2 = NULL;
+ if (ret == KSUCCESS)
+ return 0;
+ else
+ return KRB524_V4ERR;
+}
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+#include <stdio.h>
+#include <krb5/krb5.h>
+#include <krb.h>
+
+#include "krb524.h"
+
+/*
+ * I'm sure that this is reinventing the wheel, but I don't know where
+ * the wheel is hidden.
+ */
+
+int encode_v4tkt(KTEXT_ST *, char *, int *),
+ encode_ktext(char **, int *, KTEXT_ST *),
+ encode_bytes(char **, int *, char *, int),
+ encode_int32(char **, int *, krb5_int32 *);
+
+int decode_v4tkt(KTEXT_ST *, char *, int *),
+ decode_ktext(char **, int *, KTEXT_ST *),
+ decode_bytes(char **, int *, char *, int),
+ decode_int32(char **, int *, krb5_int32 *);
+
+int encode_bytes(char **out, int *outlen, char *in, int len)
+{
+ if (len > *outlen)
+ return KRB524_ENCFULL;
+ bcopy(in, *out, len);
+ *out += len;
+ *outlen -= len;
+ return 0;
+}
+
+int encode_int32(char **out, int *outlen, krb5_int32 *v)
+{
+ int ret;
+ int nv;
+
+ nv = htonl(*v);
+ return encode_bytes(out, outlen, (char *) &nv, sizeof(nv));
+}
+
+int encode_v4tkt(KTEXT_ST *v4tkt, char *buf, int *encoded_len)
+{
+ int buflen, ret;
+
+ buflen = *encoded_len;
+
+ if (ret = encode_int32(&buf, &buflen, &v4tkt->length))
+ return ret;
+ if (ret = encode_bytes(&buf, &buflen, v4tkt->dat, MAX_KTXT_LEN))
+ return ret;
+ if (ret = encode_int32(&buf, &buflen, &v4tkt->mbz))
+ return ret;
+
+ *encoded_len -= buflen;
+ return 0;
+}
+
+/* decode functions */
+
+int decode_bytes(char **out, int *outlen, char *in, int len)
+{
+ if (len > *outlen)
+ return KRB524_DECEMPTY;
+ bcopy(*out, in, len);
+ *out += len;
+ *outlen -= len;
+ return 0;
+}
+
+int decode_int32(char **out, int *outlen, krb5_int32 *v)
+{
+ int ret;
+ int nv;
+
+ if (ret = decode_bytes(out, outlen, (char *) &nv, sizeof(nv)))
+ return ret;
+ *v = ntohl(nv);
+ return 0;
+}
+
+int decode_v4tkt(KTEXT_ST *v4tkt, char *buf, int *encoded_len)
+{
+ int buflen, ret;
+
+ buflen = *encoded_len;
+ if (ret = decode_int32(&buf, &buflen, &v4tkt->length))
+ return ret;
+ if (ret = decode_bytes(&buf, &buflen, v4tkt->dat, MAX_KTXT_LEN))
+ return ret;
+ if (ret = decode_int32(&buf, &buflen, &v4tkt->mbz))
+ return ret;
+ *encoded_len -= buflen;
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+#include <stdio.h>
+#include <krb5/krb5.h>
+#include <krb.h>
+
+main(int argc, char **argv)
+{
+ krb5_principal client, server;
+ krb5_ccache cc;
+ krb5_creds v5creds;
+ CREDENTIALS v4creds;
+ int i, ret;
+
+ krb524_init_ets();
+
+ if (ret = krb5_parse_name(argv[1], &client)) {
+ com_err("getcred", ret, "parsing client name");
+ exit(1);
+ }
+ if (ret = krb5_parse_name(argv[2], &server)) {
+ com_err("getcred", ret, "parsing server name");
+ exit(1);
+ }
+ if (ret = krb5_cc_default(&cc)) {
+ com_err("getcred", ret, "opening default credentials cache");
+ exit(1);
+ }
+
+ bzero((char *) &v5creds, sizeof(v5creds));
+ v5creds.client = client;
+ v5creds.server = server;
+ v5creds.times.endtime = 0;
+ v5creds.keyblock.keytype = KEYTYPE_DES;
+ if (ret = krb5_get_credentials(0, cc, &v5creds)) {
+ com_err("getcred", ret, "getting V5 credentials");
+ exit(1);
+ }
+
+ if (ret = krb524_convert_creds_kdc(&v5creds, &v4creds)) {
+ com_err("getcred", ret, "converting to V4 credentials");
+ exit(1);
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+int krb524_debug = 0;
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+#include <stdio.h>
+#include <krb5/krb5.h>
+#include <krb.h>
+
+extern int optind;
+extern char *optarg;
+
+#if !defined(lint) && !defined(SABER)
+const char rcsid[] = "$Id$";
+#endif
+
+main(int argc, char **argv)
+{
+ krb5_principal client, server;
+ krb5_ccache cc;
+ krb5_creds v5creds;
+ CREDENTIALS v4creds;
+ int code;
+ int option;
+ char *princ = NULL;
+ int nodelete = 0;
+ int lose = 0;
+
+ while((option = getopt(argc, argv, "p:n")) != EOF) {
+ switch(option) {
+ case 'p':
+ princ = optarg;
+ break;
+ case 'n':
+ nodelete++;
+ break;
+ default:
+ lose++;
+ break;
+ }
+ }
+
+ if (lose || (argc - optind > 1)) {
+ fprintf(stderr, "Usage: k524init [-p principal]\n");
+ exit(1);
+ }
+
+ krb524_init_ets();
+
+ if (code = krb5_cc_default(&cc)) {
+ com_err("k524init", code, "opening default credentials cache");
+ exit(1);
+ }
+
+ if (code = krb5_cc_get_principal(cc, &client)) {
+ com_err("k524init", code, "while retrieving user principal name");
+ exit(1);
+ }
+
+ if (princ) {
+ if (code = krb5_parse_name(princ, &server)) {
+ com_err("k524init", code, "while parsing service principal name");
+ exit(1);
+ }
+ } else {
+ if (code = krb5_build_principal(&server,
+ krb5_princ_realm(client)->length,
+ krb5_princ_realm(client)->data,
+ "krbtgt",
+ krb5_princ_realm(client)->data,
+ NULL)) {
+ com_err("k524init", code, "while creating service principal name");
+ exit(1);
+ }
+ }
+
+ bzero((char *) &v5creds, sizeof(v5creds));
+ v5creds.client = client;
+ v5creds.server = server;
+ v5creds.times.endtime = 0;
+ v5creds.keyblock.keytype = KEYTYPE_DES;
+ if (code = krb5_get_credentials(0, cc, &v5creds)) {
+ com_err("k524init", code, "getting V5 credentials");
+ exit(1);
+ }
+
+ if (code = krb524_convert_creds_kdc(&v5creds, &v4creds)) {
+ com_err("k524init", code, "converting to V4 credentials");
+ exit(1);
+ }
+
+ /* this is stolen from the v4 kinit */
+
+ if (!nodelete) {
+ /* initialize ticket cache */
+ if (code = in_tkt(v4creds.pname,v4creds.pinst) != KSUCCESS) {
+ com_err("k524init", code, "trying to create the V4 ticket file");
+ exit(1);
+ }
+ }
+
+ /* stash ticket, session key, etc. for future use */
+ if (code = save_credentials(v4creds.service, v4creds.instance,
+ v4creds.realm, v4creds.session,
+ v4creds.lifetime, v4creds.kvno,
+ &(v4creds.ticket_st), v4creds.issue_date)) {
+ com_err("k524init", code, "trying to save the V4 ticket");
+ exit(1);
+ }
+
+ exit(0);
+}
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#ifndef __KRB524_H__
+#define __KRB524_H__
+
+/*
+ * $Id$
+ */
+
+#define KRB524_SERVICE "krb524"
+#define KRB524_PORT 4444
+
+#include <krb524_err.h>
+
+extern int krb524_debug;
+
+#endif /* __KRB524_H__ */
--- /dev/null
+# Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+#
+# 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 Geer Zolot Associates not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. Geer Zolot Associates makes no
+# representations about the suitability of this software for any
+# purpose. It is provided "as is" without express or implied warranty.
+#
+# $Id$
+
+error_table k524
+
+error_code KRB524_BADKEY, "Cannot convert V5 keyblock"
+error_code KRB524_BADADDR, "Cannot convert V5 address information"
+error_code KRB524_BADPRINC, "Cannot convert V5 principal"
+error_code KRB524_BADREALM, "V5 realm name longer than V4 maximum"
+error_code KRB524_V4ERR, "Kerberos V4 error"
+error_code KRB524_ENCFULL, "Encoding too large"
+error_code KRB524_DECEMPTY, "Decoding out of data"
+error_code KRB524_NOTRESP, "Service not responding"
+
+end
--- /dev/null
+Protocol:
+
+ -> ASN.1 encoded V5 ticket
+ <- int status_code, [int kvno, encode_v4tkt encoded KTEXT_ST]
+
+kvno and V4 ticket are only included if status_code is zero.
+
+The kvno for the converted ticket is sent explicitly because the field
+is ASN.1 encoded in the krb5_creds structure; the client would have to
+decode (but not decrypt) the entire krb5_ticket structure to get it,
+which would be inefficient.
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/signal.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <krb5/krb5.h>
+#include <krb5/asn1.h>
+#include <krb5/kdb.h>
+#include <krb5/kdb_dbm.h>
+#ifdef PROVIDE_DES_CBC_CRC
+#include <krb5/mit-des.h>
+#endif
+#include <krb.h>
+
+#include "krb524.h"
+
+#define TIMEOUT 60
+#define TKT_BUFSIZ 2048
+#define MSGSIZE 8192
+
+char *whoami;
+int signalled = 0;
+static int debug = 0;
+
+int use_keytab;
+char *keytab = NULL;
+krb5_keytab kt;
+
+int use_master;
+krb5_principal master_princ;
+krb5_encrypt_block master_encblock;
+krb5_keyblock master_keyblock;
+
+void init_keytab(), init_master();
+krb5_error_code do_connection(), lookup_service_key(), kdc_get_server_key();
+
+void usage()
+{
+ fprintf(stderr, "Usage: %s [-m[aster]] [-k[eytab]]\n", whoami);
+ cleanup_and_exit(1);
+}
+
+int request_exit()
+{
+ signalled = 1;
+}
+
+int krb5_free_keyblock_contents(krb5_keyblock *key)
+{
+ memset(key->contents, 0, key->length);
+ xfree(key->contents);
+ return 0;
+}
+
+main(int argc, char **argv)
+{
+ struct servent *serv;
+ struct sockaddr_in saddr;
+ struct timeval timeout;
+ int ret, s, conn;
+ fd_set rfds;
+
+ krb5_init_ets();
+
+ whoami = ((whoami = strrchr(argv[0], '/')) ? whoami + 1 : argv[0]);
+
+ argv++; argc--;
+ use_master = use_keytab = 0;
+ while (argc) {
+ if (strncmp(*argv, "-k", 2) == 0)
+ use_keytab = 1;
+ else if (strncmp(*argv, "-m", 2) == 0)
+ use_master = 1;
+ else
+ break;
+ argv++; argc--;
+ }
+ if (argc || use_keytab + use_master > 1 ||
+ use_keytab + use_master == 0)
+ usage();
+
+ signal(SIGINT, request_exit);
+ signal(SIGHUP, request_exit);
+ signal(SIGTERM, request_exit);
+
+ if (use_keytab)
+ init_keytab();
+ if (use_master)
+ init_master();
+
+ bzero((char *) &saddr, sizeof(struct sockaddr_in));
+ saddr.sin_family = AF_INET;
+ saddr.sin_addr.s_addr = INADDR_ANY;
+ serv = getservbyname(KRB524_SERVICE, "udp");
+ if (serv == NULL) {
+ com_err(whoami, 0, "service entry not found, using %d", KRB524_PORT);
+ saddr.sin_port = htons(KRB524_PORT);
+ } else
+ saddr.sin_port = serv->s_port;
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ com_err(whoami, errno, "creating main socket");
+ cleanup_and_exit(1);
+ }
+ if ((ret = bind(s, (struct sockaddr *) &saddr,
+ sizeof(struct sockaddr_in))) < 0) {
+ com_err(whoami, errno, "binding main socket");
+ cleanup_and_exit(1);
+ }
+
+ timeout.tv_sec = TIMEOUT;
+ timeout.tv_usec = 0;
+ while (1) {
+ FD_ZERO(&rfds);
+ FD_SET(s, &rfds);
+
+ ret = select(s+1, &rfds, NULL, NULL, &timeout);
+ if (signalled)
+ cleanup_and_exit(0);
+ else if (ret == 0) {
+ if (use_master) {
+ ret = krb5_dbm_db_fini();
+ if (ret && ret != KRB5_KDB_DBNOTINITED) {
+ com_err(whoami, ret, "closing kerberos database");
+ cleanup_and_exit(1);
+ }
+ }
+ } else if (ret < 0 && errno != EINTR) {
+ com_err(whoami, errno, "in select");
+ cleanup_and_exit(1);
+ } else if (FD_ISSET(s, &rfds)) {
+ if (debug)
+ printf("received packet\n");
+ if (ret = do_connection(s)) {
+ com_err(whoami, ret, "handling packet");
+ }
+ } else
+ com_err(whoami, 0, "impossible situation occurred!");
+ }
+
+ return cleanup_and_exit(0);
+}
+
+int cleanup_and_exit(int ret)
+{
+ if (use_master) {
+ krb5_finish_key(&master_encblock);
+ memset((char *)&master_encblock, 0, sizeof(master_encblock));
+ (void) krb5_db_fini();
+ }
+ exit(ret);
+}
+
+void init_keytab()
+{
+ int ret;
+ if (keytab == NULL) {
+ if (ret = krb5_kt_default(&kt)) {
+ com_err(whoami, ret, "while opening default keytab");
+ cleanup_and_exit(1);
+ }
+ } else {
+ if (ret = krb5_kt_resolve(keytab, &kt)) {
+ com_err(whoami, ret, "while resolving keytab %s",
+ keytab);
+ cleanup_and_exit(1);
+ }
+ }
+}
+
+void init_master()
+{
+ int ret;
+ char *realm;
+
+ if (ret = krb5_get_default_realm(&realm)) {
+ com_err(whoami, ret, "getting default realm");
+ cleanup_and_exit(1);
+ }
+ if (ret = krb5_db_setup_mkey_name(NULL, realm, (char **) 0,
+ &master_princ)) {
+ com_err(whoami, ret, "while setting up master key name");
+ cleanup_and_exit(1);
+ }
+
+#ifdef PROVIDE_DES_CBC_CRC
+ master_encblock.crypto_entry = &mit_des_cryptosystem_entry;
+#else
+ error(You gotta figure out what cryptosystem to use in the KDC);
+#endif
+
+ master_keyblock.keytype = KEYTYPE_DES;
+ if (ret = krb5_db_fetch_mkey(master_princ, &master_encblock,
+ FALSE, /* non-manual type-in */
+ FALSE, /* irrelevant, given prev. arg */
+ 0, &master_keyblock)) {
+ com_err(whoami, ret, "while fetching master key");
+ cleanup_and_exit(1);
+ }
+
+ if (ret = krb5_db_init()) {
+ com_err(whoami, ret, "while initializing master database");
+ cleanup_and_exit(1);
+ }
+ if (ret = krb5_process_key(&master_encblock, &master_keyblock)) {
+ krb5_db_fini();
+ com_err(whoami, ret, "while processing master key");
+ cleanup_and_exit(1);
+ }
+}
+
+krb5_error_code do_connection(int s)
+{
+ struct sockaddr saddr;
+ krb5_ticket *v5tkt;
+ KTEXT_ST v4tkt;
+ krb5_keyblock service_key;
+ krb5_data msgdata, tktdata;
+ char msgbuf[MSGSIZE], tktbuf[TKT_BUFSIZ], *p;
+ int n, ret, saddrlen;
+
+ msgdata.data = msgbuf;
+ msgdata.length = MSGSIZE;
+
+ saddrlen = sizeof(struct sockaddr);
+ ret = recvfrom(s, msgdata.data, msgdata.length, 0, &saddr, &saddrlen);
+ if (ret < 0) {
+ ret = errno;
+ goto error;
+ }
+ if (debug)
+ printf("message received\n");
+
+ if (ret = decode_krb5_ticket(&msgdata, &v5tkt))
+ goto error;
+ if (debug)
+ printf("V5 ticket decoded\n");
+
+ if (ret = lookup_service_key(v5tkt->server, &service_key))
+ goto error;
+ if (debug)
+ printf("service key retrieved\n");
+
+ ret = krb524_convert_tkt_skey(v5tkt, &v4tkt, &service_key);
+ if (ret)
+ goto error;
+ krb5_free_keyblock_contents(&service_key);
+ krb5_free_ticket(v5tkt);
+ if (debug)
+ printf("credentials converted\n");
+
+ tktdata.data = tktbuf;
+ tktdata.length = TKT_BUFSIZ;
+ ret = encode_v4tkt(&v4tkt, tktdata.data, &tktdata.length);
+ if (ret)
+ goto error;
+ if (debug)
+ printf("v4 credentials encoded\n");
+
+error:
+ /* create the reply */
+ p = msgdata.data;
+ msgdata.length = 0;
+
+ n = htonl(ret);
+ memcpy(p, (char *) &n, sizeof(int));
+ p += sizeof(int);
+ msgdata.length += sizeof(int);
+
+ if (ret)
+ goto write_msg;
+
+ n = htonl(v5tkt->enc_part.kvno);
+ memcpy(p, (char *) &n, sizeof(int));
+ p += sizeof(int);
+ msgdata.length += sizeof(int);
+
+ memcpy(p, tktdata.data, tktdata.length);
+ p += tktdata.length;
+ msgdata.length += tktdata.length;
+
+write_msg:
+ if (ret)
+ (void) sendto(s, msgdata.data, msgdata.length, 0, &saddr, saddrlen);
+ else
+ if (sendto(s, msgdata.data, msgdata.length, 0, &saddr, saddrlen)<0)
+ ret = errno;
+ if (debug)
+ printf("reply written\n");
+
+ return ret;
+}
+
+krb5_error_code lookup_service_key(krb5_principal p, krb5_keyblock *key)
+{
+ int ret;
+ krb5_keytab_entry entry;
+
+ if (use_keytab) {
+ if (ret = krb5_kt_get_entry(kt, p, 0, &entry))
+ return ret;
+ bcopy((char *) &entry.key, key, sizeof(krb5_keyblock));
+ return 0;
+ } else if (use_master) {
+ if (ret = krb5_dbm_db_init())
+ return ret;
+ return kdc_get_server_key(p, key, NULL);
+ }
+}
+
+/* taken from kdc/kdc_util.c, and modified somewhat */
+krb5_error_code kdc_get_server_key(service, key, kvno)
+ krb5_principal service;
+ krb5_keyblock *key;
+ krb5_kvno *kvno;
+{
+ krb5_error_code ret;
+ int nprincs;
+ krb5_db_entry server;
+ krb5_boolean more;
+
+ nprincs = 1;
+ if (ret = krb5_db_get_principal(service, &server, &nprincs, &more))
+ return(ret);
+
+ if (more) {
+ krb5_db_free_principal(&server, nprincs);
+ return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
+ } else if (nprincs != 1) {
+ krb5_db_free_principal(&server, nprincs);
+ return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN);
+ }
+
+ /*
+ * convert server.key into a real key (it is encrypted in the
+ * database)
+ */
+ ret = KDB_CONVERT_KEY_OUTOF_DB(&server.key, key);
+ if (kvno)
+ *kvno = server.kvno;
+ krb5_db_free_principal(&server, nprincs);
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+#include <stdio.h>
+#include "krb524.h"
+
+void krb524_init_ets()
+{
+ krb5_init_ets();
+ initialize_k524_error_table();
+}
--- /dev/null
+/*
+ * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * 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.
+ *
+ * Send a packet to a service and await a reply, using an exponential
+ * backoff retry algorithm. This is based on krb5_sendto_kdc.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif /* !lint & !SABER */
+
+#include <krb5/krb5.h>
+#include <krb5/ext-proto.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <krb5/los-proto.h>
+
+#ifdef _AIX
+#include <sys/select.h>
+#endif
+
+#include "krb524.h"
+
+/*
+ * Send the formatted request 'message' to the host/port specified in
+ * addr and return the response (if any) in 'reply'.
+ *
+ * If the message is sent and a response is received, 0 is returned,
+ * otherwise an error code is returned.
+ *
+ * The storage for 'reply' is allocated and should be freed by the caller
+ * when finished.
+ */
+
+extern int krb5_max_dgram_size;
+extern int krb5_max_skdc_timeout;
+extern int krb5_skdc_timeout_shift;
+extern int krb5_skdc_timeout_1;
+
+int krb524_send_message (DECLARG(const struct sock addr *, addr),
+ DECLARG(const krb5_data *, message),
+ DECLARG(krb5_data *, reply))
+ OLDDECLARG(const struct sockaddr *, addr)
+ OLDDECLARG(const krb5_data *, message)
+ OLDDECLARG(krb5_data *, reply)
+{
+ register int timeout;
+ int nready, received;
+ krb5_error_code retval;
+ fd_set readable;
+ struct timeval waitlen;
+ int s, cc;
+
+ if ((reply->data = malloc(krb5_max_dgram_size)) == NULL)
+ return ENOMEM;
+ reply->length = krb5_max_dgram_size;
+
+ /* XXX 4.2/4.3BSD has PF_xxx = AF_xxx, so the */
+ /* socket creation here will work properly... */
+ s = socket(addr->sa_family, SOCK_DGRAM, 0);
+ if (s == -1) {
+ retval = errno;
+ goto out;
+ }
+
+ /*
+ * On BSD systems, a connected UDP socket will get connection
+ * refused and net unreachable errors while an unconnected socket
+ * will time out, so use connect, send, recv instead of sendto,
+ * recvfrom. The connect here may return an error if the
+ * destination host is known to be unreachable.
+ */
+ if (connect(s, addr, sizeof(struct sockaddr)) == -1) {
+ retval = errno;
+ goto out;
+ }
+
+ /*
+ * Send the message, and wait for a reply, using an exponential
+ * backoff. Use the kdc timeout values, just for consistency.
+ */
+
+ received = 0;
+ for (timeout = krb5_skdc_timeout_1;
+ timeout < krb5_max_skdc_timeout;
+ timeout <<= krb5_skdc_timeout_shift) {
+
+ if (send(s, message->data, message->length, 0) != message->length) {
+ retval = errno;
+ goto out;
+ }
+
+ waitlen.tv_usec = 0;
+ waitlen.tv_sec = timeout;
+ FD_ZERO(&readable);
+ FD_SET(s, &readable);
+ nready = select(1 + s, &readable, 0, 0, &waitlen);
+ if (nready < 0) {
+ retval = errno;
+ goto out;
+ } else if (nready == 1) {
+ if ((cc = recv(s, reply->data, reply->length, 0)) == -1) {
+ retval = errno;
+ goto out;
+ }
+
+ /*
+ * We might consider here verifying that the reply came
+ * from the host specified, but that check can be fouled
+ * by some implementations of some network types which
+ * might show a loopback return address, for example, if
+ * the server is on the same host as the client.
+ *
+ * Besides, reply addresses can be spoofed, and we don't
+ * want to provide a false sense of security.
+ */
+ reply->length = cc;
+ retval = 0;
+ goto out;
+ }
+ /* else timeout, try again */
+ }
+
+ /* If the loop exits normally, the max timeout expired without */
+ /* a reply having arrived. */
+ retval = KRB524_NOTRESP;
+
+out:
+ (void) close(s);
+ if (retval) {
+ free(reply->data);
+ reply->data = 0;
+ reply->length = 0;
+ }
+ return retval;
+}
--- /dev/null
+/*
+ * Copyright 1993 by Geer Zolot Associates. All Rights Reserved.
+ *
+ * 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 Geer Zolot Associates not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. Geer Zolot Associates makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ */
+
+#if !defined(lint) && !defined(SABER)
+static char rcs_id[] = "$Id$";
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <des.h>
+#include <krb.h>
+#include <krb5/krb5.h>
+#include <krb5/asn1.h>
+
+#include "krb524.h"
+
+#define KEYSIZE 8
+#define CRED_BUFSIZ 2048
+
+#define krb5_print_addrs
+
+void do_local(krb5_creds *, krb5_keyblock *),
+ do_remote(krb5_creds *, char *, krb5_keyblock *);
+
+void print_key(char *msg, char *key)
+{
+ printf("%s: ", msg);
+ C_Block_print(key);
+ printf("\n");
+}
+
+void print_time(char *msg, int t)
+{
+ printf("%s: %d, %s", msg, t, ctime(&t));
+}
+
+void krb5_print_times(char *msg, krb5_ticket_times *t)
+{
+ printf("%s: Start: %d, %s", msg, t->starttime, ctime(&t->starttime));
+ printf("%s: End: %d, %s", msg, t->endtime, ctime(&t->endtime));
+ printf("%s: Auth: %d, %s", msg, t->authtime, ctime(&t->authtime));
+ printf("%s: Renew: %d, %s", msg, t->renew_till, ctime(&t->renew_till));
+}
+
+void krb5_print_keyblock(char *msg, krb5_keyblock *key)
+{
+ printf("%s: Keytype: %d\n", msg, key->keytype);
+ printf("%s: Length: %d\n", msg, key->length);
+ printf("%s: Key: ", msg);
+ C_Block_print(key->contents);
+ printf("\n");
+}
+
+void krb5_print_ticket(krb5_data *ticket_data, krb5_keyblock *key)
+{
+ char *p;
+ krb5_ticket *tkt;
+ int ret;
+
+ if (ret = decode_krb5_ticket(ticket_data, &tkt)) {
+ com_err("test", ret, "decoding ticket");
+ exit(1);
+ }
+ if (ret = krb5_decrypt_tkt_part(key, tkt)) {
+ com_err("test", ret, "decrypting V5 ticket for print");
+ exit(1);
+ }
+
+ krb5_unparse_name(tkt->server, &p);
+ printf("Ticket: Server: %s\n", p);
+ free(p);
+ printf("Ticket: EType: %d\n", tkt->enc_part.etype);
+ printf("Ticket: kvno: %d\n", tkt->enc_part.kvno);
+ printf("Ticket: Flags: 0x%08x\n", tkt->enc_part2->flags);
+ krb5_print_keyblock("Ticket: Session Keyblock",
+ tkt->enc_part2->session);
+ krb5_unparse_name(tkt->enc_part2->client, &p);
+ printf("Ticket: Client: %s\n", p);
+ free(p);
+ krb5_print_times("Ticket: Times", &tkt->enc_part2->times);
+ printf("Ticket: Address 0: %08x\n",
+ *((unsigned long *) tkt->enc_part2->caddrs[0]->contents));
+
+ krb5_free_ticket(tkt);
+}
+
+void krb5_print_creds(krb5_creds *creds, krb5_keyblock *secret_key)
+{
+ char *p, buf[BUFSIZ];
+
+ krb5_unparse_name(creds->client, &p);
+ printf("Client: %s\n", p);
+ free(p);
+ krb5_unparse_name(creds->server, &p);
+ printf("Server: %s\n", p);
+ free(p);
+ krb5_print_keyblock("Session key", &creds->keyblock);
+ krb5_print_times("Times", &creds->times);
+ printf("is_skey: %s\n", creds->is_skey ? "True" : "False");
+ printf("Flags: 0x%08x\n", creds->ticket_flags);
+ krb5_print_addrs(creds->addresses);
+ krb5_print_ticket(&creds->ticket, secret_key);
+ /* krb5_print_ticket(&creds->second_ticket, secret_key); */
+}
+
+void krb4_print_ticket(KTEXT ticket, krb5_keyblock *secret_key)
+{
+ char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
+ char sname[ANAME_SZ], sinst[INST_SZ];
+ unsigned char flags;
+ unsigned long addr, issue_time;
+ C_Block session_key;
+ int life;
+ Key_schedule keysched;
+
+ int ret;
+
+ if (des_key_sched(secret_key->contents, keysched)) {
+ fprintf(stderr, "Bug in DES key somewhere.\n");
+ exit(1);
+ }
+
+ ret = decomp_ticket(ticket, &flags, pname, pinst, prealm, &addr,
+ session_key, &life, &issue_time, sname,
+ sinst, secret_key->contents, keysched);
+ if (ret != KSUCCESS) {
+ fprintf(stderr, "krb4 decomp_ticket failed\n");
+ exit(1);
+ }
+ printf("Ticket: Client: %s.%s@%s\n", pname, pinst, prealm);
+ printf("Ticket: Service: %s.%s%\n", sname, sinst);
+ printf("Ticket: Address: %08x\n", addr);
+ print_key("Ticket: Session Key", session_key);
+ printf("Ticket: Lifetime: %d\n", life);
+ printf("Ticket: Issue Date: %d, %s", issue_time, ctime(&issue_time));
+}
+
+void krb4_print_creds(CREDENTIALS *creds, krb5_keyblock *secret_key)
+{
+ printf("Client: %s.%s@%s\n", creds->pname, creds->pinst,
+ creds->realm);
+ printf("Service: %s.%s@%s\n", creds->service, creds->instance,
+ creds->realm);
+ print_key("Session key", creds->session);
+ printf("Lifetime: %d\n", creds->lifetime);
+ printf("Key Version: %d\n", creds->kvno);
+ print_time("Issue Date", creds->issue_date);
+ krb4_print_ticket(&creds->ticket_st, secret_key);
+}
+
+usage()
+{
+ fprintf(stderr, "Usage: test [-remote server] client service\n");
+ exit(1);
+}
+
+main(int argc, char **argv)
+{
+ krb5_principal client, server;
+ krb5_ccache cc;
+ krb5_creds v5creds;
+ krb5_keyblock key;
+ char keybuf[KEYSIZE], buf[BUFSIZ];
+ int i, ret, local;
+ char *remote;
+
+ krb524_debug = 1;
+
+ krb524_init_ets();
+
+ local = 0;
+ remote = NULL;
+ argc--; argv++;
+ while (argc) {
+ if (strcmp(*argv, "-local") == 0)
+ local++;
+ else if (strcmp(*argv, "-remote") == 0) {
+ argc--; argv++;
+ if (!argc)
+ usage();
+ remote = *argv;
+ }
+ else
+ break;
+ argc--; argv++;
+ }
+ if (argc != 2)
+ usage();
+
+ if (ret = krb5_parse_name(argv[0], &client)) {
+ com_err("test", ret, "parsing client name");
+ exit(1);
+ }
+ if (ret = krb5_parse_name(argv[1], &server)) {
+ com_err("test", ret, "parsing server name");
+ exit(1);
+ }
+ if (ret = krb5_cc_default(&cc)) {
+ com_err("test", ret, "opening default credentials cache");
+ exit(1);
+ }
+
+ bzero((char *) &v5creds, sizeof(v5creds));
+ v5creds.client = client;
+ v5creds.server = server;
+ v5creds.times.endtime = 0;
+ v5creds.keyblock.keytype = KEYTYPE_DES;
+ if (ret = krb5_get_credentials(0, cc, &v5creds)) {
+ com_err("test", ret, "getting V5 credentials");
+ exit(1);
+ }
+
+ /* We need the service key in order to locally decrypt both */
+ /* tickets for testing */
+ printf("Service's key: ");
+ fflush(stdout);
+ fgets(buf, BUFSIZ, stdin);
+ for (i = 0; i < 8; i++) {
+ unsigned char c;
+ c = buf[2*i];
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'z')
+ c = c - 'a' + 0xa;
+ keybuf[i] = c << 4;
+ c = buf[2*i+1];
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'z')
+ c = c - 'a' + 0xa;
+ keybuf[i] += c;
+ }
+
+ key.keytype = KEYTYPE_DES;
+ key.length = KEYSIZE; /* presumably */
+ key.contents = keybuf;
+
+ do_remote(&v5creds, remote, &key);
+}
+
+void do_remote(krb5_creds *v5creds, char *server, krb5_keyblock *key)
+{
+ struct sockaddr_in saddr;
+ struct hostent *hp;
+ CREDENTIALS v4creds;
+ int ret;
+
+ printf("\nV5 credentials:\n");
+ krb5_print_creds(v5creds, key);
+
+ if (strcmp(server, "kdc") != 0) {
+ hp = gethostbyname(server);
+ if (hp == NULL) {
+ fprintf(stderr, "test: host %s does not exist.\n", server);
+ exit(1);
+ }
+ bzero((char *) &saddr, sizeof(struct sockaddr_in));
+ saddr.sin_family = AF_INET;
+ bcopy(hp->h_addr, (char *) &saddr.sin_addr.s_addr,
+ sizeof(struct in_addr));
+
+ if (ret = krb524_convert_creds_addr(v5creds, &v4creds, &saddr)) {
+ com_err("test", ret, "converting credentials on %s",
+ server);
+ exit(1);
+ }
+ } else {
+ if (ret = krb524_convert_creds_kdc(v5creds, &v4creds)) {
+ com_err("test", ret, "converting credentials via kdc");
+ exit(1);
+ }
+ }
+
+ printf("\nV4 credentials:\n");
+ krb4_print_creds(&v4creds, key);
+}
--- /dev/null
+ignore des.old
+ignore FOO
--- /dev/null
+ignore fp.c
+ignore ip.c
+ignore key_perm.h
+ignore odd.h
+ignore p.c
+ignore p_table.h
+ignore s_table.h
+ignore doc
--- /dev/null
+File Function Where?
+
+weak_key.c mit_des_is_weak_key crypto
+string2key.c mit_des_string_to_key ?
+random_key.c mit_des_random_key ?
+process_ky.c mit_des_process_key ?
+new_rn_key.c mit_des_new_random_key ?
+ mit_des_init_random_number_generator ?
+ mit_des_set_random_generator_seed ?
+ mit_des_set_sequence_number ?
+ mit_des_generate_random_block ?
+krb_glue.c mit_des_encrypt_func ?
+ mit_des_decrypt_func ?
+key_sched.c mit_des_key_sched crypto
+key_parity.c mit_des_fixup_key_parity crypto
+ mit_des_check_key_parity crypto
+init_rkey.c mit_des_init_random_key crypto
+finish_key.c mit_des_finish_key crypto
+fin_rndkey.c mit_des_finish_random_key crypto
+enc_dec.c mit_des_cbc_encrypt crypto
+des.c mit_des_ecb_encrypt crypto
+cs_entry.c (var) mit_des_cryptosystem_entry krb5
+ (var) krb5_des_cst_entry krb5
+ (var) mit_des_cbc_cksumtable_entry krb5
+cksum.c mit_des_cbc_cksum crypto
+cbc_cksum.c mit_des_cbc_checksum crypto
--- /dev/null
+
+ How to use the Kerberos encryption library.
+
+ Revised 10/15/85 spm
+
+1) The following include file is needed:
+
+ /projects/auth/include/des.h (VAX)
+ --------------- (PC8086)
+
+2) The encryption library that should be linked to is:
+
+ /projects/auth/lib/libdes.a (VAX)
+| /projects/auth/ibm/lib/libdes.a (PC8086 cross-compilation environment)
+
+3) For each key that may be simultaneously active,
+ allocate (either compile or malloc) a "Key_schedule" struct,
+ defined in "des.h"
+
+4) Create key schedules, as needed, prior to using the encryption
+ routines, via "des_set_key()".
+
+5) Setup the input and output areas. Make sure to note the restrictions
+ on lengths being multiples of eight bytes.
+
+6) Invoke the encryption/decryption routines, "ecb_encrypt()"
+ or "cbc_encrypt()"
+
+7) To generate a cryptographic checksum, use "cbc_cksum()"
+/* ---------------------------------------------------------------- */
+
+ Routine Interfaces--
+
+/* ----------------------------------------------------------------- */
+
+int
+ des_set_key(k,schedule)
+ C_Block *k;
+ Key_schedule schedule;
+
+ Calculates a key schedule from (all) eight bytes of the input key, and
+ puts it into the indicated "Key_schedule" struct;
+
+ Make sure to pass valid eight bytes, no padding or other processing
+ it done.
+
+ The key schedule is then used in subsequent encryption/decryption
+ operations. Many key schedules may be created and cached for later
+ use.
+
+ The user is responsible to clear keys and schedules no longer needed
+ to prevent their disclosure.
+
+| Checks the parity of the key provided, to make sure it is odd per
+| FIPS spec. Returns 0 value for key ok, 1 for key_parity error.
+
+/* ---------------------------------------------------------------- */
+
+int
+ ecb_encrypt(input,output,schedule,encrypt)
+ C_Block *input; /* ptr to eight byte input value */
+ C_Block *output; /* ptr to eight byte output value */
+ int encrypt; /* 0 ==> decrypt, else encrypt */
+ Key_schedule schedule; /* addr of key schedule */
+
+This is the low level routine that encrypts or decrypts a single 8-byte
+block in electronic code book mode. Always transforms the input
+data into the output data.
+
+If encrypt is non-zero, the input (cleartext) is encrypted into the
+output (ciphertext) using the specified key_schedule, pre-set via "des_set_key".
+
+If encrypt is zero, the input (now ciphertext) is decrypted into
+the output (now cleartext).
+
+Input and output may be the same space.
+
+Does not return any meaningful value. Void is not used for compatibility
+with other compilers.
+
+/* -------------------------------------------------------------- */
+
+int
+ cbc_encrypt(input,output,length,schedule,ivec,encrypt)
+
+ C_Block *input; /* ptr to input data */
+ C_Block *output; /* ptr to output data */
+ int length; /* desired length, in bytes */
+ Key_schedule schedule; /* addr of precomputed schedule */
+ C_Block *ivec; /* pointer to 8 byte initialization
+ * vector
+ */
+ int encrypt /* 0 ==> decrypt; else encrypt*/
+
+
+ If encrypt is non-zero, the routine cipher-block-chain encrypts
+ the INPUT (cleartext) into the OUTPUT (ciphertext) using the provided
+ key schedule and initialization vector. If the length 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.
+
+ If encrypt is zero, the routine cipher-block chain decrypts the INPUT
+ (ciphertext) into the OUTPUT (cleartext) using the provided key schedule
+ and initialization vector. Decryption ALWAYS operates on integral
+ multiples of 8 bytes, so will round the 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 cleartext lengths not integral
+ multiples of 8.
+
+ No errors or meaningful value are returned. Void is not used for
+ compatibility with other compilers.
+
+
+/* cbc checksum (MAC) only routine ---------------------------------------- */
+int
+ cbc_cksum(input,output,length,schedule,ivec)
+
+ C_Block *input; /* >= length bytes of inputtext */
+ C_Block *output; /* >= length bytes of outputtext */
+ int length; /* in bytes */
+ Key_schedule schedule; /* precomputed key schedule */
+ C_Block *ivec; /* 8 bytes of ivec */
+
+
+ Produces a cryptographic checksum, 8 bytes, by cipher-block-chain
+ encrypting the input, discarding the ciphertext output, and only retaining
+ the last ciphertext 8-byte block. Uses the provided key schedule and ivec.
+ The input is effectively zero-padded to an integral multiple of
+ eight bytes, though the original input is not modified.
+
+ No meaningful value is returned. Void is not used for compatibility
+ with other compilers.
+
+
+/* random_key ----------------------------------------*/
+int
+ random_key(key)
+
+ C_Block *key;
+
+ The start for the random number generated is set from the current time
+ in microseconds, then the random number generator is invoked
+ to create an eight byte output key (not a schedule). The key
+ generated is set to odd parity per FIPS spec.
+
+ The caller must supply space for the output key, pointed to
+ by "*key", then after getting a new key, call the des_set_key()
+ routine when needed.
+
+ No meaningfull value is returned. Void is not used for compatibility
+ with other compilers.
+
+
+/* string_to_key --------------------------------------------*/
+
+int
+ string_to_key(str,key)
+ register char *str;
+ register C_Block *key;
+
+ This routines converts an arbitrary length, null terminated string
+ to an 8 byte DES key, with each byte parity set to odd, per FIPS spec.
+
+ The algorithm is as follows:
+
+| Take the first 8 bytes and remove the parity (leaving 56 bits).
+| Do the same for the second 8 bytes, and the third, etc. Do this for
+| as many sets of 8 bytes as necessary, filling in the remainder of the
+| last set with nulls. Fold the second set back on the first (i.e. bit
+| 0 over bit 55, and bit 55 over bit 0). Fold the third over the second
+| (bit 0 of the third set is now over bit 0 of the first set). Repeat
+| until you have done this to all sets. Xor the folded sets. Break the
+| result into 8 7 bit bytes, and generate odd parity for each byte. You
+| now have 64 bits. Note that DES takes a 64 bit key, and uses only the
+| non parity bits.
+
+
+/* read_password -------------------------------------------*/
+
+read_password(k,prompt,verify)
+ C_Block *k;
+ char *prompt;
+ int verify;
+
+This routine issues the supplied prompt, turns off echo, if possible, and
+reads an input string. If verify is non-zero, it does it again, for use
+in applications such as changing a password. If verify is non-zero, both
+versions are compared, and the input is requested repeatedly until they
+match. Then, the input string is mapped into a valid DES key, internally
+using the string_to_key routine. The newly created key is copied to the
+area pointed to by parameter "k".
+
+No meaningful value is returned. If an error occurs trying to manipulate
+the terminal echo, the routine forces the process to exit.
+
+/* get_line ------------------------*/
+long get_line(p,max)
+ char *p;
+ long max;
+
+Reads input characters from standard input until either a newline appears or
+else the max length is reached. The characters read are stuffed into
+the string pointed to, which will always be null terminated. The newline
+is not inserted in the string. The max parameter includes the byte needed
+for the null terminator, so allocate and pass one more than the maximum
+string length desired.
--- /dev/null
+0101010101010101 95F8A5E5DD31D900 8000000000000000
+0101010101010101 DD7F121CA5015619 4000000000000000
+0101010101010101 2E8653104F3834EA 2000000000000000
+0101010101010101 4BD388FF6CD81D4F 1000000000000000
+0101010101010101 20B9E767B2FB1456 0800000000000000
+0101010101010101 55579380D77138EF 0400000000000000
+0101010101010101 6CC5DEFAAF04512F 0200000000000000
+0101010101010101 0D9F279BA5D87260 0100000000000000
+0101010101010101 D9031B0271BD5A0A 0080000000000000
+0101010101010101 424250B37C3DD951 0040000000000000
+0101010101010101 B8061B7ECD9A21E5 0020000000000000
+0101010101010101 F15D0F286B65BD28 0010000000000000
+0101010101010101 ADD0CC8D6E5DEBA1 0008000000000000
+0101010101010101 E6D5F82752AD63D1 0004000000000000
+0101010101010101 ECBFE3BD3F591A5E 0002000000000000
+0101010101010101 F356834379D165CD 0001000000000000
+0101010101010101 2B9F982F20037FA9 0000800000000000
+0101010101010101 889DE068A16F0BE6 0000400000000000
+0101010101010101 E19E275D846A1298 0000200000000000
+0101010101010101 329A8ED523D71AEC 0000100000000000
+0101010101010101 E7FCE22557D23C97 0000080000000000
+0101010101010101 12A9F5817FF2D65D 0000040000000000
+0101010101010101 A484C3AD38DC9C19 0000020000000000
+0101010101010101 FBE00A8A1EF8AD72 0000010000000000
+0101010101010101 750D079407521363 0000008000000000
+0101010101010101 64FEED9C724C2FAF 0000004000000000
+0101010101010101 F02B263B328E2B60 0000002000000000
+0101010101010101 9D64555A9A10B852 0000001000000000
+0101010101010101 D106FF0BED5255D7 0000000800000000
+0101010101010101 E1652C6B138C64A5 0000000400000000
+0101010101010101 E428581186EC8F46 0000000200000000
+0101010101010101 AEB5F5EDE22D1A36 0000000100000000
+0101010101010101 E943D7568AEC0C5C 0000000080000000
+0101010101010101 DF98C8276F54B04B 0000000040000000
+0101010101010101 B160E4680F6C696F 0000000020000000
+0101010101010101 FA0752B07D9C4AB8 0000000010000000
+0101010101010101 CA3A2B036DBC8502 0000000008000000
+0101010101010101 5E0905517BB59BCF 0000000004000000
+0101010101010101 814EEB3B91D90726 0000000002000000
+0101010101010101 4D49DB1532919C9F 0000000001000000
+0101010101010101 25EB5FC3F8CF0621 0000000000800000
+0101010101010101 AB6A20C0620D1C6F 0000000000400000
+0101010101010101 79E90DBC98F92CCA 0000000000200000
+0101010101010101 866ECEDD8072BB0E 0000000000100000
+0101010101010101 8B54536F2F3E64A8 0000000000080000
+0101010101010101 EA51D3975595B86B 0000000000040000
+0101010101010101 CAFFC6AC4542DE31 0000000000020000
+0101010101010101 8DD45A2DDF90796C 0000000000010000
+0101010101010101 1029D55E880EC2D0 0000000000008000
+0101010101010101 5D86CB23639DBEA9 0000000000004000
+0101010101010101 1D1CA853AE7C0C5F 0000000000002000
+0101010101010101 CE332329248F3228 0000000000001000
+0101010101010101 8405D1ABE24FB942 0000000000000800
+0101010101010101 E643D78090CA4207 0000000000000400
+0101010101010101 48221B9937748A23 0000000000000200
+0101010101010101 DD7C0BBD61FAFD54 0000000000000100
+0101010101010101 2FBC291A570DB5C4 0000000000000080
+0101010101010101 E07C30D7E4E26E12 0000000000000040
+0101010101010101 0953E2258E8E90A1 0000000000000020
+0101010101010101 5B711BC4CEEBF2EE 0000000000000010
+0101010101010101 CC083F1E6D9E85F6 0000000000000008
+0101010101010101 D2FD8867D50D2DFE 0000000000000004
+0101010101010101 06E7EA22CE92708F 0000000000000002
+0101010101010101 166B40B44ABA4BD6 0000000000000001
+8001010101010101 0000000000000000 95A8D72813DAA94D
+4001010101010101 0000000000000000 0EEC1487DD8C26D5
+2001010101010101 0000000000000000 7AD16FFB79C45926
+1001010101010101 0000000000000000 D3746294CA6A6CF3
+0801010101010101 0000000000000000 809F5F873C1FD761
+0401010101010101 0000000000000000 C02FAFFEC989D1FC
+0201010101010101 0000000000000000 4615AA1D33E72F10
+0180010101010101 0000000000000000 2055123350C00858
+0140010101010101 0000000000000000 DF3B99D6577397C8
+0120010101010101 0000000000000000 31FE17369B5288C9
+0110010101010101 0000000000000000 DFDD3CC64DAE1642
+0108010101010101 0000000000000000 178C83CE2B399D94
+0104010101010101 0000000000000000 50F636324A9B7F80
+0102010101010101 0000000000000000 A8468EE3BC18F06D
+0101800101010101 0000000000000000 A2DC9E92FD3CDE92
+0101400101010101 0000000000000000 CAC09F797D031287
+0101200101010101 0000000000000000 90BA680B22AEB525
+0101100101010101 0000000000000000 CE7A24F350E280B6
+0101080101010101 0000000000000000 882BFF0AA01A0B87
+0101040101010101 0000000000000000 25610288924511C2
+0101020101010101 0000000000000000 C71516C29C75D170
+0101018001010101 0000000000000000 5199C29A52C9F059
+0101014001010101 0000000000000000 C22F0A294A71F29F
+0101012001010101 0000000000000000 EE371483714C02EA
+0101011001010101 0000000000000000 A81FBD448F9E522F
+0101010801010101 0000000000000000 4F644C92E192DFED
+0101010401010101 0000000000000000 1AFA9A66A6DF92AE
+0101010201010101 0000000000000000 B3C1CC715CB879D8
+0101010180010101 0000000000000000 19D032E64AB0BD8B
+0101010140010101 0000000000000000 3CFAA7A7DC8720DC
+0101010120010101 0000000000000000 B7265F7F447AC6F3
+0101010110010101 0000000000000000 9DB73B3C0D163F54
+0101010108010101 0000000000000000 8181B65BABF4A975
+0101010104010101 0000000000000000 93C9B64042EAA240
+0101010102010101 0000000000000000 5570530829705592
+0101010101800101 0000000000000000 8638809E878787A0
+0101010101400101 0000000000000000 41B9A79AF79AC208
+0101010101200101 0000000000000000 7A9BE42F2009A892
+0101010101100101 0000000000000000 29038D56BA6D2745
+0101010101080101 0000000000000000 5495C6ABF1E5DF51
+0101010101040101 0000000000000000 AE13DBD561488933
+0101010101020101 0000000000000000 024D1FFA8904E389
+0101010101018001 0000000000000000 D1399712F99BF02E
+0101010101014001 0000000000000000 14C1D7C1CFFEC79E
+0101010101012001 0000000000000000 1DE5279DAE3BED6F
+0101010101011001 0000000000000000 E941A33F85501303
+0101010101010801 0000000000000000 DA99DBBC9A03F379
+0101010101010401 0000000000000000 B7FC92F91D8E92E9
+0101010101010201 0000000000000000 AE8E5CAA3CA04E85
+0101010101010180 0000000000000000 9CC62DF43B6EED74
+0101010101010140 0000000000000000 D863DBB5C59A91A0
+0101010101010120 0000000000000000 A1AB2190545B91D7
+0101010101010110 0000000000000000 0875041E64C570F7
+0101010101010108 0000000000000000 5A594528BEBEF1CC
+0101010101010104 0000000000000000 FCDB3291DE21F0C0
+0101010101010102 0000000000000000 869EFD7F9F265A09
+1046913489980131 0000000000000000 88D55E54F54C97B4
+1007103489988020 0000000000000000 0C0CC00C83EA48FD
+10071034C8980120 0000000000000000 83BC8EF3A6570183
+1046103489988020 0000000000000000 DF725DCAD94EA2E9
+1086911519190101 0000000000000000 E652B53B550BE8B0
+1086911519580101 0000000000000000 AF527120C485CBB0
+5107B01519580101 0000000000000000 0F04CE393DB926D5
+1007B01519190101 0000000000000000 C9F00FFC74079067
+3107915498080101 0000000000000000 7CFD82A593252B4E
+3107919498080101 0000000000000000 CB49A2F9E91363E3
+10079115B9080140 0000000000000000 00B588BE70D23F56
+3107911598080140 0000000000000000 406A9A6AB43399AE
+1007D01589980101 0000000000000000 6CB773611DCA9ADA
+9107911589980101 0000000000000000 67FD21C17DBB5D70
+9107D01589190101 0000000000000000 9592CB4110430787
+1007D01598980120 0000000000000000 A6B7FF68A318DDD3
+1007940498190101 0000000000000000 4D102196C914CA16
+0107910491190401 0000000000000000 2DFA9F4573594965
+0107910491190101 0000000000000000 B46604816C0E0774
+0107940491190401 0000000000000000 6E7E6221A4F34E87
+19079210981A0101 0000000000000000 AA85E74643233199
+1007911998190801 0000000000000000 2E5A19DB4D1962D6
+10079119981A0801 0000000000000000 23A866A809D30894
+1007921098190101 0000000000000000 D812D961F017D320
+100791159819010B 0000000000000000 055605816E58608F
+1004801598190101 0000000000000000 ABD88E8B1B7716F1
+1004801598190102 0000000000000000 537AC95BE69DA1E1
+1004801598190108 0000000000000000 AED0F6AE3C25CDD8
+1002911598100104 0000000000000000 B3E35A5EE53E7B8D
+1002911598190104 0000000000000000 61C79C71921A2EF8
+1002911598100201 0000000000000000 E2F5728F0995013C
+1002911698100101 0000000000000000 1AEAC39A61F0A464
+7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B
+0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271
+07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A
+3849674C2602319E 51454B582DDF440A 7178876E01F19B2A
+04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095
+0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B
+0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09
+43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A
+07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F
+04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088
+37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77
+1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A
+584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56
+025816164629B007 480D39006EE762F2 A1F9915541020B56
+49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556
+4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC
+49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A
+018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41
+1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793
--- /dev/null
+ignore RFC1186.TXT
+ignore RFC1186B.TXT
--- /dev/null
+
+
+
+
+
+
+Network Working Group R. Rivest
+Request for Comments: 1186 MIT Laboratory for Computer Science
+ October 1990
+
+
+ The MD4 Message Digest Algorithm
+
+Status of this Memo
+
+ This RFC is the specification of the MD4 Digest Algorithm. If you
+ are going to implement MD4, it is suggested you do it this way. This
+ memo is for informational use and does not constitute a standard.
+ Distribution of this memo is unlimited.
+
+Table of Contents
+
+ 1. Abstract .................................................... 1
+ 2. Terminology and Notation .................................... 2
+ 3. MD4 Algorithm Description ................................... 2
+ 4. Extensions .................................................. 6
+ 5. Summary ..................................................... 7
+ 6. Acknowledgements ............................................ 7
+ APPENDIX - Reference Implementation ............................. 7
+ Security Considerations.......................................... 18
+ Author's Address................................................. 18
+
+1. Abstract
+
+ This note describes the MD4 message digest algorithm. The algorithm
+ takes as input an input message of arbitrary length and produces as
+ output a 128-bit "fingerprint" or "message digest" of the input. It
+ is conjectured that it is computationally infeasible to produce two
+ messages having the same message digest, or to produce any message
+ having a given prespecified target message digest. The MD4 algorithm
+ is thus ideal for digital signature applications, where a large file
+ must be "compressed" in a secure manner before being signed with the
+ RSA public-key cryptosystem.
+
+ The MD4 algorithm is designed to be quite fast on 32-bit machines.
+ On a SUN Sparc station, MD4 runs at 1,450,000 bytes/second. On a DEC
+ MicroVax II, MD4 runs at approximately 70,000 bytes/second. On a
+ 20MHz 80286, MD4 runs at approximately 32,000 bytes/second. In
+ addition, the MD4 algorithm does not require any large substitution
+ tables; the algorithm can be coded quite compactly.
+
+ The MD4 algorithm is being placed in the public domain for review and
+ possible adoption as a standard.
+
+
+
+
+Rivest [Page 1]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ (Note: The document supersedes an earlier draft. The algorithm
+ described here is a slight modification of the one described in the
+ draft.)
+
+2. Terminology and Notation
+
+ In this note a "word" is a 32-bit quantity and a byte is an 8-bit
+ quantity. A sequence of bits can be interpreted in a natural manner
+ as a sequence of bytes, where each consecutive group of 8 bits is
+ interpreted as a byte with the high-order (most significant) bit of
+ each byte listed first. Similarly, a sequence of bytes can be
+ interpreted as a sequence of 32-bit words, where each consecutive
+ group of 4 bytes is interpreted as a word with the low-order (least
+ significant) byte given first.
+
+ Let x_i denote "x sub i". If the subscript is an expression, we
+ surround it in braces, as in x_{i+1}. Similarly, we use ^ for
+ superscripts (exponentiation), so that x^i denotes x to the i-th
+ power.
+
+ Let the symbol "+" denote addition of words (i.e., modulo- 2^32
+ addition). Let X <<< s denote the 32-bit value obtained by circularly
+ shifting (rotating) X left by s bit positions. Let not(X) denote the
+ bit-wise complement of X, and let X v Y denote the bit-wise OR of X
+ and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY
+ denote the bit-wise AND of X and Y.
+
+3. MD4 Algorithm Description
+
+ We begin by supposing that we have a b-bit message as input, and that
+ we wish to find its message digest. Here b is an arbitrary
+ nonnegative integer; b may be zero, it need not be a multiple of 8,
+ and it may be arbitrarily large. We imagine the bits of the message
+ written down as follows:
+
+ m_0 m_1 ... m_{b-1} .
+
+ The following five steps are performed to compute the message digest
+ of the message.
+
+ Step 1. Append padding bits
+
+ The message is "padded" (extended) so that its length (in bits)
+ is congruent to 448, modulo 512. That is, the message is
+ extended so that it is just 64 bits shy of being a multiple of
+ 512 bits long. Padding is always performed, even if the length
+ of the message is already congruent to 448, modulo 512 (in
+ which case 512 bits of padding are added).
+
+
+
+Rivest [Page 2]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ Padding is performed as follows: a single "1" bit is appended
+ to the message, and then enough zero bits are appended so that
+ the length in bits of the padded message becomes congruent to
+ 448, modulo 512.
+
+ Step 2. Append length
+
+ A 64-bit representation of b (the length of the message before
+ the padding bits were added) is appended to the result of the
+ previous step. In the unlikely event that b is greater than
+ 2^64, then only the low-order 64 bits of b are used. (These
+ bits are appended as two 32-bit words and appended low-order
+ word first in accordance with the previous conventions.)
+
+ At this point the resulting message (after padding with bits
+ and with b) has a length that is an exact multiple of 512 bits.
+ Equivalently, this message has a length that is an exact
+ multiple of 16 (32-bit) words. Let M[0 ... N-1] denote the
+ words of the resulting message, where N is a multiple of 16.
+
+ Step 3. Initialize MD buffer
+
+ A 4-word buffer (A,B,C,D) is used to compute the message
+ digest. Here each of A,B,C,D are 32-bit registers. These
+ registers are initialized to the following values in
+ hexadecimal, low-order bytes first):
+
+ word A: 01 23 45 67
+ word B: 89 ab cd ef
+ word C: fe dc ba 98
+ word D: 76 54 32 10
+
+ Step 4. Process message in 16-word blocks
+
+ We first define three auxiliary functions that each take
+ as input three 32-bit words and produce as output one
+ 32-bit word.
+
+ f(X,Y,Z) = XY v not(X)Z
+ g(X,Y,Z) = XY v XZ v YZ
+ h(X,Y,Z) = X xor Y xor Z
+
+ In each bit position f acts as a conditional: if x then y else
+ z. (The function f could have been defined using + instead of
+ v since XY and not(X)Z will never have 1's in the same bit
+ position.) In each bit position g acts as a majority function:
+ if at least two of x, y, z are on, then g has a one in that bit
+ position, else g has a zero. It is interesting to note that if
+
+
+
+Rivest [Page 3]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ the bits of X, Y, and Z are independent and unbiased, the each
+ bit of f(X,Y,Z) will be independent and unbiased, and similarly
+ each bit of g(X,Y,Z) will be independent and unbiased. The
+ function h is the bit-wise "xor" or "parity" function; it has
+ properties similar to those of f and g.
+
+ Do the following:
+
+ For i = 0 to N/16-1 do /* process each 16-word block */
+ For j = 0 to 15 do: /* copy block i into X */
+ Set X[j] to M[i*16+j].
+ end /* of loop on j */
+ Save A as AA, B as BB, C as CC, and D as DD.
+
+ [Round 1]
+ Let [A B C D i s] denote the operation
+ A = (A + f(B,C,D) + X[i]) <<< s .
+ Do the following 16 operations:
+ [A B C D 0 3]
+ [D A B C 1 7]
+ [C D A B 2 11]
+ [B C D A 3 19]
+ [A B C D 4 3]
+ [D A B C 5 7]
+ [C D A B 6 11]
+ [B C D A 7 19]
+ [A B C D 8 3]
+ [D A B C 9 7]
+ [C D A B 10 11]
+ [B C D A 11 19]
+ [A B C D 12 3]
+ [D A B C 13 7]
+ [C D A B 14 11]
+ [B C D A 15 19]
+
+ [Round 2]
+ Let [A B C D i s] denote the operation
+ A = (A + g(B,C,D) + X[i] + 5A827999) <<< s .
+ (The value 5A..99 is a hexadecimal 32-bit
+ constant, written with the high-order digit
+ first. This constant represents the square
+ root of 2. The octal value of this constant
+ is 013240474631. See Knuth, The Art of
+ Programming, Volume 2 (Seminumerical
+ Algorithms), Second Edition (1981),
+ Addison-Wesley. Table 2, page 660.)
+ Do the following 16 operations:
+ [A B C D 0 3]
+
+
+
+Rivest [Page 4]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ [D A B C 4 5]
+ [C D A B 8 9]
+ [B C D A 12 13]
+ [A B C D 1 3]
+ [D A B C 5 5]
+ [C D A B 9 9]
+ [B C D A 13 13]
+ [A B C D 2 3]
+ [D A B C 6 5]
+ [C D A B 10 9]
+ [B C D A 14 13]
+ [A B C D 3 3]
+ [D A B C 7 5]
+ [C D A B 11 9]
+ [B C D A 15 13]
+
+ [Round 3]
+ Let [A B C D i s] denote the operation
+ A = (A + h(B,C,D) + X[i] + 6ED9EBA1) <<< s .
+ (The value 6E..A1 is a hexadecimal 32-bit
+ constant, written with the high-order digit
+ first. This constant represents the square
+ root of 3. The octal value of this constant
+ is 015666365641. See Knuth, The Art of
+ Programming, Volume 2 (Seminumerical
+ Algorithms), Second Edition (1981),
+ Addison-Wesley. Table 2, page 660.)
+ Do the following 16 operations:
+ [A B C D 0 3]
+ [D A B C 8 9]
+ [C D A B 4 11]
+ [B C D A 12 15]
+ [A B C D 2 3]
+ [D A B C 10 9]
+ [C D A B 6 11]
+ [B C D A 14 15]
+ [A B C D 1 3]
+ [D A B C 9 9]
+ [C D A B 5 11]
+ [B C D A 13 15]
+ [A B C D 3 3]
+ [D A B C 11 9]
+ [C D A B 7 11]
+ [B C D A 15 15]
+
+ Then perform the following additions:
+ A = A + AA
+ B = B + BB
+
+
+
+Rivest [Page 5]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ C = C + CC
+ D = D + DD
+ (That is, each of the four registers is incremented by
+ the value it had before this block was started.)
+
+ end /* of loop on i */
+
+ Step 5. Output
+
+ The message digest produced as output is A,B,C,D. That is, we
+ begin with the low-order byte of A, and end with the high-order
+ byte of D.
+
+ This completes the description of MD4. A reference
+ implementation in C is given in the Appendix.
+
+4. Extensions
+
+ If more than 128 bits of output are required, then the following
+ procedure is recommended to obtain a 256-bit output. (There is no
+ provision made for obtaining more than 256 bits.)
+
+ Two copies of MD4 are run in parallel over the input. The first copy
+ is standard as described above. The second copy is modified as
+ follows.
+
+ The initial state of the second copy is:
+ word A: 00 11 22 33
+ word B: 44 55 66 77
+ word C: 88 99 aa bb
+ word D: cc dd ee ff
+
+ The magic constants in rounds 2 and 3 for the second copy of MD4 are
+ changed from sqrt(2) and sqrt(3) to cuberoot(2) and cuberoot(3):
+
+ Octal Hex
+ Round 2 constant 012050505746 50a28be6
+ Round 3 constant 013423350444 5c4dd124
+
+ Finally, after every 16-word block is processed (including the last
+ block), the values of the A registers in the two copies are
+ exchanged.
+
+ The final message digest is obtaining by appending the result of the
+ second copy of MD4 to the end of the result of the first copy of MD4.
+
+
+
+
+
+
+Rivest [Page 6]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+5. Summary
+
+ The MD4 message digest algorithm is simple to implement, and provides
+ a "fingerprint" or message digest of a message of arbitrary length.
+
+ It is conjectured that the difficulty of coming up with two messages
+ having the same message digest is on the order of 2^64 operations,
+ and that the difficulty of coming up with any message having a given
+ message digest is on the order of 2^128 operations. The MD4
+ algorithm has been carefully scrutinized for weaknesses. It is,
+ however, a relatively new algorithm and further security analysis is
+ of course justified, as is the case with any new proposal of this
+ sort. The level of security provided by MD4 should be sufficient for
+ implementing very high security hybrid digital signature schemes
+ based on MD4 and the RSA public-key cryptosystem.
+
+6. Acknowledgements
+
+ I'd like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle, and
+ Noam Nisan for numerous helpful comments and suggestions.
+
+APPENDIX - Reference Implementation
+
+This appendix contains the following files:
+
+ md4.h -- header file for using MD4 implementation
+ md4.c -- the source code for MD4 routines
+ md4driver.c -- a sample "user" routine
+ session -- sample results of running md4driver
+
+ /*
+ ** ********************************************************************
+ ** md4.h -- Header file for implementation of **
+ ** MD4 Message Digest Algorithm **
+ ** Updated: 2/13/90 by Ronald L. Rivest **
+ ** (C) 1990 RSA Data Security, Inc. **
+ ** ********************************************************************
+ */
+
+ /* MDstruct is the data structure for a message digest computation.
+ */
+ typedef struct {
+ unsigned int buffer[4]; /* Holds 4-word result of MD computation */
+ unsigned char count[8]; /* Number of bits processed so far */
+ unsigned int done; /* Nonzero means MD computation finished */
+ } MDstruct, *MDptr;
+
+ /* MDbegin(MD)
+
+
+
+Rivest [Page 7]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ ** Input: MD -- an MDptr
+ ** Initialize the MDstruct prepatory to doing a message digest
+ ** computation.
+ */
+ extern void MDbegin();
+
+ /* MDupdate(MD,X,count)
+ ** Input: MD -- an MDptr
+ ** X -- a pointer to an array of unsigned characters.
+ ** count -- the number of bits of X to use (an unsigned int).
+ ** Updates MD using the first "count" bits of X.
+ ** The array pointed to by X is not modified.
+ ** If count is not a multiple of 8, MDupdate uses high bits of
+ ** last byte.
+ ** This is the basic input routine for a user.
+ ** The routine terminates the MD computation when count < 512, so
+ ** every MD computation should end with one call to MDupdate with a
+ ** count less than 512. Zero is OK for a count.
+ */
+ extern void MDupdate();
+
+ /* MDprint(MD)
+ ** Input: MD -- an MDptr
+ ** Prints message digest buffer MD as 32 hexadecimal digits.
+ ** Order is from low-order byte of buffer[0] to high-order byte
+ ** of buffer[3].
+ ** Each byte is printed with high-order hexadecimal digit first.
+ */
+ extern void MDprint();
+
+ /*
+ ** End of md4.h
+ ****************************(cut)***********************************/
+
+ /*
+ ** ********************************************************************
+ ** md4.c -- Implementation of MD4 Message Digest Algorithm **
+ ** Updated: 2/16/90 by Ronald L. Rivest **
+ ** (C) 1990 RSA Data Security, Inc. **
+ ** ********************************************************************
+ */
+
+ /*
+ ** To use MD4:
+ ** -- Include md4.h in your program
+ ** -- Declare an MDstruct MD to hold the state of the digest
+ ** computation.
+ ** -- Initialize MD using MDbegin(&MD)
+
+
+
+Rivest [Page 8]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ ** -- For each full block (64 bytes) X you wish to process, call
+ ** MDupdate(&MD,X,512)
+ ** (512 is the number of bits in a full block.)
+ ** -- For the last block (less than 64 bytes) you wish to process,
+ ** MDupdate(&MD,X,n)
+ ** where n is the number of bits in the partial block. A partial
+ ** block terminates the computation, so every MD computation
+ ** should terminate by processing a partial block, even if it
+ ** has n = 0.
+ ** -- The message digest is available in MD.buffer[0] ...
+ ** MD.buffer[3]. (Least-significant byte of each word
+ ** should be output first.)
+ ** -- You can print out the digest using MDprint(&MD)
+ */
+
+ /* Implementation notes:
+ ** This implementation assumes that ints are 32-bit quantities.
+ ** If the machine stores the least-significant byte of an int in the
+ ** least-addressed byte (e.g., VAX and 8086), then LOWBYTEFIRST
+ ** should be set to TRUE. Otherwise (e.g., SUNS), LOWBYTEFIRST
+ ** should be set to FALSE. Note that on machines with LOWBYTEFIRST
+ ** FALSE the routine MDupdate modifies has a side-effect on its input
+ ** array (the order of bytes in each word are reversed). If this is
+ ** undesired a call to MDreverse(X) can reverse the bytes of X back
+ ** into order after each call to MDupdate.
+
+ */
+ #define TRUE 1
+ #define FALSE 0
+ #define LOWBYTEFIRST FALSE
+
+ /* Compile-time includes
+ */
+ #include <stdio.h>
+ #include "md4.h"
+
+ /* Compile-time declarations of MD4 "magic constants".
+ */
+ #define I0 0x67452301 /* Initial values for MD buffer */
+ #define I1 0xefcdab89
+ #define I2 0x98badcfe
+ #define I3 0x10325476
+ #define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
+ #define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
+ /* C2 and C3 are from Knuth, The Art of Programming, Volume 2
+ ** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
+ ** Table 2, page 660.
+ */
+
+
+
+Rivest [Page 9]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ #define fs1 3 /* round 1 shift amounts */
+ #define fs2 7
+ #define fs3 11
+ #define fs4 19
+ #define gs1 3 /* round 2 shift amounts */
+ #define gs2 5
+ #define gs3 9
+ #define gs4 13
+ #define hs1 3 /* round 3 shift amounts */
+ #define hs2 9
+ #define hs3 11
+ #define hs4 15
+
+ /* Compile-time macro declarations for MD4.
+ ** Note: The "rot" operator uses the variable "tmp".
+ ** It assumes tmp is declared as unsigned int, so that the >>
+ ** operator will shift in zeros rather than extending the sign bit.
+ */
+ #define f(X,Y,Z) ((X&Y) | ((~X)&Z))
+ #define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
+ #define h(X,Y,Z) (X^Y^Z)
+ #define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
+ #define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
+ #define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
+ #define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
+
+ /* MDprint(MDp)
+ ** Print message digest buffer MDp as 32 hexadecimal digits.
+ ** Order is from low-order byte of buffer[0] to high-order byte of
+ ** buffer[3].
+ ** Each byte is printed with high-order hexadecimal digit first.
+ ** This is a user-callable routine.
+ */
+ void
+ MDprint(MDp)
+ MDptr MDp;
+ { int i,j;
+ for (i=0;i<4;i++)
+ for (j=0;j<32;j=j+8)
+ printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
+ }
+
+ /* MDbegin(MDp)
+ ** Initialize message digest buffer MDp.
+ ** This is a user-callable routine.
+ */
+ void
+ MDbegin(MDp)
+
+
+
+Rivest [Page 10]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ MDptr MDp;
+ { int i;
+ MDp->buffer[0] = I0;
+ MDp->buffer[1] = I1;
+ MDp->buffer[2] = I2;
+ MDp->buffer[3] = I3;
+ for (i=0;i<8;i++) MDp->count[i] = 0;
+ MDp->done = 0;
+ }
+
+ /* MDreverse(X)
+ ** Reverse the byte-ordering of every int in X.
+ ** Assumes X is an array of 16 ints.
+ ** The macro revx reverses the byte-ordering of the next word of X.
+ */
+ #define revx { t = (*X << 16) | (*X >> 16); \
+ *X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); }
+ MDreverse(X)
+ unsigned int *X;
+ { register unsigned int t;
+ revx; revx; revx; revx; revx; revx; revx; revx;
+ revx; revx; revx; revx; revx; revx; revx; revx;
+ }
+
+ /* MDblock(MDp,X)
+ ** Update message digest buffer MDp->buffer using 16-word data block X.
+ ** Assumes all 16 words of X are full of data.
+ ** Does not update MDp->count.
+ ** This routine is not user-callable.
+ */
+ static void
+ MDblock(MDp,X)
+ MDptr MDp;
+ unsigned int *X;
+ {
+ register unsigned int tmp, A, B, C, D;
+ #if LOWBYTEFIRST == FALSE
+ MDreverse(X);
+ #endif
+ A = MDp->buffer[0];
+ B = MDp->buffer[1];
+ C = MDp->buffer[2];
+ D = MDp->buffer[3];
+ /* Update the message digest buffer */
+ ff(A , B , C , D , 0 , fs1); /* Round 1 */
+ ff(D , A , B , C , 1 , fs2);
+ ff(C , D , A , B , 2 , fs3);
+ ff(B , C , D , A , 3 , fs4);
+
+
+
+Rivest [Page 11]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ ff(A , B , C , D , 4 , fs1);
+ ff(D , A , B , C , 5 , fs2);
+ ff(C , D , A , B , 6 , fs3);
+ ff(B , C , D , A , 7 , fs4);
+ ff(A , B , C , D , 8 , fs1);
+ ff(D , A , B , C , 9 , fs2);
+ ff(C , D , A , B , 10 , fs3);
+ ff(B , C , D , A , 11 , fs4);
+ ff(A , B , C , D , 12 , fs1);
+ ff(D , A , B , C , 13 , fs2);
+ ff(C , D , A , B , 14 , fs3);
+ ff(B , C , D , A , 15 , fs4);
+ gg(A , B , C , D , 0 , gs1); /* Round 2 */
+ gg(D , A , B , C , 4 , gs2);
+ gg(C , D , A , B , 8 , gs3);
+ gg(B , C , D , A , 12 , gs4);
+ gg(A , B , C , D , 1 , gs1);
+ gg(D , A , B , C , 5 , gs2);
+ gg(C , D , A , B , 9 , gs3);
+ gg(B , C , D , A , 13 , gs4);
+ gg(A , B , C , D , 2 , gs1);
+ gg(D , A , B , C , 6 , gs2);
+ gg(C , D , A , B , 10 , gs3);
+ gg(B , C , D , A , 14 , gs4);
+ gg(A , B , C , D , 3 , gs1);
+ gg(D , A , B , C , 7 , gs2);
+ gg(C , D , A , B , 11 , gs3);
+ gg(B , C , D , A , 15 , gs4);
+ hh(A , B , C , D , 0 , hs1); /* Round 3 */
+ hh(D , A , B , C , 8 , hs2);
+ hh(C , D , A , B , 4 , hs3);
+ hh(B , C , D , A , 12 , hs4);
+ hh(A , B , C , D , 2 , hs1);
+ hh(D , A , B , C , 10 , hs2);
+ hh(C , D , A , B , 6 , hs3);
+ hh(B , C , D , A , 14 , hs4);
+ hh(A , B , C , D , 1 , hs1);
+ hh(D , A , B , C , 9 , hs2);
+ hh(C , D , A , B , 5 , hs3);
+ hh(B , C , D , A , 13 , hs4);
+ hh(A , B , C , D , 3 , hs1);
+ hh(D , A , B , C , 11 , hs2);
+ hh(C , D , A , B , 7 , hs3);
+ hh(B , C , D , A , 15 , hs4);
+ MDp->buffer[0] += A;
+ MDp->buffer[1] += B;
+ MDp->buffer[2] += C;
+ MDp->buffer[3] += D;
+
+
+
+Rivest [Page 12]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ }
+
+ /* MDupdate(MDp,X,count)
+ ** Input: MDp -- an MDptr
+ ** X -- a pointer to an array of unsigned characters.
+ ** count -- the number of bits of X to use.
+ ** (if not a multiple of 8, uses high bits of last byte.)
+ ** Update MDp using the number of bits of X given by count.
+ ** This is the basic input routine for an MD4 user.
+ ** The routine completes the MD computation when count < 512, so
+ ** every MD computation should end with one call to MDupdate with a
+ ** count less than 512. A call with count 0 will be ignored if the
+ ** MD has already been terminated (done != 0), so an extra call with
+ ** count 0 can be given as a "courtesy close" to force termination
+ ** if desired.
+ */
+ void
+ MDupdate(MDp,X,count)
+ MDptr MDp;
+ unsigned char *X;
+ unsigned int count;
+ { unsigned int i, tmp, bit, byte, mask;
+ unsigned char XX[64];
+ unsigned char *p;
+ /* return with no error if this is a courtesy close with count
+ ** zero and MDp->done is true.
+ */
+ if (count == 0 && MDp->done) return;
+ /* check to see if MD is already done and report error */
+ if (MDp->done)
+ { printf("\nError: MDupdate MD already done."); return; }
+ /* Add count to MDp->count */
+ tmp = count;
+ p = MDp->count;
+ while (tmp)
+ { tmp += *p;
+ *p++ = tmp;
+ tmp = tmp >> 8;
+ }
+ /* Process data */
+ if (count == 512)
+ { /* Full block of data to handle */
+ MDblock(MDp,(unsigned int *)X);
+ }
+ else if (count > 512) /* Check for count too large */
+ { printf("\nError: MDupdate called with illegal count value %d."
+ ,count);
+ return;
+
+
+
+Rivest [Page 13]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ }
+ else /* partial block -- must be last block so finish up */
+ { /* Find out how many bytes and residual bits there are */
+ byte = count >> 3;
+ bit = count & 7;
+ /* Copy X into XX since we need to modify it */
+ for (i=0;i<=byte;i++) XX[i] = X[i];
+ for (i=byte+1;i<64;i++) XX[i] = 0;
+ /* Add padding '1' bit and low-order zeros in last byte */
+ mask = 1 << (7 - bit);
+ XX[byte] = (XX[byte] | mask) & ~( mask - 1);
+ /* If room for bit count, finish up with this block */
+ if (byte <= 55)
+ { for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,(unsigned int *)XX);
+ }
+ else /* need to do two blocks to finish up */
+ { MDblock(MDp,(unsigned int *)XX);
+ for (i=0;i<56;i++) XX[i] = 0;
+ for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,(unsigned int *)XX);
+ }
+ /* Set flag saying we're done with MD computation */
+ MDp->done = 1;
+ }
+ }
+
+ /*
+ ** End of md4.c
+ ****************************(cut)***********************************/
+
+ /*
+ ** ********************************************************************
+ ** md4driver.c -- sample routines to test **
+ ** MD4 message digest algorithm. **
+ ** Updated: 2/16/90 by Ronald L. Rivest **
+ ** (C) 1990 RSA Data Security, Inc. **
+ ** ********************************************************************
+ */
+
+ #include <stdio.h>
+ #include "md4.h"
+
+ /* MDtimetrial()
+ ** A time trial routine, to measure the speed of MD4.
+ ** Measures speed for 1M blocks = 64M bytes.
+ */
+ MDtimetrial()
+
+
+
+Rivest [Page 14]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ { unsigned int X[16];
+ MDstruct MD;
+ int i;
+ double t;
+ for (i=0;i<16;i++) X[i] = 0x01234567 + i;
+ printf
+ ("MD4 time trial. Processing 1 million 64-character blocks...\n");
+ clock();
+ MDbegin(&MD);
+ for (i=0;i<1000000;i++) MDupdate(&MD,X,512);
+ MDupdate(&MD,X,0);
+ t = (double) clock(); /* in microseconds */
+ MDprint(&MD); printf(" is digest of 64M byte test input.\n");
+ printf("Seconds to process test input: %g\n,t/1e6);
+ printf("Characters processed per second: %ld.\n,(int)(64e12/t));
+ }
+
+ /* MDstring(s)
+ ** Computes the message digest for string s.
+ ** Prints out message digest, a space, the string (in quotes) and a
+ ** carriage return.
+ */
+ MDstring(s)
+ unsigned char *s;
+ { unsigned int i, len = strlen(s);
+ MDstruct MD;
+ MDbegin(&MD);
+ for (i=0;i+64<=len;i=i+64) MDupdate(&MD,s+i,512);
+ MDupdate(&MD,s+i,(len-i)*8);
+ MDprint(&MD);
+ printf(" \"%s\"\n",s);
+ }
+
+ /* MDfile(filename)
+ ** Computes the message digest for a specified file.
+ ** Prints out message digest, a space, the file name, and a
+ ** carriage return.
+ */
+ MDfile(filename)
+ char *filename;
+ { FILE *f = fopen(filename,"rb");
+ unsigned char X[64];
+ MDstruct MD;
+ int b;
+ if (f == NULL)
+ { printf("%s can't be opened.\n",filename); return; }
+ MDbegin(&MD);
+ while ((b=fread(X,1,64,f))!=0) MDupdate(&MD,X,b*8);
+
+
+
+Rivest [Page 15]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ MDupdate(&MD,X,0);
+ MDprint(&MD);
+ printf(" %s\n",filename);
+ fclose(f);
+ }
+
+ /* MDfilter()
+ ** Writes the message digest of the data from stdin onto stdout,
+ ** followed by a carriage return.
+ */
+ MDfilter()
+ { unsigned char X[64];
+ MDstruct MD;
+ int b;
+ MDbegin(&MD);
+ while ((b=fread(X,1,64,stdin))!=0) MDupdate(&MD,X,b*8);
+ MDupdate(&MD,X,0);
+ MDprint(&MD);
+ printf("\n");
+ }
+
+ /* MDtestsuite()
+ ** Run a standard suite of test data.
+ */
+ MDtestsuite()
+ {
+ printf("MD4 test suite results:\n");
+ MDstring("");
+ MDstring("a");
+ MDstring("abc");
+ MDstring("message digest");
+ MDstring("abcdefghijklmnopqrstuvwxyz");
+ MDstring
+ ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ MDfile("foo"); /* Contents of file foo are "abc" */
+ }
+
+ main(argc,argv)
+ int argc;
+ char *argv[];
+ { int i;
+ /* For each command line argument in turn:
+ ** filename -- prints message digest and name of file
+ ** -sstring -- prints message digest and contents of string
+ ** -t -- prints time trial statistics for 64M bytes
+ ** -x -- execute a standard suite of test data
+ ** (no args) -- writes messages digest of stdin onto stdout
+ */
+
+
+
+Rivest [Page 16]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ if (argc==1) MDfilter();
+ else
+ for (i=1;i<argc;i++)
+ if (argv[i][0]=='-' && argv[i][1]=='s') MDstring(argv[i]+2);
+ else if (strcmp(argv[i],"-t")==0) MDtimetrial();
+ else if (strcmp(argv[i],"-x")==0) MDtestsuite();
+ else MDfile(argv[i]);
+ }
+
+ /*
+ ** end of md4driver.c
+ ****************************(cut)***********************************/
+
+
+ --------------------------------------------------------------------
+ --- Sample session. Compiling and using MD4 on SUN Sparcstation ---
+ --------------------------------------------------------------------
+ >ls
+ total 66
+ -rw-rw-r-- 1 rivest 3 Feb 14 17:40 abcfile
+ -rwxrwxr-x 1 rivest 24576 Feb 17 12:28 md4
+ -rw-rw-r-- 1 rivest 9347 Feb 17 00:37 md4.c
+ -rw-rw-r-- 1 rivest 25150 Feb 17 12:25 md4.doc
+ -rw-rw-r-- 1 rivest 1844 Feb 16 21:21 md4.h
+ -rw-rw-r-- 1 rivest 3497 Feb 17 12:27 md4driver.c
+ >
+ >cc -o md4 -O4 md4.c md4driver.c
+ md4.c:
+ md4driver.c:
+ Linking:
+ >
+ >md4 -x
+ MD4 test suite results:
+ 31d6cfe0d16ae931b73c59d7e0c089c0 ""
+ bde52cb31de33e46245e05fbdbd6fb24 "a"
+ a448017aaf21d8525fc10ae87aa6729d "abc"
+ d9130a8164549fe818874806e1c7014b "message digest"
+ d79e1c308aa5bbcdeea8ed63df412da9 "abcdefghijklmnopqrstuvwxyz"
+ 043f8582f241db351ce627e153e7f0e4
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+ a448017aaf21d8525fc10ae87aa6729d abcfile
+ >
+ >md4 -sabc -shi
+ a448017aaf21d8525fc10ae87aa6729d "abc"
+ cfaee2512bd25eb033236f0cd054e308 "hi"
+ >
+ >md4 *
+ a448017aaf21d8525fc10ae87aa6729d abcfile
+
+
+
+Rivest [Page 17]
+\f
+RFC 1186 MD4 Message Digest Algorithm October 1990
+
+
+ d316f994da0e951cf9502928a1f73300 md4
+ 379adb39eada0dfdbbdfdcd0d9def8c4 md4.c
+ 9a3f73327c65954198b1f45a3aa12665 md4.doc
+ 37fe165ac177b461ff78b86d10e4ff33 md4.h
+ 7dcba2e2dc4d8f1408d08beb17dabb2a md4.o
+ 08790161bfddc6f5788b4353875cb1c3 md4driver.c
+ 1f84a7f690b0545d2d0480d5d3c26eea md4driver.o
+ >
+ >cat abcfile | md4
+ a448017aaf21d8525fc10ae87aa6729d
+ >
+ >md4 -t
+ MD4 time trial. Processing 1 million 64-character blocks...
+ 6325bf77e5891c7c0d8104b64cc6e9ef is digest of 64M byte test input.
+ Seconds to process test input: 44.0982
+ Characters processed per second: 1451305.
+ >
+ >
+ ------------------------ end of sample session --------------------
+
+ Note: A version of this document including the C source code is
+ available for FTP from THEORY.LSC.MIT.EDU in the file "md4.doc".
+
+Security Considerations
+
+ The level of security discussed in this memo by MD4 is considered to
+ be sufficient for implementing very high security hybrid digital
+ signature schemes based on MD4 and the RSA public-key cryptosystem.
+
+Author's Address
+
+ Ronald L. Rivest
+ Massachusetts Institute of Technology
+ Laboratory for Computer Science
+ NE43-324
+ 545 Technology Square
+ Cambridge, MA 02139-1986
+
+ Phone: (617) 253-5880
+
+ EMail: rivest@theory.lcs.mit.edu
+
+
+
+
+
+
+
+
+
+
+Rivest [Page 18]
+\f
\ No newline at end of file
--- /dev/null
+*** Note: This is a revised version of "md4.doc", obtained as "md4.doc"
+*** by anonymous ftp from theory.lcs.mit.edu. The original version is
+*** still available as "md4.doc.old". The MD4 algorithm is unchanged, but
+*** the newer version of the code is somewhat more portable, although slightly
+*** slower. [Ronald L. Rivest 1/13/91]
+\f
+Network Working Group R. Rivest
+Request for Comments: 1186B MIT Laboratory for Computer Science
+Updates: RFC 1186 S. Dusse
+ RSA Data Security, Inc.
+ 9 January 1991
+
+
+
+ The MD4 Message Digest Algorithm
+
+
+STATUS OF THIS MEMO
+
+ This RFC is the specification of the MD4 Digest Algorithm. If you
+ are going to implement MD4, it is suggested you do it this way. This
+ memo is for informational use and does not constitute a standard.
+ Distribution of this memo is unlimited.
+
+Table of Contents
+
+ 1. Executive Summary 1
+ 2. Terminology and Notation 2
+ 3. MD4 Algorithm Description 2
+ 4. Extensions 6
+ 5. Summary 6
+ 6. Acknowledgements 7
+ Security Considerations 7
+ References 7
+ APPENDIX - Reference Implementation 7
+
+1. Executive Summary
+
+ This note describes the MD4 message digest algorithm. The algorithm
+ takes as input an input message of arbitrary length and produces as
+ output a 128-bit "fingerprint" or "message digest" of the input. It
+ is conjectured that it is computationally infeasible to produce two
+ messages having the same message digest, or to produce any message
+ having a given prespecified target message digest. The MD4 algorithm
+ is thus ideal for digital signature applications, where a large file
+ must be "compressed" in a secure manner before being signed with the
+ RSA public-key cryptosystem.
+
+ The MD4 algorithm is designed to be quite fast on 32-bit machines.
+ In addition, the MD4 algorithm does not require any large
+ substitution tables; the algorithm can be coded quite compactly.
+
+ The MD4 algorithm is being placed in the public domain for review and
+ possible adoption as a standard.
+
+ This RFC is a revision of the October 1990 RFC 1186. The main
+ difference is that the reference implementation of MD4 in the
+ appendix is more portable.
+
+
+Rivest [Page 1]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+2. Terminology and Notation
+
+ In this note a "word" is a 32-bit quantity and a byte is an 8-bit
+ quantity. A sequence of bits can be interpreted in a natural manner
+ as a sequence of bytes, where each consecutive group of 8 bits is
+ interpreted as a byte with the high-order (most significant) bit of
+ each byte listed first. Similarly, a sequence of bytes can be
+ interpreted as a sequence of 32-bit words, where each consecutive
+ group of 4 bytes is interpreted as a word with the low-order (least
+ significant) byte given first.
+
+ Let x_i denote "x sub i". If the subscript is an expression, we
+ surround it in braces, as in x_{i+1}. Similarly, we use ^ for
+ superscripts (exponentiation), so that x^i denotes x to the i-th
+ power.
+
+ Let the symbol "+" denote addition of words (i.e., modulo- 2^32
+ addition). Let X <<< s denote the 32-bit value obtained by
+ circularly shifting (rotating) X left by s bit positions. Let not(X)
+ denote the bit-wise complement of X, and let X v Y denote the bit-
+ wise OR of X and Y. Let X xor Y denote the bit-wise XOR of X and Y,
+ and let XY denote the bit-wise AND of X and Y.
+
+
+3. MD4 Algorithm Description
+
+ We begin by supposing that we have a b-bit message as input, and that
+ we wish to find its message digest. Here b is an arbitrary
+ nonnegative integer; b may be zero, it need not be a multiple of 8,
+ and it may be arbitrarily large. We imagine the bits of the message
+ written down as follows:
+
+ m_0 m_1 ... m_{b-1} .
+
+ The following five steps are performed to compute the message digest
+ of the message.
+
+
+3.1 Step 1. Append padding bits
+
+ The message is "padded" (extended) so that its length (in bits) is
+ congruent to 448, modulo 512. That is, the message is extended so
+ that it is just 64 bits shy of being a multiple of 512 bits long.
+ Padding is always performed, even if the length of the message is
+ already congruent to 448, modulo 512 (in which case 512 bits of
+ padding are added).
+
+ Padding is performed as follows: a single "1" bit is appended to the
+ message, and then enough zero bits are appended so that the length in
+ bits of the padded message becomes congruent to 448, modulo 512.
+
+
+
+
+Rivest [Page 2]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+3.2 Step 2. Append length
+
+ A 64-bit representation of b (the length of the message before the
+ padding bits were added) is appended to the result of the previous
+ step. In the unlikely event that b is greater than 2^64, then only
+ the low-order 64 bits of b are used. (These bits are appended as two
+ 32-bit words and appended low-order word first in accordance with the
+ previous conventions.)
+
+ At this point the resulting message (after padding with bits and with
+ b) has a length that is an exact multiple of 512 bits. Equivalently,
+ this message has a length that is an exact multiple of 16 (32-bit)
+ words. Let M[0 ... N-1] denote the words of the resulting message,
+ where N is a multiple of 16.
+
+
+3.3 Step 3. Initialize MD buffer
+
+ A 4-word buffer (A,B,C,D) is used to compute the message digest.
+ Here each of A,B,C,D are 32-bit registers. These registers are
+ initialized to the following values in hexadecimal, low-order bytes
+ first):
+
+ word A: 01 23 45 67
+ word B: 89 ab cd ef
+ word C: fe dc ba 98
+ word D: 76 54 32 10
+
+
+3.4 Step 4. Process message in 16-word blocks
+
+ We first define three auxiliary functions that each take as input
+ three 32-bit words and produce as output one 32-bit word.
+
+ f(X,Y,Z) = XY v not(X)Z
+ g(X,Y,Z) = XY v XZ v YZ
+ h(X,Y,Z) = X xor Y xor Z
+
+ In each bit position f acts as a conditional: if x then y else z.
+ (The function f could have been defined using + instead of v since XY
+ and not(X)Z will never have 1's in the same bit position.) In each
+ bit position g acts as a majority function: if at least two of x, y,
+ z are on, then g has a one in that bit position, else g has a zero.
+ It is interesting to note that if the bits of X, Y, and Z are
+ independent and unbiased, the each bit of f(X,Y,Z) will be
+ independent and unbiased, and similarly each bit of g(X,Y,Z) will be
+ independent and unbiased. The function h is the bit-wise "xor" or
+ "parity" function; it has properties similar to those of f and g.
+
+ Do the following:
+
+ For i = 0 to N/16-1 do: /* process each 16-word block */
+ For j = 0 to 15 do: /* copy block i into X */
+ Set X[j] to M[i*16+j].
+Rivest [Page 3]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+ end /* of loop on j */
+ Save A as AA, B as BB, C as CC, and D as DD.
+
+ [Round 1]
+ Let [A B C D i s] denote the operation
+ A = (A + f(B,C,D) + X[i]) <<< s .
+
+ Do the following 16 operations:
+ [A B C D 0 3]
+ [D A B C 1 7]
+ [C D A B 2 11]
+ [B C D A 3 19]
+ [A B C D 4 3]
+ [D A B C 5 7]
+ [C D A B 6 11]
+ [B C D A 7 19]
+ [A B C D 8 3]
+ [D A B C 9 7]
+ [C D A B 10 11]
+ [B C D A 11 19]
+ [A B C D 12 3]
+ [D A B C 13 7]
+ [C D A B 14 11]
+ [B C D A 15 19]
+
+ [Round 2]
+ Let [A B C D i s] denote the operation
+ A = (A + g(B,C,D) + X[i] + 5A827999) <<< s .
+
+ (The value 5A..99 is a hexadecimal 32-bit
+ constant, written with the high-order digit
+ first. This constant represents the square
+ root of 2. The octal value of this constant
+ is 013240474631. See Knuth, The Art of
+ Programming, Volume 2 (Seminumerical
+ Algorithms), Second Edition (1981),
+ Addison-Wesley. Table 2, page 660.)
+
+ Do the following 16 operations:
+ [A B C D 0 3]
+ [D A B C 4 5]
+ [C D A B 8 9]
+ [B C D A 12 13]
+ [A B C D 1 3]
+ [D A B C 5 5]
+ [C D A B 9 9]
+ [B C D A 13 13]
+ [A B C D 2 3]
+ [D A B C 6 5]
+ [C D A B 10 9]
+ [B C D A 14 13]
+ [A B C D 3 3]
+ [D A B C 7 5]
+ [C D A B 11 9]
+Rivest [Page 4] [B C D A 15 13]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+
+ [Round 3]
+ Let [A B C D i s] denote the operation
+ A = (A + h(B,C,D) + X[i] + 6ED9EBA1) <<< s .
+
+ (The value 6E..A1 is a hexadecimal 32-bit
+ constant, written with the high-order digit
+ first. This constant represents the square
+ root of 3. The octal value of this constant
+ is 015666365641. See Knuth, The Art of
+ Programming, Volume 2 (Seminumerical
+ Algorithms), Second Edition (1981),
+ Addison-Wesley. Table 2, page 660.)
+
+ Do the following 16 operations:
+ [A B C D 0 3]
+ [D A B C 8 9]
+ [C D A B 4 11]
+ [B C D A 12 15]
+ [A B C D 2 3]
+ [D A B C 10 9]
+ [C D A B 6 11]
+ [B C D A 14 15]
+ [A B C D 1 3]
+ [D A B C 9 9]
+ [C D A B 5 11]
+ [B C D A 13 15]
+ [A B C D 3 3]
+ [D A B C 11 9]
+ [C D A B 7 11]
+ [B C D A 15 15]
+
+ Then perform the following additions:
+ A = A + AA
+ B = B + BB
+ C = C + CC
+ D = D + DD
+
+ (That is, each of the four registers is
+ incremented by the value it had before
+ this block was started.)
+
+ end /* of loop on i */
+
+
+3.5 Step 5. Output
+
+ The message digest produced as output is A,B,C,D. That is, we begin
+ with the low-order byte of A, and end with the high-order byte of D.
+
+ This completes the description of MD4. A reference implementation in
+ C is given in the Appendix.
+
+
+Rivest [Page 5]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+4. Extensions
+
+ If more than 128 bits of output are required, then the following
+ procedure is recommended to obtain a 256-bit output. (There is no
+ provision made for obtaining more than 256 bits.)
+
+ Two copies of MD4 are run in parallel over the input. The first copy
+ is standard as described above. The second copy is modified as
+ follows.
+
+ The initial state of the second copy is:
+
+ word A: 00 11 22 33
+ word B: 44 55 66 77
+ word C: 88 99 aa bb
+ word D: cc dd ee ff
+
+ The magic constants in rounds 2 and 3 for the second copy of MD4 are
+ changed from sqrt(2) and sqrt(3) to cuberoot(2) and cuberoot(3):
+
+ Octal Hex
+ Round 2 constant 012050505746 50a28be6
+ Round 3 constant 013423350444 5c4dd124
+
+ Finally, after every 16-word block is processed (including the last
+ block), the values of the A registers in the two copies are
+ exchanged.
+
+ The final message digest is obtaining by appending the result of the
+ second copy of MD4 to the end of the result of the first copy of MD4.
+
+
+5. Summary
+
+ The MD4 message digest algorithm is simple to implement, and provides
+ a "fingerprint" or message digest of a message of arbitrary length.
+ It is conjectured that the difficulty of coming up with two messages
+ having the same message digest is on the order of 2^64 operations,
+ and that the difficulty of coming up with any message having a given
+ message digest is on the order of 2^128 operations. The MD4
+ algorithm has been carefully scrutinized for weaknesses. It is,
+ however, a relatively new algorithm and further security analysis is
+ of course justified, as is the case with any new proposal of this
+ sort. The level of security provided by MD4 should be sufficient for
+ implementing very high security hybrid digital signature schemes
+ based on MD4 and the RSA public-key cryptosystem.
+
+
+6. Acknowledgements
+
+ We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle,
+ and Noam Nisan for numerous helpful comments and suggestions.
+
+
+Rivest [Page 6]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+Security Considerations
+
+ The level of security discussed in this memo by MD4 is considered to
+ be sufficient for implementing very high security hybrid digital
+ signature schemes based on MD4 and the RSA public-key cryptosystem.
+
+
+Authors' Addresses
+
+ Ronald L. Rivest
+ Massachusetts Institute of Technology
+ Laboratory for Computer Science
+ NE43-324
+ 545 Technology Square
+ Cambridge, MA 02139-1986
+ Phone: (617) 253-5880
+ EMail: rivest@theory.lcs.mit.edu
+
+ Steve Dusse
+ RSA Data Security, Inc.
+ 10 Twin Dolphin Dr.
+ Redwood City, CA 94065
+ Phone: (415) 595-8782
+ EMail: dusse@rsa.com
+
+
+References
+
+ [1] Rivest, R.L. The MD4 message digest algorithm. Presented at
+ CRYPTO '90 (Santa Barbara, CA, August 11-15, 1990).
+
+
+APPENDIX - Reference Implementation
+
+ This appendix contains the following files:
+
+ md4.h -- header file for using MD4 implementation
+
+ md4.c -- the source code for MD4 routines
+
+ md4driver.c -- a sample "user" routine
+
+ session -- sample results of running md4driver
+
+ The implementation of MD4 given in this appendix differs from the one
+ given in [1] and again in RFC 1186. The main difference is that this
+ version should compile and run correctly on more platforms than the
+ other ones. We have sacrificed performance for portability. MD4
+ speeds given in [1] and RFC 1186 are not necessarily the same as
+ those one might obtain with this reference implementation. However,
+ it is not difficult to improve this implementation on particular
+ platforms, an exercise left to the reader. Following are some
+ suggestions:
+
+Rivest [Page 7]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+ 1. Change MD4Block so that the context is not used at all if
+ it is empty (mdi == 0) and 64 or more bytes remain (inLen
+ >= 64). In other words, call Transform with inBuf in this
+ case. (This requires that byte ordering is correct in
+ inBuf.)
+
+ 2. Implement a procedure MD4BlockLong modeled after MD4Block
+ where inBuf is UINT4 * instead of unsigned char *.
+ MD4BlockLong would call Transform directly with 16 word
+ blocks from inBuf. Call this instead of MD4Block in
+ general. This works well if you have an I/O procedure that
+ can read long words from a file.
+
+ 3. On "little-endian" platforms where the lowest-address byte
+ in a long word is the least significant (and there are no
+ alignment restrictions), change MD4Block to call Transform
+ directly with 64-byte blocks from inBuf (casted to a UINT4
+ *).
+
+/*
+ **********************************************************************
+ ** md4.h -- Header file for implementation of MD4 **
+ ** RSA Data Security, Inc. MD4 Message Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
+ **********************************************************************
+ */
+
+/*
+ **********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** License to copy and use this software is granted provided that **
+ ** it is identified as the "RSA Data Security, Inc. MD4 Message **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function. **
+ ** **
+ ** License is also granted to make and use derivative works **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD4 Message Digest Algorithm" in all **
+ ** material mentioning or referencing the derived work. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ **********************************************************************
+ */
+
+/* typedef a 32 bit type */
+typedef unsigned long int UINT4;
+Rivest [Page 8]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+
+/* Data structure for MD4 (Message Digest) computation */
+typedef struct {
+ UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
+ UINT4 buf[4]; /* scratch buffer */
+ unsigned char in[64]; /* input buffer */
+ unsigned char digest[16]; /* actual digest after MD4Final call */
+} MD4_CTX;
+
+void MD4Init ();
+void MD4Update ();
+void MD4Final ();
+
+/*
+ **********************************************************************
+ ** End of md4.h **
+ ******************************* (cut) ********************************
+ */
+
+/*
+ **********************************************************************
+ ** md4.c **
+ ** RSA Data Security, Inc. MD4 Message Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version **
+ **********************************************************************
+ */
+
+/*
+ **********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** License to copy and use this software is granted provided that **
+ ** it is identified as the "RSA Data Security, Inc. MD4 Message **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function. **
+ ** **
+ ** License is also granted to make and use derivative works **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD4 Message Digest Algorithm" in all **
+ ** material mentioning or referencing the derived work. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ **********************************************************************
+ */
+
+#include "md4.h"
+
+Rivest [Page 9]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+/* forward declaration */
+static void Transform ();
+
+static unsigned char PADDING[64] = {
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* F, G and H are basic MD4 functions: selection, majority, parity */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are MD4 transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s) \
+ {(a) += F ((b), (c), (d)) + (x); \
+ (a) = ROTATE_LEFT ((a), (s));}
+#define GG(a, b, c, d, x, s) \
+ {(a) += G ((b), (c), (d)) + (x) + (UINT4)013240474631; \
+ (a) = ROTATE_LEFT ((a), (s));}
+#define HH(a, b, c, d, x, s) \
+ {(a) += H ((b), (c), (d)) + (x) + (UINT4)015666365641; \
+ (a) = ROTATE_LEFT ((a), (s));}
+
+void MD4Init (mdContext)
+MD4_CTX *mdContext;
+{
+ mdContext->i[0] = mdContext->i[1] = (UINT4)0;
+
+ /* Load magic initialization constants.
+ */
+ mdContext->buf[0] = (UINT4)0x67452301;
+ mdContext->buf[1] = (UINT4)0xefcdab89;
+ mdContext->buf[2] = (UINT4)0x98badcfe;
+ mdContext->buf[3] = (UINT4)0x10325476;
+}
+
+void MD4Update (mdContext, inBuf, inLen)
+MD4_CTX *mdContext;
+unsigned char *inBuf;
+unsigned int inLen;
+{
+ UINT4 in[16];
+ int mdi;
+Rivest [Page 10]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+ unsigned int i, ii;
+
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+ /* update number of bits */
+ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
+ mdContext->i[1]++;
+ mdContext->i[0] += ((UINT4)inLen << 3);
+ mdContext->i[1] += ((UINT4)inLen >> 29);
+
+ while (inLen--) {
+ /* add new character to buffer, increment mdi */
+ mdContext->in[mdi++] = *inBuf++;
+
+ /* transform if necessary */
+ if (mdi == 0x40) {
+ for (i = 0, ii = 0; i < 16; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+ mdi = 0;
+ }
+ }
+}
+
+void MD4Final (mdContext)
+MD4_CTX *mdContext;
+{
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
+ unsigned int padLen;
+
+ /* save number of bits */
+ in[14] = mdContext->i[0];
+ in[15] = mdContext->i[1];
+
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+ /* pad out to 56 mod 64 */
+ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+ MD4Update (mdContext, PADDING, padLen);
+
+ /* append length in bits and transform */
+ for (i = 0, ii = 0; i < 14; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+Rivest [Page 11]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+
+ /* store buffer in digest */
+ for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+ mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+ mdContext->digest[ii+1] =
+ (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+ mdContext->digest[ii+2] =
+ (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+ mdContext->digest[ii+3] =
+ (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+ }
+}
+
+/* Basic MD4 step. Transform buf based on in.
+ */
+static void Transform (buf, in)
+UINT4 *buf;
+UINT4 *in;
+{
+ UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+ /* Round 1 */
+ FF (a, b, c, d, in[ 0], 3);
+ FF (d, a, b, c, in[ 1], 7);
+ FF (c, d, a, b, in[ 2], 11);
+ FF (b, c, d, a, in[ 3], 19);
+ FF (a, b, c, d, in[ 4], 3);
+ FF (d, a, b, c, in[ 5], 7);
+ FF (c, d, a, b, in[ 6], 11);
+ FF (b, c, d, a, in[ 7], 19);
+ FF (a, b, c, d, in[ 8], 3);
+ FF (d, a, b, c, in[ 9], 7);
+ FF (c, d, a, b, in[10], 11);
+ FF (b, c, d, a, in[11], 19);
+ FF (a, b, c, d, in[12], 3);
+ FF (d, a, b, c, in[13], 7);
+ FF (c, d, a, b, in[14], 11);
+ FF (b, c, d, a, in[15], 19);
+
+ /* Round 2 */
+ GG (a, b, c, d, in[ 0], 3);
+ GG (d, a, b, c, in[ 4], 5);
+ GG (c, d, a, b, in[ 8], 9);
+ GG (b, c, d, a, in[12], 13);
+ GG (a, b, c, d, in[ 1], 3);
+ GG (d, a, b, c, in[ 5], 5);
+ GG (c, d, a, b, in[ 9], 9);
+ GG (b, c, d, a, in[13], 13);
+ GG (a, b, c, d, in[ 2], 3);
+ GG (d, a, b, c, in[ 6], 5);
+ GG (c, d, a, b, in[10], 9);
+ GG (b, c, d, a, in[14], 13);
+ GG (a, b, c, d, in[ 3], 3);
+ GG (d, a, b, c, in[ 7], 5);
+Rivest [Page 12]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+ GG (c, d, a, b, in[11], 9);
+ GG (b, c, d, a, in[15], 13);
+
+ /* Round 3 */
+ HH (a, b, c, d, in[ 0], 3);
+ HH (d, a, b, c, in[ 8], 9);
+ HH (c, d, a, b, in[ 4], 11);
+ HH (b, c, d, a, in[12], 15);
+ HH (a, b, c, d, in[ 2], 3);
+ HH (d, a, b, c, in[10], 9);
+ HH (c, d, a, b, in[ 6], 11);
+ HH (b, c, d, a, in[14], 15);
+ HH (a, b, c, d, in[ 1], 3);
+ HH (d, a, b, c, in[ 9], 9);
+ HH (c, d, a, b, in[ 5], 11);
+ HH (b, c, d, a, in[13], 15);
+ HH (a, b, c, d, in[ 3], 3);
+ HH (d, a, b, c, in[11], 9);
+ HH (c, d, a, b, in[ 7], 11);
+ HH (b, c, d, a, in[15], 15);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*
+ **********************************************************************
+ ** End of md4.c **
+ ******************************* (cut) ********************************
+ */
+
+/*
+ **********************************************************************
+ ** md4driver.c -- sample routines to test **
+ ** RSA Data Security, Inc. MD4 message digest algorithm. **
+ ** Created: 2/16/90 RLR **
+ ** Updated: 1/91 SRD **
+ **********************************************************************
+ */
+
+/*
+ **********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ **********************************************************************
+Rivest [Page 13]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <time.h>
+#include <string.h>
+#include "md4.h"
+
+/* Prints message digest buffer in mdContext as 32 hexadecimal digits.
+ Order is from low-order byte to high-order byte of digest.
+ Each byte is printed with high-order hexadecimal digit first.
+ */
+static void MDPrint (mdContext)
+MD4_CTX *mdContext;
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ printf ("%02x", mdContext->digest[i]);
+}
+
+/* size of test block */
+#define TEST_BLOCK_SIZE 1000
+
+/* number of blocks to process */
+#define TEST_BLOCKS 2000
+
+/* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */
+static long TEST_BYTES = (long)TEST_BLOCK_SIZE * (long)TEST_BLOCKS;
+
+/* A time trial routine, to measure the speed of MD4.
+ Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE
+ characters.
+ */
+static void MDTimeTrial ()
+{
+ MD4_CTX mdContext;
+ time_t endTime, startTime;
+ unsigned char data[TEST_BLOCK_SIZE];
+ unsigned int i;
+
+ /* initialize test data */
+ for (i = 0; i < TEST_BLOCK_SIZE; i++)
+ data[i] = (unsigned char)(i & 0xFF);
+
+ /* start timer */
+ printf ("MD4 time trial. Processing %ld characters...\n", TEST_BYTES);
+ time (&startTime);
+
+ /* digest data in TEST_BLOCK_SIZE byte blocks */
+ MD4Init (&mdContext);
+ for (i = TEST_BLOCKS; i > 0; i--)
+ MD4Update (&mdContext, data, TEST_BLOCK_SIZE);
+ MD4Final (&mdContext);
+Rivest [Page 14]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+
+ /* stop timer, get time difference */
+ time (&endTime);
+ MDPrint (&mdContext);
+ printf (" is digest of test input.\n");
+ printf
+ ("Seconds to process test input: %ld\n", (long)(endTime-startTime));
+ printf
+ ("Characters processed per second: %ld\n",
+ TEST_BYTES/(endTime-startTime));
+}
+
+/* Computes the message digest for string inString.
+ Prints out message digest, a space, the string (in quotes) and a
+ carriage return.
+ */
+static void MDString (inString)
+char *inString;
+{
+ MD4_CTX mdContext;
+ unsigned int len = strlen (inString);
+
+ MD4Init (&mdContext);
+ MD4Update (&mdContext, inString, len);
+ MD4Final (&mdContext);
+ MDPrint (&mdContext);
+ printf (" \"%s\"\n\n", inString);
+}
+
+/* Computes the message digest for a specified file.
+ Prints out message digest, a space, the file name, and a carriage
+ return.
+ */
+static void MDFile (filename)
+char *filename;
+{
+ FILE *inFile = fopen (filename, "rb");
+ MD4_CTX mdContext;
+ int bytes;
+ unsigned char data[1024];
+
+ if (inFile == NULL) {
+ printf ("%s can't be opened.\n", filename);
+ return;
+ }
+
+ MD4Init (&mdContext);
+ while ((bytes = fread (data, 1, 1024, inFile)) != 0)
+ MD4Update (&mdContext, data, bytes);
+ MD4Final (&mdContext);
+ MDPrint (&mdContext);
+ printf (" %s\n", filename);
+ fclose (inFile);
+}
+Rivest [Page 15]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+
+/* Writes the message digest of the data from stdin onto stdout,
+ followed by a carriage return.
+ */
+static void MDFilter ()
+{
+ MD4_CTX mdContext;
+ int bytes;
+ unsigned char data[16];
+
+ MD4Init (&mdContext);
+ while ((bytes = fread (data, 1, 16, stdin)) != 0)
+ MD4Update (&mdContext, data, bytes);
+ MD4Final (&mdContext);
+ MDPrint (&mdContext);
+ printf ("\n");
+}
+
+/* Runs a standard suite of test data.
+ */
+static void MDTestSuite ()
+{
+ printf ("MD4 test suite results:\n\n");
+ MDString ("");
+ MDString ("a");
+ MDString ("abc");
+ MDString ("message digest");
+ MDString ("abcdefghijklmnopqrstuvwxyz");
+ MDString
+ ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ MDString
+ ("1234567890123456789012345678901234567890\
+1234567890123456789012345678901234567890");
+ /* Contents of file foo are "abc" */
+ MDFile ("foo");
+}
+
+void main (argc, argv)
+int argc;
+char *argv[];
+{
+ int i;
+
+ /* For each command line argument in turn:
+ ** filename -- prints message digest and name of file
+ ** -sstring -- prints message digest and contents of string
+ ** -t -- prints time trial statistics for 1M characters
+ ** -x -- execute a standard suite of test data
+ ** (no args) -- writes messages digest of stdin onto stdout
+ */
+ if (argc == 1)
+ MDFilter ();
+ else
+ for (i = 1; i < argc; i++)
+Rivest [Page 16]\f
+
+
+RFC 1186B The MD4 Message Digest Algorithm 9 January 1991
+
+
+
+ if (argv[i][0] == '-' && argv[i][1] == 's')
+ MDString (argv[i] + 2);
+ else if (strcmp (argv[i], "-t") == 0)
+ MDTimeTrial ();
+ else if (strcmp (argv[i], "-x") == 0)
+ MDTestSuite ();
+ else MDFile (argv[i]);
+}
+
+/*
+ **********************************************************************
+ ** End of md4driver.c **
+ ******************************* (cut) ********************************
+ */
+
+-----------------------------------------------------------------------
+-- Sample session output obtained by running md4driver test suite --
+-----------------------------------------------------------------------
+
+ MD4 test suite results:
+
+ 31d6cfe0d16ae931b73c59d7e0c089c0 ""
+
+ bde52cb31de33e46245e05fbdbd6fb24 "a"
+
+ a448017aaf21d8525fc10ae87aa6729d "abc"
+
+ d9130a8164549fe818874806e1c7014b "message digest"
+
+ d79e1c308aa5bbcdeea8ed63df412da9 "abcdefghijklmnopqrstuvwxyz"
+
+ 043f8582f241db351ce627e153e7f0e4 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghij
+ klmnopqrstuvwxyz0123456789"
+
+ e33b4ddc9c38f2199c3e7b164fcc0536 "123456789012345678901234567890123456
+ 78901234567890123456789012345678901234567890"
+
+ a448017aaf21d8525fc10ae87aa6729d foo
+
+
+-----------------------------------------------------------------------
+-- End of sample session --
+-------------------------------- (cut) --------------------------------
+
+
+ Note: A version of this document including the C source code is
+ available for FTP from RSA.COM in the file "md4.doc".
+
+
+
+
+
+
+
+Rivest [Page 17]\f
+
+
+
+\1f
--- /dev/null
+mit_des_cbc_cksum
+mit_des_ecb_encrypt
+mit_des_cbc_checksum
+mit_des_cryptosystem_entry
+mit_des_cbc_cksumtable_entry
+krb5_des_cst_entry
+mit_des_cbc_encrypt
+mit_des_encrypt_func
+mit_des_decrypt_func
+mit_des_finish_key
+mit_des_finish_random_key
+mit_des_init_random_key
+mit_des_process_key
+mit_des_random_key
+mit_des_string_to_key
+mit_des_fixup_key_parity
+mit_des_check_key_parity
+mit_des_key_sched
+mit_des_new_random_key
+mit_des_init_random_number_generator
+mit_des_set_random_generator_seed
+mit_des_set_sequence_number
+mit_des_generate_random_block
+mit_des_is_weak_key
+rsa_md4_cksumtable_entry
+rsa_md4_des_cksumtable_entry
+rsa_md5_cksumtable_entry
+rsa_md5_des_cksumtable_entry
+crc32_cksumtable_entry
--- /dev/null
+des_cbc_cksum
+des_ecb_encrypt
+des_cbc_encrypt
+des_fixup_key_parity
+des_check_key_parity
+des_key_sched
+des_new_random_key
+des_init_random_number_generator
+des_set_random_generator_seed
+des_set_sequence_number
+des_generate_random_block
+des_pcbc_encrypt
+des_quad_cksum
+des_random_key
+des_read_password
+des_string_to_key
+des_is_weak_key
--- /dev/null
+krb5_kdb_encrypt_key
+krb5_kdb_decrypt_key
+krb5_db_init
+krb5_db_fini
+krb5_db_open_database
+krb5_db_close_database
+krb5_db_set_name
+krb5_db_get_age
+krb5_db_lock
+krb5_db_unlock
+krb5_db_create
+kdb5_db_destroy
+krb5_db_rename
+krb5_db_get_principal
+krb5_db_free_principal
+krb5_db_put_principal
+krb5_db_delete_principal
+krb5_db_iterate
+krb5_db_set_lockmode
+krb5_db_verify_master_key
+krb5_mkey_pwd_prompt1
+krb5_mkey_pwd_prompt2
+krb5_db_fetch_mkey
+krb5_db_setup_mkey_name
+krb5_db_store_mkey
+
--- /dev/null
+krb5_cc_register
+krb5_cc_resolve
+krb5_cc_default
+krb5_cc_dfl_ops
+krb5_config_file
+krb5_trans_file
+krb5_defkeyname
+krb5_lname_file
+krb5_max_dgram_size
+krb5_max_skdc_timeout
+krb5_skdc_timeout_shift
+krb5_skdc_timeout_1
+krb5_kdc_udp_portname
+krb5_default_pwd_prompt1
+krb5_default_pwd_prompt2
+krb5_init_ets
+krb5_ticket2KRB5_Ticket
+krb5_tgs_rep2KRB5_KDC__REP
+krb5_kdc_req2KRB5_KDC__REQ__BODY
+krb5_kdc_req2KRB5_KDC__REQ
+krb5_transited2KRB5_TransitedEncoding
+krb5_safe2KRB5_KRB__SAFE
+krb5_priv2KRB5_KRB__PRIV
+krb5_principal2KRB5_PrincipalName
+krb5_priv_enc_part2KRB5_EncKrbPrivPart
+krb5_pa_data2KRB5_PA__DATA
+krb5_last_req2KRB5_LastReq
+krb5_keyblock2KRB5_EncryptionKey
+krb5_kdc_rep2KRB5_KDC__REP
+krb5_enc_tkt_part2KRB5_EncTicketPart
+krb5_error2KRB5_KRB__ERROR
+krb5_enc_kdc_rep_part2KRB5_EncKDCRepPart
+krb5_enc_data2KRB5_EncryptedData
+krb5_checksum2KRB5_Checksum
+krb5_authenticator2KRB5_Authenticator
+krb5_ap_rep_enc_part2KRB5_EncAPRepPart
+krb5_ap_req2KRB5_AP__REQ
+krb5_ap_rep2KRB5_AP__REP
+krb5_addr2KRB5_HostAddress
+krb5_address2KRB5_HostAddresses
+krb5_authdata2KRB5_AuthorizationData
+krb5_flags2KRB5_TicketFlags
+krb5_decode_generic
+krb5_encode_generic
+krb5_fcc_close_file
+krb5_fcc_open_file
+krb5_fcc_interpret
+krb5_cc_file_ops
+krb5_fcc_set_flags
+krb5_fcc_write
+krb5_fcc_store_principal
+krb5_fcc_store_addrs
+krb5_fcc_store_keyblock
+krb5_fcc_store_addr
+krb5_fcc_store_data
+krb5_fcc_store_int32
+krb5_fcc_store_ui_2
+krb5_fcc_store_keytype
+krb5_fcc_store_int
+krb5_fcc_store_bool
+krb5_fcc_store_times
+krb5_fcc_store_flags
+krb5_fcc_store_authdata
+krb5_fcc_store_authdatum
+krb5_fcc_ops
+krb5_fcc_skip_principal
+krb5_fcc_store
+krb5_fcc_start_seq_get
+krb5_fcc_retrieve
+krb5_fcc_resolve
+krb5_fcc_read
+krb5_fcc_read_principal
+krb5_fcc_read_addrs
+krb5_fcc_read_keyblock
+krb5_fcc_read_data
+krb5_fcc_read_addr
+krb5_fcc_read_int32
+krb5_fcc_read_ui_2
+krb5_fcc_read_keytype
+krb5_fcc_read_int
+krb5_fcc_read_bool
+krb5_fcc_read_times
+krb5_fcc_read_flags
+krb5_fcc_read_authdata
+krb5_fcc_read_authdatum
+krb5_fcc_next_cred
+krb5_fcc_initialize
+krb5_fcc_get_principal
+krb5_fcc_get_name
+krb5_fcc_generate_new
+krb5_fcc_end_seq_get
+krb5_fcc_destroy
+krb5_fcc_close
+krb5_scc_interpret
+krb5_cc_stdio_ops
+krb5_scc_set_flags
+krb5_scc_write
+krb5_scc_store_principal
+krb5_scc_store_addrs
+krb5_scc_store_keyblock
+krb5_scc_store_addr
+krb5_scc_store_data
+krb5_scc_store_int32
+krb5_scc_store_ui_2
+krb5_scc_store_keytype
+krb5_scc_store_int
+krb5_scc_store_bool
+krb5_scc_store_times
+krb5_scc_store_flags
+krb5_scc_store_authdata
+krb5_scc_store_authdatum
+krb5_scc_ops
+krb5_scc_skip_principal
+krb5_scc_store
+krb5_scc_start_seq_get
+krb5_scc_retrieve
+krb5_scc_resolve
+krb5_scc_read
+krb5_scc_read_principal
+krb5_scc_read_addrs
+krb5_scc_read_keyblock
+krb5_scc_read_data
+krb5_scc_read_addr
+krb5_scc_read_int32
+krb5_scc_read_ui_2
+krb5_scc_read_keytype
+krb5_scc_read_int
+krb5_scc_read_bool
+krb5_scc_read_times
+krb5_scc_read_flags
+krb5_scc_read_authdata
+krb5_scc_read_authdatum
+krb5_scc_next_cred
+krb5_scc_initialize
+krb5_scc_get_principal
+krb5_scc_get_name
+krb5_scc_generate_new
+krb5_scc_end_seq_get
+krb5_scc_destroy
+krb5_scc_close
+krb5_kt_dfl_ops
+krb5_ktfile_wresolve
+krb5_ktf_writable_ops
+krb5_ktf_ops
+krb5_ktfileint_openr
+krb5_ktfileint_openw
+krb5_ktfileint_close
+krb5_ktfileint_read_entry
+krb5_ktfileint_write_entry
+krb5_ktfile_start_seq_get
+krb5_ktfile_remove
+krb5_ktfile_resolve
+krb5_ktfile_get_next
+krb5_ktfile_get_name
+krb5_ktfile_get_entry
+krb5_ktfile_end_get
+krb5_ktfile_close
+krb5_ktfile_add
+krb5_kt_read_service_key
+krb5_kt_remove_entry
+krb5_kt_free_entry
+krb5_kt_default
+krb5_kt_register
+krb5_kt_resolve
+krb5_kt_add_entry
+krb5_walk_realm_tree
+krb5_unparse_name_ext
+krb5_unparse_name
+krb5_tgtname
+krb5_get_server_rcache
+krb5_send_tgs
+krb5_sendauth
+krb5_recvauth
+krb5_rd_safe
+krb5_rd_req_decoded
+krb5_rd_req_simple
+krb5_rd_req
+krb5_rd_rep
+krb5_rd_priv
+krb5_rd_error
+krb5_principal_compare
+krb5_principal2salt
+krb5_parse_name
+krb5_mk_safe
+krb5_mk_req_extended
+krb5_mk_req
+krb5_mk_rep
+krb5_mk_priv
+krb5_mk_error
+krb5_clockskew
+krb5_kdc_req_sumtype
+krb5_kdc_default_options
+krb5_kdc_rep_decrypt_proc
+krb5_get_in_tkt_with_skey
+krb5_get_in_tkt_with_password
+krb5_get_in_tkt
+krb5_get_credentials
+krb5_generate_subkey
+krb5_generate_seq_number
+krb5_get_cred_via_2tgt
+krb5_get_cred_via_tgt
+krb5_get_cred_from_kdc
+krb5_fulladdr_order
+krb5_free_realm_tree
+krb5_encrypt_tkt_part
+krb5_encode_kdc_rep
+krb5_decrypt_tkt_part
+krb5_decode_kdc_rep
+krb5_copy_keyblock_contents
+krb5_copy_ticket
+krb5_copy_principal
+krb5_copy_keyblock
+krb5_copy_data
+krb5_copy_creds
+krb5_copy_checksum
+krb5_copy_authenticator
+krb5_copy_authdata
+krb5_copy_addresses
+krb5_build_principal_va
+krb5_build_principal
+krb5_build_principal_ext
+krb5_address_search
+krb5_address_order
+krb5_address_compare
+krb5_auth_to_rep
+krb5_rc_dfl_ops
+krb5_rc_io_creat
+krb5_rc_io_open
+krb5_rc_io_move
+krb5_rc_io_write
+krb5_rc_io_read
+krb5_rc_io_close
+krb5_rc_io_destroy
+krb5_rc_io_mark
+krb5_rc_io_unmark
+krb5_rc_dfl_get_name
+krb5_rc_dfl_get_span
+krb5_rc_dfl_init
+krb5_rc_dfl_close
+krb5_rc_dfl_destroy
+krb5_rc_dfl_resolve
+krb5_rc_dfl_recover
+krb5_rc_dfl_store
+krb5_rc_dfl_expunge
+krb5_rc_register_type
+krb5_rc_resolve_type
+krb5_rc_get_type
+krb5_rc_default_type
+krb5_rc_default_name
+krb5_rc_default
+krb5_rc_resolve_full
+krb5_free_tkt_authent
+krb5_free_tgt_creds
+krb5_free_tickets
+krb5_free_ticket
+krb5_free_safe
+krb5_free_priv_enc_part
+krb5_free_priv
+krb5_free_principal
+krb5_free_pa_data
+krb5_free_last_req
+krb5_free_keyblock
+krb5_free_kdc_req
+krb5_free_kdc_rep
+krb5_free_error
+krb5_free_enc_tkt_part
+krb5_free_enc_kdc_rep_part
+krb5_free_cred_contents
+krb5_free_creds
+krb5_free_checksum
+krb5_free_authenticator
+krb5_free_authdata
+krb5_free_ap_rep_enc_part
+krb5_free_ap_req
+krb5_free_ap_rep
+krb5_free_addresses
+krb5_free_address
+krb5_write_message
+krb5_us_timeofday
+krb5_unlock_file
+krb5_timeofday
+krb5_sname_to_principal
+krb5_sendto_kdc
+krb5_read_password
+krb5_read_message
+krb5_random_confounder
+krb5_unpack_full_ipaddr
+krb5_net_write
+krb5_net_read
+krb5_lock_file
+krb5_locate_kdc
+krb5_os_localaddr
+krb5_kuserok
+krb5_kt_default_name
+krb5_get_host_realm
+krb5_gen_replay_name
+krb5_gen_portaddr
+krb5_get_krbhst
+krb5_make_full_ipaddr
+krb5_free_host_realm
+krb5_free_krbhst
+krb5_cc_default_name
+krb5_get_default_realm
+krb5_aname_to_localname
+krb5_csarray
+krb5_max_cryptosystem
+krb5_keytype_array
+krb5_max_keytype
+krb5_cksumarray
+krb5_max_cksum
+krb5_scc_close_file
+krb5_scc_open_file
--- /dev/null
+#include <krb5/krb5.h>
+
+krb5_data string_list[3] = {
+{11, "FOO.MIT.EDU"},
+{6, "jtkohl"},
+};
+
+krb5_data *princ[] = {&string_list[0], &string_list[1], 0};
+
+krb5_data string_list2[3] = {
+{11, "FOO.MIT.EDU"},
+{4, "rcmd"},
+{13, "lycus.mit.edu"},
+};
+
+krb5_data *princ2[] = {&string_list2[0], &string_list2[1], &string_list2[2], 0};
+
+krb5_last_req_entry lrentries[] = { {32000, 1}, {0, 3}, {10, 2} };
+krb5_last_req_entry *lrfoo1[] = {&lrentries[0], &lrentries[1], &lrentries[2], 0};
--- /dev/null
+WARNING! The contents of this directory are Alpha-test quality at
+best. The definition of the GSS API is still in flux, and this code
+has not really been tested due to a lack of an implementation to link
+against.
+
+Look in doc/gss/* for more information.
+
+
--- /dev/null
+# $Source$
+# $Author$
+# $Id$
+#
+# Copyright 1991 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# For copying and distribution information, please see the file
+# <krb5/copyright.h>.
+#
+
+ DEPLIBS = ../libgssapi.a $(DEPKLIB)
+LOCAL_LIBRARIES = ../libgssapi.a $(KLIB)
+ DEFINES = -DDEBUG
+
+SRCS = flogin.c fcmd.c flogind.c fsh.c fcp.c login.c logutil.c
+OBJS = flogin.o fcmd.o flogind.o fsh.o fcp.o login.o logutil.o
+
+FLOGINSRCS = flogin.c fcmd.c
+FLOGINOBJS = flogin.o fcmd.o
+
+LOGINSRCS = login.c logutil.c
+LOGINOBJS = login.o logutil.o
+
+FLOGINDSRCS = flogind.c logutil.c
+FLOGINDOBJS = flogind.o logutil.o
+
+FSHSRCS = fsh.c fcmd.c
+FSHOBJS = fsh.o fcmd.o
+
+FSHDSRCS = fshd.c
+FSHDOBJS = fshd.o
+
+FCPSRCS = fcp.c fcmd.c
+FCPOBJS = fcp.o fcmd.o
+
+all:: flogin login.gssapi flogind
+
+NormalProgramTarget(flogin,$(FLOGINOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),)
+NormalProgramTarget(login.gssapi,$(LOGINOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),)
+NormalProgramTarget(flogind,$(FLOGINDOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),)
+NormalProgramTarget(fsh,$(FSHOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),)
+NormalProgramTarget(fshd,$(FSHDOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),)
+NormalProgramTarget(fcp,$(FCPOBJS),$(DEPLIBS),$(LOCAL_LIBRARIES),)
+
+SaberProgramTarget(flogin, $(FLOGINSRCS), $(FLOGINOBJS),
+ $(DEPLIBS) $(LOCAL_LIBRARIES),)
+SaberProgramTarget(login.gssapi, $(LOGINSRCS), $(LOGINOBJS),
+ $(DEPLIBS) $(LOCAL_LIBRARIES),)
+SaberProgramTarget(flogind, $(FLOGINDSRCS), $(FLOGINDOBJS),
+ $(DEPLIBS) $(LOCAL_LIBRARIES),)
+SaberProgramTarget(fsh, $(FSHSRCS), $(FSHOBJS),
+ $(DEPLIBS) $(LOCAL_LIBRARIES),)
+SaberProgramTarget(fshd, $(FSHDSRCS), $(FSHDOBJS),
+ $(DEPLIBS) $(LOCAL_LIBRARIES),)
+SaberProgramTarget(fcp, $(FCPSRCS), $(FCPOBJS),
+ $(DEPLIBS) $(LOCAL_LIBRARIES),)
+
+DependTarget()
--- /dev/null
+Received: by E40-PO.MIT.EDU (5.45/4.7) id AA17675; Fri, 24 May 91 14:58:47 EDT
+Received: from uucp-gw-1.pa.dec.com by ATHENA.MIT.EDU with SMTP
+ id AA18573; Fri, 24 May 91 14:58:33 EDT
+Received: by uucp-gw-1.pa.dec.com; id AA01785; Fri, 24 May 91 11:56:31 -0700
+Received: by sejour.lkg.dec.com (5.57/Ultrix4.0)
+ id AA15569; Fri, 24 May 91 15:00:01 -0400
+Message-Id: <9105241900.AA15569@sejour.lkg.dec.com>
+To: tytso@ATHENA.MIT.EDU
+Cc: kannan@sejour.lkg.dec.com
+Subject: GSS API for SPX ready for testing
+Date: Fri, 24 May 91 15:00:00 EDT
+From: kannan@sejour.lkg.dec.com
+
+Ted,
+
+I have completed the initial implementation of the GSS API for the SPX
+mechanism and I've modified the flogin program to use this new
+interface. My "standard" GSS library includes the following routines:
+
+/*
+ * Offering "standard" GSS API for following mechanism(s) : SPX
+ *
+ * Supported jacket routines :
+ *
+ * gss_acquire_cred Assume a global identity
+ *
+ * gss_release_cred Discard credentials
+ *
+ * gss_init_sec_context Initiate a security context with a
+ * peer application
+ *
+ * gss_accept_sec_context Accept a security context from a
+ * peer application
+ *
+ * gss_display_status Convert an API status code to text
+ *
+ * gss_indicate_mechs Determine underlying mechanism
+ *
+ * gss_display_name Convert opaque name to text
+ *
+ * gss_import_name Convert a textual name to API-format
+ *
+ * gss_release_name Deallocate API internal name
+ *
+ * gss_release_buffer Deallocate a buffer descriptor
+ *
+ * gss_release_oid_set Deallocate a set of object identifiers
+ *
+ * Unofficial jacket routines :
+ *
+ * gss__stash_default_cred Bind credential handle as default
+ *
+ * gss__check_authorization Check authorization rights for principal
+ *
+ */
+
+As you can tell, I have two unofficial routines referred to as "gss__"
+instead of "gss_".
+
+The first, gss__stash_default_cred will set the specified credential as
+the default for a process. After calling this routine, GSS_C_NULL_CREDENTIAL
+can be used by the calling application to reference the stashed credentials.
+Note, if GSS_C_NULL_CREDENTIAL is passed to this routine, success is returned.
+
+/*
+ * WARNING: UNOFFICIAL GSSAPI ROUTINE!!
+ *
+ * gss__stash_default_cred() - Allows remote peer to bind delegated credential
+ * handle with remote application. Called by applications to set the
+ * delegated credentials as the default credentials for a process.
+ *
+ * OM_uint32 *minor_status (output) - mechanism specific status code
+ * gss_cred_id_t delegated_cred_handle (input) - handle for credentials
+ * received from context initiator.
+ *
+ */
+
+The second, gss__check_authorization is a bit more controversial. This
+routine will check access rights for a principal against an ACL file.
+I've added a few additional arguments to make this routine more robust
+so that access control decisions can be based on a per service and
+possible per resource basis.
+
+/*
+ * WARNING: UNOFFICIAL GSSAPI ROUTINE!!
+ *
+ * gss__check_authorization() - Check authorization rights for principal
+ * using the ACL file specified.
+ *
+ * OM_uint32 *minor_status (output) - mechanism specific status code
+ * gss_buffer_t fullname_buffer (input) - principal's printable name
+ * gss_buffer_t luser_buffer (input) - local user name
+ * gss_buffer_t acl_file_buffer (input) - acl file name
+ * gss_buffer_t service_buffer (input) - service name
+ * int access_mode (input) - type of access (rwx, etc.)
+ * gss_buffer_t resource_buffer (input) - resource name
+ *
+ */
+
+I've also defined 3 unofficial constants to describe the access modes.
+
+#define GSS_C_READ (1 << 0)
+#define GSS_C_WRITE (1 << 1)
+#define GSS_C_EXECUTE (1 << 2)
+
+You look at the application source code to see how these routines are
+being used. The next message will contain the following files:
+
+ - Makefile, flogin.c fcmd.c flogind.c login.c
+
+Talk to you later.
+
+ -kannan
+
--- /dev/null
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.51 89/12/12 12:37:30 jim Exp $
+
+# $Source$
+# $Author$
+# $Id$
+#
+
+###########################################################################
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.002934>
+# $XConsortium: Imake.tmpl,v 1.77 89/12/18 17:01:37 jim Exp $
+#
+# Platform-specific parameters may be set in the appropriate .cf
+# configuration files. Site-wide parameters may be set in the file
+# site.def. Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor doesn't define any unique symbols, you'll need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make Makefile", "make Makefiles", or "make World").
+#
+# If you absolutely can't get imake to work, you'll need to set the
+# variables at the top of each Makefile as well as the dependencies at the
+# bottom (makedepend will do this automatically).
+#
+
+###########################################################################
+# platform-specific configuration parameters - edit vaxbsd.cf to change
+
+# $Source$
+# $Author$
+# $Id$
+#
+
+###########################################################################
+# site-specific configuration parameters - edit site.def to change
+
+# $Source$
+# $Author$
+# $Id$
+#
+
+# site: $XConsortium: site.def,v 1.21 89/12/06 11:46:50 jim Exp $
+
+ SHELL = /bin/sh
+
+ TOP = ../../../.
+ CURRENT_DIR = ./lib/gssapi/sample
+
+ AR = ar cq
+ BOOTSTRAPCFLAGS =
+ CC = gcc -fstrength-reduce -fpcc-struct-return -pedantic -ansi -Wall -Dunix -Dvax
+
+ COMPRESS = compress
+ CPP = /lib/cpp $(STD_CPP_DEFINES)
+ PREPROCESSCMD = gcc -fstrength-reduce -fpcc-struct-return -pedantic -ansi -Wall -Dunix -Dvax -E $(STD_CPP_DEFINES)
+ INSTALL = install
+ LD = ld
+ LDLOCATIONS =
+ LINT = lint
+ LINTLIBFLAG = -C
+ LINTOPTS = -axz
+ LN = ln -s
+ MAKE = make
+ MV = mv
+ CP = cp
+ RANLIB = ranlib
+ RANLIBINSTFLAGS =
+ RM = rm -f
+ STD_INCLUDES =
+ STD_CPP_DEFINES =
+ STD_DEFINES =
+ SABER_DEFINES = -I/mit/gnu/vaxlib/gcc-include -Dconst=
+ EXTRA_LOAD_FLAGS = -Z
+ EXTRA_LIBRARIES =
+ TAGS = ctags
+ ETAGS = etags
+STDC_TOP_INCLUDES = -I$(TOP)/include/stdc-incl
+
+ SIGNAL_DEFINES = -DSIGNALRETURNSINT
+
+ INSTPGMFLAGS = -s
+
+ INSTSCRFLAGS =
+ INSTBINFLAGS = -m 0755
+ INSTUIDFLAGS = -o root -m 4755
+ INSTLIBFLAGS = -m 0664
+ INSTINCFLAGS = -m 0444
+ INSTMANFLAGS = -m 0444
+ INSTDATFLAGS = -m 0444
+ INSTKMEMFLAGS = -o root -m 4755
+
+ DESTDIR =
+
+ TOP_INCLUDES = -I$(TOP)
+
+ CDEBUGFLAGS = -O
+ CCOPTIONS =
+ COMPATFLAGS =
+
+ ALLINCLUDES = $(INCLUDES) $(STD_INCLUDES) $(TOP_INCLUDES) $(EXTRA_INCLUDES)
+ ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(DEFINES) $(COMPATFLAGS)
+ CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+ LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+ LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+ LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LDLOCATIONS)
+ LDCOMBINEFLAGS = -X -r
+ MDFLAGS = -D__STDC__ -I/mit/gnu/vaxlib/gcc-include
+
+ MACROFILE = vaxbsd.cf
+ RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+ IMAKE_DEFINES =
+
+ IRULESRC = $(CONFIGSRC)
+
+ IMAKE_CMD = $(IMAKE) -I$(NEWTOP)$(IRULESRC) $(IMAKE_DEFINES)
+
+ ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+ $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+ $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# Kerberos version 5 Build Parameters
+#
+# $Source$
+# $Author$
+# $Id$
+
+P_TERMIOS=-UHasPosixTermiosTrue
+
+P_FLOCKS=-UHasPosixFileLocksTrue
+
+P_TYPES=-UHasPosixTypesTrue
+
+P_SIGTYPE=-UHasVoidSignalReturnTrue
+
+P_STRINGH=-DHasStringHTrue
+
+P_BITSIZE=-DBitsize32 -UBitsize16 -UBitsize64
+
+P_DBM=-DHasNdbmTrue
+
+P_INET=-DHasInetTrue
+
+P_STDLIBH=-UHasStdlibHTrue -UForceStdlibH
+
+P_TIME_DEFS=-DUseSysTimeH -UUseTimeH
+
+P_PROTOS=-UProvidePrototypes
+
+P_NPROTO=-UUseNarrowPrototypes
+
+P_STDARG=-UUseStdarg
+
+ ARADD = ar cruv
+ TOP_INCLUDES = -I$(TOP)/include $(STDC_TOP_INCLUDES)
+ CONFIGSRC = $(TOP)/config
+ ISODE = /mit/isode/isode-6.8
+ PSYFLAGS = -f -h0 -a -s
+ PEPSY = $(ISODE)/@sys/bin/pepsy
+ TOUCH = touch
+ IMAKE = imake
+ DEPEND = makedepend
+ UNIFDEF = unifdef
+ HESDEFS = -DHESIOD
+ HESLIBS = -lhesiod
+
+ PROCESS_DEFINES = $(P_TERMIOS) $(P_FLOCKS) $(P_TYPES) $(P_SIGTYPE) $(P_STRINGH) $(P_BITSIZE) $(P_DBM) $(P_INET) $(P_STDLIBH) $(P_TIME_DEFS) $(P_PROTOS) $(P_NPROTO) $(P_STDARG) -DUnifdefRan
+ DESDEFINES = -DBIG -DLSBFIRST
+ TOPLIBD = $(TOP)/lib
+ OSLIB = os
+ OSDEPLIB = $(TOPLIBD)/libos.a
+ DESLIB = des5
+ DESDEPLIB = $(TOPLIBD)/libdes5.a
+ RSAMD4LIB = md4
+ RSAMD4DEPLIB = $(TOPLIBD)/libmd4.a
+ KRB5LIB = krb5
+ KRB5DEPLIB = $(TOPLIBD)/libkrb5.a
+ CRCLIB = crc32
+ CRCDEPLIB = $(TOPLIBD)/libcrc32.a
+ ISODELIB = -L/mit/isode/isode-6.8/@sys/lib -lisode
+
+ DBMLIB =
+ DEPKLIB = $(KRB5DEPLIB) $(DESDEPLIB) $(OSDEPLIB)
+ KLIBLOC = -L$(TOPLIBD)
+ KLIB = $(KLIBLOC) -l$(KRB5LIB) -l$(DESLIB) -l$(OSLIB) $(ISODELIB) $(COMERRLIB) $(DBMLIB)
+ KDBDEPLIB = $(TOPLIBD)/libkdb.a
+ KDBLIB = $(KLIBLOC) -lkdb
+ KRB425DEPLIB = $(TOPLIBD)/libkrb425.a
+ KRB425LIB = krb425
+ DES425DEPLIB = $(TOPLIBD)/libdes425.a
+ DES425LIB = des425
+ KRB4LIB = -lkrb $(KLIBLOC) -l$(DES425LIB)
+ KRB4INCLUDES = -I$(TOP)/include/kerberosIV
+ KRB4DEPLIB = $(DES425DEPLIB)
+
+ SSLIB = -lss
+ MK_CMDS = mk_cmds
+ COMERRLIB = -lcom_err
+ COMPILE_ET = compile_et
+
+ ADMIN_BINDIR = /krb5/admin
+ ADMIN_MANSUFFIX = 8
+ ADMIN_MANDIR = /krb5/man/man8
+ SERVER_BINDIR = /krb5/sbin
+ SERVER_MANSUFFIX = 8
+ SERVER_MANDIR = /krb5/man/man8
+ CLIENT_BINDIR = /krb5/bin
+ CLIENT_MANSUFFIX = 1
+ CLIENT_MANDIR = /krb5/man/man1
+
+# $Source$
+# $Author$
+# $Id$
+#
+
+###########################################################################
+# Imake rules for building libraries, programs, scripts, and data files
+# rules: $XConsortium: Imake.rules,v 1.67 89/12/18 17:14:15 jim Exp $
+
+###########################################################################
+# start of Imakefile
+
+# $Source$
+# $Author$
+# $Id$
+#
+# Copyright 1991 by the Massachusetts Institute of Technology.
+# All Rights Reserved.
+#
+# For copying and distribution information, please see the file
+# <krb5/copyright.h>.
+#
+
+ DEPLIBS = $(DEPKLIB) ../libgssapi.a
+LOCAL_LIBRARIES = $(KLIB) ../libgssapi.a
+ DEFINES = -DDEBUG
+
+SRCS = flogin.c fcmd.c flogind.c fsh.c fcp.c login.c logutil.c
+OBJS = flogin.o fcmd.o flogind.o fsh.o fcp.o login.o logutil.o
+
+FLOGINSRCS = flogin.c fcmd.c
+FLOGINOBJS = flogin.o fcmd.o
+
+LOGINSRCS = login.c logutil.c
+LOGINOBJS = login.o logutil.o
+
+FLOGINDSRCS = flogind.c logutil.c
+FLOGINDOBJS = flogind.o logutil.o
+
+FSHSRCS = fsh.c fcmd.c
+FSHOBJS = fsh.o fcmd.o
+
+FSHDSRCS = fshd.c
+FSHDOBJS = fshd.o
+
+FCPSRCS = fcp.c fcmd.c
+FCPOBJS = fcp.o fcmd.o
+
+all:: flogin login.gssapi flogind
+
+flogin: $(FLOGINOBJS) $(DEPLIBS)
+ $(RM) $@
+ $(CC) -o $@ $(FLOGINOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
+
+clean::
+ $(RM) flogin
+
+login.gssapi: $(LOGINOBJS) $(DEPLIBS)
+ $(RM) $@
+ $(CC) -o $@ $(LOGINOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
+
+clean::
+ $(RM) login.gssapi
+
+flogind: $(FLOGINDOBJS) $(DEPLIBS)
+ $(RM) $@
+ $(CC) -o $@ $(FLOGINDOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
+
+clean::
+ $(RM) flogind
+
+fsh: $(FSHOBJS) $(DEPLIBS)
+ $(RM) $@
+ $(CC) -o $@ $(FSHOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
+
+clean::
+ $(RM) fsh
+
+fshd: $(FSHDOBJS) $(DEPLIBS)
+ $(RM) $@
+ $(CC) -o $@ $(FSHDOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
+
+clean::
+ $(RM) fshd
+
+fcp: $(FCPOBJS) $(DEPLIBS)
+ $(RM) $@
+ $(CC) -o $@ $(FCPOBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
+
+clean::
+ $(RM) fcp
+
+saber_flogin:
+ #load $(ALLDEFINES) $(FLOGINSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+osaber_flogin:
+ #load $(ALLDEFINES) $(FLOGINOBJS)
+ $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+saber_login.gssapi:
+ #load $(ALLDEFINES) $(LOGINSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+osaber_login.gssapi:
+ #load $(ALLDEFINES) $(LOGINOBJS)
+ $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+saber_flogind:
+ #load $(ALLDEFINES) $(FLOGINDSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+osaber_flogind:
+ #load $(ALLDEFINES) $(FLOGINDOBJS)
+ $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+saber_fsh:
+ #load $(ALLDEFINES) $(FSHSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+osaber_fsh:
+ #load $(ALLDEFINES) $(FSHOBJS)
+ $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+saber_fshd:
+ #load $(ALLDEFINES) $(FSHDSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+osaber_fshd:
+ #load $(ALLDEFINES) $(FSHDOBJS)
+ $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+saber_fcp:
+ #load $(ALLDEFINES) $(FCPSRCS) $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+osaber_fcp:
+ #load $(ALLDEFINES) $(FCPOBJS)
+ $(DEPLIBS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+SRCS=$(SERVERSRCS) $(CLIENTSRCS)
+
+depend::
+ $(DEPEND) -s "# DO NOT DELETE" -- $(ALLDEFINES) $(MDFLAGS) -- $(SRCS)
+
+###########################################################################
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+ $(RM_CMD) \#*
+
+Makefile:: Imakefile
+ $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR) -s Makefile.new
+ $(MAKE) -f Makefile.new noop
+ -@if [ -f Makefile ]; then \
+ echo "$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
+ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+ fi
+ $(MV) Makefile.new Makefile
+
+noop::
+
+tags::
+ $(TAGS) -w *.[ch]
+ $(ETAGS) *.[ch]
+
+saber:
+ #load $(ALLDEFINES) $(SABER_DEFINES) $(SRCS)
+ #setopt load_flags $(ALLDEFINES) $(SABER_DEFINES)
+
+osaber:
+ #load $(ALLDEFINES) $(OBJS)
+
+###########################################################################
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+ @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+ @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+###########################################################################
+# dependencies generated by makedepend
+
+# DO NOT DELETE
--- /dev/null
+BABYL OPTIONS:
+Version: 5
+Labels:
+Note: This is the header of an rmail file.
+Note: If you are seeing it in rmail,
+Note: it means the file has no messages in it.
+\1f\f
+1,,
+Received: by E40-PO.MIT.EDU (5.45/4.7) id AA21631; Fri, 31 May 91 18:18:51 EDT
+Received: from uucp-gw-1.pa.dec.com by ATHENA.MIT.EDU with SMTP
+ id AA27178; Fri, 31 May 91 18:16:24 EDT
+Received: by uucp-gw-1.pa.dec.com; id AA17698; Fri, 31 May 91 10:48:08 -0700
+Received: by sejour.lkg.dec.com (5.57/Ultrix4.0)
+ id AA11377; Fri, 31 May 91 13:51:46 -0400
+Message-Id: <9105311751.AA11377@sejour.lkg.dec.com>
+To: tytso@ATHENA.MIT.EDU
+Cc: kannan@sejour.lkg.dec.com
+Subject: Re: testing GSS API
+In-Reply-To: Your message of Thu, 30 May 91 18:25:28 -0400.
+ <9105302225.AA24140@tsx-11.MIT.EDU>
+Date: Fri, 31 May 91 13:51:44 EDT
+From: kannan@sejour.lkg.dec.com
+
+*** EOOH ***
+To: tytso@ATHENA.MIT.EDU
+Cc: kannan@sejour.lkg.dec.com
+Subject: Re: testing GSS API
+In-Reply-To: Your message of Thu, 30 May 91 18:25:28 -0400.
+ <9105302225.AA24140@tsx-11.MIT.EDU>
+Date: Fri, 31 May 91 13:51:44 EDT
+From: kannan@sejour.lkg.dec.com
+
+Here is the new rlogin code. BTW, it is also being distributed with
+the SPX v2.1 kit.
+
+I'm sending you the following files:
+
+ Makefile, flogin.c, flogind.c, and login.c
+
+> The real test is whether or not the application runs.
+
+I agree. Does this mean that you will implement the "unofficial" GSS API
+routines used in the flogin code?
+
+ -kannan
+
+========== Makefile ======================
+
+===================== flogin.c ========================
+
+===================== flogind.c ================
+
+===================== login.c ======================
+\1f
\ No newline at end of file
--- /dev/null
+/* KITEST-MASTER.C */
+/* */
+/* Program to build GSSAPI-compliant Kerberos authentication packets, using */
+/* the Kerberos V5 (Beta 2) GSSAPI implementation, and attempt to */
+/* authenticate to a DCE/GSSAPI implementation. */
+/* */
+/* Since both GSSAPI implementations share the same routine names, two */
+/* executables are built by linking against either the DCE/GSSAPI or the */
+/* Kerberos V5 GSSAPI library. This file is compiled with the preprocessor */
+/* name KERBEROS defined if it is to invoke the Kerberos API, and with DCE */
+/* defined if it is to link against the DCE/GSSAPI. */
+/* */
+/* Invocation should specify two parameters - */
+/* 1) Name of initiating principal */
+/* 2) Name of accepting principal */
+/* */
+/* A flag '-S' is used to specify the name of the file that process will */
+/* activate as a slave. */
+/* */
+/* So to test, for example, Kerberos against Kerberos, and assuming that */
+/* the executable is called kitest-krb, you'd set up a Kerberos credential */
+/* for <client-name> using kinit, and arrange for a server Kerberos */
+/* credential for <server-name> to be available in a keytable, and issue */
+/* the command: */
+/* kitest-krb -S kitest-krb <client-name> <server-name> */
+/* */
+/* The original process becomes the context initiator, while the spawned */
+/* subprocess (running the executable specified after the -S flag) is */
+/* expected to act as the context acceptor. */
+
+#if defined(KERBEROS) && defined(DCE)
+#error "Both KERBEROS and DCE specified"
+#endif
+
+#if !defined(KERBEROS) && !defined(DCE)
+#error "Neither KERBEROS nor DCE defined"
+#endif
+
+/* You need to create links from krb-gssapi.h to the Kerberos gssapi.h, and */
+/* from dce-gssapi.h to the DCE gssapi.h. */
+#ifdef KERBEROS
+#include "krb-gssapi.h"
+#endif
+
+#ifdef DCE
+#include "dce-gssapi.h"
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <netdb.h>
+
+#ifndef GSS_ERROR
+#define GSS_ERROR(x) (x & 0xffff0000)
+/* The Kerberos gssapi.h doesn't define this macro. */
+#endif
+
+#define DOWN_CHANNEL 3
+/* Don't understand why stdin doesn't work here, but channel 3 seems to */
+/* work fine. */
+
+#define INITIAL_CHILD_MESSAGES 7
+
+extern int errno;
+
+int master = 0;
+int inpipe[2];
+int outpipe[2];
+int errpipe[2];
+
+gss_name_t source_internal_name;
+gss_name_t target_internal_name;
+gss_name_t source_authenticated_name;
+gss_buffer_desc source_name_buffer;
+gss_buffer_desc target_name_buffer;
+
+gss_cred_id_t my_cred_handle;
+gss_cred_id_t delegated_cred_handle;
+gss_ctx_id_t my_ctx_handle;
+gss_OID_set actual_cred_mech_set;
+gss_OID actual_ctx_mech_type;
+OM_uint32 actual_cred_time_rec;
+OM_uint32 actual_ctx_time_rec;
+gss_buffer_desc token_to_send;
+gss_buffer_desc token_received;
+int actual_ret_flags;
+struct gss_channel_bindings_struct my_channel_bindings;
+
+char source_name[512];
+char target_name[512];
+
+char my_host_name[50];
+char my_internet_address[4];
+struct hostent * my_hostent;
+
+unsigned char received_token_buffer[2048];
+unsigned received_length;
+
+OM_uint32 major_status;
+OM_uint32 kept_status;
+OM_uint32 minor_status;
+
+int subprocess_pid = 0;
+
+char line_buffer[128];
+int chars_read;
+
+void indicate_data(void) {
+ fprintf(stderr, "\a\n");
+ fflush(stderr);
+}
+
+void send_data(void * ptr, unsigned length) {
+ unsigned char length_buf[2];
+ unsigned char * char_ptr;
+ int data_sent;
+
+ char_ptr = (unsigned char *)ptr;
+
+ length_buf[0] = length & 0xff;
+ length_buf[1] = (length & 0xff00) >> 8;
+
+ if (master) {
+/* Data is sent via inpipe. */
+ errno = 0;
+ if ((data_sent = write(inpipe[1], length_buf, 2)) != 2) {
+ fprintf(stderr,
+ "Write of length sent %d bytes, expected 2\n",
+ data_sent);
+ fflush(stderr);
+ if (data_sent == -1) {
+ fprintf(stderr,
+ "Errno: %d\n",
+ errno);
+ fflush(stderr);
+ };
+ };
+ errno = 0;
+ if ((data_sent =write(inpipe[1], ptr, length)) != length) {
+ fprintf(stderr,
+ "Write of length sent %d bytes, expected 2\n",
+ data_sent);
+ fflush(stderr);
+ if (data_sent == -1) {
+ fprintf(stderr,
+ "Errno: %d\n",
+ errno);
+ fflush(stderr);
+ };
+ };
+ fprintf(stderr, "Sending data (length = %d):\n", length);
+ fprintf(stderr, " %2.2X %2.2X %2.2X %2.2X %2.2X...\n",
+ char_ptr[0], char_ptr[1], char_ptr[2],
+ char_ptr[3], char_ptr[4]);
+ } else {
+/* Data is sent via stdout, and a data indication on stderr. */
+ fwrite(length_buf, 2, 1, stdout);
+ fwrite(ptr, length, 1, stdout);
+ fflush(stdout);
+ indicate_data();
+ };
+}
+
+void receive_data(void * ptr, unsigned * length) {
+ unsigned char length_buf[2];
+ unsigned char * char_ptr;
+ int data_read;
+
+ char_ptr = (unsigned char *)ptr;
+
+ if (master) {
+/* Data is received via outpipe. A data indication is assumed to have been */
+/* received on errpipe, otherwise this routine will hang. */
+ read(outpipe[0], length_buf, 2);
+ *length = length_buf[0] | (length_buf[1]<<8);
+ read(outpipe[0], ptr, *length);
+ } else {
+/* Data is received on fd3 */
+ errno = 0;
+ if ((data_read = read(DOWN_CHANNEL, length_buf, 2)) != 2) {
+ fprintf(stderr,
+ "Error: received %d bytes for length, expecting 2\n",
+ data_read);
+ fflush(stderr);
+ if (data_read == -1) {
+ fprintf(stderr, "errno: %d\n", errno);
+ fflush(stderr);
+ };
+ };
+
+ *length = length_buf[0] | (length_buf[1]<<8);
+
+ errno = 0;
+ if ((data_read = read(DOWN_CHANNEL, ptr, *length)) != *length) {
+ fprintf(stderr,
+ "Error: received %d bytes for data, expecting %d\n",
+ data_read, *length);
+ fflush(stderr);
+ if (data_read == -1) {
+ fprintf(stderr, "errno: %d\n", errno);
+ fflush(stderr);
+ };
+ };
+
+ fprintf(stderr, "Received data (length = %d):\n", *length);
+ fprintf(stderr, " %2.2X %2.2X %2.2X %2.2X %2.2X...\n",
+ char_ptr[0], char_ptr[1], char_ptr[2],
+ char_ptr[3], char_ptr[4]);
+
+ };
+}
+
+int read_subproc_line(char * ptr, unsigned buf_length) {
+/* Returns length of data read, or zero if binary data waiting. */
+ int bytes_read = 0;
+ int finished = 0;
+ if (!master) {
+ fprintf(stderr, "Error: Child called read_subproc_data\n");
+ fflush(stderr);
+ exit(2);
+ } else {
+ while (!finished) {
+ read(errpipe[0], &ptr[bytes_read], 1);
+ if (ptr[bytes_read] == '\n') finished = 1;
+ if (bytes_read >= buf_length) finished = 1;
+ bytes_read ++;
+ };
+ if (bytes_read == 2 && ptr[0] == '\a') return 0;
+ else return bytes_read;
+ };
+}
+
+void display_error(char * where, OM_uint32 maj_stat, OM_uint32 min_stat) {
+ int context = 0;
+ OM_uint32 major_status, minor_status;
+ gss_buffer_desc message_buffer;
+
+ fprintf(stderr, "Error: %s\n", where);
+ fprintf(stderr, "Major status (%d) (min = %d):\n", maj_stat, min_stat);
+ fflush(stderr);
+ do {
+ message_buffer.length = 0;
+ message_buffer.value = NULL;
+ major_status = gss_display_status(&minor_status,
+ maj_stat,
+ GSS_C_GSS_CODE,
+ GSS_C_NULL_OID,
+ &context,
+ &message_buffer);
+ fprintf(stderr,
+ " message_buffer.length = %u, message_buffer.value = %p\n",
+ message_buffer.length, message_buffer.value);
+ fflush(stderr);
+ if (message_buffer.length = 0) {
+ fprintf(stderr,
+ " %.*s\n",
+ message_buffer.length,
+ message_buffer.value);
+ major_status = gss_release_buffer(&minor_status, &message_buffer);
+ } else {
+ fprintf(stderr, "-- no message --\n");
+ /* If we've been asked to translate an invalid status code */
+ };
+ fflush(stderr);
+
+ } while (context != 0);
+ fprintf(stderr, "Minor status:\n");
+ fflush(stderr);
+ major_status = gss_display_status(&minor_status,
+ min_stat,
+ GSS_C_MECH_CODE,
+ GSS_C_NULL_OID,
+ &context,
+ &message_buffer);
+ fprintf(stderr,
+ " %.*s\n",
+ message_buffer.length,
+ message_buffer.value);
+ fflush(stderr);
+
+ major_status = gss_release_buffer(&minor_status, &message_buffer);
+
+}
+
+void import_names(void) {
+
+ source_name_buffer.value = (void *)&source_name[0];
+ source_name_buffer.length = strlen(source_name);
+
+ major_status = gss_import_name(&minor_status,
+ &source_name_buffer,
+ GSS_C_NULL_OID,
+ &source_internal_name);
+
+ if (major_status != GSS_S_COMPLETE)
+ display_error("Importing source principal", major_status, minor_status);
+
+ target_name_buffer.value = (void *)&target_name[0];
+ target_name_buffer.length = strlen(target_name);
+
+ major_status = gss_import_name(&minor_status,
+ &target_name_buffer,
+ GSS_C_NULL_OID,
+ &target_internal_name);
+
+ if (major_status != GSS_S_COMPLETE)
+ display_error("Importing target principal", major_status, minor_status);
+
+}
+
+
+void alarm_handler(int sig) {
+ fprintf(stderr, "SIGALRM received, terminating subprocess\n");
+ fflush(stderr);
+ kill(subprocess_pid, SIGTERM);
+ exit(0);
+}
+
+
+void flush_subprocess_message_queue_and_exit(void) {
+
+ signal(SIGALRM, alarm_handler);
+ alarm(10);
+
+ do {
+ chars_read = read_subproc_line(line_buffer,
+ sizeof(line_buffer));
+ if (chars_read == 0) {
+ fprintf(stderr,
+ "Unexpected binary data received from child\n");
+ fflush(stderr);
+ receive_data(received_token_buffer,
+ &received_length);
+ } else {
+ fprintf(stderr,"CHILD> %.*s", chars_read, line_buffer);
+ };
+ fflush(stderr);
+ } while (1);
+}
+
+void sigpipe_handler(int sig) {
+ fprintf(stderr, "SIGPIPE received, flushing subprocess message queue\n");
+ fflush(stderr);
+ flush_subprocess_message_queue_and_exit();
+}
+
+int main(int argc, char *argv[]) {
+
+ int c;
+ int errflg = 0;
+ char * image_name;
+ int pid;
+
+ int i;
+
+ extern int optind, opterr;
+ extern char * optarg;
+
+ int blocking;
+
+ while ((c = getopt(argc, argv, "S:")) != EOF) {
+ switch (c) {
+ case 'S' : master = 1;
+ image_name = optarg;
+ break;
+ case '?' : errflg++;
+ break;
+ };
+ };
+
+ if (optind < argc) {
+ strncpy(source_name, argv[optind++], sizeof(source_name)-1);
+ } else {
+ fprintf(stderr, "Error: Source name (prin-1) missing\n");
+ errflg++;
+ };
+
+ if (optind < argc) {
+ strncpy(target_name, argv[optind++], sizeof(source_name)-1);
+ } else {
+ fprintf(stderr, "Error: Target name (prin-2) missing\n");
+ errflg++;
+ };
+
+ if (optind < argc) {
+ fprintf(stderr, "Error: too many parameters\n");
+ errflg++;
+ };
+
+ if (errflg) {
+ fprintf(stderr, "Usage: %s -S <subprocess> <princ-1> <princ-2>\n", argv[0]);
+ exit(2);
+ };
+
+ gethostname(my_host_name, sizeof(my_host_name));
+ my_hostent = gethostbyname(my_host_name);
+ memcpy(&my_internet_address, my_hostent->h_addr_list[0], 4);
+
+ fprintf(stderr,"Host: '%s', %u.%u.%u.%u\n",
+ my_host_name,
+ my_internet_address[0],
+ my_internet_address[1],
+ my_internet_address[2],
+ my_internet_address[3]);
+
+ my_channel_bindings.initiator_addrtype = GSS_C_AF_INET;
+ my_channel_bindings.initiator_address.length = 4;
+ my_channel_bindings.initiator_address.value = my_internet_address;
+
+ my_channel_bindings.acceptor_addrtype = GSS_C_AF_INET;
+ my_channel_bindings.acceptor_address.length = 4;
+ my_channel_bindings.acceptor_address.value = my_internet_address;
+
+ my_channel_bindings.application_data.length = 0;
+ my_channel_bindings.application_data.value = NULL;
+
+ my_ctx_handle = GSS_C_NO_CONTEXT;
+
+ if (!master) {
+
+/* Subprocess. */
+
+ fprintf(stderr, "Importing names\n");
+ fflush(stderr);
+
+ import_names();
+
+ fprintf(stderr, "Calling acquire_cred\n");
+ fflush(stderr);
+
+ major_status = gss_acquire_cred(&minor_status,
+ target_internal_name,
+ 60 * 60 * 24,
+ GSS_C_NULL_OID_SET,
+ GSS_C_ACCEPT,
+ &my_cred_handle,
+ &actual_cred_mech_set,
+ &actual_cred_time_rec);
+
+ if (major_status != GSS_S_COMPLETE) {
+ display_error("Acquiring ACCEPT credential for target principal",
+ major_status, minor_status);
+ while (1) ;
+ };
+
+ fprintf(stderr, "Returned from acquire_cred, waiting for token from parent\n");
+ fflush(stderr);
+
+ do {
+
+ receive_data(received_token_buffer,
+ &received_length);
+ token_received.value = (void *)received_token_buffer;
+ token_received.length = received_length;
+
+ fprintf(stderr, "Got token, calling accept_sec_context\n");
+ fflush(stderr);
+
+ major_status = gss_accept_sec_context(&minor_status,
+ &my_ctx_handle,
+ my_cred_handle,
+ &token_received,
+ &my_channel_bindings,
+ &source_authenticated_name,
+ &actual_ctx_mech_type,
+ &token_to_send,
+ &actual_ret_flags,
+ &actual_ctx_time_rec,
+ &delegated_cred_handle);
+ kept_status = major_status;
+
+ if (GSS_ERROR(major_status)) {
+ display_error("ACCEPT_SEC_CONTEXT",
+ major_status, minor_status);
+ while (1) ;
+ };
+
+ if (token_to_send.length != 0) {
+ send_data(token_to_send.value, token_to_send.length);
+ major_status = gss_release_buffer(&minor_status,
+ &token_to_send);
+ };
+
+ if (kept_status & GSS_S_CONTINUE_NEEDED) {
+ receive_data(received_token_buffer,
+ &received_length);
+ token_received.value = (void *)received_token_buffer;
+ token_received.length = received_length;
+ };
+
+ } while (kept_status & GSS_S_CONTINUE_NEEDED);
+
+ if (!GSS_ERROR(kept_status)) {
+ fprintf(stderr, "Authenticated context established\n");
+ } else {
+ fprintf(stderr, "Context not established\n");
+ };
+ fflush(stderr);
+ while (1) ;
+ } else {
+/* We need to create three pipes - inpipe, outpipe and errpipe, to which */
+/* the subprocess will connect its fd3, stdout and stderr channels. */
+
+ if (pipe(inpipe) < 0) {
+ fprintf(stderr, "Error: Can't make inpipe\n");
+ exit(2);
+ };
+ if (pipe(outpipe) < 0) {
+ fprintf(stderr, "Error: Can't make outpipe\n");
+ exit(2);
+ };
+ if (pipe(errpipe) < 0) {
+ fprintf(stderr, "Error: Can't make errpipe\n");
+ exit(2);
+ };
+
+ if ((subprocess_pid = fork()) == 0) {
+/* This is the slave subprocess in a two-process chain. Connect inpipe, */
+/* outpipe and errpipe to fd3, stderr and stdout, and then exec the slave */
+/* image. */
+ fprintf(stderr, "CHILD: forked, closing pipes\n");
+ fflush(stderr);
+
+ close(inpipe[1]); /* Close write end of inpipe */
+ close(outpipe[0]); /* Close read end of outpipe */
+ close(errpipe[0]); /* Close read end of errpipe */
+
+
+ write (errpipe[1],
+ "Child process forked (write to errpipe[1])\n",
+ strlen("Child process forked (write to errpipe[1])\n")
+ );
+
+ if (dup2(inpipe[0], DOWN_CHANNEL) == -1) {
+ fprintf(stderr, "CHILD: Can't dup2 inpipe[0]\n");
+ fflush(stderr);
+ };
+ /* Attach inpipe to fd3 */
+ if (dup2(outpipe[1], 1) == -1) {
+ fprintf(stderr, "CHILD: Can't dup2 outpipe[1]\n");
+ fflush(stderr);
+ };
+ /* Attach outpipe to stdout */
+ if (dup2(errpipe[1], 2) == -1) {
+ fprintf(stderr, "CHILD: Can't dup2 errpipe[1]\n");
+ fflush(stderr);
+ };
+ /* Attach errpipe to stderr */
+
+ write (2,
+ "Child process forked (write to fd2)\n",
+ strlen("Child process forked (write to fd2)\n")
+ );
+
+ fprintf(stderr, "Execing %s\n", image_name);
+ fflush(stderr);
+
+ execl(image_name, image_name, source_name, target_name, (char *)0);
+
+ fprintf(stderr, "Error: Couldn't exec %s\n", image_name);
+ exit(2);
+
+ } else if (subprocess_pid < 0) {
+ fprintf(stderr, "Error: Fork returned %d\n", subprocess_pid);
+ exit(2);
+ } else {
+/* This is the master process in a two-process chain. The slave process */
+/* has connected inpipe, outpipe and errpipe to its fd3, stdout and */
+/* stderr. We have to use the other ends. */
+
+
+ close(inpipe[0]); /* Close read end of inpipe */
+ close(outpipe[1]); /* Close write end of outpipe */
+ close(errpipe[1]); /* Close write end of errpipe */
+
+/* A simple protocol will be used between master and slave processes. The */
+/* subprocess (slave) will always expect that data received on its inpipe */
+/* will be binary messages, preceeded by a two-byte count. Messages from */
+/* slave to master will be sent on the errpipe channel if they are text */
+/* messages, and on outpipe if they are binary data (preceeded as above by */
+/* a two-byte count field). The presence of a binary message in the */
+/* outpipe will be indicated by writing the sequence "\a\n" to errpipe. */
+/* This protocol is implemented in the master by the routine */
+/* read_subproc_line, which reads a single line of text from the */
+/* subprocess, returning either its length, or zero to indicate that binary */
+/* data is waiting. Binary data is received by either process by invoking */
+/* the receive_data routine, and sent by invoking the send_data routine. */
+/* The receive_data routine will block until the data is available, so */
+/* care should be taken in the master not to call this routine unless a */
+/* data indication has already been received. */
+
+/* Master: */
+ signal(SIGPIPE, sigpipe_handler);
+
+/* The child will send us messages on start-up (at least */
+/* INITIAL_CHILD_MESSAGES of them), so we'll read them here to make sure we */
+/* catch a sleepy child early. */
+
+ fprintf(stderr, "Parent waiting for wake-up call from child...\n");
+ fflush(stderr);
+
+ signal(SIGALRM, alarm_handler);
+ alarm(10);
+
+ for (i=0; i<INITIAL_CHILD_MESSAGES; i++) {
+ chars_read = read_subproc_line(line_buffer,
+ sizeof(line_buffer));
+
+ if (chars_read == 0) {
+ fprintf(stderr,
+ "Unexpected binary data received from child\n");
+ fflush(stderr);
+ receive_data(received_token_buffer,
+ &received_length);
+ } else {
+ fprintf(stderr,"CHILD> %.*s", chars_read, line_buffer);
+ };
+ fflush(stderr);
+
+ };
+
+ alarm(0);
+
+ fprintf(stderr, "Parent continuing, importing names...\n");
+ fflush(stderr);
+
+ import_names();
+
+ fprintf(stderr, "Parent got names...\n");
+ fflush(stderr);
+
+#ifdef KERBEROS
+
+/* This version of the acquire_cred code requests the client credential */
+/* explicitly by name; the DCE version uses no name, meaning "give me a */
+/* to the default credential. */
+
+ fprintf(stderr, "Parent calling acquire_cred...\n");
+ fflush(stderr);
+
+ major_status = gss_acquire_cred(&minor_status,
+ source_internal_name,
+ 60 * 60 * 24,
+ GSS_C_NULL_OID_SET,
+ GSS_C_INITIATE,
+ &my_cred_handle,
+ &actual_cred_mech_set,
+ &actual_cred_time_rec);
+
+ fprintf(stderr, "Parent returned from acquire_cred.\n");
+ fflush(stderr);
+
+#endif
+#ifdef DCE
+ major_status = gss_acquire_cred(&minor_status,
+ GSS_C_NO_NAME,
+ 60 * 60 * 24,
+ GSS_C_NULL_OID_SET,
+ GSS_C_INITIATE,
+ &my_cred_handle,
+ &actual_cred_mech_set,
+ &actual_cred_time_rec);
+#endif
+ if (major_status != GSS_S_COMPLETE)
+ display_error("Acquiring INITIATE credential for source principal",
+ major_status, minor_status);
+
+
+ token_received.length = 0;
+ token_received.value = NULL;
+
+ do {
+
+ fprintf(stderr, "Parent calling init_sec_ctx...\n");
+ fflush(stderr);
+
+ major_status = gss_init_sec_context(&minor_status,
+ my_cred_handle,
+ &my_ctx_handle,
+ target_internal_name,
+ GSS_C_NULL_OID,
+ GSS_C_MUTUAL_FLAG,
+ 60 * 60 * 23,
+ &my_channel_bindings,
+ &token_received,
+ &actual_ctx_mech_type,
+ &token_to_send,
+ &actual_ret_flags,
+ &actual_ctx_time_rec);
+
+ fprintf(stderr, "Parent returned from init_sec_ctx...\n");
+ fflush(stderr);
+
+ kept_status = major_status;
+
+ if (GSS_ERROR(major_status))
+ display_error("INIT_SEC_CONTEXT",
+ major_status, minor_status);
+
+ if (token_to_send.length != 0) {
+
+ fprintf(stderr, "Parent transmitting token...\n");
+ fflush(stderr);
+
+ send_data(token_to_send.value, token_to_send.length);
+ major_status = gss_release_buffer(&minor_status,
+ &token_to_send);
+ };
+
+ if (kept_status & GSS_S_CONTINUE_NEEDED) {
+ signal(SIGALRM, alarm_handler);
+ alarm(30);
+ while ((chars_read = read_subproc_line(line_buffer,
+ sizeof(line_buffer))
+ ) != 0) {
+ fprintf(stderr, "CHILD> %.*s", chars_read, line_buffer);
+ };
+ alarm(0);
+ receive_data(received_token_buffer,
+ &received_length);
+ token_received.value = (void *)received_token_buffer;
+ token_received.length = received_length;
+ };
+
+ } while (kept_status & GSS_S_CONTINUE_NEEDED);
+
+ if (!GSS_ERROR(kept_status)) {
+ fprintf(stderr, "Authenticated context established\n");
+ } else {
+ fprintf(stderr, "Context not established\n");
+ };
+ fflush(stderr);
+
+ flush_subprocess_message_queue_and_exit();
+
+ };
+ };
+}
--- /dev/null
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)login.c 5.1 (Berkeley) 9/27/88";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <utmp.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+
+#define UTMPFILE "/etc/utmp"
+#define WTMPFILE "/usr/adm/wtmp"
+
+void
+login(ut)
+ struct utmp *ut;
+{
+ register int fd;
+ int tty;
+ off_t lseek();
+
+ tty = ttyslot();
+ if (tty > 0 && (fd = open(UTMPFILE, O_WRONLY, 0)) >= 0) {
+ (void)lseek(fd, (long)(tty * sizeof(struct utmp)), L_SET);
+ (void)write(fd, (char *)ut, sizeof(struct utmp));
+ (void)close(fd);
+ }
+ if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) >= 0) {
+ (void)write(fd, (char *)ut, sizeof(struct utmp));
+ (void)close(fd);
+ }
+}
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)logout.c 5.1 (Berkeley) 8/31/88";
+#endif /* LIBC_SCCS and not lint */
+
+logout(line)
+ register char *line;
+{
+ register FILE *fp;
+ struct utmp ut;
+ int rval;
+ time_t time();
+
+ if (!(fp = fopen(UTMPFILE, "r+")))
+ return(0);
+ rval = 1;
+ while (fread((char *)&ut, sizeof(struct utmp), 1, fp) == 1) {
+ if (!ut.ut_name[0] ||
+ strncmp(ut.ut_line, line, sizeof(ut.ut_line)))
+ continue;
+ bzero(ut.ut_name, sizeof(ut.ut_name));
+ bzero(ut.ut_host, sizeof(ut.ut_host));
+ (void)time(&ut.ut_time);
+ (void)fseek(fp, (long)-sizeof(struct utmp), L_INCR);
+ (void)fwrite((char *)&ut, sizeof(struct utmp), 1, fp);
+ (void)fseek(fp, (long)0, L_INCR);
+ rval = 0;
+ }
+ (void)fclose(fp);
+ return(rval);
+}
+/*
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)logwtmp.c 5.2 (Berkeley) 9/20/88";
+#endif /* LIBC_SCCS and not lint */
+
+logwtmp(line, name, host)
+ char *line, *name, *host;
+{
+ struct utmp ut;
+ struct stat buf;
+ int fd;
+ time_t time();
+ char *strncpy();
+
+ if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
+ return;
+ if (!fstat(fd, &buf)) {
+ (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+ (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
+ (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+ (void)time(&ut.ut_time);
+ if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
+ sizeof(struct utmp))
+ (void)ftruncate(fd, buf.st_size);
+ }
+ (void)close(fd);
+}
--- /dev/null
+setopt load_flags -I/usr/athena/include -I/u2/krb5/include -I/mit/krb5/src/include -DNARROW_PROTOTYPES
+load /mit/krb5/src/lib/cryptoconf.c /mit/krb5/src/lib/syslog.c /mit/krb5/src/lib/strdup.c
+
+load /mit/krb5/src/lib/krb/addr_comp.c /mit/krb5/src/lib/krb/addr_order.c /mit/krb5/src/lib/krb/addr_srch.c /u2/krb5/lib/krb/bld_pr_ext.o /u2/krb5/lib/krb/bld_princ.o /mit/krb5/src/lib/krb/conv_princ.c /mit/krb5/src/lib/krb/copy_addrs.c /mit/krb5/src/lib/krb/copy_auth.c /mit/krb5/src/lib/krb/copy_athctr.c /mit/krb5/src/lib/krb/copy_checksum.c /mit/krb5/src/lib/krb/copy_creds.c /mit/krb5/src/lib/krb/copy_data.c /mit/krb5/src/lib/krb/copy_key.c /mit/krb5/src/lib/krb/copy_princ.c /mit/krb5/src/lib/krb/copy_tick.c /mit/krb5/src/lib/krb/cp_key_cnt.c /mit/krb5/src/lib/krb/decode_kdc.c /mit/krb5/src/lib/krb/decrypt_tk.c /mit/krb5/src/lib/krb/encode_kdc.c /mit/krb5/src/lib/krb/encrypt_tk.c /mit/krb5/src/lib/krb/free_rtree.c /mit/krb5/src/lib/krb/faddr_ordr.c /mit/krb5/src/lib/krb/gc_frm_kdc.c /mit/krb5/src/lib/krb/gc_via_tgt.c /mit/krb5/src/lib/krb/gc_2tgt.c /mit/krb5/src/lib/krb/gen_seqnum.c /mit/krb5/src/lib/krb/gen_subkey.c /mit/krb5/src/lib/krb/get_creds.c /mit/krb5/src/lib/krb/get_in_tkt.c /mit/krb5/src/lib/krb/in_tkt_pwd.c /mit/krb5/src/lib/krb/in_tkt_sky.c /mit/krb5/src/lib/krb/kdc_rep_dc.c /mit/krb5/src/lib/krb/krbconfig.c /mit/krb5/src/lib/krb/mk_error.c /mit/krb5/src/lib/krb/mk_priv.c /mit/krb5/src/lib/krb/mk_rep.c /mit/krb5/src/lib/krb/mk_req.c /mit/krb5/src/lib/krb/mk_req_ext.c /mit/krb5/src/lib/krb/mk_safe.c /mit/krb5/src/lib/krb/parse.c /mit/krb5/src/lib/krb/pr_to_salt.c /mit/krb5/src/lib/krb/princ_comp.c /mit/krb5/src/lib/krb/rd_error.c /mit/krb5/src/lib/krb/rd_priv.c /mit/krb5/src/lib/krb/rd_rep.c /mit/krb5/src/lib/krb/rd_req.c /mit/krb5/src/lib/krb/rd_req_sim.c /mit/krb5/src/lib/krb/rd_req_dec.c /mit/krb5/src/lib/krb/rd_safe.c /mit/krb5/src/lib/krb/recvauth.c /mit/krb5/src/lib/krb/sendauth.c /mit/krb5/src/lib/krb/send_tgs.c /mit/krb5/src/lib/krb/srv_rcache.c /mit/krb5/src/lib/krb/tgtname.c /mit/krb5/src/lib/krb/unparse.c /mit/krb5/src/lib/krb/walk_rtree.c
+
+load -DPEPSY_LINKABLE_FUNCS -I/usr/athena/include -I/u2/krb5/include -I/mit/krb5/src/include -DNARROW_PROTOTYPES /u2/krb5/src/lib/asn.1/KRB5_tables.c /mit/krb5/src/lib/asn.1/encode.c /mit/krb5/src/lib/asn.1/decode.c /mit/krb5/src/lib/asn.1/adat2kadat.c /mit/krb5/src/lib/asn.1/addr2kaddr.c /mit/krb5/src/lib/asn.1/adr2kadr.c /mit/krb5/src/lib/asn.1/aprp2kaprp.c /mit/krb5/src/lib/asn.1/aprq2kaprq.c /mit/krb5/src/lib/asn.1/arep2karep.c /mit/krb5/src/lib/asn.1/auth2kauth.c /mit/krb5/src/lib/asn.1/cvt_flags.c /mit/krb5/src/lib/asn.1/ck2kck.c /mit/krb5/src/lib/asn.1/edat2kedat.c /mit/krb5/src/lib/asn.1/ekrp2kekrp.c /mit/krb5/src/lib/asn.1/enck2kkey.c /mit/krb5/src/lib/asn.1/err2kerr.c /mit/krb5/src/lib/asn.1/etpt2ketpt.c /mit/krb5/src/lib/asn.1/g2unix.c /mit/krb5/src/lib/asn.1/kadat2adat.c /mit/krb5/src/lib/asn.1/kaddr2addr.c /mit/krb5/src/lib/asn.1/kadr2adr.c /mit/krb5/src/lib/asn.1/kaprp2aprp.c /mit/krb5/src/lib/asn.1/kaprq2aprq.c /mit/krb5/src/lib/asn.1/karep2arep.c /mit/krb5/src/lib/asn.1/kauth2auth.c /mit/krb5/src/lib/asn.1/kck2ck.c /mit/krb5/src/lib/asn.1/kdcr2kkdcr.c /mit/krb5/src/lib/asn.1/kdcr2ktgsr.c /mit/krb5/src/lib/asn.1/kedat2edat.c /mit/krb5/src/lib/asn.1/kekrp2ekrp.c /mit/krb5/src/lib/asn.1/kerr2err.c /mit/krb5/src/lib/asn.1/ketpt2etpt.c /mit/krb5/src/lib/asn.1/kkdcr2kdcr.c /mit/krb5/src/lib/asn.1/kkey2enck.c /mit/krb5/src/lib/asn.1/klsrq2lsrq.c /mit/krb5/src/lib/asn.1/kprep2prep.c /mit/krb5/src/lib/asn.1/kprin2prin.c /mit/krb5/src/lib/asn.1/kpriv2priv.c /mit/krb5/src/lib/asn.1/ksafe2safe.c /mit/krb5/src/lib/asn.1/ktran2tran.c /mit/krb5/src/lib/asn.1/ktgrq2tgrq.c /mit/krb5/src/lib/asn.1/ktgsr2kdcr.c /mit/krb5/src/lib/asn.1/ktkt2tkt.c /mit/krb5/src/lib/asn.1/lsrq2klsrq.c /mit/krb5/src/lib/asn.1/prep2kprep.c /mit/krb5/src/lib/asn.1/prin2kprin.c /mit/krb5/src/lib/asn.1/priv2kpriv.c /mit/krb5/src/lib/asn.1/qbuf2data.c /mit/krb5/src/lib/asn.1/safe2ksafe.c /mit/krb5/src/lib/asn.1/tran2ktran.c /mit/krb5/src/lib/asn.1/tgrq2ktgrq.c /mit/krb5/src/lib/asn.1/tkt2ktkt.c /mit/krb5/src/lib/asn.1/u2gen.c /mit/krb5/src/lib/asn.1/kasrp2kdcr.c /mit/krb5/src/lib/asn.1/kpwd2pwd.c /mit/krb5/src/lib/asn.1/kpwds2pwds.c /mit/krb5/src/lib/asn.1/pwd2kpwd.c /mit/krb5/src/lib/asn.1/pwds2kpwds.c
+
+load /mit/krb5/src/lib/free/f_addr.c /mit/krb5/src/lib/free/f_address.c /mit/krb5/src/lib/free/f_arep_enc.c /mit/krb5/src/lib/free/f_ap_rep.c /mit/krb5/src/lib/free/f_ap_req.c /mit/krb5/src/lib/free/f_authdata.c /mit/krb5/src/lib/free/f_authent.c /mit/krb5/src/lib/free/f_cksum.c /mit/krb5/src/lib/free/f_creds.c /mit/krb5/src/lib/free/f_cred_cnt.c /mit/krb5/src/lib/free/f_enc_kdc.c /mit/krb5/src/lib/free/f_enc_tkt.c /mit/krb5/src/lib/free/f_error.c /mit/krb5/src/lib/free/f_kdc_rep.c /mit/krb5/src/lib/free/f_kdc_req.c /mit/krb5/src/lib/free/f_keyblock.c /mit/krb5/src/lib/free/f_last_req.c /mit/krb5/src/lib/free/f_padata.c /mit/krb5/src/lib/free/f_princ.c /mit/krb5/src/lib/free/f_priv.c /mit/krb5/src/lib/free/f_priv_enc.c /mit/krb5/src/lib/free/f_safe.c /mit/krb5/src/lib/free/f_ticket.c /mit/krb5/src/lib/free/f_tickets.c /mit/krb5/src/lib/free/f_tgt_cred.c /mit/krb5/src/lib/free/f_tkt_auth.c
+
+load /mit/krb5/src/lib/keytab/ktadd.c /mit/krb5/src/lib/keytab/ktbase.c /mit/krb5/src/lib/keytab/ktdefault.c /mit/krb5/src/lib/keytab/ktfr_entry.c /mit/krb5/src/lib/keytab/ktremove.c /mit/krb5/src/lib/keytab/read_servi.c
+
+load /mit/krb5/src/lib/keytab/file/ktf_add.c /mit/krb5/src/lib/keytab/file/ktf_endget.c /mit/krb5/src/lib/keytab/file/ktf_next.c /mit/krb5/src/lib/keytab/file/ktf_resolv.c /mit/krb5/src/lib/keytab/file/ktf_wops.c /mit/krb5/src/lib/keytab/file/ktf_close.c /mit/krb5/src/lib/keytab/file/ktf_get_en.c /mit/krb5/src/lib/keytab/file/ktf_ops.c /mit/krb5/src/lib/keytab/file/ktf_ssget.c /mit/krb5/src/lib/keytab/file/ktf_wreslv.c /mit/krb5/src/lib/keytab/file/ktf_defops.c /mit/krb5/src/lib/keytab/file/ktf_get_na.c /mit/krb5/src/lib/keytab/file/ktf_remove.c /mit/krb5/src/lib/keytab/file/ktf_util.c
+
+load /mit/krb5/src/lib/ccache/ccbase.c /mit/krb5/src/lib/ccache/ccdefault.c /mit/krb5/src/lib/ccache/ccdefops.c
+
+load /mit/krb5/src/lib/ccache/file/fcc_close.c /mit/krb5/src/lib/ccache/file/fcc_destry.c /mit/krb5/src/lib/ccache/file/fcc_eseq.c /mit/krb5/src/lib/ccache/file/fcc_gennew.c /mit/krb5/src/lib/ccache/file/fcc_getnam.c /mit/krb5/src/lib/ccache/file/fcc_gprin.c /mit/krb5/src/lib/ccache/file/fcc_init.c /mit/krb5/src/lib/ccache/file/fcc_nseq.c /mit/krb5/src/lib/ccache/file/fcc_read.c /mit/krb5/src/lib/ccache/file/fcc_reslv.c /mit/krb5/src/lib/ccache/file/fcc_retrv.c /mit/krb5/src/lib/ccache/file/fcc_sseq.c /mit/krb5/src/lib/ccache/file/fcc_store.c /mit/krb5/src/lib/ccache/file/fcc_skip.c /mit/krb5/src/lib/ccache/file/fcc_ops.c /mit/krb5/src/lib/ccache/file/fcc_write.c /mit/krb5/src/lib/ccache/file/fcc_sflags.c /mit/krb5/src/lib/ccache/file/fcc_defops.c /mit/krb5/src/lib/ccache/file/fcc_errs.c /mit/krb5/src/lib/ccache/file/fcc_maybe.c
+
+load -I. -I/usr/athena/include -I/u2/krb5/include -I/mit/krb5/src/include -DNARROW_PROTOTYPES /mit/krb5/src/lib/rcache/rc_base.c /mit/krb5/src/lib/rcache/rc_dfl.c /mit/krb5/src/lib/rcache/rc_io.c /mit/krb5/src/lib/rcache/rcdef.c /mit/krb5/src/lib/rcache/rc_conv.c
--- /dev/null
+----------------
+"/mit/krb5/src/lib/krb/gc_via_tgt.c":119, krb5_get_cred_via_tgt(), Statement not reached (Warning #529)
+ 118: return retval;
+ * 119: break; /* not strictly necessary... */ 120: }
+( while sourcing "/tmp/saber.source":4 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/krb/in_tkt_sky.c":48, skey_keyproc(), Unused formal parameter (Warning #590)
+ 47: */
+ * 48: static krb5_error_code
+ 49: skey_keyproc(DECLARG(const krb5_keytype, type),
+( while sourcing "/tmp/saber.source":4 )
+Formal parameter 'padata' was not used.
+----------------
+"/mit/krb5/src/lib/krb/rd_priv.c":63, krb5_rd_priv(), Unused formal parameter (Warning #590)
+ 62:
+ * 63: krb5_error_code
+ 64: krb5_rd_priv(DECLARG(const krb5_data *, inbuf),
+( while sourcing "/tmp/saber.source":4 )
+Formal parameter 'recv_addr' was not used.
+----------------
+"/usr/include/unistd.h":182, Function redeclared (Warning #701)
+ 181:
+ * 182: extern unsigned int
+ 183: alarm(),
+( while sourcing "/tmp/saber.source":4 )
+Function 'alarm' was previously declared as:
+ extern int alarm();
+----------------
+"/usr/include/unistd.h":198, Function redeclared (Warning #701)
+ 197:
+ * 198: extern void
+ 199: _exit();
+( while sourcing "/tmp/saber.source":4 )
+Function '_exit' was previously declared as:
+ extern int _exit();
+----------------
+"/mit/krb5/src/lib/asn.1/kpwd2pwd.c":75, krb5_pwd_seq2KRB5_PWD__SEQ(), Functionredeclared (Warning #701)
+ 74: sizeof(struct type_KRB5_PasswdSequence))) == NULL) {
+ * 75: com_err("kpwd2pwd", 0, "Unable to Allocate PasswdSequence");
+ 76: *error = ENOMEM;
+( while sourcing "/tmp/saber.source":6 )
+Function 'com_err' was previously declared as:
+ extern void com_err();
+----------------
+"/mit/krb5/src/lib/keytab/file/ktf_util.c":601, krb5_ktfileint_size_entry(), Unused automatic variable (Warning #591)
+ 600: {
+ * 601: krb5_int16 count, size;
+ 602: krb5_int32 total_size, i;
+( while sourcing "/tmp/saber.source":12 )
+Automatic variable 'size' was not used.
+----------------
+"/mit/krb5/src/lib/keytab/file/ktf_util.c":757, krb5_ktfileint_find_slot(), Unused label (Warning #593)
+( while sourcing "/tmp/saber.source":12 )
+Label 'abend' was not used.
+----------------
+"/mit/krb5/src/lib/ccache/file/fcc_gennew.c":40, Unknown directive (Warning #471)
+ 39: #else
+ 40: #error find some way to use net-byte-order file version numbers.
+ ^
+ 41: #endif
+( while sourcing "/tmp/saber.source":16 )
+Directive 'error' is undefined.
+
+----------------
+"/mit/krb5/src/lib/ccache/file/fcc_gennew.c":77, krb5_fcc_generate_new(), Function redeclared (Warning #701)
+ 76: (void) strcat(scratch, "XXXXXX");
+ * 77: mktemp(scratch);
+ 78:
+( while sourcing "/tmp/saber.source":16 )
+Function 'mktemp' was previously declared as:
+ extern char *mktemp();
+----------------
+"/mit/krb5/src/lib/ccache/file/fcc_maybe.c":41, Unknown directive (Warning #471)
+ 40: #else
+ 41: #error find some way to use net-byte-order file version numbers.
+ ^
+ 42: #endif
+( while sourcing "/tmp/saber.source":16 )
+Directive 'error' is undefined.
+Warning: 1 module currently not loaded.
+Loading: -I. /mit/krb5/src/lib/rcache/rc_base.c
+
+----------------
+"/mit/krb5/src/lib/rcache/rc_base.h":13, Cannot read file (Error #400)
+ 12: #define KRB5_RC_H
+ * 13: #include <krb5/krb5.h>
+ 14: #include <krb5/ext-proto.h>
+( while sourcing "/tmp/saber.source":18 )
+Cannot open 'krb5/krb5.h' for input.
+----------------
+"/mit/krb5/src/lib/rcache/rc_dfl.c":335, krb5_rc_dfl_recover(), Unused automatic variable (Warning #591)
+ 334: struct dfl_data *t = (struct dfl_data *)id->data;
+ * 335: int i;
+ 336: krb5_donot_replay *rep;
+( while sourcing "/tmp/saber.source":18 )
+Automatic variable 'i' was not used.
+----------------
+"/mit/krb5/src/lib/rcache/rc_dfl.c":402, krb5_rc_dfl_recover(), Unused label (Warning #593)
+( while sourcing "/tmp/saber.source":18 )
+Label 'end_loop' was not used.
+----------------
+"/mit/krb5/src/lib/rcache/rc_dfl.c":443, krb5_rc_dfl_store(), Statement not reached (Warning #529)
+ 442: case CMP_MALLOC:
+ * 443: return KRB5_RC_MALLOC; break;
+ 444: case CMP_REPLAY:
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_dfl.c":445, krb5_rc_dfl_store(), Statement not reached (Warning #529)
+ 444: case CMP_REPLAY:
+ * 445: return KRB5KRB_AP_ERR_REPEAT; break;
+ 446: case 0: break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_dfl.c":438, krb5_rc_dfl_store(), Unused automatic variable (Warning #591)
+ 437: struct dfl_data *t = (struct dfl_data *)id->data;
+ * 438: int i;
+ 439:
+( while sourcing "/tmp/saber.source":18 )
+Automatic variable 'i' was not used.
+----------------
+"/mit/krb5/src/lib/rcache/rc_dfl.c":525, krb5_rc_dfl_expunge(), Benign argumentmismatch (Warning #68)
+ 524: {
+ * 525: if (krb5_rc_io_store (&tmp, &q->rep))
+ 526: return KRB5_RC_IO;
+( while sourcing "/tmp/saber.source":18 )
+Benign type mismatch in call to function 'krb5_rc_io_store':
+Argument #1 has type (struct krb5_rc_iostuff *) but type (struct dfl_data *) was expected.
+Defined/declared in "/mit/krb5/src/lib/rcache/rc_dfl.c":404
+----------------
+"/mit/krb5/src/lib/rcache/rc_dfl.c":473, krb5_rc_dfl_expunge(), Unused automatic variable (Warning #591)
+ 472: struct dfl_data *t = (struct dfl_data *)id->data;
+ * 473: int i;
+ 474: #ifdef NOIOSTUFF
+( while sourcing "/tmp/saber.source":18 )
+Automatic variable 'i' was not used.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":33, Unknown directive (Warning #471)
+ 32: #else
+ 33: #error find some way to use net-byte-order file version numbers.
+ ^
+ 34: #endif
+( while sourcing "/tmp/saber.source":18 )
+Directive 'error' is undefined.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":73, krb5_rc_io_creat(), Constant in conditional (Warning #558)
+ 72:
+ * 73: GETDIR;
+ 74: if (fn && *fn)
+( while sourcing "/tmp/saber.source":18 )
+The conditional expression for 'do/while' is always false.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":156, krb5_rc_io_open(), Constant in conditional (Warning #558)
+ 155:
+ * 156: GETDIR;
+ 157: if (!(d->fn = malloc(strlen(fn) + dirlen + 1)))
+( while sourcing "/tmp/saber.source":18 )
+The conditional expression for 'do/while' is always false.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":165, krb5_rc_io_open(), Function redeclared (Warning #701)
+ 164:
+ * 165: me = getuid();
+ 166: /* must be owned by this user, to prevent some security problems with
+( while sourcing "/tmp/saber.source":18 )
+Function 'getuid' was previously declared as:
+ extern short getuid();
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":238, krb5_rc_io_write(), Statement not reached (Warning #529)
+ 237: {
+ * 238: case EBADF: return KRB5_RC_IO_UNKNOWN; break;
+ 239: case EFBIG: return KRB5_RC_IO_SPACE; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":239, krb5_rc_io_write(), Statement not reached (Warning #529)
+ 238: case EBADF: return KRB5_RC_IO_UNKNOWN; break;
+ * 239: case EFBIG: return KRB5_RC_IO_SPACE; break;
+ 240: #ifdef EDQUOT
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":241, krb5_rc_io_write(), Statement not reached (Warning #529)
+ 240: #ifdef EDQUOT
+ * 241: case EDQUOT: return KRB5_RC_IO_SPACE; break;
+ 242: #endif
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":243, krb5_rc_io_write(), Statement not reached (Warning #529)
+ 242: #endif
+ * 243: case ENOSPC: return KRB5_RC_IO_SPACE; break;
+ 244: case EIO: return KRB5_RC_IO_IO; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":244, krb5_rc_io_write(), Statement not reached (Warning #529)
+ 243: case ENOSPC: return KRB5_RC_IO_SPACE; break;
+ * 244: case EIO: return KRB5_RC_IO_IO; break;
+ 245: default: return KRB5_RC_IO_UNKNOWN; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":245, krb5_rc_io_write(), Statement not reached (Warning #529)
+ 244: case EIO: return KRB5_RC_IO_IO; break;
+ * 245: default: return KRB5_RC_IO_UNKNOWN; break;
+ 246: }
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":256, krb5_rc_io_sync(), Statement not reached (Warning #529)
+ 255: {
+ * 256: case EBADF: return KRB5_RC_IO_UNKNOWN; break;
+ 257: case EIO: return KRB5_RC_IO_IO; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":257, krb5_rc_io_sync(), Statement not reached (Warning #529)
+ 256: case EBADF: return KRB5_RC_IO_UNKNOWN; break;
+ * 257: case EIO: return KRB5_RC_IO_IO; break;
+ 258: default: return KRB5_RC_IO_UNKNOWN; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":258, krb5_rc_io_sync(), Statement not reached (Warning #529)
+ 257: case EIO: return KRB5_RC_IO_IO; break;
+ * 258: default: return KRB5_RC_IO_UNKNOWN; break;
+ 259: }
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":273, krb5_rc_io_read(), Statement not reached (Warning #529)
+ 272: {
+ * 273: case EBADF: return KRB5_RC_IO_UNKNOWN; break;
+ 274: case EIO: return KRB5_RC_IO_IO; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":274, krb5_rc_io_read(), Statement not reached (Warning #529)
+ 273: case EBADF: return KRB5_RC_IO_UNKNOWN; break;
+ * 274: case EIO: return KRB5_RC_IO_IO; break;
+ 275: default: return KRB5_RC_IO_UNKNOWN; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":275, krb5_rc_io_read(), Statement not reached (Warning #529)
+ 274: case EIO: return KRB5_RC_IO_IO; break;
+ * 275: default: return KRB5_RC_IO_UNKNOWN; break;
+ 276: }
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":298, krb5_rc_io_destroy(), Statement not reached (Warning #529)
+ 297: {
+ * 298: case EBADF: return KRB5_RC_IO_UNKNOWN; break;
+ 299: case EIO: return KRB5_RC_IO_IO; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":299, krb5_rc_io_destroy(), Statement not reached (Warning #529)
+ 298: case EBADF: return KRB5_RC_IO_UNKNOWN; break;
+ * 299: case EIO: return KRB5_RC_IO_IO; break;
+ 300: case EPERM: return KRB5_RC_IO_PERM; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":300, krb5_rc_io_destroy(), Statement not reached (Warning #529)
+ 299: case EIO: return KRB5_RC_IO_IO; break;
+ * 300: case EPERM: return KRB5_RC_IO_PERM; break;
+ 301: case EBUSY: return KRB5_RC_IO_PERM; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":301, krb5_rc_io_destroy(), Statement not reached (Warning #529)
+ 300: case EPERM: return KRB5_RC_IO_PERM; break;
+ * 301: case EBUSY: return KRB5_RC_IO_PERM; break;
+ 302: case EROFS: return KRB5_RC_IO_PERM; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":302, krb5_rc_io_destroy(), Statement not reached (Warning #529)
+ 301: case EBUSY: return KRB5_RC_IO_PERM; break;
+ * 302: case EROFS: return KRB5_RC_IO_PERM; break;
+ 303: default: return KRB5_RC_IO_UNKNOWN; break;
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
+----------------
+"/mit/krb5/src/lib/rcache/rc_io.c":303, krb5_rc_io_destroy(), Statement not reached (Warning #529)
+ 302: case EROFS: return KRB5_RC_IO_PERM; break;
+ * 303: default: return KRB5_RC_IO_UNKNOWN; break;
+ 304: }
+( while sourcing "/tmp/saber.source":18 )
+The statement cannot be reached.
--- /dev/null
+ignore KRB5-types.c
+ignore KRB5-types.h
+ignore KRB5-types.py
+ignore TAGS
+ignore KRB5.ph
+ignore Makefile.jtk
+ignore glue2.c
+ignore process.perl
--- /dev/null
+alias hex print (unsigned)
+setopt load_flags -I../include
+load -lisode
+alias reload load
--- /dev/null
+#include <krb5/krb5.h>
+
+krb5_data string_list[3] = {
+{14, "ATHENA.MIT.EDU"},
+{6, "jtkohl"},
+{4, "root"},
+};
+
+krb5_data *princ[] = {&string_list[0], &string_list[1], &string_list[2], 0};
+
+krb5_data string_list2[3] = {
+{14, "ATHENA.MIT.EDU"},
+{6, "krbtgt"},
+{14, "ATHENA.MIT.EDU"},
+};
+
+krb5_data *princ2[] = {&string_list2[0], &string_list2[1], &string_list2[2], 0};
+
+krb5_last_req_entry lrentries[] = { {32000, 1}, {0, 3}, {10, 2} };
+krb5_last_req_entry *lrfoo1[] = {&lrentries[0], &lrentries[1], &lrentries[2], 0};
+
+krb5_authdata adarr1[] = { {3, 7, "authdat"}, {2,4,"foob"}, {257,9,"jtkohlxxx"}};
+krb5_authdata *authdats[] = {&adarr1[0],&adarr1[1],&adarr1[2],0};
+
+krb5_pa_data authdarr1[] = { {3, 7, "authdat"}, {2,4,"foob"}, {257,9,"jtkohlxxx"}};
+krb5_pa_data *padats[] = {&authdarr1[0],&authdarr1[1],&authdarr1[2],0};
+
+krb5_address adrarr1[] = { {ADDRTYPE_INET,4,"abcd"},
+ {ADDRTYPE_ISO,10,"6176432831"},
+ {ADDRTYPE_INET,4,"efgh"} };
+krb5_address *addrs[] = {&adrarr1[0],&adrarr1[1],&adrarr1[2],0};
--- /dev/null
+#
+# usage: perl process <input-c-file> <output-prefix> <c-flist> <o-flist>
+#
+$header = "";
+$count = 0;
+$pepyid = "";
+$extrainclude = '#include <krb5/asn.1/KRB5-types-aux.h>' . "\n";
+
+if ($#ARGV != 3) {die "Usage: process input-file.c output-prefix cflist-file oflist-file";}
+
+print "processing ", $ARGV[0], "\n";
+open(CFILE, "< $ARGV[0]") || die "can't open $ARGV[0]";
+open(CFLIST, "> $ARGV[2]") || die "can't open $ARGV[2]";
+open(OFLIST, "> $ARGV[3]") || die "can't open $ARGV[2]";
+
+mainloop: while (<CFILE>) {
+ next mainloop if /^# line/;
+ if (/pepyid/) {
+ $pepyid = $_;
+ } elsif (/^\/\* ARGS|^free/) {
+ print "processing output from $pepyid" if ($count == 0);
+ close(OUTFILE);
+ $ofile = "$ARGV[1]" . $count . ".c";
+ open(OUTFILE, ">$ofile" ) || die "can't open file $ofile";
+ print OUTFILE $pepyid if ($count == 0);
+ print $ofile, "\n";
+ @clist = (@clist, " " . $ofile);
+ $count++;
+ print OUTFILE $header;
+ print OUTFILE $extrainclude;
+ print OUTFILE $_;
+ } elsif ($count == 0) {
+ $header .= $_;
+ } else {
+ print OUTFILE $_;
+ }
+}
+close(OUTFILE);
+print CFLIST "TYPESSRCS= ", @clist, "\n";
+close(CFLIST);
+while ($cfile = shift(@clist)) {
+ $cfile =~ s/.c$/.o/;
+ @olist = (@olist, $cfile);
+}
+print OFLIST "TYPESOBJS=", @olist, "\n";
+close(OFLIST);
+#
+# $Source$
+# $Author$
+# $Id$
--- /dev/null
+ignore fcc_test.c
--- /dev/null
+If OPENCLOSE is defined, ecah of the functions opens and closes the
+file whenever it needs to access it. Otherwise, the file is opened
+once in initialize and closed once is close.
+
+This library depends on UNIX-like file descriptors, and UNIX-like
+behavior from the functions: open, close, read, write, lseek.
+
+The quasi-BNF grammar for a credentials cache:
+
+file ::=
+ principal list-of-credentials
+
+credential ::=
+ client (principal)
+ server (principal)
+ keyblock (keyblock)
+ times (ticket_times)
+ is_skey (boolean)
+ ticket_flags (flags)
+ ticket (data)
+ second_ticket (data)
+
+principal ::=
+ number of components (int32)
+ component 1 (data)
+ component 2 (data)
+ ...
+
+data ::=
+ length (int32)
+ string of length bytes
+
+etc.
--- /dev/null
+Make sure that each time a function returns KRB5_NOMEM, everything
+allocated earlier in the function and stack tree is freed.
+
+File locking
+
+fcc_nseq.c and fcc_read don't check return values a lot.
+
--- /dev/null
+If OPENCLOSE is defined, ecah of the functions opens and closes the
+file whenever it needs to access it. Otherwise, the file is opened
+once in initialize and closed once is close.
+
+This library depends on ANSI C library routines for file handling. It
+may also have some implicit assumptions about UNIX, but we'll get
+those out as much as possible.
+
+If you are running a UNIX system, you probably want to use the
+UNIX-based "file" cache package instead of this.
+
+The quasi-BNF grammar for a credentials cache:
+
+file ::=
+ format-vno principal list-of-credentials
+
+credential ::=
+ client (principal)
+ server (principal)
+ keyblock (keyblock)
+ times (ticket_times)
+ is_skey (boolean)
+ ticket_flags (flags)
+ ticket (data)
+ second_ticket (data)
+
+principal ::=
+ number of components (int32)
+ component 1 (data)
+ component 2 (data)
+ ...
+
+data ::=
+ length (int32)
+ string of length bytes
+
+format-vno ::= <int16>
+
+etc.
--- /dev/null
+Make sure that each time a function returns KRB5_NOMEM, everything
+allocated earlier in the function and stack tree is freed.
+
+Overwrite cache file with nulls before removing it.
+
+Check return values and sanity-check parameters more thoroughly. This
+code was derived from UNIX file I/O code, and the conversion of
+error-trapping may be incomplete. Probably lots of bugs dealing with
+end-of-file versus other errors.
--- /dev/null
+ignore *.h
+ignore *.c
+ignore .rconf
+link init_ets.c
--- /dev/null
+ignore README
+ignore RELEASE
--- /dev/null
+/*
+Copyright 1990, Daniel J. Bernstein. All rights reserved.
+
+Please address any questions or comments to the author at brnstnd@acf10.nyu.edu.
+*/
+
+The #include's should be rewritten.
+
+All functions return 0 on success.
+
+Environment variables: KRB5RCACHETYPE, KRB5RCACHENAME, KRB5RCACHEDIR,
+and TMPDIR. Obsolete: KRB5RCACHE.
+
+All header files are both ANSI-compatible and K&R-compatible. The .c files
+are only ANSI compatible. Everything passes gcc -Wall -ansi -pedantic.
+
+Strings are freed using FREE(), which is defined in terms of free().
+
+The error header files should be redone.
+
+The header files don't use __ because that's reserved.
+
+Each .c file assumes <malloc.h>. rc_io.c assumes fsync() and a gaggle of
+error codes. These assumptions are not as portable as the code itself.
+
+
+rcache.c:
+
+The rcache.c compatibility interface's type registration is a no-op; it
+simply passes the type name on to rc_base.h. rcache.h is obsolete; use
+rc_base.h if possible.
+
+There are some slight differences between rcache.c and the prototypes I
+saw in krb/func-proto.h. Don't look at me, it's your interface.
+
+rcache.c's get_name doesn't fill with zeros unless strncpy does.
+
+
+rc_base.c:
+
+If SEMAPHORE is defined and <semaphore.h> exists when rc_base.c is
+compiled, all access to the type list will be protected by appropriate
+semaphore ups and downs. This is untested.
+
+It doesn't take linker magic to preregister types. Just change the
+typehead initialization in rc_base.c, with an appropriate include file
+setting the ops.
+
+
+rc_dfl.c:
+
+If NOIOSTUFF is defined when rc_dfl.c is compiled, all dfl rcaches will
+be per-process. This is untested.
+
+Provided that separate threads use separate rcaches, rc_dfl.c is safe
+for multithreading.
+
+Getting the name of a cache is only valid after it is created and before
+it is closed. Recovering a cache is only valid after it has been created.
+
+krb5_unparse_name had better produce a zero-terminated string.
+
+rc_dfl.c isn't smart enough to try expunge/retry upon a malloc error.
+Then again, such an error indicates that the whole system's about to die;
+without real memory management there's no good solution.
+
+HASHSIZE can be defined at compile time. It defaults to 997 in rc_dfl.c.
+EXCESSREPS can be defined at compile time. It defaults to 30 in rc_dfl.c.
+
+Hopefully adding a deltat to a time to compare to another time cannot
+overflow.
+
+In rc_dfl's struct dfl_data, the name field is never freed, even though
+it may be malloced by io_creat on a generate-name call. This should not
+be a problem: a single process should not be opening and closing many
+rcaches. One fix would be another field to indicate whether the string
+was malloced or not; normally this is an unstated characteristic of a
+char pointer, but here it would have to be explicit.
+
+
+rc_io.c:
+
+rc_io.c assumes that siginterrupt() is not set. If siginterrupt() is set
+and a signal occurs during, say, close(), then the close will fail.
+
+On a machine without fsync() you might as well not use the disk at all.
--- /dev/null
+Text of Mr. Bernstein's release:
+
+"I" henceforth refers to Daniel J. Bernstein.
+
+"rcshar" henceforth refers to the attached document, as sent from Daniel
+J. Bernstein to Project Athena on 11 March 1990
+
+I am the author of and sole copyright holder upon rcshar.
+
+I hereby waive copyright upon rcshar. rcshar is hereby public domain.
+
+I hereby also waive copyright upon any works that are (1) derived from
+rcshar and (2) prepared between 11 March 1990 and 1 January 1991.
+
+Daniel J. Bernstein
+
+<signature>, dated 7 July 1990