summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/krb4/ChangeLog1135
-rw-r--r--src/lib/krb4/DNR.c309
-rw-r--r--src/lib/krb4/Makefile.in264
-rw-r--r--src/lib/krb4/Password.c433
-rw-r--r--src/lib/krb4/TAGS546
-rw-r--r--src/lib/krb4/ad_print.c66
-rw-r--r--src/lib/krb4/configure.in17
-rw-r--r--src/lib/krb4/cr_auth_repl.c112
-rw-r--r--src/lib/krb4/cr_ciph.c108
-rw-r--r--src/lib/krb4/cr_death_pkt.c59
-rw-r--r--src/lib/krb4/cr_err_repl.c90
-rw-r--r--src/lib/krb4/cr_tkt.c133
-rw-r--r--src/lib/krb4/debug.c15
-rw-r--r--src/lib/krb4/decomp_tkt.c160
-rw-r--r--src/lib/krb4/dest_tkt.c94
-rw-r--r--src/lib/krb4/err_txt.c294
-rw-r--r--src/lib/krb4/fakeenv.c88
-rw-r--r--src/lib/krb4/fgetst.c35
-rw-r--r--src/lib/krb4/g_ad_tkt.c241
-rw-r--r--src/lib/krb4/g_admhst.c77
-rw-r--r--src/lib/krb4/g_cnffile.c53
-rw-r--r--src/lib/krb4/g_cred.c58
-rw-r--r--src/lib/krb4/g_in_tkt.c387
-rw-r--r--src/lib/krb4/g_krbhst.c93
-rw-r--r--src/lib/krb4/g_krbrlm.c60
-rw-r--r--src/lib/krb4/g_phost.c75
-rw-r--r--src/lib/krb4/g_pw_in_tkt.c342
-rw-r--r--src/lib/krb4/g_pw_tkt.c67
-rw-r--r--src/lib/krb4/g_svc_in_tkt.c133
-rw-r--r--src/lib/krb4/g_tf_fname.c67
-rw-r--r--src/lib/krb4/g_tf_realm.c29
-rw-r--r--src/lib/krb4/g_tkt_svc.c173
-rw-r--r--src/lib/krb4/gethostname.c30
-rw-r--r--src/lib/krb4/getst.c33
-rw-r--r--src/lib/krb4/in_tkt.c159
-rw-r--r--src/lib/krb4/kerberos.def68
-rw-r--r--src/lib/krb4/klog.c109
-rw-r--r--src/lib/krb4/kname_parse.c230
-rw-r--r--src/lib/krb4/kntoln.c56
-rw-r--r--src/lib/krb4/kparse.c766
-rw-r--r--src/lib/krb4/krb_err.et256
-rw-r--r--src/lib/krb4/kuserok.c231
-rw-r--r--src/lib/krb4/log.c128
-rw-r--r--src/lib/krb4/mac_glue.c49
-rw-r--r--src/lib/krb4/mac_store.c731
-rw-r--r--src/lib/krb4/mac_store.h56
-rw-r--r--src/lib/krb4/mac_stubs.c526
-rw-r--r--src/lib/krb4/mac_time.c151
-rw-r--r--src/lib/krb4/macsock.c484
-rw-r--r--src/lib/krb4/memcache.c867
-rw-r--r--src/lib/krb4/memcache.h50
-rw-r--r--src/lib/krb4/mk_auth.c218
-rw-r--r--src/lib/krb4/mk_err.c59
-rw-r--r--src/lib/krb4/mk_preauth.c78
-rw-r--r--src/lib/krb4/mk_priv.c205
-rw-r--r--src/lib/krb4/mk_req.c214
-rw-r--r--src/lib/krb4/mk_safe.c154
-rw-r--r--src/lib/krb4/month_sname.c28
-rw-r--r--src/lib/krb4/netread.c52
-rw-r--r--src/lib/krb4/netwrite.c48
-rw-r--r--src/lib/krb4/one.c20
-rw-r--r--src/lib/krb4/pkt_cipher.c35
-rw-r--r--src/lib/krb4/pkt_clen.c49
-rw-r--r--src/lib/krb4/put_svc_key.c93
-rw-r--r--src/lib/krb4/rd_err.c69
-rw-r--r--src/lib/krb4/rd_preauth.c58
-rw-r--r--src/lib/krb4/rd_priv.c217
-rw-r--r--src/lib/krb4/rd_req.c358
-rw-r--r--src/lib/krb4/rd_safe.c196
-rw-r--r--src/lib/krb4/rd_svc_key.c206
-rw-r--r--src/lib/krb4/realmofhost.c141
-rw-r--r--src/lib/krb4/recvauth.c282
-rw-r--r--src/lib/krb4/ren-cyg.sh11
-rw-r--r--src/lib/krb4/ren-pc.bat29
-rw-r--r--src/lib/krb4/ren-pc.sh7
-rw-r--r--src/lib/krb4/ren-pl10.sh7
-rw-r--r--src/lib/krb4/ren.msg117
-rw-r--r--src/lib/krb4/ren2dos.sh7
-rw-r--r--src/lib/krb4/ren2long.sh7
-rw-r--r--src/lib/krb4/save_creds.c54
-rw-r--r--src/lib/krb4/sed-cyg.sh13
-rw-r--r--src/lib/krb4/sed-pc.sh11
-rw-r--r--src/lib/krb4/sed-pl10.sh10
-rw-r--r--src/lib/krb4/send_to_kdc.c388
-rw-r--r--src/lib/krb4/sendauth.c278
-rw-r--r--src/lib/krb4/setenv.c164
-rw-r--r--src/lib/krb4/stime.c40
-rw-r--r--src/lib/krb4/strcasecmp.c83
-rw-r--r--src/lib/krb4/swab.c18
-rw-r--r--src/lib/krb4/tf_shm.c171
-rw-r--r--src/lib/krb4/tf_util.c630
-rw-r--r--src/lib/krb4/tkt_string.c71
-rw-r--r--src/lib/krb4/unix_glue.c39
-rw-r--r--src/lib/krb4/unix_time.c26
-rw-r--r--src/lib/krb4/vmslink.com79
-rw-r--r--src/lib/krb4/vmsswab.c34
-rw-r--r--src/lib/krb4/win_glue.c117
-rw-r--r--src/lib/krb4/win_store.c115
-rw-r--r--src/lib/krb4/win_time.c103
-rw-r--r--src/lib/krb4/winsock.def90
100 files changed, 16292 insertions, 0 deletions
diff --git a/src/lib/krb4/ChangeLog b/src/lib/krb4/ChangeLog
new file mode 100644
index 0000000000..ecf35d82de
--- /dev/null
+++ b/src/lib/krb4/ChangeLog
@@ -0,0 +1,1135 @@
+Tue Mar 28 09:19:23 1995 Mark Eichin <eichin@cygnus.com>
+
+ * send_to_kdc.c (send_to_kdc): only use secondary port if entry
+ for primary doesn't have an explicit port number. Secondary port
+ is still guessed to be 750. Also *don't* switch to the secondary
+ port in general, since we might be using multiple realms.
+
+Tue Feb 14 23:24:50 1995 John Gilmore <gnu@cygnus.com>
+
+ * sendauth.c (krb_net_rd_sendauth): Result is a Kerberos error
+ code, not an errno.
+
+Mon Feb 6 16:11:52 1995 John Gilmore (gnu at toad.com)
+
+ * mac_store.c (DeleteServerMap): When skipping a realm map, skip
+ also the admin-flag byte; else walking the list of strings gets
+ very confused.
+
+ * mac_stubs.c (kdriver): Rename static variable to mac_stubs_kdriver,
+ and export it to callers.
+ (krb_get_ticket_for_service): Circumvent MPW compiler bug that
+ doesn't like array->memb inside a sizeof. array[0].memb works.
+
+Wed Feb 1 12:00:00 1995 John Rivlin <jrivlin@cygnus.com>
+
+ * Makefile.in: Modify install-windows and clean-windows
+ targets to install libraries into src/windows directory.
+
+Tue Jan 24 10:35:31 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * g_pw_in_tkt.c (krb_get_pw_in_tkt_preauth): Check for a NULL
+ password if _WINDOWS or macintosh.
+
+Mon Jan 23 17:06:10 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * g_pw_in_tkt.c (passwd_to_key): When not _WINDOWS or macintosh,
+ restore code to call des_read_password if passwd is NULL.
+ (krb_get_pw_in_tkt): Only error out if password is NULL if
+ _WINDOWS or macintosh.
+
+ * g_krbhst.c (get_krbhst_default): New static function.
+ (krb_get_krbhst): Use get_krbhst_default.
+
+Fri Jan 20 12:00:00 1995 John Rivlin (jrivlin@fusion.com)
+
+ * Makefile.in: Changed libentry to debug in link command as
+ libentry is no longer provided in the Visual C++ environment.
+ Libentry is part of the library in Visual C++. Debug is used
+ purely to satisfy the syntax requirements of the link command.
+
+Thu Jan 19 14:18:10 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * sendauth.c (krb_net_rd_sendauth): If the raw ticket length looks
+ like the start of a warning from SunOS4 ld.so, just ignore the
+ warning message, and look for the ticket after it.
+
+Mon Jan 16 16:11:21 1995 John Gilmore <gnu@cygnus.com>
+
+ * kuserok.c (kuserok): Allow realm to be defaulted in the
+ ~/.klogin file; this simplfies DejaGnu testing of Kerberos.
+ Fix bug that left kname_parse arguments uninitialized.
+
+Mon Jan 16 11:54:01 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * krb_err.et: Change KRBET_RD_APTIME message from ``delta_t too
+ big'' to ``time is out of bounds.''
+
+ * send_to_kdc.c: If POSIX, include <stdlib.h> instead of declaring
+ malloc, calloc, and realloc.
+ (cached_krb_udp_port): Make static.
+ (send_to_kdc): If send_recv fails, and the kerberos port number
+ used is from getservbyname, and is not 750, then try sending to
+ port 750.
+
+ * realmofhost.c (krb_realmofhost): If DO_REVERSE_RESOLVE is
+ defined, canonicalize using gethostbyaddr.
+
+Thu Jan 12 17:40:26 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * in_tkt.c (in_tkt): Set umask to 077 around creation of ticket
+ file to ensure that it is created with write access, even if the
+ user has a screwy umask value.
+
+Thu Dec 29 23:59:49 1994 Mark Eichin <eichin@cygnus.com>
+
+ * g_in_tkt.c (krb_get_in_tkt_preauth): factored out into
+ krb_mk_in_tkt_preauth and krb_parse_in_tkt. This simplifies the
+ SNK4 support on platforms that can't do callbacks from (shared)
+ libraries.
+
+Tue Dec 27 11:12:54 1994 Ian Lance Taylor <ian@cygnus.com>
+
+ * g_in_tkt.c (krb_get_in_tkt_preauth): Rewrite switch statement to
+ work when compiled by SCO 3.2v4 native C compiler.
+ * g_ad_tkt.c (get_ad_tkt): Likewise.
+
+Fri Dec 23 15:47:20 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * memcache.c (unix): Define if _AIX is defined (AIX compiler does
+ not predefine unix).
+
+Fri Dec 16 18:57:40 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * memcache.h: Use PROTOTYPE in declarations.
+ * memcache.c: Rewrite function definitions to use Classic C
+ parameter repetition rather than prototypes.
+
+Thu Dec 15 18:23:37 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * memcache.c: Add typedefs and macro definitions to make this file
+ compile on Unix as well as on Windows and the Mac.
+
+Wed Dec 14 19:31:24 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * g_in_tkt.c (krb_get_in_tkt_preauth): Comment out assignment to
+ exp_date, since it is not used.
+
+Wed Nov 23 12:30:49 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * fakeenv.c (_findenv, unsetenv): New functions, copied in from
+ setenv.c. The telnet server uses unsetenv.
+
+Wed Nov 23 00:53:10 1994 John Gilmore (gnu@cygnus.com)
+
+ * realmofhost.c (krb_realmofhost): Allow arbitrary host
+ names here, as in krb_get_phost, by canonicalizing the name
+ into a fully qualified name using gethostbyname(). This
+ has the effect of letting users not set the "local realm"
+ config knob in more cases, since a name without a dot will
+ be canonicalized and searched-for in the domain-to-realm
+ database, rather than being assumed to be in the local realm.
+ This problem was found by using unqualified hostnames in Wintel.
+
+Wed Nov 23 00:26:17 1994 John Gilmore (gnu@cygnus.com)
+
+ Clean up a few misleading error messages.
+
+ * memcache.c (krb_get_tf_fullname): Return NO_TKT_FIL if
+ there are no tickets cached, just like from tf_util.c.
+ * g_ad_tkt.c (get_ad_ticket): If we try cross-realm
+ authentication, and it fails for lack of a key in the
+ kerberos database, return AD_NOTGT ("No ticket-
+ granting ticket") rather than KDC_PR_UNKNOWN ("Principal unknown").
+ * krb_err.et, err_txt.c: Update NO_TKT_FIL error message from
+ "No ticket file (tf_util)" to "You have no tickets cached".
+
+Thu Nov 17 12:31:27 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * mk_preauth.c (krb_mk_preauth): des_key_sched takes a des_cblock
+ argument, not des_cblock *, so remove the cast.
+ * rd_preauth.c (krb_rd_preauth): Likewise.
+
+Wed Nov 16 22:13:28 1994 Mark Eichin (eichin@cygnus.com)
+
+ * mk_preauth.c (krb_mk_preauth): use des_key_sched instead; check
+ its return value and fail if it fails.
+ * rd_preauth.c (krb_rd_preauth): ditto.
+
+Wed Nov 16 17:35:07 1994 Mark Eichin (eichin@cygnus.com)
+
+ * mk_preauth.c (krb_mk_preauth): add R3 implementation (and
+ NOENCRYPTION version) which passes encrypted aname.
+ (krb_free_preauth): free storage from both implementations.
+ * rd_preauth.c (krb_rd_preauth): add R3 implementation.
+
+Wed Nov 16 17:28:14 1994 Mark Eichin (eichin@cygnus.com)
+
+ * g_pw_in_tkt.c (stub_key): use memcpy, in case the C_Block is an
+ array and not a struct.
+
+Wed Nov 9 12:45:02 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * in_tkt.c: Fix thinko in last change.
+
+Fri Nov 4 12:05:57 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * in_tkt.c: Don't redefine setreuid if both hpux and __svr4__.
+
+Fri Nov 4 02:10:58 1994 John Gilmore (gnu@cygnus.com)
+
+ Make it build on MS-Windows again.
+
+ * Makefile.in (NETIO_SRCS, NETIO_OBJS): Break out, since these
+ are required on MS-Windows and prohibited on Mac.
+ (kerberos.dll): Avoid line-length problems by copying
+ libraries from other directories and using very short names.
+
+Tue Nov 1 15:47:44 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * dest_tkt.c: Include "krb.h" before <stdio.h>.
+
+Mon Oct 31 19:41:14 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * Makefile.in (CODE): Use Makefile.in instead of Imakefile.
+
+Fri Oct 28 15:21:56 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * month_sname.c: Include conf.h.
+ * one.c: Likewise.
+
+ * rd_req.c (krb_rd_req): Pass address of the array ad->session, to
+ match function definition.
+
+Wed Oct 12 00:37:46 1994 Julia Menapace (jcm at toad.com)
+
+ * Password.c: Include kerberos.h not Krb.h. Define KRB_DEFS to
+ avoid multiple symbol definitions from krb_driver.h. Needs further
+ cleanup but not just before release.
+
+Mon Oct 10 20:07:56 1994 Julia Menapace (jcm at toad.com)
+
+ * g_tkt_svc.c: (cacheInitialTicket) moved to new file Password.c
+
+ * mac_glue.c: Remove superfluous comment.
+
+ * mac_stubs.c: Add code translating unix function call to mac
+ driver control call for krb_get_tf_fullname
+
+ * macsock.c: Remove superflous comment.
+
+ * memcache.c: Remove unused #includes
+ (krb_get_tf_realm) pass tktfile instead of blank to
+ krb_get_tf_fullname.
+
+ (get_tf_fullname): Because the symantics of GetNthCredentials
+ (called by this routine) were changed to disable multiple named
+ caches (for UNIX compatability) we have to replace the user name
+ and instance it returns with the actual name and instance of the
+ current cache, set by in_tkt and stored in file static global
+ variables.
+
+Mon Oct 10 13:37:34 1994 Julia Menapace (jcm at toad.com)
+
+ * mk_auth.c: New file, created from sendauth.c. Contains just
+ the portable parts of sendauth.c (krb_mk_auth and krb_check_auth).
+ * sendauth.c (krb_mk_auth, mrb_check_auth): Move these functions
+ to mk_auth.c.
+ * Makefile.in (SRCS, OBJS, SERVER_KRB_SRCS, SERVER_KRB_OBJS):
+ Add mk_auth.c to SRCS/OBJS; remove sendauth.c, netread.c, and
+ netwrite.c from SRCS/OBJS to SERVER_KRB_SRCS/OBJS.
+
+Thu Sep 29 15:31:24 1994 John Gilmore (gnu@cygnus.com)
+
+ * realmofhost.c (krb_realmofhost): Correct off-by-one error in
+ default handling of top and second-level domains.
+
+Fri Sep 23 12:00:00 1994 John Rivlin (jrivlin@fusion.com)
+
+ * Makefile.in: Added kstream library to kerberos.dll
+
+ * kerberos.def: Added kstream library to kerberos.dll
+
+Fri Aug 19 12:00:00 1994 John Rivlin (jrivlin@fusion.com)
+
+ * g_pw_in_.c: Added (key_proc_type) cast for stub_key to remove
+ warnings with prototypes active.
+
+ * kerberos.def: Added des_ecb_encrypt to externals for telnet.
+
+Wed Sep 14 12:58:05 1994 Julia Menapace (jcm@cygnus.com)
+
+ * mac_stubs.c (krb_get_err_text): make return type const.
+ (GetNthRealmMap): add routine to stubs library to generate a
+ driver call returning the Nth Realm mapping.
+ (GetNthServerMap): add routine to stubs library to generate a
+ driver call returning the Nth server mapping.
+ * g_tkt_svc.c (CacheInitialTicket): If user name has changed save
+ it.
+ * memcache.c (krb_save_credentials): Fill in credential with
+ currently authorized user name and instance expected by kerberos,
+ (passed to and stored by in_tkt) instead of FIXED user name and
+ instance used to select credentials cache (is same for all cases to
+ disable multi named caches, using/reusing single named cache for
+ all cases).
+
+Tue Sep 13 16:45:01 1994 Julia Menapace (jcm@cygnus.com)
+
+ * err_txt.c (MULTIDIMENSIONAL_ERR_TXT): Rename from
+ UNIDIMENSIONAL_ARRAYS to reflect what's actually going on.
+
+Thu Aug 18 20:26:16 1994 Mark Eichin (eichin@cygnus.com)
+
+ * g_tkt_svc.c (CredIsExpired): use proper style of declaration so
+ that it works with k&r compilers.
+
+Wed Aug 10 13:47:55 1994 Mark Eichin (eichin@cygnus.com)
+
+ * err_txt.c (krb_err_txt): Export it again, to avoid gratuitous
+ incompatibility. Programs that can't deal with the use of the
+ array don't have to use it.
+
+Fri Aug 5 15:55:02 1994 Mark Eichin (eichin@cygnus.com)
+
+ * tf_util.c (tf_save_cred): cast 0 to (off_t), don't assume 0L
+ will work (it doesn't in netbsd.)
+
+Mon Aug 6 12:00:00 1994 John Rivlin (jrivlin@fusion.com)
+
+ * g_cnffile.c: Added definition for getenv.
+
+ * Makefile.in: Added KADM_LIB_FOR_DLL library in kerberos.dll
+ Updated clean target to avoid deleteion of krb_err.h under
+ Windows.
+
+ * kerberos.def: Added inteface for KRB_GET_NOTIFICATION_MESSAGE,
+ KADM_INIT_LINK, KADM_CHANGE_PW, KADM_CHANGE_PW and KADM_GET_ERR_TEXT
+ and renumbered entrypoints for consistency.
+
+ * memcache.c (change_session_count, change_cache): Changed
+ change_session_count to change_cache. This
+ routine now maintains the lock on the library as well as sending
+ ot broadcast messages to all to level windows when the cache
+ changes. Also changed all calls to above routine throughout
+ memcache.c.
+
+ * netwrite.c: use newly added SOCKET_READ and SOCKET_EINTR values
+ to avoid use of read on Windows. VMS dependencies moved to c-vms.h
+ for uniformity with other platforms.
+
+ * netread.c: use newly added SOCKET_READ and SOCKET_EINTR values
+ to avoid use of read on Windows. VMS dependencies moved to c-vms.h
+ for uniformity with other platforms.
+
+ * memcache.c: sname, sinst, srealm not stored if null pointers
+ passed in. This avoids problems found porting kpasssd.
+
+Mon Aug 1 12:00:00 1994 John Rivlin (jrivlin@fusion.com)
+
+ * kerberos.def: Changed heapsize to 8192 to avoid LocalAlloc
+ failure messages on startup. Added kadm_change_pw2 to external
+ interface.
+
+ * win_glue.c (krb_get_default_user, krb_set_default_user): Have
+ been moved to win_store.c.
+
+ * win_store.c: Use KERBEROS_INI and INI_xxx values in c-windows.h
+ rather than hard coded strings.
+
+ * win_store.c (krb_get_default_user, krb_set_default_user): Added
+ to save and retieve value of "[DEFAULTS] user =" in kerberos.ini
+ file.
+
+ * realmofhost.c (krb_realmofhost): Now calls krb__get_relmsfile
+ rather than opening up the krb.realms file directly so that
+ Windows version can override the location of the file.
+
+ * win_stor.c: Stores the
+
+Wed Jul 27 12:00:00 1994 John Rivlin (jrivlin@fusion.com)
+
+ * g_cnffil.c (krb__get_realmsfile): Added a routine to open
+ the krb.realms file so that the routine can be overridden
+ in Windows implementation with a routine which looks up
+ the name of the realms file in the kerberos.ini file.
+
+ * win_store.c: Created to parallel the Mac implementation.
+ Routines in this file will provide access to the krb.conf,
+ krb.realms files and other configuration information.
+
+ * ren.msg: Created entry for win_store.
+
+ * Makefile.in: Move g_cnffile.c to REALMDBSRCS to allow
+ Windows to override this functionality with a routine in
+ win_store.c routine.
+
+Tue Jul 26 12:00:00 1994 John Rivlin (jrivlin@fusion.com)
+
+ * netread.c: errno redefinition under Windows ifdefed out.
+ * netwrite.c: errno redefinition under Windows ifdefed out.
+
+Fri Jul 22 23:07:21 1994 Mark Eichin (eichin@cygnus.com)
+
+ * rd_preauth.c (krb_rd_preauth): change interface to include the
+ decrypted key (since the server has already looked it up.)
+
+Thu Jul 21 17:24:13 1994 Mark Eichin (eichin@cygnus.com)
+
+ * g_krbrlm.c (krb_get_lrealm): use krb__get_cnffile, don't
+ (mis)declare fopen.
+ * g_krbhst.c (krb_get_krbhst): ditto.
+ * g_admhst.c (krb_get_admhst): ditto.
+ * Makefile.in (OBJS, SRCS): build get_cnffile.c.
+
+Thu Jul 21 17:10:35 1994 Mark Eichin (eichin@cygnus.com)
+
+ * g_pw_in_tkt.c (krb_get_pw_in_tkt_preauth): *MUST* continue to
+ allow the password not to be passed in, since there is code that
+ does interesting things in the passwd_to_key routine.
+
+ * g_svc_in_tkt.c (stub_key): don't assume C_Block is a struct; use
+ memcpy instead of *.
+
+ * log.c (krb_log): use char* instead of int for default args.
+ Don't declare fopen explicitly, let stdio.h do it.
+ Don't include sys/time.h under VMS.
+ * klog.c (klog): ditto.
+
+Wed Jul 20 22:34:11 1994 Mark Eichin (eichin@tweedledumber.cygnus.com)
+
+ * rd_safe.c (krb_rd_safe): handle direction bit correctly when
+ krb_ignore_ip_address is set.
+
+ * rd_priv.c (krb_rd_priv): same.
+
+ * send_to_kdc.c: support arbitrary KDC port number in krb.conf file.
+
+ * g_cnffile.c: new file. common interface to krb.conf.
+ vmslink.com: new file. linker script to build libkrb.olb under
+ VMS; run as @vmslink.
+ vmsswab.c: vms runtime doesn't have swab.
+
+Wed Jul 20 20:38:19 1994 Mark Eichin (eichin@cygnus.com)
+
+ * kparse.c (strsave): only define locally if HAVE_STRSAVE isn't set.
+
+Tue Jul 19 12:00:00 1994 John Rivlin (jrivlin@fusion.com)
+
+ * memcache.c (NewHandle, SetHandleSize, MemError): Updated to return
+ valid Mac compatable error codes. Got rid of warning messages for
+ pointer mismatches.
+
+ * memcache.c (change_session_count): added routine and calls to it
+ to facilitate cross session ticket cacheing under Windows.
+ Moved fNumSessions definition up so that Windows code can get to it.
+
+ * win_glue.c (LibMain, get_lib_instance): added to return HINSTANCE
+ of library which is now saved in LibMain.
+
+Tue Jul 19 16:08:49 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * klog.c (klog): Leave local static array logtype_array
+ uninitialized, to put it in bss.
+
+ * g_ad_tkt.c (rep_err_code): Variable deleted.
+ (get_ad_tkt): Make it automatic here. Local variables pkt_st,
+ rpkt_st, cip_st, tkt_st no longer static.
+ * kname_parse.c (kname_parse): Local variable buf no longer
+ static.
+ * rd_req.c (krb_rd_req): Local variables ticket, tkt, req_id_st,
+ seskey_sched, swap_bytes, mutual, s_kvno no longer static.
+ * rd_safe.c (calc_cksum, big_cksum, swap_bytes): Variables
+ deleted.
+ (krb_rd_safe): Make them automatic variables here. Local variable
+ src_addr no longer static.
+ * rd_priv.c (c_length, swap_bytes, t_local, delta_t): Variables
+ deleted.
+ (krb_rd_priv): Make them automatic variables here. Local variable
+ src_addr no longer static.
+ * mk_safe.c (cksum, big_cksum, msg_secs, msg_usecs, msg_time_5ms,
+ msg_time_seg): Variables deleted.
+ (krb_mk_safe): Make them automatic variables here.
+ * mk_priv.c (c_length, msg_time_5ms, msg_time_sec, msg_time_usec):
+ Variables deleted.
+ (krb_mk_priv): Make them automatic variables here. Local variable
+ c_length_ptr also no longer static.
+
+ * pkt_clen.c (swap_bytes): No longer explicitly extern.
+ * g_ad_tkt.c (swap_bytes): Make it extern here.
+
+ * kparse.c (LineNbr, ErrorMsg): Now static.
+
+ * err_txt.c (krb_err_txt): Don't export this name. Make it const
+ again.
+
+ * netread.c: Include errno.h.
+ (errno): Declare.
+ (krb_net_read): On EINTR, retry read.
+ * netwrite.c: Include errno.h.
+ (errno): Declare.
+ (krb_net_write): On EINTR, retry write.
+
+Mon Jul 18 19:04:03 1994 Julia Menapace (jcm@cygnus.com)
+
+ * err_txt.c (krb_err_txt): if the C compiler can't initialize
+ multidimentional arrays, declare it differently (controlled by
+ UNIDIMENSIONAL_ARRAYS).
+
+ * mac_stubs.c (krb_get_cred, krb_save_credentials,
+ krb_delete_cred, krb_get_nth_cred, krb_get_num_cred): new
+ functions to implement credentials caching.
+
+ * memcache.c (krb_get_cred, krb_save_credentials,
+ krb_delete_cred, krb_get_nth_cred, krb_get_num_cred): actual
+ implementation of this functionality.
+
+Fri Jul 15 17:35:30 1994 John Rivlin (jrivlin@fusion.com)
+
+ * ren.msg: updated to handle all files (changelogs, makefiles etc)
+
+ * Makefile.in: added "-" on clean: to avoid stupid messages
+
+ * g_pw_in_tkt.c (get_pw_in_tkt_preauth): added INTERFACE
+ for kinit.
+
+ * kerberos.def: clean up, removed unused function references
+
+ * win_glue.c (krb_start_session): fixed syntax error
+
+ * win_glue.c (krb_end_session): fixed syntax error
+
+Tue Jul 12 17:35:30 1994 D. V. Henkel-Wallace (gumby@rtl.cygnus.com)
+
+ * ren.msg: add record for g_tkt_svc.c
+
+Fri June 8 02:40:54 1994 John Rivlin (jrivlin@fusion.com)
+
+ * makefile.in: Updated file with portable directory syntax for PC.
+ Changed .o and .a references to portable syntax
+ Removed all response files which needed to be generated under unix
+ to simplify configure process so that it may be run on the PC.
+ Placed objects in .lib file so that DLL construction can take place
+ without a response file. This solves a problem with running out of
+ memory on the PC during builds.
+ Updated clean: target to place rm commands on seperate lines for
+ compatibility with PC DEL command.
+
+ * win_glue (krb_start_session): Added a dummy parameter to match
+ prototype.
+
+ * win_glue (krb_end_session): Added a dummy parameter to match
+ prototype.
+
+Tue Jul 5 11:25:31 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * err_txt.c (krb_err_txt): Now const.
+ (krb_get_err_text): Returns pointer to const.
+ * month_sname.c (month_sname): Month name array and return type
+ now both const.
+ * one.c (krbONE): Now const.
+
+ * g_tkt_svc.c: Include string.h.
+
+ * kntoln.c (krb_kntoln): Static variable lrealm is no longer
+ explicitly initialized; now in bss.
+ * tf_util.c (krb_shm_addr, tmp_shm_addr, krb_dummy_skey): Ditto.
+ * tkt_string.c (krb_ticket_string): Ditto.
+
+ * mk_req.c (krb_mk_req): Removed "static" from many function
+ variables.
+
+ * tkt_string.c (krb_set_tkt_string): Deleted extra whitespace,
+ unnecessary "return" statement.
+
+Fri Jul 1 04:50:06 1994 John Gilmore (gnu@cygnus.com)
+
+ * macsock.c: Eliminate "TCPTB.h".
+ * mac_stubs.c (isname, isinst, isrealm): Remove, useless.
+ (krb_get_pw_in_tkt_preauth): Stub out to be the same as
+ krb_get_pw_in_tkt, for kinit's sake.
+
+ * mac_stubs.c (hicall): Fix error handling somewhat.
+
+ * Makefile.in (SRCS, OBJS): Add g_tkt_svc.c, .o.
+
+ * kname_parse.c, rd_priv.c, rd_safe.c, unix_glue.c: Typos.
+
+Fri Jul 1 03:55:29 1994 John Gilmore (gnu@cygnus.com)
+
+ Make Kerberos work in a Macintosh driver using Think C.
+
+ * %KrbLib-project: Think C "project file" (sort of
+ makefile and object files rolled into one -- all binary)
+ for the Kerberos library built for linking into applications
+ (for debugging).
+ * %KrbLib-project-A4: Ditto, for linking into device drivers.
+
+ * mac_stubs.c: New file, implements the function-call
+ interface of "kerberos.h" by making calls to a device-driver
+ using the hairy Mac interface of "krb_driver.h". If you
+ link with this, your Mac program can use a portable, clean
+ interface to Kerberos.
+
+ * g_tkt_svc.c: New file, krb_get_ticket_for_service,
+ an "easy application kerberizer", derived from kclient.
+
+ * err_txt.c (krb_err_txt): Avoid pointers to string initializers,
+ since Think C can't cope with this in device drivers.
+ (krb_get_err_table): Remove interface, unused.
+
+ * month_sname.c: Avoid pointers to string initializers.
+ * kname_parse.c: Add FIXME comment about args.
+ * mac_glue.c (read, write krb_ignore_ip_address): Stub out.
+ * macsock.c, memcache.c, sendauth.c: Lint. Think includes.
+
+ * mac_store.h: Eliminate static and obsolete stuff.
+ * mac_store.c: Update includes for Think.
+ (gUserName): Make static.
+ (krb_get_default_user, krb_set_default_user): Add.
+ * unix_glue.c, win_glue.c (krb_set_default_user): Add stub.
+
+ * g_ad_tkt.c, kname_parse.c, memcache.c, mk_priv.c, mk_req.c,
+ mk_safe.c, pkt_clen.c, rd_priv.c, rd_safe.c: Remove uses of
+ printf, by using DEB macro.
+
+ * send_to_kdc.c: Change to "krbports.h".
+ (DEB): Remove definition in favor of krb.h.
+ (all calls to DEB): Avoid passing stdout or stderr.
+
+Thu Jun 30 22:58:59 1994 John Gilmore (gnu@tweedledumb.cygnus.com)
+
+ * *.c: Remove remaining RCS ID strings. Strings used as `char *'
+ initializers upset Think C when building device drivers, since it
+ doesn't have a good way to relocate the pointers when the driver
+ is loaded.
+
+ * *.c: Use #include "..." rather than #include <...> for
+ our own local include files, because Think C can't find them
+ when enclosed in <...>.
+
+Thu Jun 30 17:48:26 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * send_to_kdc.c (prog): Now const pointer to const.
+ (timeout): Static var deleted.
+ (send_recv): Use a local timeout structure instead, reinitialized
+ before each use, in case select modifies its value.
+
+Wed Jun 22 19:42:50 1994 Mark Eichin (eichin@cygnus.com)
+
+ * mk_preauth.c (krb_free_preauth): New function to free up storage
+ allocated by krb_mk_preauth (if any.)
+
+ * g_pw_in_tkt.c (krb_get_pw_in_tkt_preauth): use krb_free_preauth
+ to possibly release storage used by krb_mk_preauth.
+
+ * g_svc_in_tkt.c (krb_get_svc_in_tkt_preauth): use
+ krb_free_preauth to possibly release storage used by krb_mk_preauth.
+
+Wed Jun 22 19:33:21 1994 Mark Eichin (eichin@cygnus.com)
+
+ * put_svc_key.c: USE_UNISTD_H to get SEEK_CUR if neccessary.
+
+Wed Jun 22 18:11:49 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * sendauth.c (krb_mk_auth): Don't call memset with BUFSIZ, since
+ the field in question is only MAX_KTXT_LEN bytes long.
+
+ * in_tkt.c, mk_priv.c, mk_safe.c, pkt_cipher.c, pkt_clen.c,
+ rd_err.c, rd_priv.c, rd_safe.c, tf_util.c: Include string.h.
+
+Wed Jun 22 15:11:35 1994 John Gilmore (gnu@cygnus.com)
+
+ * ren.msg: Add put_svc_key.c.
+
+Wed Jun 22 15:03:53 1994 Mark Eichin (eichin at tweedledumber.cygnus.com)
+
+ * put_svc_key.c (put_svc_key): new file, new function.
+ * Makefile.in: add put_svc_key to SERVER_KRB_*.
+
+Tue Jun 21 01:20:44 1994 John Gilmore (gnu@cygnus.com)
+
+ * kname_parse.c (kname_parse, isinst): Allow periods in instance
+ names. Pull RCS crud.
+
+Tue Jun 21 00:20:20 1994 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (all): First rule in file just calls all-really.
+ (all-really): Call $(ALL_WHAT) after it's been set.
+ * memcache.c: Remove typedef kludges to
+ ../../include/mt-windows.h. Add Size. WINDOWS -> _WINDOWS.
+
+Sat Jun 18 09:11:49 1994 John Gilmore (gnu@cygnus.com)
+
+ Make DES library independent of krb library.
+
+ * unix_glue.c, mac_glue.c, win_glue.c: Remove time-handling
+ code to ../../lib/des/*_time.c.
+
+Sat Jun 18 07:46:32 1994 John Gilmore (gnu@cygnus.com)
+
+ * send_to_kdc.c (send_recv): Use SOCKET_NFDS as first arg to
+ select().
+ * macsock.c (gethostname): Add incomplete stab at gethostname(),
+ under #if 0.
+ * cr_ciph.c, cr_tkt.c, decomp_tkt.c, g_ad_tkt.c, mac_store.c,
+ mk_req.c, mk_safe.c: Lint.
+
+Fri Jun 17 02:02:00 1994 John Gilmore (gnu@cygnus.com)
+
+ * DNR.c: New file of MacTCP interface code.
+ * macsock.c: To avoid using StreamPtr in <macsock.h>, declare
+ fStream as unsigned long. Cast it whenever we need it. This
+ removes the need to include MacTCP header files in <macsock.h>.
+ * macsock.c, mac_glue.c: Eliminate inclusion of "mac_glue.h".
+ * mac_glue.h: Remove.
+
+Thu Jun 16 17:30:04 1994 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (unixmac): New target.
+ * g_in_tkt.c: MPW complains about types without a cast.
+ * mac_glue.c: Pull networking code out into macsock.c.
+ (krb_get_phost): Pull this; use ordinary common version.
+ (krb_start_session, krb_end_session): Add.
+ * mac_store.c (gUserName): Add definition.
+ Move static declarations above where they're needed.
+ (krb_realmofhost): Return null pointer, not KFAILURE.
+ * macsock.c: New file, implements socket abstraction for UDP.
+ * memcache.c: Update header file handling. FIXME, works on Mac,
+ not on Windows too.
+ * send_to_kdc.c (send_to_kdc): Clean up error handling.
+ Improve comments. Add prototype for static function.
+ * stime.c: #define NEED_TIME_H. Use proper type for time_t.
+
+Wed Jun 15 16:35:52 1994 John Gilmore (gnu@cygnus.com)
+
+ * unix_glue.c (krb_start_session, krb_end_session): Take
+ args and ignore them, to match the prototypes.
+
+Fri Jun 10 22:52:14 1994 John Gilmore (gnu@cygnus.com)
+
+ * g_in_tkt.c (swap_bytes): Declare extern, not common.
+ * mac_glue.h: New (was called MacMachineDependencies.h in
+ an earlier incarnation).
+ * mac_glue.c: Add code for time zone and Domain Name
+ Service resolution.
+ * mac_store.c: Eliminate credential storage, leaving just
+ configuration storage. Initialize the store whenever a
+ high-level routine is called and we haven't initialized.
+ Return result from init_store, so callers can return
+ KFAILURE if we can't read the config data.
+ * mac_store.h: Pull credential storage (now in memcache.h).
+ * unix_glue.c (krb_start_session, krb_end_session,
+ krb_get_default_user): Provide dummy ones on Unix.
+
+Thu Jun 9 00:47:59 1994 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (SRCS, OBJS): Move cr_death_pkt.c and kparse.c
+ to SERVER_SRCS and SERVER_OBJS.
+ (DELIVERABLES, INSTALL_DELIVERABLES): Replace with ALL_WHAT
+ and INSTALL_WHAT, which actually work.
+ (all-unix): Main rule for building on Unix now.
+ (clean): Consolidate `make clean' entries so it actually works.
+
+Wed Jun 8 23:47:30 1994 John Gilmore (gnu@cygnus.com)
+
+ Further DLL support for Windows, plus, make previous
+ changes work on Unix again.
+
+ * memcache.c: New file implements ticket cacheing in RAM.
+ * memcache.h: Interface for memcache.c.
+
+ * win_glue.c: Remove stub interfaces for in_tkt, save_credentials,
+ krb_save_credentials, krb_get_cred, dest_tkt, krb_get_tf_realm.
+
+ * g_ad_tkt.c, g_in_tkt.c: Rename save_credentials to
+ krb_save_credentials.
+ * save_creds.c (save_credentials): Remove.
+ * g_in_tkt.c (decrypt_tkt, krb_get_in_tkt_preauth):
+ Declare and use new key_proc_type and decrypt_tkt_type
+ typedefs for pointers to function prototypes.
+ (krb_get_in_tkt): Move after krb_get_in_tkt_preauth.
+ * mk_preauth.c (krb_mk_preauth): Declare and use key_proc_type.
+
+ * dest_tkt.c (dest_tkt), in_tkt.c (in_tkt), g_tf_fname.c
+ (krb_get_tf_fullname): If ticket cache selector is null, use
+ default cache. (Cache selector used to be the result of
+ tkt_string; now tkt_string is called when it is null.)
+
+ * send_to_kdc.c: Replace all debug printf's with calls to
+ the DEB macro, which is a no-op unless #define DEBUG.
+ Insert #ifdef DEBUG where that is inconvenient. (DLL libc
+ doesn't seem to have printf.) Lint.
+
+ * g_krbrlm.c (krb_get_lrealm): Declare as INTERFACE.
+ Break out KRB_CONF into a static variable so we can debug it
+ easier.
+
+ * g_pw_in_tkt.c (krb_get_pw_in_tkt): Declare as INTERFACE.
+ Give an explicit error if the supplied password is null;
+ this forces the caller to supply us one, rather than relying
+ on a Kerberos library routine to interact with the user. Lint.
+ (passwd_to_key): Make extern. Don't call *_read_password.
+ (krb_get_pw_in_tkt_preauth): Give error for null password.
+ (placebo_read_password): Add FIXME comment.
+
+ * kerberos.def: Use PASCAL calling sequence (uppercase names,
+ no leading underlines) for interface functions.
+
+ * in_tkt.c, g_pw_in_tkt.c, kparse.c: Remove RCS crud.
+
+Fri May 27 09:25:14 1994 John Gilmore (gnu@cygnus.com)
+
+ Initial Dynamic Link Library support for MS-Windows.
+
+ * Makefile.in: Move more files to only build on SERVER machines.
+ (kerberos.dll, c-krbdll.rsp): Build dynamic link library for
+ MS-Windows.
+ (kerberos.lib): Build import library for MS-Windows.
+ (all-windows, install-windows): New targets for MS-Windows.
+
+ * kerberos.def: New file defines the Kerberos DLL interface.
+
+ * winsock.def: New file defines the WinSock DLL interface that
+ we rely upon. This file is from FTP:
+ //sunsite.unc.edu/pub/micro/pc-stuff/ms-windows/winsock/winsock-1.1
+ except that we made all the routine names uppercase, to match what
+ MicroSoft C does when you declare an interface routine PASCAL
+ (like all these routines).
+
+ * err_txt.c (krb_get_err_table, krb_get_err_text): New
+ functions for DLL access to the error table.
+
+ * g_admhst.c, g_cred.c, g_krbhst.c, g_phost.c, g_svc_in_tkt.c,
+ kname_parse.c, mk_err.c, mk_priv.c, mk_req.c, mk_safe.c, rd_err.c,
+ rd_priv.c, rd_req.c, rd_safe.c, realmofhost.c, recvauth.c,
+ sendauth.c: Add INTERFACE declaration to definitions of functions
+ that are exported via the DLL interface.
+
+ * win_glue.c (win_time_gmt_unixsec): Use static storage for
+ _ftime() arg, since it takes a near pointer and can't point to
+ stack storage when SS!=DS.
+ (in_tkt, save_credentials, krb_save_credentials, krb_get_cred,
+ dest_tkt, krb_get_tf_realm, krb_set_tkt_string,
+ krb_ignore_ip_address): Dummy routines for now.
+ (LibMain, WEP): No-op routines required for DLL initialization.
+ (krb_start_session, krb_end_session): No-op routines required for
+ Kerberos Mac interface compatability.
+
+ * save_creds.c (krb_save_credentials): Add new interface function
+ to replace save_credentials, which isn't well enough named to
+ export as part of the Kerberos interface.
+
+ * kname_parse.c, kparse.c, rd_safe.c, send_to_kdc.c: Move
+ printf's under #ifdef DEBUG since printf is not usually available
+ in MS-Windows. Change exit()'s under "can't happen" conditions to
+ return statements.
+
+ * g_krbhst.c: Clean up #ifdef'd braces so they match up.
+ * sendauth.c: Remove unused "extern int errno;".
+ * kname_parse.c: Remove unused extern of krb_err_txt.
+ * mk_err.c, save_creds.c: Remove RCS crud.
+ * ren.msg: Add rd_preauth.c and mk_preauth.c to DOS rename table.
+
+Wed May 25 09:17:06 1994 D V Henkel-Wallace (gumby@tweedledumb.cygnus.com)
+
+ * g_pw_in_tkt.c: when read_password.c was inserted whole into this
+ file, des.h and conf.h were #include'ed, which causes circularity
+ problems. #include's removed; they weren't needed anyway.
+
+Tue May 24 00:55:30 1994 John Gilmore (gnu@cygnus.com)
+
+ * sendauth.c: Break up into separately callable functions to
+ avoid pushing binary data down a socket supposedly controlled
+ by the kerberos library's caller.
+ (krb_mk_auth): New; builds a packet and returns it to you.
+ (krb_net_rd_sendauth): Reads a packet from the net.
+ (krb_check_auth): Checks an incoming response for validity.
+ FIXME: ATHENA_COMPAT code in here is now broken. Remove it?
+ FIXME: Break up into separate files so that the non file
+ descriptor part can be included on Mac.
+
+ * g_admhst.c, mk_req.c: Pull RCS crud.
+
+ * mk_req.c: Allow the realm argument to be defaulted with a null
+ pointer. This makes it suitable for building krb_sendauth
+ messages directly.
+
+ * tf_util.c (tf_init): If argument is null, call tkt_string to
+ select a ticket cache. See also ../../include/krb-sed.h, where
+ the default argument was changed to be null.
+
+ * send_to_kdc.c (MAX_HSTNM): Eliminate only use of this obsolete
+ define; use MAXHOSTNAMELEN which is set properly in each system.
+
+ * fakeenv.c: Update copyright notice (it's now public domain,
+ freed by Cygnus Support, for whom the work was done for hire).
+
+Mon May 23 00:19:46 1994 Mark Eichin (eichin at tweedledumb.cygnus.com)
+
+ * rd_svc_key.c (get_service_key): new function. Same as original
+ read_service_key except that it takes argument kvno by reference,
+ so the caller can figure out what key actually matched. Also
+ defaults to KEYFILE if file argument is NULL (instead of just
+ calling open with that value.) Also defaults to current realm if
+ realm argument not passed in.
+ (read_service_key): now calls get_service_key.
+
+ * rd_safe.c (krb_rd_safe): check krb_ignore_ip_address before
+ deciding to fail on an IP address check.
+ (krb_rd_safe): remove "direction checking" code which doesn't
+ actually help, and can interfere if IP addresses are optional.
+
+ * rd_req.c (krb_rd_req): check krb_ignore_ip_address before
+ deciding to fail on an IP address check; move test to end of
+ function as well (to provide more information value in the
+ RD_AP_BADD error return.)
+
+ * rd_req.c: define (allocate) krb_ignore_ip_address.
+
+ * rd_priv.c (krb_rd_priv): check global variable
+ krb_ignore_ip_address before deciding to fail on an IP address
+ check.
+ (krb_rd_priv): remove "direction checking" code which doesn't
+ actually help, and can interfere if IP addresses are optional.
+
+ * netread.c (krb_net_read): use socket_read under VMS, assuming
+ MultiNet.
+
+ * netwrite.c (krb_net_write): use socket_write under VMS, assuming
+ MultiNet.
+
+ * mk_priv.c (krb_mk_priv): If private_msg_ver isn't set yet, use
+ the expected version (KRB_PROT_VERSION) instead.
+
+ * Makefile.in (SRCS, OBJS): added mk_preauth, rd_preauth.
+
+ * g_in_tkt.c (krb_get_in_tkt_preauth): New function. Supports
+ simple preauthentication by appending data to the initial packet.
+ Demonstration hooks only.
+
+ * g_svc_in_tkt.c (krb_get_svc_in_tkt_preauth): New function.
+ Preauthentication support for initial tickets for servers.
+ (krb_svc_init): New function. An interface to krb_get_svc_in_tkt
+ that is provided by DEC's dss-kerberos, added here for
+ compatibility.
+ (krb_svc_init_preauth): preauthentication version of krb_svc_init.
+
+ * g_pw_in_tkt.c (krb_get_pw_in_tkt_preauth): New function.
+ Higher level interface to g_in_tkt for users.
+
+ * g_pw_in_tkt.c: in NOENCRYPTION section, pull in <sgtty.h>
+ under __svr4__ so the ioctls work under Solaris.
+
+Sat May 21 04:02:59 1994 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (c-libkrb.${LIBEXT}): Typos, do .o->.obj.
+ * gethostname.c: Simplify to call GETHOSTNAME macro.
+ * stime.c: Arg is *time, not time. Oops. Also simplify.
+ * win_glue.c: Support CONVERT_TIME_EPOCH and make it work
+ for the odd epoch on MSC 7.0.
+ (win_socket_initialize): New routine implements SOCKET_INITIALIZE.
+ (in_tkt, save_credentials, dest_tkt): Stubs to link kinit with.
+
+ First FAR crap in our clean sources (sigh).
+
+ * win_glue.c (far_fputs): Print a far string returned by WinSock.
+ * ad_print.c: Handle FAR pointer from inet_ntoa.
+ * g_phost.c: Handle FAR pointer returned by gethostby*.
+
+ * send_to_kdc.c: Convert to WinSock plus local macros that make
+ compatability easier. Initialize and terminate WinSock access
+ each time we are called. Handle FAR pointer from get*by* and
+ inet_ntoa. Bind the datagram socket before using it, to get
+ beyond a bug in FTP Software's WinSock libraries. Improve debug
+ messages.
+
+Thu May 19 22:57:13 1994 John Gilmore (gnu@cygnus.com)
+
+ More Windows support.
+
+ * Makefile.in (LIBEXT): Use everywhere.
+ (SERVER_KRB_{SRCS,OBJS}): Rename from SERVERSIDE*.
+ (ARCHIVEARGS): Implement MSC LIB support.
+ (####): Move insertion point of host-configuration fragments
+ down so they can override the various Makefile macros.
+ (libkrb.$(LIBEXT)): Avoid keeping a .bak file. Use ARCHIVEARGS.
+ (unixdos): New target for things that have to run on Unix
+ after configuring for DOS. (FIXME, make these work on DOS.)
+ (c-libkrb.$(LIBEXT)): Build control file for MSC. This
+ currently must run on Unix (FIXME).
+
+ * stime.c: Use CONVERT_TIME_EPOCH.
+
+Sat May 14 00:49:11 1994 John Gilmore (gnu@cygnus.com)
+
+ More Macintosh merging.
+
+ * Makefile.in (CACHESRCS, CACHEOBJS, REALMDBSRCS, REALMDBOBJS,
+ SERVERSIDESRCS, SERVERSIDEOBJS): Update the lists of files that
+ belong to each category.
+ * unix-glue.c, mac-glue.c, win-glue.c: Rename to unix_glue.c,
+ mac_glue.c, win_glue.c.
+ * g_ad_tkt.c: Improve comments on cross-realm support.
+ * g_phost.c: Remove RCS crud.
+ * store.c, store.h: Rename to mac_store.c, mac_store.h. Insert
+ all the Kerberos glue routines needed to talk to the Cygnus code.
+
+Fri May 13 17:40:02 1994 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (SERVERSIDESRCS, SERVERSIDEOBJS): Create
+ as lists of lib/krb files only used on servers, so they can
+ be avoided when on client-only machines.
+ (CACHESRCS, CACHEOBJS): Put all the rightful files in there.
+ * realmofhost.c: Pull <sys/param.h> and default MAXHOSTNAMELEN.
+ * dest_tkt.c, realmofhost.c, tf_shm.c: Remove RCS crud.
+ * rd_safe.c, tf_shm.c: Remove errno declaration, <errno.h>, etc.
+ * mk_priv.c: Comment changes.
+ * g_ad_tkt.c: Remove obsolete defn of <sys/time.h>.
+
+Fri May 13 12:17:32 1994 John Gilmore (gnu@cygnus.com)
+
+ Macintosh changes.
+
+ * store.h, store.c: Ticket storage in memory on the Mac.
+ * mac-glue.c: New file, deals with OS and time interface.
+ * Makefile.in: Pull tf_util.[co] out into CACHESRCS and
+ CACHEOBJS, so it can be excluded on Mac and Windows.
+ * g_in_tkt.c: Don't declare signed difference t_diff as unsigned!
+ * g_ad_tkt.c, rd_safe.c, rd_req.c, rd_priv.c, mk_safe.c, mk_req.c:
+ Remove <sys/time.h>. Use TIME_GMT_UNIXSEC and clean up datatype
+ issues around clock-skew/ticket-replay checking. Remove __i960__
+ conditionals, which should be handled by changing CLOCK_SKEW in
+ 960-specific config files.
+ * mk_priv.c: Rename TIME_GMT_UNIXSEC_MS to TIME_GMT_UNIXSEC_US.
+ * setenv.c: Remove <sys/types.h>.
+ * rd_priv.c, mk_safe.c: Remove <errno.h>, and decls of errno and
+ errmsg.
+ * rd_req.c, stime.c, mk_safe.c: Remove RCS crud.
+
+Fri May 13 02:02:56 1994 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in: Support glue files for each major architecture
+ (Unix, mac, windows). Replace {} with () for DOS NMAKE.
+ Build krb_err.h without `make depend'. Remove -DBSD42 since it
+ is no longer used.
+ * unix-glue.c: New file, interfaces to Unix gettimeofday.
+ * win-glue.c: New file, interfaces to Windows _ftime.
+ * g_in_tkt.c, mk_priv.c: Pull <sys/time.h>, use new macro interface
+ TIME_GMT_UNIXSEC to get the time.
+ * gethostname.c: Pull BSD42. Insert FIXME comments about the
+ poor DOS support.
+ * mk_priv.c: Pull <errno.h>, errno, and errmsg as unused.
+
+ * ad_print.c: Pull <arpa/inet.h>, which is now in <krb.h>.
+ * decomp_tkt.c: Add file name to title comments.
+ * fakeenv.c: Pull <sys/types.h> and <stdio.h>.
+ * g_phost.c: Replace <netdb.h> and <osconf.h> with <krb.h>.
+ * ren.msg: Remove get_request.c (g_request.c), now gone.
+ * send_to_kdc.c: Pull <netdb.h>.
+ * setenv.c: Add "conf.h" for non-cmd-line configuration.
+
+Sun May 8 23:34:16 1994 John Gilmore (gnu@cygnus.com)
+
+ Include-file straightening: Remove Unix include
+ files from as many routines as possible -- particularly
+ <sys/types.h> and network include files.
+
+ * ad_print.c: Use DEFINE_SOCKADDR to get struct sockaddr_in.
+ Lint. Pull RCS crud.
+ * cr_err_repl.c, tf_shm.c, tf_util.c, tkt_string.c: Pull
+ <sys/types.h>.
+ * cr_tkt.c, decomp_tkt.c: Pull <stdio.h>.
+ * dest_tkt.c, in_tkt.c, mk_err.c: Pull <sys/types.h>
+ * g_ad_tkt.c: Pull <sys/types.h>, <errno.h>, RCS crud.
+ * g_cred.c: Pull RCS crud, add <string.h>.
+ * g_in_tkt.c: Pull <sys/types.h>, <errno.h>, <stdio.h>, RCS crud.
+ * g_tf_fname.c: Lint, pull RCS crud.
+ * kuserok.c: <pull <sys/types.h> and <sys/socket.h>.
+ * rd_err.c: Pull <stdio.h>, <errno.h>, <sys/types.h>, <sys/times.h>.
+ * mk_priv.c, mk_safe.c, rd_err.c, rd_priv.c, rd_safe.c,
+ recvauth.c, send_to_kdc.c, sendauth.c: Use DEFINE_SOCKADDR to get
+ struct sockaddr_in.
+ * cr_tkt.c, debug.c, mk_safe.c, rd_err.c, rd_safe.c, recvauth.c,
+ sendauth.c: Pull RCS crud.
+ * rd_safe.c, sendauth.c: Lint.
+ * strcasecmp.c: Remove <sys/types.h> and change the few
+ occurrances of u_foo types to `unsigned foo'. Pull SCCS crud(!).
+
+Sun May 8 19:24:08 1994 John Gilmore (gnu@cygnus.com)
+
+ * add_tkt.c, ext_tkt.c: Remove, unused. As its comments say:
+ This routine is now obsolete. It used to be possible to request
+ more than one ticket at a time from the authentication server, and
+ it looks like this routine was used by the server to package the
+ tickets to be returned to the client.
+
+ * g_request.c: Remove, unused. Its comments:
+ This procedure is obsolete. It is used in the kerberos_slave
+ code for Version 3 tickets.
+
+ * getopt.c: Remove, unused.
+ * Makefile.in: Remove unused files.
+
+Sat May 7 13:44:20 1994 John Gilmore (gnu@cygnus.com)
+
+ * krbglue.c: Remove, unused. Mark Eichin says:
+ krbglue, if I recall correctly, was backwards compatibility code so
+ that programs that were written with V3 could be relinked with V4
+ without recompiling. The Zephyr code used it at one point, though I
+ doubt it does anymore. It's probably sufficient to note that in the
+ cvs log when you delete it.
+
+ * krbglue.c, recvauth.c, sendauth.c: Lint.
+
+Fri May 6 21:11:10 1994 John Gilmore (gnu@cygnus.com)
+
+ * ren-cyg.sh, ren-pc.sh, ren-pl10.sh, ren.msg.sh, ren2dos,
+ ren2long.sh sed-cyg.sh, ren-pc.bat, sed-pc.sh: Update for final
+ DOS renaming.
+
+Fri May 6 18:32:11 1994 John Gilmore (gnu@cygnus.com)
+
+ * rd_priv.c, mk_priv.c, rd_safe.c, mk_safe.c: Rename include
+ file "lsb_addr_comp.h" to "lsb_addr_cmp.h" for DOS/SYSV.
+
+Fri May 6 02:10:50 1994 John Gilmore (gnu@cygnus.com)
+
+ * krbglue.c: Move Kerberos function prototypes to ../include/krb.h.
+ Yank RCS. Lint.
+ * mk_priv.c (krb_mk_priv), rd_priv.c (krb_rd_priv): Lint. Yank RCS.
+
+Thu May 5 12:49:34 1994 John Gilmore (gnu@cygnus.com)
+
+ * decomp_tkt.c: Remove need for <sys/file.h> under KRB_CRYPT_DEBUG
+ by using stdio. Call krb_log, not log. Lint. Remove RCS ID's.
+
+ * g_tf_realm.c: Lint.
+
+Tue Apr 26 20:54:29 1994 John Gilmore (gnu@tweedledumb.cygnus.com)
+
+ Massive file renaming for DOS compatability.
+
+ * ren.msg, ren-cyg.sh, sed-cyg.sh: New files.
+
+ * Imakefile, Makefile.in: File names edited throughout.
+
+ * add_ticket.c, cr_auth_reply.c, cr_err_reply.c, create_ciph.c,
+ create_ticket.c, debug_decl.c, decomp_ticket.c, extract_tkt.c,
+ get_ad_tkt.c, get_admhst.c, get_cred.c, get_in_tkt.c, get_krbhst.c,
+ get_krbrlm.c, get_phost.c, get_pw_tkt.c, get_request.c, get_svc_in.c,
+ get_tf_fname.c, get_tf_realm.c, getrealm.c, k_gethostname.c,
+ krb_err_txt.c, krb_get_in.c, read_svc_key.c, util.c: Renamed.
+
+ * ad_print.c, add_tkt.c, cr_auth_repl.c, cr_ciph.c, cr_err_repl.c,
+ cr_tkt.c, debug.c, decomp_tkt.c, err_txt.c, ext_tkt.c, g_ad_tkt.c,
+ g_admhst.c, g_cred.c, g_in_tkt.c, g_krbhst.c, g_krbrlm.c,
+ g_phost.c, g_pw_in_tkt.c, g_pw_tkt.c, g_request.c, g_svc_in_tkt.c,
+ g_tf_fname.c, g_tf_realm.c, gethostname.c, rd_svc_key.c,
+ realmofhost.c: Same files, renamed.
+
+Sun Jan 30 17:28:57 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * getrealm.c (krb_realmofhost): Rearrange loop so that strcasecmp
+ is called only once for domains listed in krb.conf, and exiting
+ function is cleaner.
+
diff --git a/src/lib/krb4/DNR.c b/src/lib/krb4/DNR.c
new file mode 100644
index 0000000000..4f49121ade
--- /dev/null
+++ b/src/lib/krb4/DNR.c
@@ -0,0 +1,309 @@
+/* DNR.c - DNR library for MPW
+
+ (c) Copyright 1988 by Apple Computer. All rights reserved
+
+ Modifications by Jim Matthews, Dartmouth College, 5/91
+
+ FIXME jcm - copied from Authman 1.0.7 release, file not in ftp.seeding.apple.com
+ FIXME jcm - slight improvments over the version in the KClient 1.1b1 release
+ FIXME jcm - All rights reserved Apple Computer
+*/
+
+#include <OSUtils.h>
+#include <Errors.h>
+#include <Files.h>
+#include <Resources.h>
+#include <Memory.h>
+#include <Traps.h>
+#include <GestaltEqu.h>
+#include <Folders.h>
+#include <ToolUtils.h>
+
+#define OPENRESOLVER 1L
+#define CLOSERESOLVER 2L
+#define STRTOADDR 3L
+#define ADDRTOSTR 4L
+#define ENUMCACHE 5L
+#define ADDRTONAME 6L
+#define HINFO 7L
+#define MXINFO 8L
+
+Handle codeHndl = nil;
+
+typedef OSErr (*OSErrProcPtr)(long,...);
+OSErrProcPtr dnr = nil;
+
+
+TrapType GetTrapType(theTrap)
+unsigned long theTrap;
+{
+ if (BitAnd(theTrap, 0x0800) > 0)
+ return(ToolTrap);
+ else
+ return(OSTrap);
+ }
+
+Boolean TrapAvailable(trap)
+unsigned long trap;
+{
+TrapType trapType = ToolTrap;
+unsigned long numToolBoxTraps;
+
+ if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
+ numToolBoxTraps = 0x200;
+ else
+ numToolBoxTraps = 0x400;
+
+ trapType = GetTrapType(trap);
+ if (trapType == ToolTrap) {
+ trap = BitAnd(trap, 0x07FF);
+ if (trap >= numToolBoxTraps)
+ trap = _Unimplemented;
+ }
+ return(NGetTrapAddress(trap, trapType) != NGetTrapAddress(_Unimplemented, ToolTrap));
+
+}
+
+void GetSystemFolder(short *vRefNumP, long *dirIDP)
+{
+ SysEnvRec info;
+ long wdProcID;
+
+ SysEnvirons(1, &info);
+ if (GetWDInfo(info.sysVRefNum, vRefNumP, dirIDP, &wdProcID) != noErr) {
+ *vRefNumP = 0;
+ *dirIDP = 0;
+ }
+ }
+
+void GetCPanelFolder(short *vRefNumP, long *dirIDP)
+{
+ Boolean hasFolderMgr = false;
+ long feature;
+
+/*
+ if (TrapAvailable(_GestaltDispatch)) if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) hasFolderMgr = true;
+
+ FIXME jcm - what defines _Gestalt
+ if (TrapAvailable(_Gestalt))
+*/
+ if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) hasFolderMgr = true;
+ if (!hasFolderMgr) {
+ GetSystemFolder(vRefNumP, dirIDP);
+ return;
+ }
+ else {
+ if (FindFolder(kOnSystemDisk, kControlPanelFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
+ *vRefNumP = 0;
+ *dirIDP = 0;
+ }
+ }
+ }
+
+/* SearchFolderForDNRP is called to search a folder for files that might
+ contain the 'dnrp' resource */
+short SearchFolderForDNRP(long targetType, long targetCreator, short vRefNum, long dirID)
+{
+ HParamBlockRec fi;
+ Str255 filename;
+ short refnum;
+
+ fi.fileParam.ioCompletion = nil;
+ fi.fileParam.ioNamePtr = filename;
+ fi.fileParam.ioVRefNum = vRefNum;
+ fi.fileParam.ioDirID = dirID;
+ fi.fileParam.ioFDirIndex = 1;
+
+ while (PBHGetFInfo(&fi, false) == noErr) {
+ /* scan system folder for driver resource files of specific type & creator */
+ if (fi.fileParam.ioFlFndrInfo.fdType == targetType &&
+ fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) {
+ /* found the MacTCP driver file? */
+
+ refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm);
+
+ SetResLoad(false);
+ if (GetIndResource('dnrp', 1) == NULL) {
+ SetResLoad(true);
+ CloseResFile(refnum);
+ }
+ else {
+ SetResLoad(true);
+ return refnum;
+ }
+ SetResLoad(true);
+ }
+ /* check next file in system folder */
+ fi.fileParam.ioFDirIndex++;
+ fi.fileParam.ioDirID = dirID; /* PBHGetFInfo() clobbers ioDirID */
+ }
+ return(-1);
+ }
+
+/* OpenOurRF is called to open the MacTCP driver resources */
+
+short OpenOurRF()
+{
+ short refnum;
+ short vRefNum;
+ long dirID;
+
+ /* first search Control Panels for MacTCP 1.1 */
+ GetCPanelFolder(&vRefNum, &dirID);
+ refnum = SearchFolderForDNRP('cdev', 'ztcp', vRefNum, dirID);
+ if (refnum != -1) return(refnum);
+
+ /* next search System Folder for MacTCP 1.0.x */
+ GetSystemFolder(&vRefNum, &dirID);
+ refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
+ if (refnum != -1) return(refnum);
+
+ /* finally, search Control Panels for MacTCP 1.0.x */
+ GetCPanelFolder(&vRefNum, &dirID);
+ refnum = SearchFolderForDNRP('cdev', 'mtcp', vRefNum, dirID);
+ if (refnum != -1) return(refnum);
+
+ return -1;
+ }
+
+
+OSErr OpenResolver(fileName)
+char *fileName;
+{
+ short refnum;
+ OSErr rc;
+
+ if (dnr != nil)
+ /* resolver already loaded in */
+ return(noErr);
+
+ /* open the MacTCP driver to get DNR resources. Search for it based on
+ creator & type rather than simply file name */
+ refnum = OpenOurRF();
+
+ /* ignore failures since the resource may have been installed in the
+ System file if running on a Mac 512Ke */
+
+ /* load in the DNR resource package */
+ codeHndl = GetIndResource('dnrp', 1);
+ if (codeHndl == nil) {
+ /* can't open DNR */
+ return(ResError());
+ }
+
+ DetachResource(codeHndl);
+ if (refnum != -1) {
+ CloseWD(refnum);
+ CloseResFile(refnum);
+ }
+
+ /* lock the DNR resource since it cannot be reloated while opened */
+ HLock(codeHndl);
+ dnr = (OSErrProcPtr) *codeHndl;
+
+ /* call open resolver */
+ rc = (*dnr)(OPENRESOLVER, fileName);
+ if (rc != noErr) {
+ /* problem with open resolver, flush it */
+ HUnlock(codeHndl);
+ DisposHandle(codeHndl);
+ dnr = nil;
+ }
+ return(rc);
+ }
+
+
+OSErr CloseResolver()
+{
+ if (dnr == nil)
+ /* resolver not loaded error */
+ return(notOpenErr);
+
+ /* call close resolver */
+ (void) (*dnr)(CLOSERESOLVER);
+
+ /* release the DNR resource package */
+ HUnlock(codeHndl);
+ DisposHandle(codeHndl);
+ dnr = nil;
+ return(noErr);
+ }
+
+OSErr StrToAddr(hostName, rtnStruct, resultproc, userDataPtr)
+char *hostName;
+struct hostInfo *rtnStruct;
+long resultproc;
+char *userDataPtr;
+{
+ if (dnr == nil)
+ /* resolver not loaded error */
+ return(notOpenErr);
+
+ return((*dnr)(STRTOADDR, hostName, rtnStruct, resultproc, userDataPtr));
+ }
+
+OSErr AddrToStr(addr, addrStr)
+unsigned long addr;
+char *addrStr;
+{
+ if (dnr == nil)
+ /* resolver not loaded error */
+ return(notOpenErr);
+
+ (*dnr)(ADDRTOSTR, addr, addrStr);
+ return(noErr);
+ }
+
+OSErr EnumCache(resultproc, userDataPtr)
+long resultproc;
+char *userDataPtr;
+{
+ if (dnr == nil)
+ /* resolver not loaded error */
+ return(notOpenErr);
+
+ return((*dnr)(ENUMCACHE, resultproc, userDataPtr));
+ }
+
+
+OSErr AddrToName(addr, rtnStruct, resultproc, userDataPtr)
+unsigned long addr;
+struct hostInfo *rtnStruct;
+long resultproc;
+char *userDataPtr;
+{
+ if (dnr == nil)
+ /* resolver not loaded error */
+ return(notOpenErr);
+
+ return((*dnr)(ADDRTONAME, addr, rtnStruct, resultproc, userDataPtr));
+ }
+
+
+extern OSErr HInfo(hostName, returnRecPtr, resultProc, userDataPtr)
+char *hostName;
+struct returnRec *returnRecPtr;
+long resultProc;
+char *userDataPtr;
+{
+ if (dnr == nil)
+ /* resolver not loaded error */
+ return(notOpenErr);
+
+ return((*dnr)(HINFO, hostName, returnRecPtr, resultProc, userDataPtr));
+
+ }
+
+extern OSErr MXInfo(hostName, returnRecPtr, resultProc, userDataPtr)
+char *hostName;
+struct returnRec *returnRecPtr;
+long resultProc;
+char *userDataPtr;
+{
+ if (dnr == nil)
+ /* resolver not loaded error */
+ return(notOpenErr);
+
+ return((*dnr)(MXINFO, hostName, returnRecPtr, resultProc, userDataPtr));
+
+ } \ No newline at end of file
diff --git a/src/lib/krb4/Makefile.in b/src/lib/krb4/Makefile.in
new file mode 100644
index 0000000000..6571db95b1
--- /dev/null
+++ b/src/lib/krb4/Makefile.in
@@ -0,0 +1,264 @@
+WHAT=unix
+CFLAGS = $(CCOPTS) $(DEFS) $(DEFINES)
+
+##DOSBUILDTOP = ..\..\..
+##DOSLIBNAME=..\krb5.lib
+##DOS!include $(BUILDTOP)\config\windows.in
+
+OBJS = \
+ cr_auth_repl.$(OBJEXT) \
+ cr_ciph.$(OBJEXT) \
+ cr_tkt.$(OBJEXT) \
+ debug.$(OBJEXT) \
+ decomp_tkt.$(OBJEXT) \
+ err_txt.$(OBJEXT) \
+ g_ad_tkt.$(OBJEXT) \
+ g_in_tkt.$(OBJEXT) \
+ g_phost.$(OBJEXT) \
+ g_pw_in_tkt.$(OBJEXT) \
+ g_pw_tkt.$(OBJEXT) \
+ g_tkt_svc.$(OBJEXT) \
+ gethostname.$(OBJEXT) \
+ getst.$(OBJEXT) \
+ kname_parse.$(OBJEXT) \
+ mk_auth.$(OBJEXT) \
+ mk_err.$(OBJEXT) \
+ mk_priv.$(OBJEXT) \
+ mk_req.$(OBJEXT) \
+ mk_safe.$(OBJEXT) \
+ month_sname.$(OBJEXT) \
+ one.$(OBJEXT) \
+ pkt_cipher.$(OBJEXT) \
+ pkt_clen.$(OBJEXT) \
+ rd_err.$(OBJEXT) \
+ rd_priv.$(OBJEXT) \
+ rd_safe.$(OBJEXT) \
+ send_to_kdc.$(OBJEXT) \
+ stime.$(OBJEXT) \
+ rd_preauth.$(OBJEXT) \
+ mk_preauth.$(OBJEXT) \
+ unix_time.$(OBJEXT) \
+ $(CACHEOBJS) $(SETENVOBJS) $(STRCASEOBJS) $(SHMOBJS) \
+ $(LIB_KRB_HOSTOBJS) $(SERVER_KRB_OBJS) $(NETIO_OBJS) $(REALMDBOBJS)
+
+SRCS = \
+ $(srcdir)/cr_auth_repl.c \
+ $(srcdir)/cr_ciph.c \
+ $(srcdir)/cr_tkt.c \
+ $(srcdir)/debug.c \
+ $(srcdir)/decomp_tkt.c \
+ $(srcdir)/g_ad_tkt.c \
+ $(srcdir)/g_pw_in_tkt.c \
+ $(srcdir)/g_phost.c \
+ $(srcdir)/g_pw_tkt.c \
+ $(srcdir)/g_tkt_svc.c \
+ $(srcdir)/getst.c \
+ $(srcdir)/gethostname.c \
+ $(srcdir)/kname_parse.c \
+ $(srcdir)/err_txt.c \
+ $(srcdir)/g_in_tkt.c \
+ $(srcdir)/mk_auth.c \
+ $(srcdir)/mk_err.c \
+ $(srcdir)/mk_priv.c \
+ $(srcdir)/mk_req.c \
+ $(srcdir)/mk_safe.c \
+ $(srcdir)/month_sname.c \
+ $(srcdir)/one.c \
+ $(srcdir)/pkt_cipher.c \
+ $(srcdir)/pkt_clen.c \
+ $(srcdir)/rd_err.c \
+ $(srcdir)/rd_priv.c \
+ $(srcdir)/rd_safe.c \
+ $(srcdir)/send_to_kdc.c \
+ $(srcdir)/stime.c \
+ $(srcdir)/rd_preauth.c \
+ $(srcdir)/mk_preauth.c \
+ $(srcdir)/unix_time.c \
+ $(CACHESRCS) $(SETENVSRCS) $(STRCASESRCS) $(SHMSRCS) \
+ $(LIB_KRB_HOSTSRCS) $(SERVER_KRB_SRCS) $(NETIO_OBJS) $(REALMDBSRCS)
+
+
+#
+# These objects implement ticket cacheing for Unix. They are
+# replaced by other files when compiling for Windows or Mac.
+#
+CACHESRCS=$(srcdir)/tf_util.c $(srcdir)/dest_tkt.c $(srcdir)/in_tkt.c \
+ $(srcdir)/tkt_string.c $(srcdir)/g_tf_fname.c \
+ $(srcdir)/g_tf_realm.c $(srcdir)/g_cred.c $(srcdir)/save_creds.c
+CACHEOBJS=tf_util.$(OBJEXT) dest_tkt.$(OBJEXT) in_tkt.$(OBJEXT) \
+ tkt_string.$(OBJEXT) g_tf_fname.$(OBJEXT) g_tf_realm.$(OBJEXT) \
+ g_cred.$(OBJEXT) save_creds.$(OBJEXT)
+
+#
+# These objects implement Kerberos realm<->host database lookup.
+# They read config files and/or network databases in various ways
+# on various platforms.
+#
+REALMDBSRCS= $(srcdir)/g_cnffile.c $(srcdir)/g_krbhst.c $(srcdir)/g_krbrlm.c \
+ $(srcdir)/g_admhst.c $(srcdir)/realmofhost.c
+REALMDBOBJS= g_cnffile.$(OBJEXT) g_krbhst.$(OBJEXT) g_krbrlm.$(OBJEXT) \
+ g_admhst.$(OBJEXT) realmofhost.$(OBJEXT)
+
+#
+# These objects are only used on server or debug implementations of Kerberos,
+# and they cause some major or minor sort of trouble for some
+# client-only platform (Mac or Windows).
+#
+SERVER_KRB_SRCS=$(srcdir)/klog.c $(srcdir)/kuserok.c $(srcdir)/log.c \
+ $(srcdir)/kntoln.c $(srcdir)/fgetst.c $(srcdir)/rd_svc_key.c \
+ $(srcdir)/cr_err_repl.c $(srcdir)/rd_req.c \
+ $(srcdir)/g_svc_in_tkt.c $(srcdir)/recvauth.c \
+ krb_err.c $(srcdir)/ad_print.c \
+ $(srcdir)/cr_death_pkt.c $(srcdir)/kparse.c \
+ $(srcdir)/put_svc_key.c $(srcdir)/sendauth.c
+SERVER_KRB_OBJS=klog.$(OBJEXT) kuserok.$(OBJEXT) log.$(OBJEXT) \
+ kntoln.$(OBJEXT) \
+ fgetst.$(OBJEXT) rd_svc_key.$(OBJEXT) cr_err_repl.$(OBJEXT) \
+ rd_req.$(OBJEXT) g_svc_in_tkt.$(OBJEXT) recvauth.$(OBJEXT) \
+ krb_err.$(OBJEXT) ad_print.$(OBJEXT) cr_death_pkt.$(OBJEXT) \
+ kparse.$(OBJEXT) put_svc_key.$(OBJEXT) sendauth.$(OBJEXT)
+#
+# These objects are included on Unix and Windows (for kstream and kadm)
+# but not under Mac (there are no file descriptors).
+#
+NETIO_SRCS=$(srcdir)/netread.c $(srcdir)/netwrite.c
+NETIO_OBJS=netread.$(OBJEXT) netwrite.$(OBJEXT)
+
+#
+# These objects glue the Kerberos library to the operating system
+# (time-of-day access, etc). They are replaced in Mac and Windows
+# by other _glue.* routines.
+#
+LIB_KRB_HOSTSRCS=$(srcdir)/unix_glue.c
+LIB_KRB_HOSTOBJS=unix_glue.$(OBJEXT)
+
+LIBNAME=libkrb4.$(LIBEXT)
+
+ARCHIVEARGS= $@ $(OBJS)
+
+CODE=$(SRCS) Makefile.in krb_err.et
+
+all:: all-really
+
+#### include configury here
+##DOS!include ..\..\config\common
+##DOS!include ..\..\config\mt-win
+
+# We only have a final value of $(WHAT) at this point, and Microsoft
+# NMAKE expands the macros in dependency lines before it finishes reading
+# the whole file (sigh)...
+all-really:: all-$(WHAT)
+install:: install-$(WHAT)
+
+# We want *library* compiler options...
+DBG=$(DBG_LIB)
+
+all-unix:: $(LIBNAME) krb_err.h
+
+# comp_et_depend(krb_err)
+krb_err.h:: krb_err.et
+krb_err.c: krb_err.et
+
+depend:: krb_err.h
+#
+
+depend:: $(CODE)
+
+krb_err.h::
+ -if cmp krb_err.h ../../include/krb_err.h >/dev/null 2>&1; then \
+ echo ; \
+ else \
+ $(RM) ../../include/krb_err.h ; \
+ $(CP) krb_err.h ../../include/krb_err.h; \
+ fi
+
+#install-unix::
+# $(INSTALL_DATA) krb_err.h $(DESTDIR)$(KRB5_INCDIR)/kerberosIV/krb_err.h
+
+
+DEFINES=$(FALLBACK) $(OLD_SRVTAB) $(OLD_KLOGIN) -I$(srcdir)/../../include/kerberosIV
+
+all-unix:: krb_err.h
+
+$(LIBNAME): $(OBJS)
+ $(RM) $@
+ $(ARCHIVE) $(ARCHIVEARGS)
+ $(RANLIB) $@
+
+#
+# What we build for `all' and `install' targets on Windows
+#
+all-windows: winsock.lib kerberos.lib kerberos.dll
+
+install-windows:
+ copy winsock.lib ..\..\floppy
+ copy kerberos.lib ..\..\floppy
+ copy kerberos.dll ..\..\floppy
+
+#
+# The "Import Library" definitions for MS-Windows
+#
+kerberos.lib: kerberos.dll
+ implib /nologo $@ $(@R).dll
+
+winsock.lib: winsock.def
+ implib /nologo winsock.lib winsock.def
+
+#
+# The Kerberos "Dynamic Link Library" for MS-Windows
+#
+kerberos.dll: kerberos.def winsock.lib \
+ $(DES_LIB_FOR_DLL) $(KADM_LIB_FOR_DLL) $(KSTREAM_LIB_FOR_DLL) \
+ $(LIBNAME)
+ $(RM) $@
+# this a.def and a.dll stuff is for line-too-long crap
+ copy kerberos.def a.def
+ copy $(DES_LIB_FOR_DLL) a.lib
+ copy $(KADM_LIB_FOR_DLL) b.lib
+ copy $(KSTREAM_LIB_FOR_DLL) c.lib
+ link /nologo /noe debug, $@,,\
+ $(LIBNAME) a.lib b.lib c.lib\
+ winsock ldllcew libw, $(@R).def
+ del a.lib
+ del b.lib
+ del c.lib
+ rc /p /k $@
+
+clean:: clean-$(WHAT)
+ -$(RM) $(LIBNAME)
+ -$(RM) *.$(OBJEXT)
+
+clean-:: clean-unix
+clean-unix::
+ -$(RM) krb_err.c
+ -$(RM) krb_err.h
+
+clean-windows::
+ -$(RM) kerberos.lib
+ -$(RM) kerberos.bak
+ -$(RM) kerberos.dll
+ -$(RM) kerberos.lst
+ -$(RM) kerberos.map
+ -$(RM) libkrb.lst
+ -$(RM) libkrb.bak
+ -$(RM) winsock.lib
+ -$(RM) msvc.pdb
+ -$(RM) proj.err
+ -$(RM) ..\..\floppy\winsock.lib
+ -$(RM) ..\..\floppy\kerberos.lib
+ -$(RM) ..\..\floppy\kerberos.dll
+
+install-unix::
+ $(INSTALL_DATA) $(LIBNAME) $(DESTDIR)$(KRB5_LIBDIR)/$(LIBNAME)
+ $(CHMOD) 644 $(DESTDIR)$(KRB5_LIBDIR)/$(LIBNAME)
+ $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/$(LIBNAME)
+ $(CHMOD) 444 $(DESTDIR)$(KRB5_LIBDIR)/$(LIBNAME)
+
+
+check:: check-$(WHAT)
+
+check-unix:: $(TEST_PROGS)
+check-mac:: $(TEST_PROGS)
+
+check-windows::
+
diff --git a/src/lib/krb4/Password.c b/src/lib/krb4/Password.c
new file mode 100644
index 0000000000..b296630068
--- /dev/null
+++ b/src/lib/krb4/Password.c
@@ -0,0 +1,433 @@
+#include "kerberos.h"
+#define KRB_DEFS
+#include "krb_driver.h"
+
+#include <Types.h>
+#include <Dialogs.h>
+#include <Controls.h>
+#include <ToolUtils.h>
+#include <OSUtils.h>
+#include <Resources.h>
+
+/* added for OpenInitRF.c
+ FIXME jcm - should check that they are not in c-mac
+ or other included file
+*/
+
+#include <Errors.h>
+#include <Files.h>
+#include <Memory.h>
+#include <Traps.h>
+#include <GestaltEqu.h>
+#include <Folders.h>
+
+
+// #include "debug.h"
+
+#define kLoginDLOGID -4081
+#define kErrorALERTID -4082
+#define kLoginOKItem 1
+#define kLoginCnclItem 2
+#define kLoginNameItem 10
+#define kLoginVisPwItem 9
+#define kLoginFrameItem 5
+#define kLoginIvisPwItem 6
+#define kBadUserError 1
+#define kNotUniqueError 2
+#define kGenError 3
+#define kIntegrityError 4
+#define kBadPasswordError 5
+#define cr 0x0D
+#define enter 0x03
+#define bs 0x08
+#define tab 0x09
+#define larrow 0x1C
+#define rarrow 0x1D
+#define uarrow 0x1E
+#define darrow 0x1F
+#define DialogNotDone 1
+
+typedef union { // used to convert ProcPtr to Handle
+ Handle H;
+ ProcPtr P;
+} Proc2Hand;
+
+static char gPassword [MAX_K_NAME_SZ] = "\0";
+
+pascal void FrameOKbtn( WindowPtr myWindow, short itemNo );
+pascal Boolean TwoItemFilter( DialogPtr dlog, EventRecord *event, short *itemHit );
+
+/*
+ FIXME jcm - begin OpenInitRF
+ Mac_store thinks that it is managing the open resource file
+ is this code in conflict?
+*/
+
+void GetExtensionsFolder(short *vRefNumP, long *dirIDP)
+{
+ Boolean hasFolderMgr = false;
+ long feature;
+
+/*
+ FIXME Error: Ô_GestaltDispatchÕ has not been declared - not needed now? - jcm
+ if (TrapAvailable(_GestaltDispatch))
+*/
+ if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) hasFolderMgr = true;
+ if (!hasFolderMgr) {
+ GetSystemFolder(vRefNumP, dirIDP);
+ return;
+ }
+ else {
+ if (FindFolder(kOnSystemDisk, kExtensionFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
+ *vRefNumP = 0;
+ *dirIDP = 0;
+ }
+ }
+}
+
+short SearchFolderForINIT(long targetType, long targetCreator, short vRefNum, long dirID)
+{
+ HParamBlockRec fi;
+ Str255 filename;
+ short refnum;
+
+ fi.fileParam.ioCompletion = nil;
+ fi.fileParam.ioNamePtr = filename;
+ fi.fileParam.ioVRefNum = vRefNum;
+ fi.fileParam.ioDirID = dirID;
+ fi.fileParam.ioFDirIndex = 1;
+
+ while (PBHGetFInfo(&fi, false) == noErr) {
+ /* scan system folder for driver resource files of specific type & creator */
+ if (fi.fileParam.ioFlFndrInfo.fdType == targetType &&
+ fi.fileParam.ioFlFndrInfo.fdCreator == targetCreator) {
+ refnum = HOpenResFile(vRefNum, dirID, filename, fsRdPerm);
+ return refnum;
+ }
+ /* check next file in folder */
+ fi.fileParam.ioFDirIndex++;
+ fi.fileParam.ioDirID = dirID; /* PBHGetFInfo() clobbers ioDirID */
+ }
+ return(-1);
+}
+
+short OpenInitRF()
+{
+ short refnum;
+ short vRefNum;
+ long dirID;
+
+ /* first search Extensions Panels */
+ GetExtensionsFolder(&vRefNum, &dirID);
+ refnum = SearchFolderForINIT('INIT', 'krbL', vRefNum, dirID);
+ if (refnum != -1) return(refnum);
+
+ /* next search System Folder */
+ GetSystemFolder(&vRefNum, &dirID);
+ refnum = SearchFolderForINIT('INIT', 'krbL', vRefNum, dirID);
+ if (refnum != -1) return(refnum);
+
+ /* finally, search Control Panels */
+ GetCPanelFolder(&vRefNum, &dirID);
+ refnum = SearchFolderForINIT('INIT', 'krbL', vRefNum, dirID);
+ if (refnum != -1) return(refnum);
+
+ return -1;
+}
+
+int DisplayError( short errorID )
+{
+ OSErr err;
+ Str255 errText;
+
+ GetIndString(errText,kErrorALERTID,errorID);
+ if (errText[0] == 0) {
+ SysBeep(1); // nothing else we can do
+ return cKrbCorruptedFile;
+ }
+
+ ParamText(errText,"\p","\p","\p");
+ err = StopAlert(kErrorALERTID,nil);
+
+ return DialogNotDone;
+}
+
+
+
+OSErr GetUserInfo( char *password )
+{
+ DialogPtr myDLOG;
+ short itemHit;
+ short itemType;
+ Handle itemHandle;
+ Rect itemRect;
+ OSErr rc = DialogNotDone;
+ Str255 tempStr,tpswd,tuser;
+ Proc2Hand procConv;
+ short rf;
+ char uname[ANAME_SZ]="\0";
+ char uinst[INST_SZ]="\0";
+ char realm[REALM_SZ]="\0";
+ char UserName[MAX_K_NAME_SZ]="\0";
+ CursHandle aCursor;
+
+ krb_get_lrealm (realm, 1);
+
+ //////////////////////////////////////////////////////
+ // already got a password, just get the initial ticket
+ //////////////////////////////////////////////////////
+ if (*gPassword) {
+ strcpy (UserName, krb_get_default_user( ));
+ /* FIXME jcm - if we have a password then no dialog
+ comes up for setting the uinstance. */
+ rc = kname_parse(uname, uinst, realm, UserName);
+ if (rc) return rc;
+ (void) dest_all_tkts(); // start from scratch
+ rc = krb_get_pw_in_tkt(uname,uinst,realm,"krbtgt",realm,DEFAULT_TKT_LIFE,gPassword);
+ *gPassword = 0; // Always clear, password only good for one shot
+ return rc;
+ }
+
+ /////////////////////////
+ // Ask user for password
+ /////////////////////////
+ rf = OpenInitRF(); // need the resource file for the dialog resources
+ if (rf<=0) return rf;
+ password[0] = 0;
+ myDLOG = GetNewDialog( kLoginDLOGID, (void *) NULL, (WindowPtr) -1 );
+ if( myDLOG == NULL ) {
+ CloseResFile(rf);
+ return cKrbCorruptedFile;
+ }
+
+ // Insert user's name in dialog
+ strcpy (UserName, krb_get_default_user( ));
+ if (*UserName) {
+ tempStr[0] = strlen(UserName);
+ memcpy( &(tempStr[1]), UserName, tempStr[0]);
+ GetDItem( myDLOG, kLoginNameItem, &itemType, &itemHandle, &itemRect );
+ SetIText( itemHandle, tempStr );
+ SelIText( myDLOG, kLoginVisPwItem,0,0 );
+ }
+ else SelIText( myDLOG, kLoginNameItem,0,0 );
+
+ // Establish a user item around the OK button to draw the default button frame in
+ GetDItem( myDLOG, kLoginOKItem, &itemType, &itemHandle, &itemRect );
+ InsetRect( &itemRect, -4, -4 ); // position user item around OK button
+ procConv.P = (ProcPtr) FrameOKbtn; // convert ProcPtr to a Handle
+ SetDItem( myDLOG, kLoginFrameItem, userItem, procConv.H, &itemRect );
+
+ InitCursor();
+ do {
+ do { // display the dialog & handle events
+ SetOKEnable(myDLOG);
+ ModalDialog( (ModalFilterProcPtr) TwoItemFilter, (short *) &itemHit );
+ } while( itemHit != kLoginOKItem && itemHit != kLoginCnclItem );
+
+ if( itemHit == kLoginOKItem ) { // OK button pressed?
+ GetDItem( myDLOG, kLoginNameItem, &itemType, &itemHandle, &itemRect );
+ GetIText( itemHandle, tempStr );
+
+ tempStr[0] = ( tempStr[0] < MAX_K_NAME_SZ ) ? tempStr[0] : MAX_K_NAME_SZ-1 ;
+ memcpy ((void*) UserName, (void*) &(tempStr[1]), tempStr[0]);
+ UserName[tempStr[0]] = 0;
+
+ GetDItem( myDLOG, kLoginIvisPwItem, &itemType, &itemHandle, &itemRect );
+ GetIText( itemHandle, tempStr );
+
+ tempStr[0] = ( tempStr[0] < ANAME_SZ ) ? tempStr[0] : ANAME_SZ-1 ;
+ memcpy( (void*) password, (void*) &(tempStr[1]), tempStr[0]);
+ password[tempStr[0]] = 0;
+
+ //----------------------------------------------------
+ // Get the ticket
+ //----------------------------------------------------
+ aCursor = GetCursor(watchCursor);
+ SetCursor(*aCursor);
+ ShowCursor();
+
+ rc = kname_parse(uname, uinst, realm, UserName);
+ if (rc) return rc;
+
+ (void) dest_all_tkts(); // start from scratch
+ rc = krb_get_pw_in_tkt(uname,uinst,realm,"krbtgt",realm,DEFAULT_TKT_LIFE,password);
+ InitCursor();
+ if (!rc)
+ switch (rc) {
+ case KDC_PR_UNKNOWN:
+ case KDC_NULL_KEY:
+ rc = DisplayError(kBadUserError);
+ SelIText( myDLOG, kLoginNameItem,0,256 );
+ break;
+ case KDC_PR_N_UNIQUE:
+ rc = DisplayError(kNotUniqueError);
+ SelIText( myDLOG, kLoginNameItem,0,256 );
+ break;
+ case KDC_GEN_ERR:
+ rc = DisplayError(kGenError);
+ SelIText( myDLOG, kLoginNameItem,0,256 );
+ break;
+ case RD_AP_MODIFIED:
+ rc = DisplayError(kIntegrityError);
+ SelIText( myDLOG, kLoginNameItem,0,256 );
+ break;
+ case INTK_BADPW:
+ rc = DisplayError(kBadPasswordError);
+ SelIText( myDLOG, kLoginVisPwItem,0,256 );
+ break;
+ default:
+ break;
+ }
+ //----------------------------------------------------
+ }
+ else rc = cKrbUserCancelled; // pressed the Cancel button
+ } while( rc == DialogNotDone );
+
+ DisposDialog( myDLOG );
+ CloseResFile(rf);
+ return rc;
+}
+
+
+static pascal void FrameOKbtn( WindowPtr myWindow, short itemNo )
+{
+ short tempType;
+ Handle tempHandle;
+ Rect itemRect;
+
+ GetDItem( (DialogPtr) myWindow, itemNo, &tempType, &tempHandle, &itemRect );
+ PenSize( 3, 3 );
+ FrameRoundRect( &itemRect, 16, 16 ); // make it an OK button suitable for framing
+}
+
+
+static pascal Boolean TwoItemFilter( DialogPtr dlog, EventRecord *event, short *itemHit )
+{
+ DialogPtr evtDlog;
+ short selStart, selEnd;
+ Handle okBtnHandle;
+ short tempType;
+ Rect tempRect;
+ long tempTicks;
+
+ if( event->what != keyDown && event->what != autoKey )
+ return false; // don't care about this event
+
+ switch( event->message & charCodeMask )
+ {
+ case cr: // Return (hitting return or enter is the same as hitting the OK button)
+ case enter: // Enter
+
+ if (!OKIsEnabled(dlog)) {
+ event->what = nullEvent;
+ return false;
+ }
+
+ GetDItem( dlog, kLoginOKItem, &tempType, &okBtnHandle, &tempRect );
+ HiliteControl( (ControlHandle) okBtnHandle, 1 ); // hilite the OK button
+ Delay( 10, &tempTicks ); // wait a little while
+ HiliteControl( (ControlHandle) okBtnHandle, 0 );
+
+ *itemHit = kLoginOKItem; // OK Button
+ return true; // We handled the event
+
+ case tab: // Tab
+ case larrow: // Left arrow (Keys that just change the selection)
+ case rarrow: // Right arrow
+ case uarrow: // Up arrow
+ case darrow: // Down arrow
+ return false; // Let ModalDialog handle them
+
+ default:
+
+ // First see if we're in password field, do stuff to make ¥ displayed
+
+ if( ((DialogPeek) dlog)->editField == kLoginVisPwItem - 1 ) {
+
+ selStart = (**((DialogPeek) dlog)->textH).selStart; // Get the selection in the visible item
+ selEnd = (**((DialogPeek) dlog)->textH).selEnd;
+
+ SelIText( dlog, kLoginIvisPwItem, selStart, selEnd ); // Select text in invisible item
+ DialogSelect( event,&evtDlog, itemHit ); // Input key
+
+ SelIText( dlog, kLoginVisPwItem, selStart, selEnd ); // Select same area in visible item
+ if( ( event->message & charCodeMask ) != bs ) // If it's not a backspace (backspace is the only key that can affect both the text and the selection- thus we need to process it in both fields, but not change it for the hidden field.
+ event->message = '¥'; // Replace with character to use
+ }
+
+ // Do the key event and set the hilite on the OK button accordingly
+
+ DialogSelect( event,&evtDlog, itemHit ); // Input key
+ SetOKEnable(dlog);
+
+ // Pass a NULL event back to DialogMgr
+
+ event->what = nullEvent;
+
+ return false;
+ }
+}
+
+static int SetOKEnable( DialogPtr dlog )
+{
+ short itemType,state;
+ Handle itemHandle;
+ Rect itemRect;
+ Str255 tpswd,tuser;
+ ControlHandle okButton;
+
+ GetDItem( dlog, kLoginNameItem, &itemType, &itemHandle, &itemRect );
+ GetIText( itemHandle, tuser );
+ GetDItem( dlog, kLoginVisPwItem, &itemType, &itemHandle, &itemRect );
+ GetIText( itemHandle, tpswd );
+ GetDItem( dlog, kLoginOKItem, &itemType, (Handle *) &okButton, &itemRect );
+ state = (tuser[0] && tpswd[0]) ? 0 : 255;
+ HiliteControl(okButton,state);
+}
+
+static int OKIsEnabled( DialogPtr dlog )
+{
+ short itemType;
+ Rect itemRect;
+ ControlHandle okButton;
+
+ GetDItem( dlog, kLoginOKItem, &itemType, (Handle *) &okButton, &itemRect );
+ return ((**okButton).contrlHilite != 255);
+}
+
+
+extern OSErr INTERFACE
+CacheInitialTicket( serviceName )
+ char *serviceName;
+{
+ char service[ANAME_SZ]="\0";
+ char instance[INST_SZ]="\0";
+ char realm[REALM_SZ]="\0";
+ OSErr err = noErr;
+ char uname[ANAME_SZ]="\0";
+ char uinst[INST_SZ]="\0";
+ char urealm[REALM_SZ]="\0";
+ char password[KKEY_SZ]="\0";
+ char UserName[MAX_K_NAME_SZ]="\0";
+ char oldName[120]="\0";
+
+ err = GetUserInfo( password );
+ if (err) return err;
+
+ if (!serviceName || (serviceName[0] == '\0'))
+ return err;
+
+ strcpy (UserName, krb_get_default_user());
+
+ err = kname_parse(uname, uinst, urealm, UserName);
+ if (err) return err;
+
+ if (urealm[0] == '\0')
+ krb_get_lrealm (urealm, 1);
+
+ err = kname_parse(service, instance, realm, serviceName); // check if there is a service name
+ if (err) return err;
+
+ err = krb_get_pw_in_tkt(uname,uinst,urealm,service,instance,DEFAULT_TKT_LIFE,password);
+ return err;
+}
diff --git a/src/lib/krb4/TAGS b/src/lib/krb4/TAGS
new file mode 100644
index 0000000000..2ed539d8c1
--- /dev/null
+++ b/src/lib/krb4/TAGS
@@ -0,0 +1,546 @@
+
+DNR.c,663
+#define OPENRESOLVER 22,556
+#define CLOSERESOLVER 23,580
+#define STRTOADDR 24,605
+#define ADDRTOSTR 25,627
+#define ENUMCACHE 26,649
+#define ADDRTONAME 27,671
+#define HINFO 28,694
+#define MXINFO 29,713
+typedef OSErr (*OSErrProcPtr)OSErrProcPtr33,758
+TrapType GetTrapType(37,825
+Boolean TrapAvailable(46,963
+void GetSystemFolder(67,1459
+void GetCPanelFolder(79,1685
+short SearchFolderForDNRP(105,2393
+short OpenOurRF(145,3485
+OSErr OpenResolver(170,4133
+OSErr CloseResolver(216,5135
+OSErr StrToAddr(232,5411
+OSErr AddrToStr(245,5710
+OSErr EnumCache(257,5919
+OSErr AddrToName(269,6134
+extern OSErr HInfo(283,6440
+extern OSErr MXInfo(297,6749
+
+Password.c,991
+#define KRB_DEFS2,22
+#define kLoginDLOGID 27,452
+#define kErrorALERTID 28,480
+#define kLoginOKItem 29,509
+#define kLoginCnclItem 30,533
+#define kLoginNameItem 31,559
+#define kLoginVisPwItem 32,586
+#define kLoginFrameItem 33,613
+#define kLoginIvisPwItem 34,640
+#define kBadUserError 35,667
+#define kNotUniqueError 36,692
+#define kGenError 37,719
+#define kIntegrityError 38,741
+#define kBadPasswordError 39,768
+#define cr 40,796
+#define enter 41,817
+#define bs 42,840
+#define tab 43,861
+#define larrow 44,882
+#define rarrow 45,906
+#define uarrow 46,930
+#define darrow 47,954
+#define DialogNotDone 48,978
+} Proc2Hand;Proc2Hand53,1090
+void GetExtensionsFolder(66,1422
+short SearchFolderForINIT(88,1960
+short OpenInitRF(114,2754
+int DisplayError(138,3362
+OSErr GetUserInfo(157,3679
+static pascal void FrameOKbtn(292,8039
+static pascal Boolean TwoItemFilter(304,8348
+static int SetOKEnable(371,10583
+static int OKIsEnabled(388,11096
+CacheInitialTicket(400,11349
+
+ad_print.c,79
+#define DEFINE_SOCKADDR 13,251
+ad_print(26,573
+placebo_cblock_print(52,1219
+
+cr_auth_repl.c,27
+create_auth_reply(61,1603
+
+cr_ciph.c,21
+create_ciph(56,1230
+
+cr_death_pkt.c,32
+krb_create_death_packet(44,991
+
+cr_err_repl.c,22
+cr_err_reply(54,1331
+
+cr_tkt.c,31
+int krb_create_ticket(73,1787
+
+debug.c,0
+
+decomp_tkt.c,23
+decomp_ticket(50,1450
+
+dest_tkt.c,17
+dest_tkt(34,732
+
+err_txt.c,27
+krb_get_err_text 287,7833
+
+fakeenv.c,51
+setenv(15,278
+_findenv(53,1645
+unsetenv(76,2062
+
+fgetst.c,15
+fgetst(22,669
+
+g_ad_tkt.c,20
+get_ad_tkt(55,1537
+
+g_admhst.c,24
+krb_get_admhst(38,1153
+
+g_cnffile.c,54
+krb__get_cnffile(22,747
+krb__get_realmsfile(39,1037
+
+g_cred.c,21
+krb_get_cred(26,675
+
+g_in_tkt.c,246
+typedef int (*key_proc_type)key_proc_type26,648
+typedef int (*decrypt_tkt_type)decrypt_tkt_type30,782
+decrypt_tkt(41,1089
+krb_mk_in_tkt_preauth(120,3778
+krb_parse_in_tkt(236,7145
+krb_get_in_tkt_preauth(335,10019
+krb_get_in_tkt(370,10932
+
+g_krbhst.c,52
+get_krbhst_default(49,1607
+krb_get_krbhst(65,1896
+
+g_krbrlm.c,24
+krb_get_lrealm(35,1036
+
+g_phost.c,55
+#define DEFINE_SOCKADDR 11,205
+krb_get_phost(36,1122
+
+g_pw_in_tkt.c,295
+#define NULL 15,264
+passwd_to_key(44,1139
+krb_get_pw_in_tkt(90,2830
+static int stub_key(120,3852
+krb_get_pw_in_tkt_preauth(129,4064
+placebo_read_password(192,5623
+placebo_read_pw_string(223,6146
+static push_signals(321,8059
+static pop_signals(328,8174
+static void sig_restore(335,8274
+
+g_pw_tkt.c,20
+get_pw_tkt(44,1500
+
+g_svc_in_tkt.c,202
+#define NULL 15,265
+static int srvtab_to_key(41,1088
+krb_get_svc_in_tkt(63,1791
+static int stub_key(75,2164
+krb_get_svc_in_tkt_preauth(83,2337
+krb_svc_init(104,2954
+krb_svc_init_preauth(120,3286
+
+g_tf_fname.c,28
+krb_get_tf_fullname(30,757
+
+g_tf_realm.c,25
+krb_get_tf_realm(24,453
+
+g_tkt_svc.c,165
+#define DEFINE_SOCKADDR8,102
+#define KRB_SENDAUTH_VERS 12,210
+ParseFullName(16,299
+CopyTicket(40,813
+CredIsExpired(71,1637
+krb_get_ticket_for_service 106,2706
+
+gethostname.c,81
+#define DEFINE_SOCKADDR11,215
+#define GETHOSTNAME 15,277
+k_gethostname(25,603
+
+getst.c,14
+getst(22,665
+
+in_tkt.c,65
+#define setreuid(36,783
+#define setreuid(39,845
+in_tkt(43,892
+
+klog.c,44
+char * klog(52,1310
+kset_logfile(104,2777
+
+kname_parse.c,167
+#define FULL_SZ 17,301
+#define NAME 19,350
+#define INST 20,398
+#define REALM 21,416
+kname_parse(55,1544
+k_isname(137,3567
+k_isinst(175,4272
+k_isrealm(205,4807
+
+kntoln.c,20
+krb_kntoln(41,1276
+
+kparse.c,479
+#define FALSE 42,1412
+#define TRUE 43,1428
+#define void 46,1451
+#define MAXKEY 48,1469
+#define MAXVALUE 49,1496
+int fGetParameterSet(63,1850
+int ParmCompare(129,3679
+void FreeParameterSet(149,4117
+int fGetKeywordValue(163,4368
+int fGetToken(355,9540
+int fGetLiteral(451,12130
+int fUngetChar(528,13897
+int fGetChar(541,14110
+static char * strsave(569,14601
+static char * strutol(582,14833
+#define MAXTOKEN 594,15059
+main(598,15106
+main(653,16115
+main(712,17445
+
+kuserok.c,192
+#define seteuid(31,564
+#define setegid(32,602
+#define OK 35,648
+#define NOTOK 36,661
+#define MAX_USERNAME 37,677
+#define REALM_SUBSCRIPT 83,2464
+#define KPARMS 91,2682
+kuserok(94,2728
+
+log.c,69
+void krb_log(57,1405
+krb_set_logfile(86,2175
+krb_new_log(101,2508
+
+mac_glue.c,152
+#define DEFINE_SOCKADDR 13,264
+void swab(22,486
+mymemset(24,534
+krb_start_session 33,723
+krb_end_session 40,792
+int read(47,888
+int write 48,911
+
+mac_store.c,856
+#define prefname 31,711
+#define kNumTemplates 39,1000
+#define kFirstTemplate 40,1024
+#define kMapResNum 41,1051
+krb_get_admhst 88,2480
+int krb_get_krbhst(118,3439
+int krb_get_lrealm(143,4151
+char *krb_realmofhost(170,4907
+krb_get_default_user 185,5148
+krb_set_default_user 196,5281
+void GetPrefsFolder(213,5549
+init_store(243,6441
+OSErr OpenPrefsFile(306,7953
+OSErr CreatePrefFile(332,8652
+OSErr WriteUser(372,9704
+OSErr WritePref(387,9953
+OSErr WritePrefStr(426,11022
+OSErr WriteRealmMap(439,11365
+OSErr WriteServerMap(454,11622
+OSErr GetLocalRealm(469,11877
+OSErr SetLocalRealm(478,12001
+OSErr GetRealm(498,12358
+OSErr AddRealmMap(533,13063
+OSErr DeleteRealmMap(556,13600
+OSErr GetNthRealmMap(594,14515
+OSErr GetNthServer(613,14906
+OSErr AddServerMap(639,15506
+OSErr DeleteServerMap(665,16119
+OSErr GetNthServerMap(712,17212
+
+mac_store.h,0
+
+mac_stubs.c,665
+#define DEFINE_SOCKADDR 11,258
+#define kdriver 24,712
+short lowcall 30,831
+short hicall 50,1309
+krb_start_session 70,1798
+krb_end_session 90,2068
+krb_realmofhost 108,2319
+krb_get_lrealm 126,2662
+kname_parse 146,2917
+krb_get_err_text 163,3262
+krb_get_pw_in_tkt(178,3529
+krb_get_pw_in_tkt_preauth(201,4083
+krb_get_default_user 224,4567
+krb_set_default_user 239,4831
+krb_get_cred 251,5020
+krb_save_credentials 272,5363
+krb_delete_cred 305,6163
+dest_tkt 323,6467
+krb_get_nth_cred 339,6793
+krb_get_num_cred 363,7251
+GetNthRealmMap(387,7716
+GetNthServerMap(411,8268
+krb_get_ticket_for_service 448,9169
+krb_get_tf_fullname 486,10223
+ if 512,10747
+
+macsock.c,319
+#define ENOMEM 27,575
+#define SOCKET_SET_ERRNO 39,895
+WSAStartup(67,1843
+WSACleanup(79,2117
+socket(86,2183
+closesocket 145,3382
+bind 167,3808
+sendto 194,4301
+select 243,5537
+recvfrom 261,5973
+inet_ntoa(327,7560
+gethostbyname 352,8177
+gethostbyaddr 392,9310
+DNRresultproc(433,10537
+ gethostname(449,10974
+
+memcache.c,952
+#define unix22,484
+#define _nmalloc 38,701
+#define _nfree 39,725
+#define _nrealloc 40,745
+#define NPSTR 41,771
+#define OFFSETOF(42,792
+typedef int OSErr;OSErr44,815
+#define noErr 45,834
+#define memFullErr 46,850
+#define change_cache(59,1053
+#define Handle 64,1169
+#define Size 65,1192
+NewHandleSys(77,1585
+DisposHandle(112,2094
+SetHandleSize(129,2545
+MemError(163,2944
+change_cache(184,3535
+krb_get_notification_message(210,4094
+in_tkt(268,5927
+dest_tkt(295,6451
+int dest_all_tkts(320,6865
+krb_get_tf_realm 354,7399
+krb_get_tf_fullname 366,7696
+krb_get_cred 417,9236
+krb_save_credentials(457,10308
+krb_delete_cred 488,11202
+krb_get_nth_cred 508,11604
+krb_get_num_cred 525,11970
+OSErr GetNumSessions(539,12136
+GetNthSession(548,12243
+OSErr DeleteSession(566,12615
+OSErr GetCredentials(605,13426
+OSErr AddCredentials(649,14313
+DeleteCredentials 733,16435
+OSErr GetNumCredentials(786,17522
+GetNthCredentials(822,18182
+
+memcache.h,78
+struct Session Session11,218
+typedef struct Session Session;Session18,349
+
+mk_auth.c,113
+#define DEFINE_SOCKADDR 14,276
+#define KRB_SENDAUTH_VERS 20,424
+krb_mk_auth(102,3181
+krb_check_auth 189,6067
+
+mk_err.c,19
+krb_mk_err(37,958
+
+mk_preauth.c,100
+typedef int (*key_proc_type)key_proc_type22,912
+krb_mk_preauth(27,1018
+krb_free_preauth(72,2223
+
+mk_priv.c,53
+#define DEFINE_SOCKADDR 23,490
+krb_mk_priv(83,2295
+
+mk_req.c,78
+#define DEFINE_SOCKADDR11,198
+krb_mk_req(72,2283
+krb_set_lifetime(207,7103
+
+mk_safe.c,53
+#define DEFINE_SOCKADDR 23,519
+krb_mk_safe(64,1795
+
+month_sname.c,32
+const char *month_sname(20,427
+
+netread.c,52
+#define DEFINE_SOCKADDR12,230
+krb_net_read(28,638
+
+netwrite.c,53
+#define DEFINE_SOCKADDR12,231
+krb_net_write(27,564
+
+one.c,0
+
+pkt_cipher.c,19
+pkt_cipher(25,484
+
+pkt_clen.c,17
+pkt_clen(27,655
+
+put_svc_key.c,44
+#define KEYSZ 36,1152
+put_svc_key(42,1333
+
+rd_err.c,19
+krb_rd_err(36,862
+
+rd_preauth.c,23
+krb_rd_preauth(24,745
+
+rd_priv.c,53
+#define DEFINE_SOCKADDR 28,728
+krb_rd_priv(69,2013
+
+rd_req.c,42
+krb_set_key(64,2022
+krb_rd_req(123,4100
+
+rd_safe.c,53
+#define DEFINE_SOCKADDR 26,591
+krb_rd_safe(52,1501
+
+rd_svc_key.c,321
+#define open 50,1523
+#define close 51,1556
+#define getst 52,1591
+#define read 53,1626
+int vxworks_srvtab_getchar(57,1720
+int vxworks_srvtab_getst(71,1971
+int vxworks_srvtab_open(84,2224
+int vxworks_srvtab_close(92,2347
+int vxworks_srvtab_read(99,2432
+int read_service_key(112,2649
+int get_service_key(126,3256
+
+realmofhost.c,57
+#define DEFINE_SOCKADDR 21,387
+krb_realmofhost(45,1173
+
+recvauth.c,111
+#define DEFINE_SOCKADDR 12,213
+#define KRB_SENDAUTH_VERS 19,362
+#define max(112,4010
+krb_recvauth(116,4085
+
+save_creds.c,29
+krb_save_credentials(32,921
+
+send_to_kdc.c,97
+#define DEFINE_SOCKADDR 12,216
+#define S_AD_SZ 19,385
+send_to_kdc(67,1871
+send_recv(299,8782
+
+sendauth.c,171
+#define DEFINE_SOCKADDR 13,216
+#define KRB_SENDAUTH_VERS 19,364
+#define raw_tkt_len 111,3858
+krb_net_rd_sendauth 124,4235
+krb_sendauth(182,6044
+krb_sendsvc(259,8501
+
+setenv.c,74
+int setenv(31,1159
+unsetenv(89,2635
+getenv(129,3954
+_findenv(148,4386
+
+stime.c,82
+#define DEFINE_SOCKADDR12,224
+#define NEED_TIME_H13,248
+char *krb_stime(25,559
+
+strcasecmp.c,41
+strcasecmp(58,3120
+strncasecmp(71,3362
+
+swab.c,11
+swab(3,38
+
+tf_shm.c,105
+#define MAX_BUFF 23,478
+krb_shm_create(35,700
+int krb_is_diskless(123,3062
+int krb_shm_dest(136,3284
+
+tf_util.c,415
+#define TOO_BIG 26,439
+#define TF_LCK_RETRY 27,458
+int utimes(51,897
+#define LOCK_SH 62,1105
+#define LOCK_EX 63,1148
+#define LOCK_NB 64,1194
+#define LOCK_UN 65,1250
+int emul_flock(73,1381
+#define flock(90,1677
+int tf_init(176,4583
+int tf_get_pname(319,8154
+int tf_get_pinst(342,8870
+int tf_get_cred(366,9520
+tf_close(431,11158
+tf_gets(469,12193
+tf_read(511,13102
+int tf_save_cred(547,14097
+
+tkt_string.c,53
+char *tkt_string(35,945
+krb_set_tkt_string(66,1900
+
+unix_glue.c,108
+krb_start_session 15,300
+krb_end_session 22,369
+krb_get_default_user 29,443
+krb_set_default_user 35,510
+
+vmsswab.c,13
+swab(19,739
+
+win_glue.c,218
+#define DEFINE_SOCKADDR10,175
+win_socket_initialize(30,651
+far_fputs(60,1474
+LibMain(69,1594
+WEP(82,1763
+get_lib_instance(90,1815
+krb_start_session(97,1876
+krb_end_session(104,1948
+krb_set_tkt_string(111,2009
+
+win_store.c,115
+krb__get_cnffile(27,682
+krb__get_realmsfile(59,1447
+krb_get_default_user(88,2057
+krb_set_default_user(103,2323
diff --git a/src/lib/krb4/ad_print.c b/src/lib/krb4/ad_print.c
new file mode 100644
index 0000000000..797293751c
--- /dev/null
+++ b/src/lib/krb4/ad_print.c
@@ -0,0 +1,66 @@
+/*
+ * ad_print.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Miscellaneous debug printing utilities
+ */
+
+#include "mit-copyright.h"
+#define DEFINE_SOCKADDR /* Request definitions for sockets */
+#include "krb.h"
+#include "des.h"
+#include <stdio.h>
+
+/*
+ * Print some of the contents of the given authenticator structure
+ * (AUTH_DAT defined in "krb.h"). Fields printed are:
+ *
+ * pname, pinst, prealm, netaddr, flags, cksum, timestamp, session
+ */
+
+void
+ad_print(x)
+ AUTH_DAT *x;
+{
+ struct in_addr ina;
+ ina.s_addr = x->address;
+
+ printf("\n%s %s %s ", x->pname, x->pinst, x->prealm);
+ far_fputs (inet_ntoa(ina), stdout);
+ printf(" flags %u cksum 0x%lX\n\ttkt_tm 0x%lX sess_key",
+ x->k_flags, x->checksum, x->time_sec);
+ printf("[8] =");
+#ifdef NOENCRYPTION
+ placebo_cblock_print(x->session);
+#else /* Do Encryption */
+ des_cblock_print_file(x->session,stdout);
+#endif /* NOENCRYPTION */
+ /* skip reply for now */
+}
+
+#ifdef NOENCRYPTION
+/*
+ * Print in hex the 8 bytes of the given session key.
+ *
+ * Printed format is: " 0x { x, x, x, x, x, x, x, x }"
+ */
+
+placebo_cblock_print(x)
+ des_cblock x;
+{
+ unsigned char *y = (unsigned char *) x;
+ register int i = 0;
+
+ printf(" 0x { ");
+
+ while (i++ <8) {
+ printf("%x",*y++);
+ if (i<8) printf(", ");
+ }
+ printf(" }");
+}
+#endif /* NOENCRYPTION */
diff --git a/src/lib/krb4/configure.in b/src/lib/krb4/configure.in
new file mode 100644
index 0000000000..8f10ace40f
--- /dev/null
+++ b/src/lib/krb4/configure.in
@@ -0,0 +1,17 @@
+AC_INIT(configure.in)
+WITH_CCOPTS
+WITH_KRB5ROOT
+CONFIG_RULES
+AC_SET_BUILDTOP
+WITH_NETLIB
+AC_PROG_ARCHIVE
+AC_PROG_ARCHIVE_ADD
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+AC_CONST
+CHECK_FCNTL
+AC_HEADER_CHECK(unistd.h,AC_DEFINE(HAS_UNISTD_H))
+ET_RULES
+SubdirLibraryRule([$(OBJS)])
+KRB_INCLUDE
+V5_AC_OUTPUT_MAKEFILE
diff --git a/src/lib/krb4/cr_auth_repl.c b/src/lib/krb4/cr_auth_repl.c
new file mode 100644
index 0000000000..5203506d34
--- /dev/null
+++ b/src/lib/krb4/cr_auth_repl.c
@@ -0,0 +1,112 @@
+/*
+ * cr_auth_repl.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+/*
+ * This routine is called by the Kerberos authentication server
+ * to create a reply to an authentication request. The routine
+ * takes the user's name, instance, and realm, the client's
+ * timestamp, the number of tickets, the user's key version
+ * number and the ciphertext containing the tickets themselves.
+ * It constructs a packet and returns a pointer to it.
+ *
+ * Notes: The packet returned by this routine is static. Thus, if you
+ * intend to keep the result beyond the next call to this routine, you
+ * must copy it elsewhere.
+ *
+ * The packet is built in the following format:
+ *
+ * variable
+ * type or constant data
+ * ---- ----------- ----
+ *
+ * unsigned char KRB_PROT_VERSION protocol version number
+ *
+ * unsigned char AUTH_MSG_KDC_REPLY protocol message type
+ *
+ * [least significant HOST_BYTE_ORDER sender's (server's) byte
+ * bit of above field] order
+ *
+ * string pname principal's name
+ *
+ * string pinst principal's instance
+ *
+ * string prealm principal's realm
+ *
+ * unsigned long time_ws client's timestamp
+ *
+ * unsigned char n number of tickets
+ *
+ * unsigned long x_date expiration date
+ *
+ * unsigned char kvno master key version
+ *
+ * short w_1 cipher length
+ *
+ * --- cipher->dat cipher data
+ */
+
+KTEXT
+create_auth_reply(pname,pinst,prealm,time_ws,n,x_date,kvno,cipher)
+ char *pname; /* Principal's name */
+ char *pinst; /* Principal's instance */
+ char *prealm; /* Principal's authentication domain */
+ long time_ws; /* Workstation time */
+ int n; /* Number of tickets */
+ unsigned long x_date; /* Principal's expiration date */
+ int kvno; /* Principal's key version number */
+ KTEXT cipher; /* Cipher text with tickets and
+ * session keys */
+{
+ static KTEXT_ST pkt_st;
+ KTEXT pkt = &pkt_st;
+ unsigned char *v = pkt->dat; /* Prot vers number */
+ unsigned char *t = (pkt->dat+1); /* Prot message type */
+ short w_l; /* Cipher length */
+
+ /* Create fixed part of packet */
+ *v = (unsigned char) KRB_PROT_VERSION;
+ *t = (unsigned char) AUTH_MSG_KDC_REPLY;
+ *t |= HOST_BYTE_ORDER;
+
+ if (n != 0)
+ *v = 3;
+
+ /* Add the basic info */
+ (void) strcpy((char *) (pkt->dat+2), pname);
+ pkt->length = 3 + strlen(pname);
+ (void) strcpy((char *) (pkt->dat+pkt->length),pinst);
+ pkt->length += 1 + strlen(pinst);
+ (void) strcpy((char *) (pkt->dat+pkt->length),prealm);
+ pkt->length += 1 + strlen(prealm);
+ /* Workstation timestamp */
+ memcpy((char *) (pkt->dat+pkt->length), (char *) &time_ws, 4);
+ pkt->length += 4;
+ *(pkt->dat+(pkt->length)++) = (unsigned char) n;
+ /* Expiration date */
+ memcpy((char *) (pkt->dat+pkt->length), (char *) &x_date, 4);
+ pkt->length += 4;
+
+ /* Now send the ciphertext and info to help decode it */
+ *(pkt->dat+(pkt->length)++) = (unsigned char) kvno;
+ w_l = (short) cipher->length;
+ memcpy((char *) (pkt->dat+pkt->length), (char *) &w_l, 2);
+ pkt->length += 2;
+ memcpy((char *) (pkt->dat+pkt->length), (char *) (cipher->dat),
+ cipher->length);
+ pkt->length += cipher->length;
+
+ /* And return the packet */
+ return pkt;
+}
diff --git a/src/lib/krb4/cr_ciph.c b/src/lib/krb4/cr_ciph.c
new file mode 100644
index 0000000000..d15a4e0fd2
--- /dev/null
+++ b/src/lib/krb4/cr_ciph.c
@@ -0,0 +1,108 @@
+/*
+ * cr_ciph.c
+ *
+ * Copyright 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "des.h"
+#include <string.h>
+
+/*
+ * This routine is used by the authentication server to create
+ * a packet for its client, containing a ticket for the requested
+ * service (given in "tkt"), and some information about the ticket,
+#ifndef NOENCRYPTION
+ * all encrypted in the given key ("key").
+#endif
+ *
+ * Returns KSUCCESS no matter what.
+ *
+ * The length of the cipher is stored in c->length; the format of
+ * c->dat is as follows:
+ *
+ * variable
+ * type or constant data
+ * ---- ----------- ----
+ *
+ *
+ * 8 bytes session session key for client, service
+ *
+ * string service service name
+ *
+ * string instance service instance
+ *
+ * string realm KDC realm
+ *
+ * unsigned char life ticket lifetime
+ *
+ * unsigned char kvno service key version number
+ *
+ * unsigned char tkt->length length of following ticket
+ *
+ * data tkt->dat ticket for service
+ *
+ * 4 bytes kdc_time KDC's timestamp
+ *
+ * <=7 bytes null null pad to 8 byte multiple
+ *
+ */
+
+create_ciph(c, session, service, instance, realm, life, kvno, tkt,
+ kdc_time, key)
+ KTEXT c; /* Text block to hold ciphertext */
+ C_Block session; /* Session key to send to user */
+ char *service; /* Service name on ticket */
+ char *instance; /* Instance name on ticket */
+ char *realm; /* Realm of this KDC */
+ unsigned long life; /* Lifetime of the ticket */
+ int kvno; /* Key version number for service */
+ KTEXT tkt; /* The ticket for the service */
+ unsigned long kdc_time; /* KDC time */
+ C_Block key; /* Key to encrypt ciphertext with */
+{
+ char *ptr;
+ Key_schedule key_s;
+
+ ptr = (char *) c->dat;
+
+ memcpy(ptr, (char *) session, 8);
+ ptr += 8;
+
+ (void) strcpy(ptr,service);
+ ptr += strlen(service) + 1;
+
+ (void) strcpy(ptr,instance);
+ ptr += strlen(instance) + 1;
+
+ (void) strcpy(ptr,realm);
+ ptr += strlen(realm) + 1;
+
+ *(ptr++) = (unsigned char) life;
+ *(ptr++) = (unsigned char) kvno;
+ *(ptr++) = (unsigned char) tkt->length;
+
+ memcpy(ptr, (char *)(tkt->dat), tkt->length);
+ ptr += tkt->length;
+
+ memcpy(ptr, (char *) &kdc_time, 4);
+ ptr += 4;
+
+ /* guarantee null padded encrypted data to multiple of 8 bytes */
+ memset(ptr, 0, 7);
+
+ c->length = (((ptr - (char *) c->dat) + 7) / 8) * 8;
+
+#ifndef NOENCRYPTION
+ key_sched(key,key_s);
+ pcbc_encrypt((C_Block *)c->dat,(C_Block *)c->dat,
+ (long) c->length,key_s,(C_Block*) key,ENCRYPT);
+#endif /* NOENCRYPTION */
+
+ return(KSUCCESS);
+}
diff --git a/src/lib/krb4/cr_death_pkt.c b/src/lib/krb4/cr_death_pkt.c
new file mode 100644
index 0000000000..8daa2d6881
--- /dev/null
+++ b/src/lib/krb4/cr_death_pkt.c
@@ -0,0 +1,59 @@
+/*
+ * cr_death_pkt.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+/*
+ * This routine creates a packet to type AUTH_MSG_DIE which is sent to
+ * the Kerberos server to make it shut down. It is used only in the
+ * development environment.
+ *
+ * It takes a string "a_name" which is sent in the packet. A pointer
+ * to the packet is returned.
+ *
+ * The format of the killer packet is:
+ *
+ * type variable data
+ * or constant
+ * ---- ----------- ----
+ *
+ * unsigned char KRB_PROT_VERSION protocol version number
+ *
+ * unsigned char AUTH_MSG_DIE message type
+ *
+ * [least significant HOST_BYTE_ORDER byte order of sender
+ * bit of above field]
+ *
+ * string a_name presumably, name of
+ * principal sending killer
+ * packet
+ */
+
+#ifdef DEBUG
+KTEXT
+krb_create_death_packet(a_name)
+ char *a_name;
+{
+ static KTEXT_ST pkt_st;
+ KTEXT pkt = &pkt_st;
+
+ unsigned char *v = pkt->dat;
+ unsigned char *t = (pkt->dat+1);
+ *v = (unsigned char) KRB_PROT_VERSION;
+ *t = (unsigned char) AUTH_MSG_DIE;
+ *t |= HOST_BYTE_ORDER;
+ (void) strcpy((char *) (pkt->dat+2),a_name);
+ pkt->length = 3 + strlen(a_name);
+ return pkt;
+}
+#endif /* DEBUG */
diff --git a/src/lib/krb4/cr_err_repl.c b/src/lib/krb4/cr_err_repl.c
new file mode 100644
index 0000000000..068d4e2baa
--- /dev/null
+++ b/src/lib/krb4/cr_err_repl.c
@@ -0,0 +1,90 @@
+/*
+ * cr_err_repl.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+extern int req_act_vno; /* this is defined in the kerberos
+ * server code */
+
+/*
+ * This routine is used by the Kerberos authentication server to
+ * create an error reply packet to send back to its client.
+ *
+ * It takes a pointer to the packet to be built, the name, instance,
+ * and realm of the principal, the client's timestamp, an error code
+ * and an error string as arguments. Its return value is undefined.
+ *
+ * The packet is built in the following format:
+ *
+ * type variable data
+ * or constant
+ * ---- ----------- ----
+ *
+ * unsigned char req_ack_vno protocol version number
+ *
+ * unsigned char AUTH_MSG_ERR_REPLY protocol message type
+ *
+ * [least significant HOST_BYTE_ORDER sender's (server's) byte
+ * bit of above field] order
+ *
+ * string pname principal's name
+ *
+ * string pinst principal's instance
+ *
+ * string prealm principal's realm
+ *
+ * unsigned long time_ws client's timestamp
+ *
+ * unsigned long e error code
+ *
+ * string e_string error text
+ */
+
+void
+cr_err_reply(pkt,pname,pinst,prealm,time_ws,e,e_string)
+ KTEXT pkt;
+ char *pname; /* Principal's name */
+ char *pinst; /* Principal's instance */
+ char *prealm; /* Principal's authentication domain */
+ u_long time_ws; /* Workstation time */
+ u_long e; /* Error code */
+ char *e_string; /* Text of error */
+{
+ u_char *v = (u_char *) pkt->dat; /* Prot vers number */
+ u_char *t = (u_char *)(pkt->dat+1); /* Prot message type */
+
+ /* Create fixed part of packet */
+ *v = (unsigned char) req_act_vno; /* KRB_PROT_VERSION; */
+ *t = (unsigned char) AUTH_MSG_ERR_REPLY;
+ *t |= HOST_BYTE_ORDER;
+
+ /* Add the basic info */
+ (void) strcpy((char *) (pkt->dat+2),pname);
+ pkt->length = 3 + strlen(pname);
+ (void) strcpy((char *)(pkt->dat+pkt->length),pinst);
+ pkt->length += 1 + strlen(pinst);
+ (void) strcpy((char *)(pkt->dat+pkt->length),prealm);
+ pkt->length += 1 + strlen(prealm);
+ /* ws timestamp */
+ memcpy((char *)(pkt->dat+pkt->length), (char *) &time_ws, 4);
+ pkt->length += 4;
+ /* err code */
+ memcpy((char *)(pkt->dat+pkt->length), (char *) &e, 4);
+ pkt->length += 4;
+ /* err text */
+ (void) strcpy((char *)(pkt->dat+pkt->length),e_string);
+ pkt->length += 1 + strlen(e_string);
+
+ /* And return */
+ return;
+}
diff --git a/src/lib/krb4/cr_tkt.c b/src/lib/krb4/cr_tkt.c
new file mode 100644
index 0000000000..39ed53859c
--- /dev/null
+++ b/src/lib/krb4/cr_tkt.c
@@ -0,0 +1,133 @@
+/*
+ * cr_tkt.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "des.h"
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+/*
+ * Create ticket takes as arguments information that should be in a
+ * ticket, and the KTEXT object in which the ticket should be
+ * constructed. It then constructs a ticket and returns, leaving the
+ * newly created ticket in tkt.
+#ifndef NOENCRYPTION
+ * The data in tkt->dat is encrypted in the server's key.
+#endif
+ * The length of the ticket is a multiple of
+ * eight bytes and is in tkt->length.
+ *
+ * If the ticket is too long, the ticket will contain nulls.
+ * The return value of the routine is undefined.
+ *
+ * The corresponding routine to extract information from a ticket it
+ * decomp_ticket. When changes are made to this routine, the
+ * corresponding changes should also be made to that file.
+ *
+ * The packet is built in the following format:
+ *
+ * variable
+ * type or constant data
+ * ---- ----------- ----
+ *
+ * tkt->length length of ticket (multiple of 8 bytes)
+ *
+#ifdef NOENCRYPTION
+ * tkt->dat:
+#else
+ * tkt->dat: (encrypted in server's key)
+#endif
+ *
+ * unsigned char flags namely, HOST_BYTE_ORDER
+ *
+ * string pname client's name
+ *
+ * string pinstance client's instance
+ *
+ * string prealm client's realm
+ *
+ * 4 bytes paddress client's address
+ *
+ * 8 bytes session session key
+ *
+ * 1 byte life ticket lifetime
+ *
+ * 4 bytes time_sec KDC timestamp
+ *
+ * string sname service's name
+ *
+ * string sinstance service's instance
+ *
+ * <=7 bytes null null pad to 8 byte multiple
+ *
+ */
+
+int krb_create_ticket(tkt, flags, pname, pinstance, prealm, paddress,
+ session, life, time_sec, sname, sinstance, key)
+ KTEXT tkt; /* Gets filled in by the ticket */
+ unsigned char flags; /* Various Kerberos flags */
+ char *pname; /* Principal's name */
+ char *pinstance; /* Principal's instance */
+ char *prealm; /* Principal's authentication domain */
+ long paddress; /* Net address of requesting entity */
+ char *session; /* Session key inserted in ticket */
+ short life; /* Lifetime of the ticket */
+ long time_sec; /* Issue time and date */
+ char *sname; /* Service Name */
+ char *sinstance; /* Instance Name */
+ C_Block key; /* Service's secret key */
+{
+ Key_schedule key_s;
+ register char *data; /* running index into ticket */
+
+ tkt->length = 0; /* Clear previous data */
+ flags |= HOST_BYTE_ORDER; /* ticket byte order */
+ memcpy((char *) (tkt->dat), (char *) &flags, sizeof(flags));
+ data = ((char *)tkt->dat) + sizeof(flags);
+ (void) strcpy(data, pname);
+ data += 1 + strlen(pname);
+ (void) strcpy(data, pinstance);
+ data += 1 + strlen(pinstance);
+ (void) strcpy(data, prealm);
+ data += 1 + strlen(prealm);
+ memcpy(data, (char *) &paddress, 4);
+ data += 4;
+
+ memcpy(data, (char *) session, 8);
+ data += 8;
+ *(data++) = (char) life;
+ /* issue time */
+ memcpy(data, (char *) &time_sec, 4);
+ data += 4;
+ (void) strcpy(data, sname);
+ data += 1 + strlen(sname);
+ (void) strcpy(data, sinstance);
+ data += 1 + strlen(sinstance);
+
+ /* guarantee null padded ticket to multiple of 8 bytes */
+ memset(data, 0, 7);
+ tkt->length = ((data - ((char *)tkt->dat) + 7)/8)*8;
+
+ /* Check length of ticket */
+ if (tkt->length > (sizeof(KTEXT_ST) - 7)) {
+ memset(tkt->dat, 0, tkt->length);
+ tkt->length = 0;
+ return KFAILURE /* XXX */;
+ }
+
+#ifndef NOENCRYPTION
+ /* Encrypt the ticket in the services key */
+ key_sched(key,key_s);
+ pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,
+ (long) tkt->length,key_s,(C_Block *)key,1);
+#endif /* !NOENCRYPTION */
+ return 0;
+}
diff --git a/src/lib/krb4/debug.c b/src/lib/krb4/debug.c
new file mode 100644
index 0000000000..bd2ec904a6
--- /dev/null
+++ b/src/lib/krb4/debug.c
@@ -0,0 +1,15 @@
+/*
+ * debug.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+
+/* Declare global debugging variables. */
+
+int krb_ap_req_debug = 0;
+int krb_debug = 0;
diff --git a/src/lib/krb4/decomp_tkt.c b/src/lib/krb4/decomp_tkt.c
new file mode 100644
index 0000000000..5a9213b60b
--- /dev/null
+++ b/src/lib/krb4/decomp_tkt.c
@@ -0,0 +1,160 @@
+/*
+ * decomp_tkt.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "des.h"
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+#ifdef KRB_CRYPT_DEBUG
+extern int krb_debug;
+#endif
+
+/*
+ * This routine takes a ticket and pointers to the variables that
+ * should be filled in based on the information in the ticket. It
+#ifndef NOENCRYPTION
+ * decrypts the ticket using the given key, and
+#endif
+ * fills in values for its arguments.
+ *
+ * Note: if the client realm field in the ticket is the null string,
+ * then the "prealm" variable is filled in with the local realm (as
+ * defined by KRB_REALM).
+ *
+ * If the ticket byte order is different than the host's byte order
+ * (as indicated by the byte order bit of the "flags" field), then
+ * the KDC timestamp "time_sec" is byte-swapped. The other fields
+ * potentially affected by byte order, "paddress" and "session" are
+ * not byte-swapped.
+ *
+ * The routine returns KFAILURE if any of the "pname", "pinstance",
+ * or "prealm" fields is too big, otherwise it returns KSUCCESS.
+ *
+ * The corresponding routine to generate tickets is create_ticket.
+ * When changes are made to this routine, the corresponding changes
+ * should also be made to that file.
+ *
+ * See create_ticket.c for the format of the ticket packet.
+ */
+
+int
+decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session,
+ life, time_sec, sname, sinstance, key, key_s)
+ KTEXT tkt; /* The ticket to be decoded */
+ unsigned char *flags; /* Kerberos ticket flags */
+ char *pname; /* Authentication name */
+ char *pinstance; /* Principal's instance */
+ char *prealm; /* Principal's authentication domain */
+ unsigned KRB4_32 *paddress; /* Net address of entity
+ * requesting ticket */
+ C_Block session; /* Session key inserted in ticket */
+ int *life; /* Lifetime of the ticket */
+ unsigned KRB4_32 *time_sec; /* Issue time and date */
+ char *sname; /* Service name */
+ char *sinstance; /* Service instance */
+ C_Block key; /* Service's secret key
+ * (to decrypt the ticket) */
+ Key_schedule key_s; /* The precomputed key schedule */
+{
+ static int tkt_swap_bytes;
+ unsigned char *uptr;
+ char *ptr = (char *)tkt->dat;
+
+#ifndef NOENCRYPTION
+ /* Do the decryption */
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_debug) {
+ FILE *fp;
+ char *keybuf[BUFSIZ]; /* Avoid secret stuff in stdio buffers */
+
+ fp = fopen("/kerberos/tkt.des", "wb");
+ setbuf(fp, keybuf);
+ fwrite(tkt->dat, 1, tkt->length, fp);
+ fclose(fp);
+ memset(keybuf, sizeof(keybuf), 0); /* Clear the buffer */
+ }
+#endif
+ pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,
+ (long) tkt->length,key_s,(C_Block *) key,0);
+#endif /* ! NOENCRYPTION */
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_debug) {
+ FILE *fp;
+ char *keybuf[BUFSIZ]; /* Avoid secret stuff in stdio buffers */
+
+ fp = fopen("/kerberos/tkt.clear", "wb");
+ setbuf(fp, keybuf);
+ fwrite(tkt->dat, 1, tkt->length, fp);
+ fclose(fp);
+ memset(keybuf, sizeof(keybuf), 0); /* Clear the buffer */
+ }
+#endif
+
+ *flags = *ptr; /* get flags byte */
+ ptr += sizeof(*flags);
+ tkt_swap_bytes = 0;
+ if (HOST_BYTE_ORDER != ((*flags >> K_FLAG_ORDER)& 1))
+ tkt_swap_bytes++;
+
+ if (strlen(ptr) > ANAME_SZ)
+ return(KFAILURE);
+ (void) strcpy(pname,ptr); /* pname */
+ ptr += strlen(pname) + 1;
+
+ if (strlen(ptr) > INST_SZ)
+ return(KFAILURE);
+ (void) strcpy(pinstance,ptr); /* instance */
+ ptr += strlen(pinstance) + 1;
+
+ if (strlen(ptr) > REALM_SZ)
+ return(KFAILURE);
+ (void) strcpy(prealm,ptr); /* realm */
+ ptr += strlen(prealm) + 1;
+ /* temporary hack until realms are dealt with properly */
+ if (*prealm == 0)
+ (void) strcpy(prealm,KRB_REALM);
+
+ memcpy((char *)paddress, ptr, 4); /* net address */
+ ptr += 4;
+
+ memcpy((char *)session, ptr, 8); /* session key */
+ ptr+= 8;
+#ifdef notdef /* DONT SWAP SESSION KEY spm 10/22/86 */
+ if (tkt_swap_bytes)
+ swap_C_Block(session);
+#endif
+
+ /* get lifetime, being certain we don't get negative lifetimes */
+ uptr = (unsigned char *) ptr++;
+ *life = (int) *uptr;
+
+ memcpy((char *) time_sec, ptr, 4); /* issue time */
+ ptr += 4;
+ if (tkt_swap_bytes)
+ swap_u_long(*time_sec);
+
+ (void) strcpy(sname,ptr); /* service name */
+ ptr += 1 + strlen(sname);
+
+ (void) strcpy(sinstance,ptr); /* instance */
+ ptr += 1 + strlen(sinstance);
+
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_debug) {
+ krb_log("service=%s.%s len(sname)=%d, len(sinstance)=%d",
+ sname, sinstance, strlen(sname), strlen(sinstance));
+ krb_log("ptr - tkt->dat=%d",(char *)ptr - (char *)tkt->dat);
+ }
+#endif
+
+ return(KSUCCESS);
+}
diff --git a/src/lib/krb4/dest_tkt.c b/src/lib/krb4/dest_tkt.c
new file mode 100644
index 0000000000..1358322edd
--- /dev/null
+++ b/src/lib/krb4/dest_tkt.c
@@ -0,0 +1,94 @@
+/*
+ * dest_tkt.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include <stdio.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#ifdef TKT_SHMEM
+#include <sys/param.h>
+#endif
+#include <errno.h>
+#ifdef NEED_SYS_FCNTL_H
+/* for sconix, to get O_RDWR */
+#include <sys/fcntl.h>
+#endif
+
+/*
+ * dest_tkt() is used to destroy the ticket store upon logout.
+ * If the ticket file does not exist, dest_tkt() returns RET_TKFIL.
+ * Otherwise the function returns RET_OK on success, KFAILURE on
+ * failure.
+ *
+ * The ticket file (TKT_FILE) is defined in "krb.h".
+ */
+
+dest_tkt()
+{
+ char *file = TKT_FILE;
+ int i,fd;
+ extern int errno;
+ struct stat statb;
+ char buf[BUFSIZ];
+#ifdef TKT_SHMEM
+ char shmidname[MAXPATHLEN];
+#endif /* TKT_SHMEM */
+
+ /* If ticket cache selector is null, use default cache. */
+ if (file == 0)
+ file = tkt_string();
+
+ errno = 0;
+ if (lstat(file,&statb) < 0)
+ goto out;
+
+ if (!(statb.st_mode & S_IFREG)
+#ifdef notdef
+ || statb.st_mode & 077
+#endif
+ )
+ goto out;
+
+ if ((fd = open(file, O_RDWR|O_SYNC, 0)) < 0)
+ goto out;
+
+ memset(buf, 0, BUFSIZ);
+
+ for (i = 0; i < statb.st_size; i += BUFSIZ)
+ if (write(fd, buf, BUFSIZ) != BUFSIZ) {
+#ifndef NO_FSYNC
+ (void) fsync(fd);
+#endif
+ (void) close(fd);
+ goto out;
+ }
+
+#ifndef NO_FSYNC
+ (void) fsync(fd);
+#endif
+ (void) close(fd);
+
+ (void) unlink(file);
+
+out:
+ if (errno == ENOENT) return RET_TKFIL;
+ else if (errno != 0) return KFAILURE;
+#ifdef TKT_SHMEM
+ /*
+ * handle the shared memory case
+ */
+ (void) strcpy(shmidname, file);
+ (void) strcat(shmidname, ".shm");
+ if ((i = krb_shm_dest(shmidname)) != KSUCCESS)
+ return(i);
+#endif /* TKT_SHMEM */
+ return(KSUCCESS);
+}
diff --git a/src/lib/krb4/err_txt.c b/src/lib/krb4/err_txt.c
new file mode 100644
index 0000000000..0b7697ea8b
--- /dev/null
+++ b/src/lib/krb4/err_txt.c
@@ -0,0 +1,294 @@
+/*
+ * err_txt.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+
+/*
+ * This file contains an array of error text strings.
+ * The associated error codes (which are defined in "krb.h")
+ * follow the string in the comments at the end of each line.
+ */
+
+const
+/* Some C compilers (like ThinkC when producing a driver) can't grok
+ initialized multimentional arrays! */
+#ifdef MULTIDIMENSIONAL_ERR_TXT
+ char krb_err_txt[256][60] = {
+#else
+ char *const krb_err_txt [256] = {
+#endif
+ "OK", /* 000 */
+ "Principal expired (kerberos)", /* 001 */
+ "Service expired (kerberos)", /* 002 */
+ "Authentication expired (kerberos)", /* 003 */
+ "Unknown protocol version number (kerberos)", /* 004 */
+ "Principal: Incorrect master key version (kerberos)", /* 005 */
+ "Service: Incorrect master key version (kerberos)", /* 006 */
+ "Bad byte order (kerberos)", /* 007 */
+ "Principal unknown (kerberos)", /* 008 */
+ "Principal not unique (kerberos)", /* 009 */
+ "Principal has null key (kerberos)", /* 010 */
+ "Reserved error message 11 (kerberos)", /* 011 */
+ "Reserved error message 12 (kerberos)", /* 012 */
+ "Reserved error message 13 (kerberos)", /* 013 */
+ "Reserved error message 14 (kerberos)", /* 014 */
+ "Reserved error message 15 (kerberos)", /* 015 */
+ "Reserved error message 16 (kerberos)", /* 016 */
+ "Reserved error message 17 (kerberos)", /* 017 */
+ "Reserved error message 18 (kerberos)", /* 018 */
+ "Reserved error message 19 (kerberos)", /* 019 */
+ "Permission Denied (kerberos)", /* 020 */
+ "Can't read ticket file (krb_get_cred)", /* 021 */
+ "Can't find ticket (krb_get_cred)", /* 022 */
+ "Reserved error message 23 (krb_get_cred)", /* 023 */
+ "Reserved error message 24 (krb_get_cred)", /* 024 */
+ "Reserved error message 25 (krb_get_cred)", /* 025 */
+ "Ticket granting ticket expired (krb_mk_req)", /* 026 */
+ "Reserved error message 27 (krb_mk_req)", /* 027 */
+ "Reserved error message 28 (krb_mk_req)", /* 028 */
+ "Reserved error message 29 (krb_mk_req)", /* 029 */
+ "Reserved error message 30 (krb_mk_req)", /* 030 */
+ "Can't decode authenticator (krb_rd_req)", /* 031 */
+ "Ticket expired (krb_rd_req)", /* 032 */
+ "Ticket issue date too far in the future (krb_rd_req)",/* 033 */
+ "Repeat request (krb_rd_req)", /* 034 */
+ "Ticket for wrong server (krb_rd_req)", /* 035 */
+ "Request inconsistent (krb_rd_req)", /* 036 */
+ "Time is out of bounds (krb_rd_req)", /* 037 */
+ "Incorrect network address (krb_rd_req)", /* 038 */
+ "Protocol version mismatch (krb_rd_req)", /* 039 */
+ "Illegal message type (krb_rd_req)", /* 040 */
+ "Message integrity error (krb_rd_req)", /* 041 */
+ "Message duplicate or out of order (krb_rd_req)", /* 042 */
+ "Unauthorized request (krb_rd_req)", /* 043 */
+ "Reserved error message 44 (krb_rd_req)", /* 044 */
+ "Reserved error message 45 (krb_rd_req)", /* 045 */
+ "Reserved error message 46 (krb_rd_req)", /* 046 */
+ "Reserved error message 47 (krb_rd_req)", /* 047 */
+ "Reserved error message 48 (krb_rd_req)", /* 048 */
+ "Reserved error message 49 (krb_rd_req)", /* 049 */
+ "Reserved error message 50 (krb_rd_req)", /* 050 */
+ "Current password is NULL (get_pw_tkt)", /* 051 */
+ "Current password incorrect (get_pw_tkt)", /* 052 */
+ "Protocol error (gt_pw_tkt)", /* 053 */
+ "Error returned by KDC (gt_pw_tkt)", /* 054 */
+ "Null ticket returned by KDC (gt_pw_tkt)", /* 055 */
+ "Retry count exceeded (send_to_kdc)", /* 056 */
+ "Can't send request (send_to_kdc)", /* 057 */
+ "Reserved error message 58 (send_to_kdc)", /* 058 */
+ "Reserved error message 59 (send_to_kdc)", /* 059 */
+ "Reserved error message 60 (send_to_kdc)", /* 060 */
+ "Warning: Not ALL tickets returned", /* 061 */
+ "Password incorrect", /* 062 */
+ "Protocol error (get_intkt)", /* 063 */
+ "Reserved error message 64 (get_in_tkt)", /* 064 */
+ "Reserved error message 65 (get_in_tkt)", /* 065 */
+ "Reserved error message 66 (get_in_tkt)", /* 066 */
+ "Reserved error message 67 (get_in_tkt)", /* 067 */
+ "Reserved error message 68 (get_in_tkt)", /* 068 */
+ "Reserved error message 69 (get_in_tkt)", /* 069 */
+ "Generic error (get_intkt)", /* 070 */
+ "Don't have ticket granting ticket (get_ad_tkt)", /* 071 */
+ "Reserved error message 72 (get_ad_tkt)", /* 072 */
+ "Reserved error message 73 (get_ad_tkt)", /* 073 */
+ "Reserved error message 74 (get_ad_tkt)", /* 074 */
+ "Reserved error message 75 (get_ad_tkt)", /* 075 */
+ "You have no tickets cached", /* 076 */
+ "Can't access ticket file (tf_util)", /* 077 */
+ "Can't lock ticket file; try later (tf_util)", /* 078 */
+ "Bad ticket file format (tf_util)", /* 079 */
+ "Read ticket file before tf_init (tf_util)", /* 080 */
+ "Bad Kerberos name format (kname_parse)", /* 081 */
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "(reserved)",
+ "Generic kerberos error (kfailure)", /* 255 */
+};
+
+
+const char * INTERFACE
+krb_get_err_text (errno)
+ int errno;
+{
+ if (errno >= 0 && errno < (sizeof (krb_err_txt))/(sizeof *krb_err_txt))
+ return krb_err_txt[errno];
+ else
+ return "Invalid Kerberos error code";
+}
diff --git a/src/lib/krb4/fakeenv.c b/src/lib/krb4/fakeenv.c
new file mode 100644
index 0000000000..d4f4d7638f
--- /dev/null
+++ b/src/lib/krb4/fakeenv.c
@@ -0,0 +1,88 @@
+/*
+ * fakeenv.c
+ *
+ * Originally written by Mark Eichin, Cygnus Support, 1992.
+ * Public Domain.
+ *
+ * setenv --
+ * Set the value of the environmental variable "name" to be
+ * "value". If rewrite is set, replace any current value.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+setenv(name, value, rewrite)
+ register char *name, *value;
+ int rewrite;
+{
+ char *combo = malloc(strlen(name)+strlen(value)+2);
+ strcpy(combo,name);
+ strcat(combo,"=");
+ strcat(combo,value);
+ putenv(combo);
+}
+
+/*
+ * 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.
+ */
+
+/*
+ * _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.
+ */
+static 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);
+}
+
+/*
+ * 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;
+}
diff --git a/src/lib/krb4/fgetst.c b/src/lib/krb4/fgetst.c
new file mode 100644
index 0000000000..b5d8aa5cbb
--- /dev/null
+++ b/src/lib/krb4/fgetst.c
@@ -0,0 +1,35 @@
+/*
+ * fgetst.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+
+/*
+ * fgetst takes a file descriptor, a character pointer, and a count.
+ * It reads from the file it has either read "count" characters, or
+ * until it reads a null byte. When finished, what has been read exists
+ * in "s". If "count" characters were actually read, the last is changed
+ * to a null, so the returned string is always null-terminated. fgetst
+ * returns the number of characters read, including the null terminator.
+ */
+
+fgetst(f, s, n)
+ FILE *f;
+ register char *s;
+ int n;
+{
+ register count = n;
+ int ch; /* NOT char; otherwise you don't see EOF */
+
+ while ((ch = getc(f)) != EOF && ch && --count) {
+ *s++ = ch;
+ }
+ *s = '\0';
+ return (n - count);
+}
diff --git a/src/lib/krb4/g_ad_tkt.c b/src/lib/krb4/g_ad_tkt.c
new file mode 100644
index 0000000000..55a82bb71e
--- /dev/null
+++ b/src/lib/krb4/g_ad_tkt.c
@@ -0,0 +1,241 @@
+/*
+ * g_ad_tkt.c
+ *
+ * Copyright 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "des.h"
+#include "prot.h"
+#include <string.h>
+
+#include <stdio.h>
+
+extern int krb_debug;
+extern int swap_bytes;
+
+/*
+ * get_ad_tkt obtains a new service ticket from Kerberos, using
+ * the ticket-granting ticket which must be in the ticket file.
+ * It is typically called by krb_mk_req() when the client side
+ * of an application is creating authentication information to be
+ * sent to the server side.
+ *
+ * get_ad_tkt takes four arguments: three pointers to strings which
+ * contain the name, instance, and realm of the service for which the
+ * ticket is to be obtained; and an integer indicating the desired
+ * lifetime of the ticket.
+ *
+ * It returns an error status if the ticket couldn't be obtained,
+ * or AD_OK if all went well. The ticket is stored in the ticket
+ * cache.
+ *
+ * The request sent to the Kerberos ticket-granting service looks
+ * like this:
+ *
+ * pkt->dat
+ *
+ * TEXT original contents of authenticator+ticket
+ * pkt->dat built in krb_mk_req call
+ *
+ * 4 bytes time_ws always 0 (?) FIXME!
+ * char lifetime lifetime argument passed
+ * string service service name argument
+ * string sinstance service instance arg.
+ *
+ * See "prot.h" for the reply packet layout and definitions of the
+ * extraction macros like pkt_version(), pkt_msg_type(), etc.
+ */
+
+get_ad_tkt(service,sinstance,realm,lifetime)
+ char *service;
+ char *sinstance;
+ char *realm;
+ int lifetime;
+{
+ unsigned long rep_err_code;
+
+ KTEXT_ST pkt_st;
+ KTEXT pkt = & pkt_st; /* Packet to KDC */
+ KTEXT_ST rpkt_st;
+ KTEXT rpkt = &rpkt_st; /* Returned packet */
+ KTEXT_ST cip_st;
+ KTEXT cip = &cip_st; /* Returned Ciphertext */
+ KTEXT_ST tkt_st;
+ KTEXT tkt = &tkt_st; /* Current ticket */
+ C_Block ses; /* Session key for tkt */
+ CREDENTIALS cr;
+ int kvno; /* Kvno for session key */
+ char lrealm[REALM_SZ];
+ Key_schedule key_s;
+ KRB4_32 time_ws = 0;
+ char s_name[SNAME_SZ];
+ char s_instance[INST_SZ];
+ int msg_byte_order;
+ int kerror;
+ char rlm[REALM_SZ];
+ char *ptr;
+ unsigned KRB4_32 t_local; /* Must be 4 bytes long for memcpy below! */
+ KRB4_32 t_diff; /* Difference between timestamps */
+ unsigned KRB4_32 kdc_time; /* KDC time */
+ unsigned int t_switch;
+
+ if ((kerror = krb_get_tf_realm(TKT_FILE, lrealm)) != KSUCCESS)
+ return(kerror);
+
+ /* Create skeleton of packet to be sent */
+ pkt->length = 0;
+
+ /*
+ * Look for the session key (and other stuff we don't need)
+ * in the ticket file for krbtgt.realm@lrealm where "realm"
+ * is the service's realm (passed in "realm" argument) and
+ * "lrealm" is the realm of our initial ticket (the local realm).
+ * If that fails, and the server's realm and the local realm are
+ * the same thing, give up - no TGT available for local realm.
+ *
+ * If the server realm and local realm are different, though,
+ * try getting a ticket-granting ticket for the server's realm,
+ * i.e. a ticket for "krbtgt.alienrealm@lrealm", by calling get_ad_tkt().
+ * If that succeeds, the ticket will be in ticket cache, get it
+ * into the "cr" structure by calling krb_get_cred().
+ */
+
+ if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS) {
+ /*
+ * If realm == lrealm, we have no hope, so let's not even try.
+ */
+ if ((strncmp(realm, lrealm, REALM_SZ)) == 0)
+ return(AD_NOTGT);
+ else{
+ if ((kerror =
+ get_ad_tkt("krbtgt",realm,lrealm,lifetime)) != KSUCCESS) {
+ if (kerror == KDC_PR_UNKNOWN) /* no cross-realm ticket */
+ return AD_NOTGT; /* So call it no ticket */
+ return(kerror);
+ }
+ if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS)
+ return(kerror);
+ }
+ }
+
+ /*
+ * Make up a request packet to the "krbtgt.realm@lrealm".
+ * Start by calling krb_mk_req() which puts ticket+authenticator
+ * into "pkt". Then tack other stuff on the end.
+ */
+
+ kerror = krb_mk_req(pkt,"krbtgt",realm,lrealm,0L);
+
+ if (kerror)
+ return(AD_NOTGT);
+
+ /* timestamp */ /* FIXME -- always 0 now, should we fill it in??? */
+ memcpy((char *) (pkt->dat+pkt->length), (char *) &time_ws, 4);
+ pkt->length += 4;
+ *(pkt->dat+(pkt->length)++) = (char) lifetime;
+ (void) strcpy((char *) (pkt->dat+pkt->length),service);
+ pkt->length += 1 + strlen(service);
+ (void) strcpy((char *)(pkt->dat+pkt->length),sinstance);
+ pkt->length += 1 + strlen(sinstance);
+
+ rpkt->length = 0;
+
+ /* Send the request to the local ticket-granting server */
+ if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror);
+
+ /* check packet version of the returned packet */
+ if (pkt_version(rpkt) != KRB_PROT_VERSION )
+ return(INTK_PROT);
+
+ /* Check byte order */
+ msg_byte_order = pkt_msg_type(rpkt) & 1;
+ swap_bytes = 0;
+ if (msg_byte_order != HOST_BYTE_ORDER)
+ swap_bytes++;
+
+ /* This used to be
+ switch (pkt_msg_type(rpkt) & ~1) {
+ but SCO 3.2v4 cc compiled that incorrectly. */
+ t_switch = pkt_msg_type(rpkt);
+ t_switch &= ~1;
+ switch (t_switch) {
+ case AUTH_MSG_KDC_REPLY:
+ break;
+ case AUTH_MSG_ERR_REPLY:
+ memcpy((char *) &rep_err_code, pkt_err_code(rpkt), 4);
+ if (swap_bytes)
+ swap_u_long(rep_err_code);
+ return(rep_err_code);
+
+ default:
+ return(INTK_PROT);
+ }
+
+ /* Extract the ciphertext */
+ cip->length = pkt_clen(rpkt); /* let clen do the swap */
+
+ memcpy((char *) (cip->dat), (char *) pkt_cipher(rpkt), cip->length);
+
+#ifndef NOENCRYPTION
+ /* Attempt to decrypt it */
+
+ key_sched(cr.session,key_s);
+ DEB (("About to do decryption ..."));
+ pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat,
+ (long) cip->length,key_s,(C_Block *)cr.session,0);
+#endif /* !NOENCRYPTION */
+ /* Get rid of all traces of key */
+ memset((char *) cr.session, 0, sizeof(cr.session));
+ memset((char *) key_s, 0, sizeof(key_s));
+
+ ptr = (char *) cip->dat;
+
+ memcpy((char *)ses, ptr, 8);
+ ptr += 8;
+
+ (void) strcpy(s_name,ptr);
+ ptr += strlen(s_name) + 1;
+
+ (void) strcpy(s_instance,ptr);
+ ptr += strlen(s_instance) + 1;
+
+ (void) strcpy(rlm,ptr);
+ ptr += strlen(rlm) + 1;
+
+ lifetime = (unsigned long) ptr[0];
+ kvno = (unsigned long) ptr[1];
+ tkt->length = (int) ptr[2];
+ ptr += 3;
+ memcpy((char *)(tkt->dat), ptr, tkt->length);
+ ptr += tkt->length;
+
+ if (strcmp(s_name, service) || strcmp(s_instance, sinstance) ||
+ strcmp(rlm, realm)) /* not what we asked for */
+ return(INTK_ERR); /* we need a better code here XXX */
+
+ /* check KDC time stamp */
+ memcpy((char *)&kdc_time, ptr, 4); /* Time (coarse) */
+ if (swap_bytes) swap_u_long(kdc_time);
+
+ ptr += 4;
+
+ t_local = TIME_GMT_UNIXSEC;
+ t_diff = t_local - kdc_time;
+ if (t_diff < 0) t_diff = -t_diff; /* Absolute value of difference */
+ if (t_diff > CLOCK_SKEW) {
+ return(RD_AP_TIME); /* XXX should probably be better
+ code */
+ }
+
+ if (kerror = krb_save_credentials(s_name,s_instance,rlm,ses,lifetime,
+ kvno,tkt,t_local))
+ return(kerror);
+
+ return(AD_OK);
+}
diff --git a/src/lib/krb4/g_admhst.c b/src/lib/krb4/g_admhst.c
new file mode 100644
index 0000000000..68ac1f0dac
--- /dev/null
+++ b/src/lib/krb4/g_admhst.c
@@ -0,0 +1,77 @@
+/*
+ * g_admhst.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include "krb.h"
+#include <string.h>
+
+/*
+ * Given a Kerberos realm, find a host on which the Kerberos database
+ * administration server can be found.
+ *
+ * krb_get_admhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer n, and
+ * returns (in h) the nth administrative host entry from the configuration
+ * file (KRB_CONF, defined in "krb.h") associated with the specified realm.
+ * If ATHENA_CONF_FALLBACK is defined, also look in old location.
+ *
+ * On error, get_admhst returns KFAILURE. If all goes well, the routine
+ * returns KSUCCESS.
+ *
+ * For the format of the KRB_CONF file, see comments describing the routine
+ * krb_get_krbhst().
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * a Kerberos admin server. In the long run, this functionality will be
+ * provided by a nameserver.
+ */
+
+int INTERFACE
+krb_get_admhst(h, r, n)
+ char *h;
+ char *r;
+ int n;
+{
+ FILE *cnffile, *krb__get_cnffile();
+ char tr[REALM_SZ];
+ char linebuf[BUFSIZ];
+ char scratch[64];
+ register int i;
+
+ cnffile = krb__get_cnffile();
+ if (!cnffile)
+ return(KFAILURE);
+ if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
+ /* error reading */
+ (void) fclose(cnffile);
+ return(KFAILURE);
+ }
+ if (!strchr(linebuf, '\n')) {
+ /* didn't all fit into buffer, punt */
+ (void) fclose(cnffile);
+ return(KFAILURE);
+ }
+ for (i = 0; i < n; ) {
+ /* run through the file, looking for admin host */
+ if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
+ (void) fclose(cnffile);
+ return(KFAILURE);
+ }
+ /* need to scan for a token after 'admin' to make sure that
+ admin matched correctly */
+ if (sscanf(linebuf, "%s %s admin %s", tr, h, scratch) != 3)
+ continue;
+ if (!strcmp(tr,r))
+ i++;
+ }
+ (void) fclose(cnffile);
+ return(KSUCCESS);
+}
diff --git a/src/lib/krb4/g_cnffile.c b/src/lib/krb4/g_cnffile.c
new file mode 100644
index 0000000000..b1d38efdfd
--- /dev/null
+++ b/src/lib/krb4/g_cnffile.c
@@ -0,0 +1,53 @@
+/* Copyright 1994 Cygnus Support */
+/* Mark W. Eichin */
+/*
+ * 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.
+ * Cygnus Support makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/* common code for looking at krb.conf and krb.realms file */
+/* this may be superceded by <gnu>'s work for the Mac port, but
+ it solves a problem for now. */
+
+#include <stdio.h>
+#include <krb.h>
+
+FILE*
+krb__get_cnffile()
+{
+ char *s;
+ FILE *cnffile = 0;
+ extern char *getenv();
+
+ s = getenv("KRB_CONF");
+ if (s) cnffile = fopen(s,"r");
+ if (!cnffile) cnffile = fopen(KRB_CONF,"r");
+#ifdef ATHENA_CONF_FALLBACK
+ if (!cnffile) cnffile = fopen(KRB_FB_CONF,"r");
+#endif
+ return cnffile;
+}
+
+
+FILE*
+krb__get_realmsfile()
+{
+ FILE *realmsfile;
+
+ realmsfile = fopen(KRB_RLM_TRANS, "r");
+
+#ifdef ATHENA_CONF_FALLBACK
+ if (realmsfile == (FILE *) 0)
+ realmsfile = fopen(KRB_FB_RLM_TRANS, "r");
+#endif
+
+ return realmsfile;
+}
+
+
diff --git a/src/lib/krb4/g_cred.c b/src/lib/krb4/g_cred.c
new file mode 100644
index 0000000000..491861be66
--- /dev/null
+++ b/src/lib/krb4/g_cred.c
@@ -0,0 +1,58 @@
+/*
+ * g_cred.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include <string.h>
+#include "krb.h"
+
+/*
+ * krb_get_cred takes a service name, instance, and realm, and a
+ * structure of type CREDENTIALS to be filled in with ticket
+ * information. It then searches the ticket file for the appropriate
+ * ticket and fills in the structure with the corresponding
+ * information from the file. If successful, it returns KSUCCESS.
+ * On failure it returns a Kerberos error code.
+ */
+
+int INTERFACE
+krb_get_cred(service,instance,realm,c)
+ char *service; /* Service name */
+ char *instance; /* Instance */
+ char *realm; /* Auth domain */
+ CREDENTIALS *c; /* Credentials struct */
+{
+ int tf_status; /* return value of tf function calls */
+
+ /* Open ticket file and lock it for shared reading */
+ if ((tf_status = tf_init(TKT_FILE, R_TKT_FIL)) != KSUCCESS)
+ return(tf_status);
+
+ /* Copy principal's name and instance into the CREDENTIALS struc c */
+
+ if ( (tf_status = tf_get_pname(c->pname)) != KSUCCESS ||
+ (tf_status = tf_get_pinst(c->pinst)) != KSUCCESS )
+ return (tf_status);
+
+ /* Search for requested service credentials and copy into c */
+
+ while ((tf_status = tf_get_cred(c)) == KSUCCESS) {
+ /* Is this the right ticket? */
+ if ((strcmp(c->service,service) == 0) &&
+ (strcmp(c->instance,instance) == 0) &&
+ (strcmp(c->realm,realm) == 0))
+ break;
+ }
+ (void) tf_close();
+
+ if (tf_status == EOF)
+ return (GC_NOTKT);
+ return(tf_status);
+}
diff --git a/src/lib/krb4/g_in_tkt.c b/src/lib/krb4/g_in_tkt.c
new file mode 100644
index 0000000000..35abf2e903
--- /dev/null
+++ b/src/lib/krb4/g_in_tkt.c
@@ -0,0 +1,387 @@
+/*
+ * g_in_tkt.c
+ *
+ * CoKRB4_32yright 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "des.h"
+#include "prot.h"
+
+#include <string.h>
+
+extern int swap_bytes;
+
+/* Define a couple of function types including parameters. These
+ are needed on MS-Windows to convert arguments of the function pointers
+ to the proper types during calls. These declarations are found
+ in <krb-sed.h>, but the code below is too opaque if you can't also
+ see them here. */
+#ifndef KEY_PROC_TYPE_DEFINED
+typedef int (*key_proc_type) PROTOTYPE ((char *, char *, char *,
+ char *, C_Block));
+#endif
+#ifndef DECRYPT_TKT_TYPE_DEFINED
+typedef int (*decrypt_tkt_type) PROTOTYPE ((char *, char *, char *, char *,
+ key_proc_type, KTEXT *));
+#endif
+
+/*
+ * decrypt_tkt(): Given user, instance, realm, passwd, key_proc
+ * and the cipher text sent from the KDC, decrypt the cipher text
+ * using the key returned by key_proc.
+ */
+
+static int
+decrypt_tkt(user, instance, realm, arg, key_proc, cipp)
+ char *user;
+ char *instance;
+ char *realm;
+ char *arg;
+ key_proc_type key_proc;
+ KTEXT *cipp;
+{
+ KTEXT cip = *cipp;
+ C_Block key; /* Key for decrypting cipher */
+ Key_schedule key_s;
+
+#ifndef NOENCRYPTION
+ /* Attempt to decrypt it */
+#endif
+
+ /* generate a key from the supplied arg or password. */
+
+ {
+ register int rc;
+ rc = (*key_proc) (user,instance,realm,arg,key);
+ if (rc)
+ return(rc);
+ }
+
+#ifndef NOENCRYPTION
+ key_sched(key,key_s);
+ pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat,
+ (long) cip->length,key_s,(C_Block *)&key,0);
+#endif /* !NOENCRYPTION */
+ /* Get rid of all traces of key */
+ memset((char *)key, 0,sizeof(key));
+ memset((char *)key_s, 0,sizeof(key_s));
+
+ return(0);
+}
+
+/*
+ * krb_get_in_tkt() gets a ticket for a given principal to use a given
+ * service and stores the returned ticket and session key for future
+ * use.
+ *
+ * The "user", "instance", and "realm" arguments give the identity of
+ * the client who will use the ticket. The "service" and "sinstance"
+ * arguments give the identity of the server that the client wishes
+ * to use. (The realm of the server is the same as the Kerberos server
+ * to whom the request is sent.) The "life" argument indicates the
+ * desired lifetime of the ticket; the "key_proc" argument is a pointer
+ * to the routine used for getting the client's private key to decrypt
+ * the reply from Kerberos. The "decrypt_proc" argument is a pointer
+ * to the routine used to decrypt the reply from Kerberos; and "arg"
+ * is an argument to be passed on to the "key_proc" routine.
+ *
+ * If all goes well, krb_get_in_tkt() returns INTK_OK, otherwise it
+ * returns an error code: If an AUTH_MSG_ERR_REPLY packet is returned
+ * by Kerberos, then the error code it contains is returned. Other
+ * error codes returned by this routine include INTK_PROT to indicate
+ * wrong protocol version, INTK_BADPW to indicate bad password (if
+ * decrypted ticket didn't make sense), INTK_ERR if the ticket was for
+ * the wrong server or the ticket store couldn't be initialized.
+ *
+ * The format of the message sent to Kerberos is as follows:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * 1 byte KRB_PROT_VERSION protocol version number
+ * 1 byte AUTH_MSG_KDC_REQUEST | message type
+ * HOST_BYTE_ORDER local byte order in lsb
+ * string user client's name
+ * string instance client's instance
+ * string realm client's realm
+ * 4 bytes tlocal.tv_sec timestamp in seconds
+ * 1 byte life desired lifetime
+ * string service service's name
+ * string sinstance service's instance
+ */
+
+int
+krb_mk_in_tkt_preauth(user, instance, realm, service, sinstance, life,
+ preauth_p, preauth_len, cip)
+ char *user;
+ char *instance;
+ char *realm;
+ char *service;
+ char *sinstance;
+ int life;
+ char *preauth_p;
+ int preauth_len;
+ KTEXT cip;
+{
+ KTEXT_ST pkt_st;
+ KTEXT pkt = &pkt_st; /* Packet to KDC */
+ KTEXT_ST rpkt_st;
+ KTEXT rpkt = &rpkt_st; /* Returned packet */
+ unsigned char *v = pkt->dat; /* Prot vers no */
+ unsigned char *t = (pkt->dat+1); /* Prot msg type */
+
+ int msg_byte_order;
+ int kerror;
+#if 0
+ unsigned long exp_date;
+#endif
+ unsigned long rep_err_code;
+ unsigned int t_switch;
+ unsigned KRB4_32 t_local; /* Must be 4 bytes long for memcpy below! */
+
+ /* BUILD REQUEST PACKET */
+
+ /* Set up the fixed part of the packet */
+ *v = (unsigned char) KRB_PROT_VERSION;
+ *t = (unsigned char) AUTH_MSG_KDC_REQUEST;
+ *t |= HOST_BYTE_ORDER;
+
+ /* Now for the variable info */
+ (void) strcpy((char *)(pkt->dat+2),user); /* aname */
+ pkt->length = 3 + strlen(user);
+ (void) strcpy((char *)(pkt->dat+pkt->length),
+ instance); /* instance */
+ pkt->length += 1 + strlen(instance);
+ (void) strcpy((char *)(pkt->dat+pkt->length),realm); /* realm */
+ pkt->length += 1 + strlen(realm);
+
+ /* timestamp */
+ t_local = TIME_GMT_UNIXSEC;
+ memcpy((char *)(pkt->dat+pkt->length), (char *)&t_local, 4);
+ pkt->length += 4;
+
+ *(pkt->dat+(pkt->length)++) = (char) life;
+ (void) strcpy((char *)(pkt->dat+pkt->length),service);
+ pkt->length += 1 + strlen(service);
+ (void) strcpy((char *)(pkt->dat+pkt->length),sinstance);
+
+ pkt->length += 1 + strlen(sinstance);
+
+ if (preauth_len)
+ memcpy((char *)(pkt->dat+pkt->length), preauth_p, preauth_len);
+ pkt->length += preauth_len;
+
+ rpkt->length = 0;
+
+ /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */
+
+ if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror);
+
+ /* check packet version of the returned packet */
+ if (pkt_version(rpkt) != KRB_PROT_VERSION)
+ return(INTK_PROT);
+
+ /* Check byte order */
+ msg_byte_order = pkt_msg_type(rpkt) & 1;
+ swap_bytes = 0;
+ if (msg_byte_order != HOST_BYTE_ORDER) {
+ swap_bytes++;
+ }
+
+ /* This used to be
+ switch (pkt_msg_type(rpkt) & ~1) {
+ but SCO 3.2v4 cc compiled that incorrectly. */
+ t_switch = pkt_msg_type(rpkt);
+ t_switch &= ~1;
+ switch (t_switch) {
+ case AUTH_MSG_KDC_REPLY:
+ break;
+ case AUTH_MSG_ERR_REPLY:
+ memcpy((char *) &rep_err_code, pkt_err_code(rpkt), 4);
+ if (swap_bytes) swap_u_long(rep_err_code);
+ return((int)rep_err_code);
+ default:
+ return(INTK_PROT);
+ }
+
+ /* EXTRACT INFORMATION FROM RETURN PACKET */
+
+#if 0
+ /* not used */
+ /* get the principal's expiration date */
+ memcpy((char *) &exp_date, pkt_x_date(rpkt), sizeof(exp_date));
+ if (swap_bytes) swap_u_long(exp_date);
+#endif
+
+ /* Extract the ciphertext */
+ cip->length = pkt_clen(rpkt); /* let clen do the swap */
+
+ if ((cip->length < 0) || (cip->length > sizeof(cip->dat)))
+ return(INTK_ERR); /* no appropriate error code
+ currently defined for INTK_ */
+ /* copy information from return packet into "cip" */
+ memcpy((char *)(cip->dat), (char *) pkt_cipher(rpkt), cip->length);
+
+ return INTK_OK;
+}
+
+
+int
+krb_parse_in_tkt(user, instance, realm, service, sinstance, life, cip)
+ char *user;
+ char *instance;
+ char *realm;
+ char *service;
+ char *sinstance;
+ int life;
+ KTEXT cip;
+{
+ char *ptr;
+ C_Block ses; /* Session key for tkt */
+ int kvno; /* Kvno for session key */
+ char s_name[SNAME_SZ];
+ char s_instance[INST_SZ];
+ char rlm[REALM_SZ];
+ KTEXT_ST tkt_st;
+ KTEXT tkt = &tkt_st; /* Current ticket */
+ unsigned long kdc_time; /* KDC time */
+ unsigned KRB4_32 t_local; /* Must be 4 bytes long for memcpy below! */
+ KRB4_32 t_diff; /* Difference between timestamps */
+ int kerror;
+ int lifetime;
+
+ ptr = (char *) cip->dat;
+
+ /* extract session key */
+ memcpy((char *)ses, ptr, 8);
+ ptr += 8;
+
+ if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
+ return(INTK_BADPW);
+
+ /* extract server's name */
+ (void) strncpy(s_name,ptr, sizeof(s_name)-1);
+ s_name[sizeof(s_name)-1] = '\0';
+ ptr += strlen(s_name) + 1;
+
+ if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
+ return(INTK_BADPW);
+
+ /* extract server's instance */
+ (void) strncpy(s_instance,ptr, sizeof(s_instance)-1);
+ s_instance[sizeof(s_instance)-1] = '\0';
+ ptr += strlen(s_instance) + 1;
+
+ if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length)
+ return(INTK_BADPW);
+
+ /* extract server's realm */
+ (void) strncpy(rlm,ptr, sizeof(rlm));
+ rlm[sizeof(rlm)-1] = '\0';
+ ptr += strlen(rlm) + 1;
+
+ /* extract ticket lifetime, server key version, ticket length */
+ /* be sure to avoid sign extension on lifetime! */
+ lifetime = (unsigned char) ptr[0];
+ kvno = (unsigned char) ptr[1];
+ tkt->length = (unsigned char) ptr[2];
+ ptr += 3;
+
+ if ((tkt->length < 0) ||
+ ((tkt->length + (ptr - (char *) cip->dat)) > cip->length))
+ return(INTK_BADPW);
+
+ /* extract ticket itself */
+ memcpy((char *)(tkt->dat), ptr, tkt->length);
+ ptr += tkt->length;
+
+ if (strcmp(s_name, service) || strcmp(s_instance, sinstance) ||
+ strcmp(rlm, realm)) /* not what we asked for */
+ return(INTK_ERR); /* we need a better code here XXX */
+
+ /* check KDC time stamp */
+ memcpy((char *)&kdc_time, ptr, 4); /* Time (coarse) */
+ if (swap_bytes) swap_u_long(kdc_time);
+
+ ptr += 4;
+
+ t_local = TIME_GMT_UNIXSEC;
+ t_diff = t_local - kdc_time;
+ if (t_diff < 0) t_diff = -t_diff; /* Absolute value of difference */
+ if (t_diff > CLOCK_SKEW) {
+ return(RD_AP_TIME); /* XXX should probably be better
+ code */
+ }
+
+ /* initialize ticket cache */
+ if (in_tkt(user,instance) != KSUCCESS)
+ return(INTK_ERR);
+
+ /* stash ticket, session key, etc. for future use */
+ if (kerror = krb_save_credentials(s_name, s_instance, rlm, ses,
+ lifetime, kvno, tkt, t_local))
+ return(kerror);
+
+ return(INTK_OK);
+}
+
+int
+krb_get_in_tkt_preauth(user, instance, realm, service, sinstance, life,
+ key_proc, decrypt_proc, arg, preauth_p, preauth_len)
+ char *user;
+ char *instance;
+ char *realm;
+ char *service;
+ char *sinstance;
+ int life;
+ key_proc_type key_proc;
+ decrypt_tkt_type decrypt_proc;
+ char *arg;
+ char *preauth_p;
+ int preauth_len;
+{
+ KTEXT_ST cip_st;
+ KTEXT cip = &cip_st; /* Returned Ciphertext */
+ int kerror;
+ if (kerror = krb_mk_in_tkt_preauth(user, instance, realm,
+ service, sinstance,
+ life, preauth_p, preauth_len, cip))
+ return kerror;
+
+ /* Attempt to decrypt the reply. */
+ if (decrypt_proc == NULL)
+ decrypt_tkt (user, instance, realm, arg, key_proc, &cip);
+ else
+ (*decrypt_proc)(user, instance, realm, arg, key_proc, &cip);
+
+ return
+ krb_parse_in_tkt(user, instance, realm, service, sinstance,
+ life, cip);
+
+}
+
+int
+krb_get_in_tkt(user, instance, realm, service, sinstance, life,
+ key_proc, decrypt_proc, arg)
+ char *user;
+ char *instance;
+ char *realm;
+ char *service;
+ char *sinstance;
+ int life;
+ key_proc_type key_proc;
+ decrypt_tkt_type decrypt_proc;
+ char *arg;
+{
+ return krb_get_in_tkt_preauth(user, instance, realm,
+ service, sinstance, life,
+ key_proc, decrypt_proc, arg, (char *)0, 0);
+
+}
+
diff --git a/src/lib/krb4/g_krbhst.c b/src/lib/krb4/g_krbhst.c
new file mode 100644
index 0000000000..eaab289281
--- /dev/null
+++ b/src/lib/krb4/g_krbhst.c
@@ -0,0 +1,93 @@
+/*
+ * g_krbhst.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include "krb.h"
+#include <string.h>
+
+/*
+ * Given a Kerberos realm, find a host on which the Kerberos authenti-
+ * cation server can be found.
+ *
+ * krb_get_krbhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer, n, and
+ * returns (in h) the nth entry from the configuration file (KRB_CONF,
+ * defined in "krb.h") associated with the specified realm.
+ *
+ * On end-of-file, krb_get_krbhst returns KFAILURE. If n=1 and the
+ * configuration file does not exist, krb_get_krbhst will return KRB_HOST
+ * (also defined in "krb.h"). If all goes well, the routine returnes
+ * KSUCCESS.
+ *
+ * The KRB_CONF file contains the name of the local realm in the first
+ * line (not used by this routine), followed by lines indicating realm/host
+ * entries. The words "admin server" following the hostname indicate that
+ * the host provides an administrative database server.
+ * This will also look in KRB_FB_CONF if ATHENA_CONF_FALLBACK is defined.
+ *
+ * For example:
+ *
+ * ATHENA.MIT.EDU
+ * ATHENA.MIT.EDU kerberos-1.mit.edu admin server
+ * ATHENA.MIT.EDU kerberos-2.mit.edu
+ * LCS.MIT.EDU kerberos.lcs.mit.edu admin server
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * kerberos. In the long run, this functionality will be provided by a
+ * nameserver.
+ */
+
+static int
+get_krbhst_default(h, r, n)
+ char *h;
+ char *r;
+ int n;
+{
+ if (n==1) {
+ (void) strcpy(h,KRB_HOST);
+ (void) strcat(h,".");
+ (void) strcat(h,r); /* KRB_HOST.REALM (ie. kerberos.CYGNUS.COM) */
+ return(KSUCCESS);
+ }
+ else
+ return(KFAILURE);
+}
+
+int INTERFACE
+krb_get_krbhst(h,r,n)
+ char *h;
+ char *r;
+ int n;
+{
+ FILE *cnffile, *krb__get_cnffile();
+ char tr[REALM_SZ];
+ char linebuf[BUFSIZ];
+ register int i;
+
+ cnffile = krb__get_cnffile();
+ if (!cnffile)
+ return get_krbhst_default(h, r, n);
+ if (fscanf(cnffile,"%s",tr) == EOF)
+ return get_krbhst_default(h, r, n);
+ /* run through the file, looking for the nth server for this realm */
+ for (i = 1; i <= n;) {
+ if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
+ (void) fclose(cnffile);
+ return get_krbhst_default(h, r, n);
+ }
+ if (sscanf(linebuf, "%s %s", tr, h) != 2)
+ continue;
+ if (!strcmp(tr,r))
+ i++;
+ }
+ (void) fclose(cnffile);
+ return(KSUCCESS);
+}
diff --git a/src/lib/krb4/g_krbrlm.c b/src/lib/krb4/g_krbrlm.c
new file mode 100644
index 0000000000..f83beba366
--- /dev/null
+++ b/src/lib/krb4/g_krbrlm.c
@@ -0,0 +1,60 @@
+/*
+ * g_krbrlm.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include "krb.h"
+#include <string.h>
+
+/*
+ * krb_get_lrealm takes a pointer to a string, and a number, n. It fills
+ * in the string, r, with the name of the nth realm specified on the
+ * first line of the kerberos config file (KRB_CONF, defined in "krb.h").
+ * It returns 0 (KSUCCESS) on success, and KFAILURE on failure. If the
+ * config file does not exist, and if n=1, a successful return will occur
+ * with r = KRB_REALM (also defined in "krb.h").
+ *
+ * NOTE: for archaic & compatibility reasons, this routine will only return
+ * valid results when n = 1.
+ *
+ * For the format of the KRB_CONF file, see comments describing the routine
+ * krb_get_krbhst(). This will also look in KRB_FB_CONF is
+ * ATHENA_CONF_FALLBACK is defined.
+ */
+static char *krb_conf = KRB_CONF;
+
+
+int INTERFACE
+krb_get_lrealm(r,n)
+ char *r;
+ int n;
+{
+ FILE *cnffile, *krb__get_cnffile();
+
+ if (n > 1)
+ return(KFAILURE); /* Temporary restriction */
+
+ cnffile = krb__get_cnffile();
+ if (!cnffile) {
+ if (n == 1) {
+ (void) strcpy(r, KRB_REALM);
+ return(KSUCCESS);
+ }
+ else
+ return(KFAILURE);
+ }
+
+ if (fscanf(cnffile,"%s",r) != 1) {
+ (void) fclose(cnffile);
+ return(KFAILURE);
+ }
+ (void) fclose(cnffile);
+ return(KSUCCESS);
+}
diff --git a/src/lib/krb4/g_phost.c b/src/lib/krb4/g_phost.c
new file mode 100644
index 0000000000..2e3d0402e3
--- /dev/null
+++ b/src/lib/krb4/g_phost.c
@@ -0,0 +1,75 @@
+/*
+ * g_phost.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#define DEFINE_SOCKADDR /* For struct hostent, <netdb.h>, etc */
+#include "krb.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <netdb.h> /* For struct hostent, gethostbyname, etc */
+#include <sys/param.h> /* For MAXHOSTNAMELEN */
+
+/*
+ * This routine takes an alias for a host name and returns the first
+ * field, lower case, of its domain name. For example, if "menel" is
+ * an alias for host officially named "menelaus" (in /etc/hosts), for
+ * the host whose official name is "MENELAUS.MIT.EDU", the name "menelaus"
+ * is returned.
+ *
+ * This is done for historical Athena reasons: the Kerberos name of
+ * rcmd servers (rlogin, rsh, rcp) is of the form "rcmd.host@realm"
+ * where "host"is the lowercase for of the host name ("menelaus").
+ * This should go away: the instance should be the domain name
+ * (MENELAUS.MIT.EDU). But for now we need this routine...
+ *
+ * A pointer to the name is returned, if found, otherwise a pointer
+ * to the original "alias" argument is returned.
+ */
+
+char * INTERFACE
+krb_get_phost(alias)
+ char *alias;
+{
+ struct hostent FAR *h;
+ char *p;
+ static char hostname_mem[MAXHOSTNAMELEN];
+#ifdef DO_REVERSE_RESOLVE
+ char *rev_addr; int rev_type, rev_len;
+#endif
+
+ if ((h=gethostbyname(alias)) != (struct hostent *)NULL ) {
+#ifdef DO_REVERSE_RESOLVE
+ if (! h->h_addr_list ||! h->h_addr_list[0]) {
+ return(0);
+ }
+ rev_type = h->h_addrtype;
+ rev_len = h->h_length;
+ rev_addr = malloc(rev_len);
+ _fmemcpy(rev_addr, h->h_addr_list[0], rev_len);
+ h = gethostbyaddr(rev_addr, rev_len, rev_type);
+ free(rev_addr);
+ if (h == 0) {
+ return (0);
+ }
+#endif
+ /* We don't want to return a FAR *, so we copy to a safe location. */
+ _fstrncpy (hostname_mem, h->h_name, sizeof (hostname_mem));
+ hostname_mem[MAXHOSTNAMELEN-1]='\0';
+ p = strchr( hostname_mem, '.' );
+ if (p)
+ *p = 0;
+ p = hostname_mem;
+ do {
+ if (isupper(*p)) *p=tolower(*p);
+ } while (*p++);
+ }
+ return(hostname_mem);
+}
diff --git a/src/lib/krb4/g_pw_in_tkt.c b/src/lib/krb4/g_pw_in_tkt.c
new file mode 100644
index 0000000000..213540e690
--- /dev/null
+++ b/src/lib/krb4/g_pw_in_tkt.c
@@ -0,0 +1,342 @@
+/*
+ * g_pw_in_tkt.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "prot.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * This file contains two routines: passwd_to_key() converts
+ * a password into a DES key (prompting for the password if
+ * not supplied), and krb_get_pw_in_tkt() gets an initial ticket for
+ * a user.
+ */
+
+/*
+ * passwd_to_key(): given a password, return a DES key.
+ * There are extra arguments here which (used to be?)
+ * used by srvtab_to_key().
+ *
+ * If the "passwd" argument is not null, generate a DES
+ * key from it, using string_to_key().
+ *
+ * If the "passwd" argument is null, then on a Unix system we call
+ * des_read_password() to prompt for a password and then convert it
+ * into a DES key. But "prompting" the user is harder in a Windows or
+ * Macintosh environment, so we rely on our caller to explicitly do
+ * that now.
+ *
+ * In either case, the resulting key is put in the "key" argument,
+ * and 0 is returned.
+ */
+/*ARGSUSED */
+int
+passwd_to_key(user,instance,realm,passwd,key)
+ char *user, *instance, *realm, *passwd;
+ C_Block key;
+{
+#if defined(_WINDOWS) || defined(macintosh)
+ string_to_key(passwd, key);
+#else /* unix */
+#ifdef NOENCRYPTION
+ if (!passwd)
+ placebo_read_password(key, "Password: ", 0);
+#else /* Do encyryption */
+ if (passwd)
+ string_to_key(passwd, key);
+ else {
+ des_read_password(key, "Password: ", 0);
+ }
+#endif /* NOENCRYPTION */
+#endif /* unix */
+ return (0);
+}
+
+/*
+ * krb_get_pw_in_tkt() takes the name of the server for which the initial
+ * ticket is to be obtained, the name of the principal the ticket is
+ * for, the desired lifetime of the ticket, and the user's password.
+ * It passes its arguments on to krb_get_in_tkt(), which contacts
+ * Kerberos to get the ticket, decrypts it using the password provided,
+ * and stores it away for future use.
+ *
+ * On a Unix system, krb_get_pw_in_tkt() is able to prompt the user
+ * for a password, if the supplied password is null. On a a non Unix
+ * system, it now requires the caller to supply a non-null password.
+ * This is because of the complexities of prompting the user in a
+ * non-terminal-oriented environment like the Macintosh (running in a
+ * driver) or MS-Windows (in a DLL).
+ *
+ * krb_get_pw_in_tkt() passes two additional arguments to krb_get_in_tkt():
+ * the name of a routine (passwd_to_key()) to be used to get the
+ * password in case the "password" argument is null and NULL for the
+ * decryption procedure indicating that krb_get_in_tkt should use the
+ * default method of decrypting the response from the KDC.
+ *
+ * The result of the call to krb_get_in_tkt() is returned.
+ */
+
+int INTERFACE
+krb_get_pw_in_tkt(user,instance,realm,service,sinstance,life,password)
+ char *user, *instance, *realm, *service, *sinstance;
+ int life;
+ char *password;
+{
+#if defined(_WINDOWS) || defined(macintosh)
+ /* In spite of the comments above, we don't allow that path here,
+ to simplify coding the non-UNIX clients. The only code that now
+ depends on this behavior is the preauth support, which has a
+ seperate function without this trap. Strictly speaking, this
+ is an API change. */
+
+ if (password == 0)
+ return INTK_PW_NULL;
+#endif
+
+ return(krb_get_in_tkt(user,instance,realm,service,sinstance,life,
+ passwd_to_key,
+ (decrypt_tkt_type)NULL, password));
+}
+
+/*
+ * krb_get_pw_in_tkt_preauth() gets handed the password or key explicitly,
+ * since the whole point of "pre" authentication is to prove that we've
+ * already got the key, and the only way to do that is to ask the user
+ * for it. Clearly we shouldn't ask twice.
+ */
+
+static C_Block old_key;
+
+static int stub_key(user,instance,realm,passwd,key)
+ char *user, *instance, *realm, *passwd;
+ C_Block key;
+{
+ (void) memcpy((char *) key, (char *) old_key, sizeof(old_key));
+ return 0;
+}
+
+int INTERFACE
+krb_get_pw_in_tkt_preauth(user,instance,realm,service,sinstance,life,password)
+ char *user, *instance, *realm, *service, *sinstance;
+ int life;
+ char *password;
+{
+ char *preauth_p;
+ int preauth_len;
+ int ret_st;
+
+#if defined(_WINDOWS) || defined(macintosh)
+ /* On non-Unix systems, we can't handle a null password, because
+ passwd_to_key can't handle prompting for the password. */
+ if (password == 0)
+ return INTK_PW_NULL;
+#endif
+
+ krb_mk_preauth(&preauth_p,&preauth_len, passwd_to_key,
+ user,instance,realm,password,old_key);
+ ret_st = krb_get_in_tkt_preauth(user,instance,realm,service,sinstance,life,
+ (key_proc_type) stub_key,
+ (decrypt_tkt_type) NULL, password,
+ preauth_p, preauth_len);
+
+ krb_free_preauth(preauth_p, preauth_len);
+ return ret_st;
+}
+
+/* FIXME! This routine belongs in the krb library and should simply
+ be shared between the encrypted and NOENCRYPTION versions! */
+
+#ifdef NOENCRYPTION
+/*
+ * This routine prints the supplied string to standard
+ * output as a prompt, and reads a password string without
+ * echoing.
+ */
+
+#include <stdio.h>
+#ifdef BSDUNIX
+#include <string.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <setjmp.h>
+#else
+char *strcpy();
+int strcmp();
+#endif
+#ifdef __svr4__
+#include <sgtty.h>
+#endif
+
+#ifdef BSDUNIX
+static jmp_buf env;
+#endif
+
+#ifdef BSDUNIX
+static void sig_restore();
+static push_signals(), pop_signals();
+int placebo_read_pw_string();
+#endif
+
+/*** Routines ****************************************************** */
+int
+placebo_read_password(k,prompt,verify)
+ des_cblock *k;
+ char *prompt;
+ int verify;
+{
+ int ok;
+ char key_string[BUFSIZ];
+
+#ifdef BSDUNIX
+ if (setjmp(env)) {
+ ok = -1;
+ goto lose;
+ }
+#endif
+
+ ok = placebo_read_pw_string(key_string, BUFSIZ, prompt, verify);
+ if (ok == 0)
+ memset(k, 0, sizeof(C_Block));
+
+lose:
+ memset(key_string, 0, sizeof (key_string));
+ return ok;
+}
+
+/*
+ * This version just returns the string, doesn't map to key.
+ *
+ * Returns 0 on success, non-zero on failure.
+ */
+
+int
+placebo_read_pw_string(s,max,prompt,verify)
+ char *s;
+ int max;
+ char *prompt;
+ int verify;
+{
+ int ok = 0;
+ char *ptr;
+
+#ifdef BSDUNIX
+ jmp_buf old_env;
+ struct sgttyb tty_state;
+#endif
+ char key_string[BUFSIZ];
+
+ if (max > BUFSIZ) {
+ return -1;
+ }
+
+#ifdef BSDUNIX
+ memcpy(env, old_env, sizeof(env));
+ if (setjmp(env))
+ goto lose;
+
+ /* save terminal state */
+ if (ioctl(0,TIOCGETP,&tty_state) == -1)
+ return -1;
+
+ push_signals();
+ /* Turn off echo */
+ tty_state.sg_flags &= ~ECHO;
+ if (ioctl(0,TIOCSETP,&tty_state) == -1)
+ return -1;
+#endif
+ while (!ok) {
+ printf(prompt);
+ fflush(stdout);
+#ifdef CROSSMSDOS
+ h19line(s,sizeof(s),0);
+ if (!strlen(s))
+ continue;
+#else
+ if (!fgets(s, max, stdin)) {
+ clearerr(stdin);
+ continue;
+ }
+ if ((ptr = strchr(s, '\n')))
+ *ptr = '\0';
+#endif
+ if (verify) {
+ printf("\nVerifying, please re-enter %s",prompt);
+ fflush(stdout);
+#ifdef CROSSMSDOS
+ h19line(key_string,sizeof(key_string),0);
+ if (!strlen(key_string))
+ continue;
+#else
+ if (!fgets(key_string, sizeof(key_string), stdin)) {
+ clearerr(stdin);
+ continue;
+ }
+ if ((ptr = strchr(key_string, '\n')))
+ *ptr = '\0';
+#endif
+ if (strcmp(s,key_string)) {
+ printf("\n\07\07Mismatch - try again\n");
+ fflush(stdout);
+ continue;
+ }
+ }
+ ok = 1;
+ }
+
+#ifdef BSDUNIX
+lose:
+ if (!ok)
+ memset(s, 0, max);
+ printf("\n");
+ /* turn echo back on */
+ tty_state.sg_flags |= ECHO;
+ if (ioctl(0,TIOCSETP,&tty_state))
+ ok = 0;
+ pop_signals();
+ memcpy(old_env, env, sizeof(env));
+#endif
+ if (verify)
+ memset(key_string, 0, sizeof (key_string));
+ s[max-1] = 0; /* force termination */
+ return !ok; /* return nonzero if not okay */
+}
+
+#ifdef BSDUNIX
+/*
+ * this can be static since we should never have more than
+ * one set saved....
+ */
+static sigtype (*old_sigfunc[NSIG])();
+
+static push_signals()
+{
+ register i;
+ for (i = 0; i < NSIG; i++)
+ old_sigfunc[i] = signal(i,sig_restore);
+}
+
+static pop_signals()
+{
+ register i;
+ for (i = 0; i < NSIG; i++)
+ signal(i,old_sigfunc[i]);
+}
+
+static void sig_restore(sig,code,scp)
+ int sig,code;
+ struct sigcontext *scp;
+{
+ longjmp(env,1);
+}
+#endif
+#endif /* NOENCRYPTION */
diff --git a/src/lib/krb4/g_pw_tkt.c b/src/lib/krb4/g_pw_tkt.c
new file mode 100644
index 0000000000..faacab9d0b
--- /dev/null
+++ b/src/lib/krb4/g_pw_tkt.c
@@ -0,0 +1,67 @@
+/*
+ * g_pw_tkt.c
+ *
+ * Copyright 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+
+/*
+ * Get a ticket for the password-changing server ("changepw.KRB_MASTER").
+ *
+ * Given the name, instance, realm, and current password of the
+ * principal for which the user wants a password-changing-ticket,
+ * return either:
+ *
+ * GT_PW_BADPW if current password was wrong,
+ * GT_PW_NULL if principal had a NULL password,
+ * or the result of the krb_get_pw_in_tkt() call.
+ *
+ * First, try to get a ticket for "user.instance@realm" to use the
+ * "changepw.KRB_MASTER" server (KRB_MASTER is defined in "krb.h").
+ * The requested lifetime for the ticket is "1", and the current
+ * password is the "cpw" argument given.
+ *
+ * If the password was bad, give up.
+ *
+ * If the principal had a NULL password in the Kerberos database
+ * (indicating that the principal is known to Kerberos, but hasn't
+ * got a password yet), try instead to get a ticket for the principal
+ * "default.changepw@realm" to use the "changepw.KRB_MASTER" server.
+ * Use the password "changepwkrb" instead of "cpw". Return GT_PW_NULL
+ * if all goes well, otherwise the error.
+ *
+ * If this routine succeeds, a ticket and session key for either the
+ * principal "user.instance@realm" or "default.changepw@realm" to use
+ * the password-changing server will be in the user's ticket file.
+ */
+
+get_pw_tkt(user,instance,realm,cpw)
+ char *user;
+ char *instance;
+ char *realm;
+ char *cpw;
+{
+ int kerror;
+
+ kerror = krb_get_pw_in_tkt(user, instance, realm, "changepw",
+ KRB_MASTER, 1, cpw);
+
+ if (kerror == INTK_BADPW)
+ return(GT_PW_BADPW);
+
+ if (kerror == KDC_NULL_KEY) {
+ kerror = krb_get_pw_in_tkt("default","changepw",realm,"changepw",
+ KRB_MASTER,1,"changepwkrb");
+ if (kerror)
+ return(kerror);
+ return(GT_PW_NULL);
+ }
+
+ return(kerror);
+}
diff --git a/src/lib/krb4/g_svc_in_tkt.c b/src/lib/krb4/g_svc_in_tkt.c
new file mode 100644
index 0000000000..72fae3be77
--- /dev/null
+++ b/src/lib/krb4/g_svc_in_tkt.c
@@ -0,0 +1,133 @@
+/*
+ * g_svc_in_tkt.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "prot.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * This file contains two routines: srvtab_to_key(), which gets
+ * a server's key from a srvtab file, and krb_get_svc_in_tkt() which
+ * gets an initial ticket for a server.
+ */
+
+/*
+ * srvtab_to_key(): given a "srvtab" file (where the keys for the
+ * service on a host are stored), return the private key of the
+ * given service (user.instance@realm).
+ *
+ * srvtab_to_key() passes its arguments on to read_service_key(),
+ * plus one additional argument, the key version number.
+ * (Currently, the key version number is always 0; this value
+ * is treated as a wildcard by read_service_key().)
+ *
+ * If the "srvtab" argument is null, KEYFILE (defined in "krb.h")
+ * is passed in its place.
+ *
+ * It returns the return value of the read_service_key() call.
+ * The service key is placed in "key".
+ */
+
+static int srvtab_to_key(user, instance, realm, srvtab, key)
+ char *user, *instance, *realm, *srvtab;
+ C_Block key;
+{
+ if (!srvtab)
+ srvtab = KEYFILE;
+
+ return(read_service_key(user, instance, realm, 0, srvtab,
+ (char *)key));
+}
+
+/*
+ * krb_get_svc_in_tkt() passes its arguments on to krb_get_in_tkt(),
+ * plus two additional arguments: a pointer to the srvtab_to_key()
+ * function to be used to get the key from the key file and a NULL
+ * for the decryption procedure indicating that krb_get_in_tkt should
+ * use the default method of decrypting the response from the KDC.
+ *
+ * It returns the return value of the krb_get_in_tkt() call.
+ */
+
+int INTERFACE
+krb_get_svc_in_tkt(user, instance, realm, service, sinstance, life, srvtab)
+ char *user, *instance, *realm, *service, *sinstance;
+ int life;
+ char *srvtab;
+{
+ return(krb_get_in_tkt(user, instance, realm, service, sinstance,
+ life, srvtab_to_key, NULL, srvtab));
+}
+
+/* and we need a preauth version as well. */
+static C_Block old_key;
+
+static int stub_key(user,instance,realm,passwd,key)
+ char *user, *instance, *realm, *passwd;
+ C_Block key;
+{
+ memcpy(key, old_key, sizeof(C_Block));
+ return 0;
+}
+
+krb_get_svc_in_tkt_preauth(user, instance, realm, service, sinstance, life, srvtab)
+ char *user, *instance, *realm, *service, *sinstance;
+ int life;
+ char *srvtab;
+{
+ char *preauth_p;
+ int preauth_len;
+ int ret_st;
+
+ krb_mk_preauth(&preauth_p,&preauth_len,
+ srvtab_to_key,user,instance,realm,srvtab,old_key);
+ ret_st = krb_get_in_tkt_preauth(user,instance,realm,service,sinstance,life,
+ stub_key, NULL, srvtab,
+ preauth_p, preauth_len);
+
+ krb_free_preauth(preauth_p, preauth_len);
+ return ret_st;
+}
+
+/* DEC's dss-kerberos adds krb_svc_init; simple enough */
+
+krb_svc_init(user,instance,realm,lifetime,srvtab_file,tkt_file)
+ char *user;
+ char *instance;
+ char *realm;
+ int lifetime;
+ char *srvtab_file;
+ char *tkt_file;
+{
+ if (tkt_file)
+ krb_set_tkt_string(tkt_file);
+
+ return krb_get_svc_in_tkt(user,instance,realm,
+ "krbtgt",realm,lifetime,srvtab_file);
+}
+
+
+krb_svc_init_preauth(user,instance,realm,lifetime,srvtab_file,tkt_file)
+ char *user;
+ char *instance;
+ char *realm;
+ int lifetime;
+ char *srvtab_file;
+ char *tkt_file;
+{
+ if (tkt_file)
+ krb_set_tkt_string(tkt_file);
+
+ return krb_get_svc_in_tkt_preauth(user,instance,realm,
+ "krbtgt",realm,lifetime,srvtab_file);
+}
diff --git a/src/lib/krb4/g_tf_fname.c b/src/lib/krb4/g_tf_fname.c
new file mode 100644
index 0000000000..9aef3cfdf2
--- /dev/null
+++ b/src/lib/krb4/g_tf_fname.c
@@ -0,0 +1,67 @@
+/*
+ * g_tf_fname.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include <string.h>
+#include <stdio.h> /* For EOF */
+
+/*
+ * This file contains a routine to extract the fullname of a user
+ * from the ticket file.
+ */
+
+/*
+ * krb_get_tf_fullname() takes four arguments: the name of the
+ * ticket file, and variables for name, instance, and realm to be
+ * returned in. Since the realm of a ticket file is not really fully
+ * supported, the realm used will be that of the the first ticket in
+ * the file as this is the one that was obtained with a password by
+ * krb_get_in_tkt().
+ */
+
+int
+krb_get_tf_fullname(ticket_file, name, instance, realm)
+ char *ticket_file;
+ char *name;
+ char *instance;
+ char *realm;
+{
+ int tf_status;
+ CREDENTIALS c;
+
+ /* If ticket cache selector is null, use default cache. */
+ if (ticket_file == 0)
+ ticket_file = tkt_string();
+
+ if ((tf_status = tf_init(ticket_file, R_TKT_FIL)) != KSUCCESS)
+ return(tf_status);
+
+ if (((tf_status = tf_get_pname(c.pname)) != KSUCCESS) ||
+ ((tf_status = tf_get_pinst(c.pinst)) != KSUCCESS))
+ return (tf_status);
+
+ if (name)
+ strcpy(name, c.pname);
+ if (instance)
+ strcpy(instance, c.pinst);
+ if ((tf_status = tf_get_cred(&c)) == KSUCCESS) {
+ if (realm)
+ strcpy(realm, c.realm);
+ }
+ else {
+ if (tf_status == EOF)
+ return(KFAILURE);
+ else
+ return(tf_status);
+ }
+ (void) tf_close();
+
+ return(tf_status);
+}
diff --git a/src/lib/krb4/g_tf_realm.c b/src/lib/krb4/g_tf_realm.c
new file mode 100644
index 0000000000..5de1528494
--- /dev/null
+++ b/src/lib/krb4/g_tf_realm.c
@@ -0,0 +1,29 @@
+/*
+ * g_tf_realm.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+
+/*
+ * This file contains a routine to extract the realm of a kerberos
+ * ticket file.
+ */
+
+/*
+ * krb_get_tf_realm() takes two arguments: the name of a ticket
+ * and a variable to store the name of the realm in.
+ *
+ */
+
+krb_get_tf_realm(ticket_file, realm)
+ char *ticket_file;
+ char *realm;
+{
+ return(krb_get_tf_fullname(ticket_file, (char *)0, (char *)0, realm));
+}
diff --git a/src/lib/krb4/g_tkt_svc.c b/src/lib/krb4/g_tkt_svc.c
new file mode 100644
index 0000000000..a4f5c183c3
--- /dev/null
+++ b/src/lib/krb4/g_tkt_svc.c
@@ -0,0 +1,173 @@
+/*
+ * g_tkt_svc.c
+ *
+ * Gets a ticket for a service. Adopted from KClient.
+ */
+
+#include <string.h>
+#define DEFINE_SOCKADDR
+#include "krb.h"
+
+/* FIXME -- this should probably be calling mk_auth nowadays. */
+#define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */
+
+
+static int
+ParseFullName(name, instance, realm, fname)
+ char *name;
+ char *instance;
+ char *realm;
+ char *fname;
+{
+ int err;
+
+ if (!*fname) return KNAME_FMT; /* null names are not OK */
+ *instance = '\0';
+ err = kname_parse(name,instance,realm,fname);
+ if (err) return err;
+ if (!*name) return KNAME_FMT; /* null names are not OK */
+ if (!*realm) {
+ if (err = krb_get_lrealm (realm, 1))
+ return err;
+ if (!*realm) return KNAME_FMT; /* FIXME -- should give better error */
+ }
+ return KSUCCESS;
+}
+
+
+
+static void
+CopyTicket(dest, src, numBytes, version, includeVersion)
+ char *dest;
+ KTEXT src;
+ unsigned long *numBytes;
+ char *version;
+ int includeVersion;
+{
+ unsigned long tkt_len;
+ unsigned long nbytes = 0;
+
+ /* first put version info into the buffer */
+ if (includeVersion) {
+ (void) strncpy(dest, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN);
+ (void) strncpy(dest+KRB_SENDAUTH_VLEN, version, KRB_SENDAUTH_VLEN);
+ nbytes = 2*KRB_SENDAUTH_VLEN;
+ }
+
+ /* put ticket length into buffer */
+ tkt_len = htonl((unsigned long) src->length);
+ (void) memcpy((char *)(dest+nbytes), (char *) &tkt_len, sizeof(tkt_len));
+ nbytes += sizeof(tkt_len);
+
+ /* put ticket into buffer */
+ (void) memcpy ((char *)(dest+nbytes), (char *) src->dat, src->length);
+ nbytes += src->length;
+
+ *numBytes = nbytes;
+}
+
+
+static int
+CredIsExpired( cr )
+ CREDENTIALS *cr;
+{
+ KRB4_32 time;
+
+ /* This routine is for use with clients only in order to determine if a credential
+ is still good
+ Note: twice CLOCK_SKEW was added to age of ticket so that we could
+ be more sure that the ticket was good.
+ FIXME: I think this is a bug -- should use the same algorithm
+ everywhere to determine ticket expiration. */
+
+ time = TIME_GMT_UNIXSEC;
+ return ( (time - cr->issue_date + (2*CLOCK_SKEW)) > (5 * 60 * cr->lifetime) );
+}
+
+
+/*
+ * Gets a ticket and returns it to application in buf
+ -> service Formal Kerberos name of service
+ -> buf Buffer to receive ticket
+ -> checksum checksum for this service
+ <-> buflen length of ticket buffer (must be at least
+ 1258 bytes)
+ <- sessionKey for internal use
+ <- schedule for internal use
+
+ * Result is:
+ * GC_NOTKT if there is no matching TGT in the cache
+ * MK_AP_TGTEXP if the matching TGT is expired
+ * Other errors possible. These could cause a dialogue with the user
+ * to get a new TGT.
+ */
+
+int INTERFACE
+krb_get_ticket_for_service (serviceName, buf, buflen, checksum, sessionKey,
+ schedule, version, includeVersion)
+ char *serviceName;
+ char *buf;
+ unsigned KRB4_32 *buflen;
+ int checksum;
+ des_cblock sessionKey;
+ Key_schedule schedule;
+ char *version;
+ int includeVersion;
+{
+ char service[SNAME_SZ];
+ char instance[INST_SZ];
+ char realm[REALM_SZ];
+ int err;
+ char lrealm[REALM_SZ];
+ CREDENTIALS cr;
+
+ service[0] = '\0';
+ instance[0] = '\0';
+ realm[0] = '\0';
+
+ /* parse out service name */
+
+ err = ParseFullName(service, instance, realm, serviceName);
+ if (err)
+ return err;
+
+ if ((err = krb_get_tf_realm(TKT_FILE, lrealm)) != KSUCCESS)
+ return(err);
+
+ /* Make sure we have an intial ticket for the user in this realm
+ Check local realm, not realm for service since krb_mk_req will
+ get additional krbtgt if necessary. This is so that inter-realm
+ works without asking for a password twice.
+ FIXME gnu - I think this is a bug. We should allow direct
+ authentication to the desired realm, regardless of what the "local"
+ realm is. I fixed it. FIXME -- not quite right. */
+ err = krb_get_cred ("krbtgt", realm, lrealm, &cr);
+ if (err)
+ return err;
+
+ err = CredIsExpired(&cr);
+ if (err)
+ return RD_AP_EXP; /* Expired ticket */
+
+ /* Get a ticket for the service */
+ err = krb_mk_req(&(cr.ticket_st),service,instance,realm,checksum);
+ if (err)
+ return err;
+
+ CopyTicket(buf, &(cr.ticket_st), buflen, version, includeVersion);
+
+ /* get the session key for later use in deciphering the server response */
+ err = krb_get_cred(service,instance,realm,&cr);
+ if (err)
+ return err;
+ memcpy((char *)sessionKey, (char *)cr.session, sizeof(C_Block));
+ err = key_sched(sessionKey, schedule);
+ if (err)
+ return KFAILURE; /* Bad DES key for some reason (FIXME better error) */
+
+ else
+ return KSUCCESS;
+
+}
+
+
diff --git a/src/lib/krb4/gethostname.c b/src/lib/krb4/gethostname.c
new file mode 100644
index 0000000000..cac202e3fd
--- /dev/null
+++ b/src/lib/krb4/gethostname.c
@@ -0,0 +1,30 @@
+/*
+ * gethostname.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#define DEFINE_SOCKADDR
+#include "krb.h"
+
+#ifndef GETHOSTNAME
+#define GETHOSTNAME gethostname /* A rather simple default */
+#endif
+
+/*
+ * Return the local host's name in "name", up to "namelen" characters.
+ * "name" will be null-terminated if "namelen" is big enough.
+ * The return code is 0 on success, -1 on failure. (The calling
+ * interface is identical to BSD gethostname(2).)
+ */
+
+k_gethostname(name, namelen)
+ char *name;
+ int namelen;
+{
+ return GETHOSTNAME(name, namelen);
+}
diff --git a/src/lib/krb4/getst.c b/src/lib/krb4/getst.c
new file mode 100644
index 0000000000..3ff05bd31f
--- /dev/null
+++ b/src/lib/krb4/getst.c
@@ -0,0 +1,33 @@
+/*
+ * getst.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+
+/*
+ * getst() takes a file descriptor, a string and a count. It reads
+ * from the file until either it has read "count" characters, or until
+ * it reads a null byte. When finished, what has been read exists in
+ * the given string "s". If "count" characters were actually read, the
+ * last is changed to a null, so the returned string is always null-
+ * terminated. getst() returns the number of characters read, including
+ * the null terminator.
+ */
+
+getst(fd, s, n)
+ int fd;
+ register char *s;
+ int n;
+{
+ register count = n;
+ while (read(fd, s, 1) > 0 && --count)
+ if (*s++ == '\0')
+ return (n - count);
+ *s = '\0';
+ return (n - count);
+}
diff --git a/src/lib/krb4/in_tkt.c b/src/lib/krb4/in_tkt.c
new file mode 100644
index 0000000000..4674f3116c
--- /dev/null
+++ b/src/lib/krb4/in_tkt.c
@@ -0,0 +1,159 @@
+/*
+ * in_tkt.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include <string.h>
+#include "krb.h"
+#include <sys/file.h>
+#ifdef NEED_SYS_FCNTL_H
+/* just for O_RDWR for sco */
+#include <sys/fcntl.h>
+#endif
+#include <sys/stat.h>
+#ifdef TKT_SHMEM
+#include <sys/param.h>
+#endif
+
+extern int krb_debug;
+
+/*
+ * in_tkt() is used to initialize the ticket store. It creates the
+ * file to contain the tickets and writes the given user's name "pname"
+ * and instance "pinst" in the file. in_tkt() returns KSUCCESS on
+ * success, or KFAILURE if something goes wrong.
+ */
+
+#ifdef hpux
+/* should be HAS_RESUID */
+#define setreuid(r,e) setresuid(r,e,-1)
+#else
+#ifdef __svr4__
+#define setreuid(r,e) setuid(r)
+#endif
+#endif
+
+in_tkt(pname,pinst)
+ char *pname;
+ char *pinst;
+{
+ int tktfile;
+ uid_t me, metoo, getuid(), geteuid();
+ struct stat buf;
+ int count;
+ char *file = TKT_FILE;
+ int fd;
+ register int i;
+ char charbuf[BUFSIZ];
+ int mask;
+#ifdef TKT_SHMEM
+ char shmidname[MAXPATHLEN];
+#endif /* TKT_SHMEM */
+
+ /* If ticket cache selector is null, use default cache. */
+ if (file == 0)
+ file = tkt_string();
+
+ me = getuid ();
+ metoo = geteuid();
+ if (lstat(file,&buf) == 0) {
+ if (buf.st_uid != me || !(buf.st_mode & S_IFREG) ||
+ buf.st_mode & 077) {
+ if (krb_debug)
+ fprintf(stderr,"Error initializing %s",file);
+ return(KFAILURE);
+ }
+ /* file already exists, and permissions appear ok, so nuke it */
+ if ((fd = open(file, O_RDWR|O_SYNC, 0)) < 0)
+ goto out; /* can't zero it, but we can still try truncating it */
+
+ memset(charbuf, 0, sizeof(charbuf));
+
+ for (i = 0; i < buf.st_size; i += sizeof(charbuf))
+ if (write(fd, charbuf, sizeof(charbuf)) != sizeof(charbuf)) {
+#ifndef NO_FSYNC
+ (void) fsync(fd);
+#endif
+ (void) close(fd);
+ goto out;
+ }
+
+#ifndef NO_FSYNC
+ (void) fsync(fd);
+#endif
+ (void) close(fd);
+ }
+ out:
+ /* arrange so the file is owned by the ruid
+ (swap real & effective uid if necessary).
+ This isn't a security problem, since the ticket file, if it already
+ exists, has the right uid (== ruid) and mode. */
+ if (me != metoo) {
+ if (setreuid(metoo, me) < 0) {
+ /* can't switch??? barf! */
+ if (krb_debug)
+ perror("in_tkt: setreuid");
+ return(KFAILURE);
+ } else
+ if (krb_debug)
+ printf("swapped UID's %d and %d\n",metoo,me);
+ }
+ /* Set umask to ensure that we have write access on the created
+ ticket file. */
+ mask = umask(077);
+ if ((tktfile = creat(file,0600)) < 0) {
+ umask(mask);
+ if (krb_debug)
+ fprintf(stderr,"Error initializing %s",TKT_FILE);
+ return(KFAILURE);
+ }
+ umask(mask);
+ if (me != metoo) {
+ if (setreuid(me, metoo) < 0) {
+ /* can't switch??? barf! */
+ if (krb_debug)
+ perror("in_tkt: setreuid2");
+ return(KFAILURE);
+ } else
+ if (krb_debug)
+ printf("swapped UID's %d and %d\n",me,metoo);
+ }
+ if (lstat(file,&buf) < 0) {
+ if (krb_debug)
+ fprintf(stderr,"Error initializing %s",TKT_FILE);
+ return(KFAILURE);
+ }
+
+ if (buf.st_uid != me || !(buf.st_mode & S_IFREG) ||
+ buf.st_mode & 077) {
+ if (krb_debug)
+ fprintf(stderr,"Error initializing %s",TKT_FILE);
+ return(KFAILURE);
+ }
+
+ count = strlen(pname)+1;
+ if (write(tktfile,pname,count) != count) {
+ (void) close(tktfile);
+ return(KFAILURE);
+ }
+ count = strlen(pinst)+1;
+ if (write(tktfile,pinst,count) != count) {
+ (void) close(tktfile);
+ return(KFAILURE);
+ }
+ (void) close(tktfile);
+#ifdef TKT_SHMEM
+ (void) strcpy(shmidname, file);
+ (void) strcat(shmidname, ".shm");
+ return(krb_shm_create(shmidname));
+#else /* !TKT_SHMEM */
+ return(KSUCCESS);
+#endif /* TKT_SHMEM */
+}
diff --git a/src/lib/krb4/kerberos.def b/src/lib/krb4/kerberos.def
new file mode 100644
index 0000000000..f8124aa8c3
--- /dev/null
+++ b/src/lib/krb4/kerberos.def
@@ -0,0 +1,68 @@
+;-----------------------------
+; KERBEROS.DEF - module definition file
+;-----------------------------
+
+LIBRARY KERBEROS
+DESCRIPTION 'DLL for Kerberos support'
+EXETYPE WINDOWS
+CODE PRELOAD MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE SINGLE
+HEAPSIZE 8192
+
+EXPORTS
+ WEP @1 RESIDENTNAME
+ LIBMAIN @2
+
+ DES_CBC_ENCRYPT @3
+ DES_KEY_SCHED @4
+ DES_STRING_TO_KEY @5
+ DEST_TKT @6
+ KNAME_PARSE @7
+ KRB_CHECK_AUTH @8
+ KRB_END_SESSION @9
+ KRB_GET_ADMHST @10
+ KRB_GET_CRED @11
+ KRB_GET_DEFAULT_USER @12
+ KRB_GET_ERR_TEXT @14
+ KRB_GET_LREALM @15
+ KRB_GET_PHOST @16
+ KRB_GET_PW_IN_TKT @17
+ KRB_MK_AUTH @18
+ KRB_MK_PRIV @19
+ KRB_MK_REQ @20
+ KRB_RD_PRIV @21
+ KRB_REALMOFHOST @22
+ KRB_SAVE_CREDENTIALS @23
+ KRB_START_SESSION @24
+ KRB_GET_PW_IN_TKT_PREAUTH @25
+ KRB_GET_NOTIFICATION_MESSAGE @26
+ KADM_CHANGE_PW2 @27
+ KADM_INIT_LINK @28
+ KADM_GET_ERR_TEXT @29
+ KADM_CHANGE_PW @30
+ DES_ECB_ENCRYPT @31
+ DES_PCBC_ENCRYPT @32
+ DES_IS_WEAK_KEY @33
+ DES_FIXUP_KEY_PARITY @34
+ DES_CHECK_KEY_PARITY @35
+ IN_TKT @36
+ KRB_DELETE_CRED @37
+ KRB_GET_KRBHST @38
+ KRB_GET_NTH_CRED @39
+ KRB_GET_NUM_CRED @40
+ KRB_GET_TF_FULLNAME @41
+ KRB_GET_TICKET_FOR_SERVICE @42
+ KRB_MK_ERR @43
+ KRB_MK_SAFE @44
+ KRB_RD_ERR @45
+ KRB_RD_SAFE @46
+ KRB_SET_DEFAULT_USER @47
+ KSTREAM_CREATE_FROM_FD @48
+ KSTREAM_CREATE_RLOGIN_FROM_FD @49
+ KSTREAM_CREATE_RCP_FROM_FD @50
+ KSTREAM_WRITE @51
+ KSTREAM_READ @52
+ KSTREAM_FLUSH @53
+ KSTREAM_DESTROY @54
+ KSTREAM_SET_BUFFER_MODE @55
+
diff --git a/src/lib/krb4/klog.c b/src/lib/krb4/klog.c
new file mode 100644
index 0000000000..9a65ae9ef7
--- /dev/null
+++ b/src/lib/krb4/klog.c
@@ -0,0 +1,109 @@
+/*
+ * klog.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#ifdef NEED_TIME_H
+#include <time.h>
+#endif
+#ifndef VMS
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+
+#include "krb.h"
+#include <klog.h>
+
+static char *log_name = KRBLOG;
+static int is_open;
+static char logtxt[1000];
+
+/*
+ * This file contains two logging routines: kset_logfile()
+ * to determine the file to which log entries should be written;
+ * and klog() to write log entries to the file.
+ */
+
+/*
+ * klog() is used to add entries to the logfile (see kset_logfile()
+ * below). Note that it is probably not portable since it makes
+ * assumptions about what the compiler will do when it is called
+ * with less than the correct number of arguments which is the
+ * way it is usually called.
+ *
+ * The log entry consists of a timestamp and the given arguments
+ * printed according to the given "format" string.
+ *
+ * The log file is opened and closed for each log entry.
+ *
+ * If the given log type "type" is unknown, or if the log file
+ * cannot be opened, no entry is made to the log file.
+ *
+ * The return value is always a pointer to the formatted log
+ * text string "logtxt".
+ */
+
+char * klog(type,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0)
+ int type;
+ char *format;
+ char *a1,*a2,*a3,*a4,*a5,*a6,*a7,*a8,*a9,*a0;
+{
+ FILE *logfile;
+ time_t now;
+ char *month_sname();
+ struct tm *tm;
+ static int logtype_array[NLOGTYPE];
+ static int array_initialized;
+
+ if (!(array_initialized++)) {
+ logtype_array[L_NET_ERR] = 1;
+ logtype_array[L_KRB_PERR] = 1;
+ logtype_array[L_KRB_PWARN] = 1;
+ logtype_array[L_APPL_REQ] = 1;
+ logtype_array[L_INI_REQ] = 1;
+ logtype_array[L_DEATH_REQ] = 1;
+ logtype_array[L_NTGT_INTK] = 1;
+ logtype_array[L_ERR_SEXP] = 1;
+ logtype_array[L_ERR_MKV] = 1;
+ logtype_array[L_ERR_NKY] = 1;
+ logtype_array[L_ERR_NUN] = 1;
+ logtype_array[L_ERR_UNK] = 1;
+ }
+
+ (void) sprintf(logtxt,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0);
+
+ if (!logtype_array[type])
+ return(logtxt);
+
+ if ((logfile = fopen(log_name,"a")) == NULL)
+ return(logtxt);
+
+ (void) time(&now);
+ tm = localtime(&now);
+
+ fprintf(logfile,"%2d-%s-%02d %02d:%02d:%02d ",tm->tm_mday,
+ month_sname(tm->tm_mon + 1),tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ fprintf(logfile,"%s\n",logtxt);
+ (void) fclose(logfile);
+ return(logtxt);
+}
+
+/*
+ * kset_logfile() changes the name of the file to which
+ * messages are logged. If kset_logfile() is not called,
+ * the logfile defaults to KRBLOG, defined in "krb.h".
+ */
+
+kset_logfile(filename)
+ char *filename;
+{
+ log_name = filename;
+ is_open = 0;
+}
diff --git a/src/lib/krb4/kname_parse.c b/src/lib/krb4/kname_parse.c
new file mode 100644
index 0000000000..059d084283
--- /dev/null
+++ b/src/lib/krb4/kname_parse.c
@@ -0,0 +1,230 @@
+/*
+ * kname_parse.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+
+#include <stdio.h>
+#include "krb.h"
+#include <string.h>
+
+/* max size of full name */
+#define FULL_SZ (ANAME_SZ + INST_SZ + REALM_SZ)
+
+#define NAME 0 /* which field are we in? */
+#define INST 1
+#define REALM 2
+
+/*
+ * This file contains four routines for handling Kerberos names.
+ *
+ * kname_parse() breaks a Kerberos name into its name, instance,
+ * and realm components.
+ *
+ * k_isname(), k_isinst(), and k_isrealm() check a given string to see if
+ * it's a syntactically legitimate respective part of a Kerberos name,
+ * returning 1 if it is, 0 if it isn't.
+ *
+ * Definition of "syntactically legitimate" names is according to
+ * the Project Athena Technical Plan Section E.2.1, page 7 "Specifying
+ * names", version dated 21 Dec 1987.
+ */
+
+/*
+ * kname_parse() takes a Kerberos name "fullname" of the form:
+ *
+ * username[.instance][@realm]
+ *
+ * and returns the three components ("name", "instance", and "realm"
+ * in the example above) in the given arguments "np", "ip", and "rp".
+ *
+ * If successful, it returns KSUCCESS. If there was an error,
+ * KNAME_FMT is returned.
+ *
+ * For proper operation, this routine requires that the ip, np, and rp
+ * arguments be initialized, either to null strings, or to default values
+ * of name, instance, and realm. FIXME-gnu: Does anyone use it this way?
+ */
+
+int INTERFACE
+kname_parse(np, ip, rp, fullname)
+ char *np, *ip, *rp, *fullname;
+{
+ char buf[FULL_SZ];
+ char *rnext, *wnext; /* next char to read, write */
+ register char c;
+ int backslash;
+ int field;
+
+ backslash = 0;
+ rnext = buf;
+ wnext = np;
+ field = NAME;
+
+ if (strlen(fullname) > FULL_SZ)
+ return KNAME_FMT;
+ (void) strcpy(buf, fullname);
+
+ while (c = *rnext++) {
+ if (backslash) {
+ *wnext++ = c;
+ backslash = 0;
+ continue;
+ }
+ switch (c) {
+ case '\\':
+ backslash++;
+ break;
+ case '.':
+ switch (field) {
+ case NAME:
+ if (wnext == np)
+ return KNAME_FMT;
+ *wnext = '\0';
+ field = INST;
+ wnext = ip;
+ break;
+ case INST: /* We now allow period in instance */
+ case REALM:
+ *wnext++ = c;
+ break;
+ default:
+ DEB (("unknown field value\n"));
+ return KNAME_FMT;
+ }
+ break;
+ case '@':
+ switch (field) {
+ case NAME:
+ if (wnext == np)
+ return KNAME_FMT;
+ *ip = '\0';
+ /* fall through */
+ case INST:
+ *wnext = '\0';
+ field = REALM;
+ wnext = rp;
+ break;
+ case REALM:
+ return KNAME_FMT;
+ default:
+ DEB (("unknown field value\n"));
+ return KNAME_FMT;
+ }
+ break;
+ default:
+ *wnext++ = c;
+ }
+ }
+ *wnext = '\0';
+ if ((strlen(np) > ANAME_SZ - 1) ||
+ (strlen(ip) > INST_SZ - 1) ||
+ (strlen(rp) > REALM_SZ - 1))
+ return KNAME_FMT;
+ return KSUCCESS;
+}
+
+/*
+ * k_isname() returns 1 if the given name is a syntactically legitimate
+ * Kerberos name; returns 0 if it's not.
+ */
+
+k_isname(s)
+ char *s;
+{
+ register char c;
+ int backslash = 0;
+
+ if (!*s)
+ return 0;
+ if (strlen(s) > ANAME_SZ - 1)
+ return 0;
+ while(c = *s++) {
+ if (backslash) {
+ backslash = 0;
+ continue;
+ }
+ switch(c) {
+ case '\\':
+ backslash = 1;
+ break;
+ case '.':
+ return 0;
+ /* break; */
+ case '@':
+ return 0;
+ /* break; */
+ }
+ }
+ return 1;
+}
+
+
+/*
+ * k_isinst() returns 1 if the given name is a syntactically legitimate
+ * Kerberos instance; returns 0 if it's not.
+ *
+ * We now allow periods in instance names -- they are unambiguous.
+ */
+
+k_isinst(s)
+ char *s;
+{
+ register char c;
+ int backslash = 0;
+
+ if (strlen(s) > INST_SZ - 1)
+ return 0;
+ while(c = *s++) {
+ if (backslash) {
+ backslash = 0;
+ continue;
+ }
+ switch(c) {
+ case '\\':
+ backslash = 1;
+ break;
+ case '@':
+ return 0;
+ /* break; */
+ }
+ }
+ return 1;
+}
+
+/*
+ * k_isrealm() returns 1 if the given name is a syntactically legitimate
+ * Kerberos realm; returns 0 if it's not.
+ */
+
+k_isrealm(s)
+ char *s;
+{
+ register char c;
+ int backslash = 0;
+
+ if (!*s)
+ return 0;
+ if (strlen(s) > REALM_SZ - 1)
+ return 0;
+ while(c = *s++) {
+ if (backslash) {
+ backslash = 0;
+ continue;
+ }
+ switch(c) {
+ case '\\':
+ backslash = 1;
+ break;
+ case '@':
+ return 0;
+ /* break; */
+ }
+ }
+ return 1;
+}
diff --git a/src/lib/krb4/kntoln.c b/src/lib/krb4/kntoln.c
new file mode 100644
index 0000000000..8b6cdfe0e5
--- /dev/null
+++ b/src/lib/krb4/kntoln.c
@@ -0,0 +1,56 @@
+/*
+ * kntoln.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include <string.h>
+
+/*
+ * krb_kntoln converts an auth name into a local name by looking up
+ * the auth name in the /etc/aname file. The format of the aname
+ * file is:
+ *
+ * +-----+-----+-----+-----+------+----------+-------+-------+
+ * | anl | inl | rll | lnl | name | instance | realm | lname |
+ * +-----+-----+-----+-----+------+----------+-------+-------+
+ * | 1by | 1by | 1by | 1by | name | instance | realm | lname |
+ * +-----+-----+-----+-----+------+----------+-------+-------+
+ *
+ * If the /etc/aname file can not be opened it will set the
+ * local name to the auth name. Thus, in this case it performs as
+ * the identity function.
+ *
+ * The name instance and realm are passed to krb_kntoln through
+ * the AUTH_DAT structure (ad).
+ *
+ * Now here's what it *really* does:
+ *
+ * Given a Kerberos name in an AUTH_DAT structure, check that the
+ * instance is null, and that the realm is the same as the local
+ * realm, and return the principal's name in "lname". Return
+ * KSUCCESS if all goes well, otherwise KFAILURE.
+ */
+
+krb_kntoln(ad,lname)
+ AUTH_DAT *ad;
+ char *lname;
+{
+ static char lrealm[REALM_SZ];
+
+ if (!(*lrealm) && (krb_get_lrealm(lrealm,1) == KFAILURE))
+ return(KFAILURE);
+
+ if (strcmp(ad->pinst,""))
+ return(KFAILURE);
+ if (strcmp(ad->prealm,lrealm))
+ return(KFAILURE);
+ (void) strcpy(lname,ad->pname);
+ return(KSUCCESS);
+}
diff --git a/src/lib/krb4/kparse.c b/src/lib/krb4/kparse.c
new file mode 100644
index 0000000000..fb4f6e2432
--- /dev/null
+++ b/src/lib/krb4/kparse.c
@@ -0,0 +1,766 @@
+/*
+ * kparse.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Purpose:
+ * This module was developed to parse the "~/.klogin" files for
+ * Kerberos-authenticated rlogin/rcp/rsh services. However, it is
+ * general purpose and can be used to parse any such parameter file.
+ *
+ * The parameter file should consist of one or more entries, with each
+ * entry on a separate line and consisting of zero or more
+ * "keyword=value" combinations. The keyword is case insensitive, but
+ * the value is not. Any string may be enclosed in quotes, and
+ * c-style "\" literals are supported. A comma may be used to
+ * separate the k/v combinations, and multiple commas are ignored.
+ * Whitespace (blank or tab) may be used freely and is ignored.
+ *
+ * Full error processing is available. When PS_BAD_KEYWORD or
+ * PS_SYNTAX is returned from fGetParameterSet(), the string ErrorMsg
+ * contains a meaningful error message.
+ *
+ * Keywords and their default values are programmed by an external
+ * table.
+ *
+ * Routines:
+ * fGetParameterSet() parse one line of the parameter file
+ * fGetKeywordValue() parse one "keyword=value" combo
+ * fGetToken() parse one token
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <kparse.h>
+#include <string.h>
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+#define void int
+
+#define MAXKEY 80
+#define MAXVALUE 80
+
+extern char *malloc();
+
+static char *strutol();
+#ifndef HAVE_STRSAVE
+static char *strsave();
+#endif
+
+static int LineNbr=1; /* current line nbr in parameter file */
+static char ErrorMsg[80]; /* meaningful only when KV_SYNTAX, PS_SYNTAX,
+ * or PS_BAD_KEYWORD is returned by
+ * fGetKeywordValue or fGetParameterSet */
+
+int fGetParameterSet( fp,parm,parmcount )
+ FILE *fp;
+ parmtable parm[];
+ int parmcount;
+{
+ int rc,i;
+ char keyword[MAXKEY];
+ char value[MAXVALUE];
+
+ while (TRUE) {
+ rc=fGetKeywordValue(fp,keyword,MAXKEY,value,MAXVALUE);
+
+ switch (rc) {
+
+ case KV_EOF:
+ return(PS_EOF);
+
+ case KV_EOL:
+ return(PS_OKAY);
+
+ case KV_SYNTAX:
+ return(PS_SYNTAX);
+
+ case KV_OKAY:
+ /*
+ * got a reasonable keyword/value pair. Search the
+ * parameter table to see if we recognize the keyword; if
+ * not, return an error. If we DO recognize it, make sure
+ * it has not already been given. If not already given,
+ * save the value.
+ */
+ for (i=0; i<parmcount; i++) {
+ if (strcmp(strutol(keyword),parm[i].keyword)==0) {
+ if (parm[i].value) {
+ sprintf(ErrorMsg,"duplicate keyword \"%s\" found",
+ keyword);
+ return(PS_BAD_KEYWORD);
+ }
+ parm[i].value = strsave( value );
+ break;
+ }
+ }
+ if (i >= parmcount) {
+ sprintf(ErrorMsg, "unrecognized keyword \"%s\" found",
+ keyword);
+ return(PS_BAD_KEYWORD);
+ }
+ break;
+
+ default:
+ sprintf(ErrorMsg,
+ "panic: bad return (%d) from fGetToken()",rc);
+ break;
+ }
+ }
+}
+
+/*
+ * Routine: ParmCompare
+ *
+ * Purpose:
+ * ParmCompare checks a specified value for a particular keyword.
+ * fails if keyword not found or keyword found but the value was
+ * different. Like strcmp, ParmCompare returns 0 for a match found, -1
+ * otherwise
+ */
+int ParmCompare( parm, parmcount, keyword, value )
+ parmtable parm[];
+ int parmcount;
+ char *keyword;
+ char *value;
+{
+ int i;
+
+ for (i=0; i<parmcount; i++) {
+ if (strcmp(parm[i].keyword,keyword)==0) {
+ if (parm[i].value) {
+ return(strcmp(parm[i].value,value));
+ } else {
+ return(strcmp(parm[i].defvalue,value));
+ }
+ }
+ }
+ return(-1);
+}
+
+void FreeParameterSet(parm,parmcount)
+ parmtable parm[];
+ int parmcount;
+{
+ int i;
+
+ for (i=0; i<parmcount; i++) {
+ if (parm[i].value) {
+ free(parm[i].value);
+ parm[i].value = (char *)NULL;
+ }
+ }
+}
+
+int fGetKeywordValue( fp, keyword, klen, value, vlen )
+ FILE *fp;
+ char *keyword;
+ int klen;
+ char *value;
+ int vlen;
+{
+ int rc;
+ int gotit;
+
+ *keyword = *value = '\0'; /* preset strings to NULL */
+
+ /*
+ * Looking for a keyword.
+ * return an exception for EOF or BAD_QSTRING
+ * ignore leading WHITEspace
+ * ignore any number of leading commas
+ * newline means we have all the parms for this
+ * statement; give an indication that there is
+ * nothing more on this line.
+ * stop looking if we find QSTRING, STRING, or NUMBER
+ * return syntax error for any other PUNKtuation
+ */
+ gotit = FALSE;
+ do {
+ rc = fGetToken(fp,keyword,klen);
+
+ switch (rc) {
+
+ case GTOK_WHITE:
+ break;
+
+ case GTOK_EOF:
+ return(KV_EOF);
+
+ case GTOK_BAD_QSTRING:
+ sprintf(ErrorMsg,"unterminated string \"%s found",keyword);
+ return(KV_SYNTAX);
+
+ case GTOK_PUNK:
+ if (strcmp("\n",keyword)==0) {
+ return(KV_EOL);
+ } else if (strcmp(",",keyword)!=0) {
+ sprintf(ErrorMsg,"expecting rvalue, found \'%s\'",keyword);
+ }
+ break;
+
+ case GTOK_STRING:
+ case GTOK_QSTRING:
+ case GTOK_NUMBER:
+ gotit = TRUE;
+ break;
+
+ default:
+ sprintf(ErrorMsg,"panic: bad return (%d) from fGetToken()",rc);
+ return(KV_SYNTAX);
+ }
+
+ } while (!gotit);
+
+ /*
+ * now we expect an equal sign.
+ * skip any whitespace
+ * stop looking if we find an equal sign
+ * anything else causes a syntax error
+ */
+ gotit = FALSE;
+ do {
+ rc = fGetToken(fp,value,vlen);
+
+ switch (rc) {
+
+ case GTOK_WHITE:
+ break;
+
+ case GTOK_BAD_QSTRING:
+ sprintf(ErrorMsg,
+ "expecting \'=\', found unterminated string \"%s",
+ value);
+ return(KV_SYNTAX);
+
+ case GTOK_PUNK:
+ if (strcmp("=",value)==0) {
+ gotit = TRUE;
+ } else {
+ if (strcmp("\n",value)==0) {
+ sprintf(ErrorMsg,"expecting \"=\", found newline");
+ fUngetChar('\n',fp);
+ } else {
+ sprintf(ErrorMsg,
+ "expecting rvalue, found \'%s\'",keyword);
+ }
+ return(KV_SYNTAX);
+ }
+ break;
+
+ case GTOK_STRING:
+ case GTOK_QSTRING:
+ case GTOK_NUMBER:
+ sprintf(ErrorMsg,"expecting \'=\', found \"%s\"",value);
+ return(KV_SYNTAX);
+
+ case GTOK_EOF:
+ sprintf(ErrorMsg,"expecting \'=\', found EOF");
+ return(KV_SYNTAX);
+
+ default:
+ sprintf(ErrorMsg,
+ "panic: bad return (%d) from fGetToken()",rc);
+ return(KV_SYNTAX);
+ }
+
+ } while ( !gotit );
+
+ /*
+ * got the keyword and equal sign, now get a value.
+ * ignore any whitespace
+ * any punctuation is a syntax error
+ */
+ gotit = FALSE;
+ do {
+ rc = fGetToken(fp,value,vlen);
+
+ switch (rc) {
+
+ case GTOK_WHITE:
+ break;
+
+ case GTOK_EOF:
+ sprintf(ErrorMsg,"expecting rvalue, found EOF");
+ return(KV_SYNTAX);
+
+ case GTOK_BAD_QSTRING:
+ sprintf(ErrorMsg,"unterminated quoted string \"%s",value);
+ return(KV_SYNTAX);
+
+ case GTOK_PUNK:
+ if (strcmp("\n",value)==0) {
+ sprintf(ErrorMsg,"expecting rvalue, found newline");
+ fUngetChar('\n',fp);
+ } else {
+ sprintf(ErrorMsg,
+ "expecting rvalue, found \'%s\'",value);
+ }
+ return(KV_SYNTAX);
+ break;
+
+ case GTOK_STRING:
+ case GTOK_QSTRING:
+ case GTOK_NUMBER:
+ gotit = TRUE;
+ return(KV_OKAY);
+
+ default:
+ sprintf(ErrorMsg,
+ "panic: bad return (%d) from fGetToken()",rc);
+ return(KV_SYNTAX);
+ }
+
+ } while ( !gotit );
+ /*NOTREACHED*/
+}
+
+/*
+ * Routine Name: fGetToken
+ *
+ * Function: read the next token from the specified file.
+ * A token is defined as a group of characters
+ * terminated by a white space char (SPACE, CR,
+ * LF, FF, TAB). The token returned is stripped of
+ * both leading and trailing white space, and is
+ * terminated by a NULL terminator. An alternate
+ * definition of a token is a string enclosed in
+ * single or double quotes.
+ *
+ * Explicit Parameters:
+ * fp pointer to the input FILE
+ * dest pointer to destination buffer
+ * maxlen length of the destination buffer. The buffer
+ * length INCLUDES the NULL terminator.
+ *
+ * Implicit Parameters: stderr where the "token too long" message goes
+ *
+ * External Procedures: fgetc
+ *
+ * Side Effects: None
+ *
+ * Return Value: A token classification value, as
+ * defined in kparse.h. Note that the
+ * classification for end of file is
+ * always zero.
+ */
+int fGetToken(fp, dest, maxlen)
+ FILE *fp;
+ char *dest;
+ int maxlen;
+{
+ int ch='\0';
+ int len=0;
+ char *p = dest;
+ int digits;
+
+ ch=fGetChar(fp);
+
+ /*
+ * check for a quoted string. If found, take all characters
+ * that fit until a closing quote is found. Note that this
+ * algorithm will not behave well for a string which is too long.
+ */
+ if (ISQUOTE(ch)) {
+ int done = FALSE;
+ do {
+ ch = fGetChar(fp);
+ done = ((maxlen<++len)||ISLINEFEED(ch)||(ch==EOF)
+ ||ISQUOTE(ch));
+ if (ch=='\\')
+ ch = fGetLiteral(fp);
+ if (!done)
+ *p++ = ch;
+ else if ((ch!=EOF) && !ISQUOTE(ch))
+ fUngetChar(ch,fp);
+ } while (!done);
+ *p = '\0';
+ if (ISLINEFEED(ch)) return(GTOK_BAD_QSTRING);
+ return(GTOK_QSTRING);
+ }
+
+ /*
+ * Not a quoted string. If its a token character (rules are
+ * defined via the ISTOKENCHAR macro, in kparse.h) take it and all
+ * token chars following it until we run out of space.
+ */
+ digits=TRUE;
+ if (ISTOKENCHAR(ch)) {
+ while ( (ISTOKENCHAR(ch)) && len<maxlen-1 ) {
+ if (!isdigit(ch)) digits=FALSE;
+ *p++ = ch;
+ len++;
+ ch = fGetChar(fp);
+ };
+ *p = '\0';
+
+ if (ch!=EOF) {
+ fUngetChar(ch,fp);
+ }
+ if (digits) {
+ return(GTOK_NUMBER);
+ } else {
+ return(GTOK_STRING);
+ }
+ }
+
+ /*
+ * Neither a quoted string nor a token character. Return a string
+ * with just that one character in it.
+ */
+ if (ch==EOF) {
+ return(GTOK_EOF);
+ }
+ if (!ISWHITESPACE(ch)) {
+ *p++ = ch;
+ *p='\0';
+ } else {
+ *p++ = ' '; /* white space is always the
+ * blank character */
+ *p='\0';
+ /*
+ * The character is a white space. Flush all additional white
+ * space.
+ */
+ while (ISWHITESPACE(ch) && ((ch=fGetChar(fp)) != EOF))
+ ;
+ if (ch!=EOF) {
+ fUngetChar(ch,fp);
+ }
+ return(GTOK_WHITE);
+ }
+ return(GTOK_PUNK);
+}
+
+/*
+ * fGetLiteral is called after we find a '\' in the input stream. A
+ * string of numbers following the backslash are converted to the
+ * appropriate value; hex (0xn), octal (0n), and decimal (otherwise)
+ * are all supported. If the char after the \ is not a number, we
+ * special case certain values (\n, \f, \r, \b) or return a literal
+ * otherwise (useful for \", for example).
+ */
+int fGetLiteral(fp)
+ FILE *fp;
+{
+ int ch;
+ int n=0;
+ int base;
+
+ ch = fGetChar(fp);
+
+ if (!isdigit(ch)) {
+ switch (ch) {
+ case 'n': return('\n');
+ case 'f': return('\f');
+ case 'r': return('\r');
+ case 'b': return('\b');
+ default: return(ch);
+ }
+ }
+
+ /*
+ * got a number. might be decimal (no prefix), octal (prefix 0),
+ * or hexadecimal (prefix 0x). Set the base appropriately.
+ */
+ if (ch!='0') {
+ base=10; /* its a decimal number */
+ } else {
+ /*
+ * found a zero, its either hex or octal
+ */
+ ch = fGetChar(fp);
+ if ((ch!='x') && (ch!='X')) {
+ base=010;
+ } else {
+ ch = fGetChar(fp);
+ base=0x10;
+ }
+ }
+
+ switch (base) {
+
+ case 010: /* octal */
+ while (ISOCTAL(ch)) {
+ n = (n*base) + ch - '0';
+ ch = fGetChar(fp);
+ }
+ break;
+
+ case 10: /* decimal */
+ while (isdigit(ch)) {
+ n = (n*base) + ch - '0';
+ ch = fGetChar(fp);
+ }
+ break;
+ case 0x10: /* hexadecimal */
+ while (isxdigit(ch)) {
+ if (isdigit(ch)) {
+ n = (n*base) + ch - '0';
+ } else {
+ n = (n*base) + toupper(ch) - 'A' + 0xA ;
+ }
+ ch = fGetChar(fp);
+ }
+ break;
+ default:
+#ifdef DEBUG
+ fprintf(stderr,"fGetLiteral() died real bad. Fix kparse.c.");
+#endif
+ break;
+ }
+ fUngetChar(ch,fp);
+ return(n);
+}
+
+/*
+ * exactly the same as ungetc(3) except that the line number of the
+ * input file is maintained.
+ */
+int fUngetChar(ch,fp)
+ int ch;
+ FILE *fp;
+{
+ if (ch=='\n') LineNbr--;
+ return(ungetc(ch,fp));
+}
+
+
+/*
+ * exactly the same as fgetc(3) except that the line number of the
+ * input file is maintained.
+ */
+int fGetChar(fp)
+ FILE *fp;
+{
+ int ch = fgetc(fp);
+ if (ch=='\n') LineNbr++;
+ return(ch);
+}
+
+
+/*
+ * Routine Name: strsave
+ *
+ * Function: return a pointer to a saved copy of the
+ * input string. the copy will be allocated
+ * as large as necessary.
+ *
+ * Explicit Parameters: pointer to string to save
+ *
+ * Implicit Parameters: None
+ *
+ * External Procedures: malloc,strcpy,strlen
+ *
+ * Side Effects: None
+ *
+ * Return Value: pointer to copied string
+ *
+ */
+#ifndef HAVE_STRSAVE
+static char * strsave(p)
+ char *p;
+{
+ return(strcpy(malloc(strlen(p)+1),p));
+}
+#endif
+
+
+/*
+ * strutol changes all characters in a string to lower case, in place.
+ * the pointer to the beginning of the string is returned.
+ */
+
+static char * strutol( start )
+ char *start;
+{
+ char *q;
+ for (q=start; *q; q++)
+ if (isupper(*q))
+ *q=tolower(*q);
+ return(start);
+}
+
+#ifdef GTOK_TEST /* mainline test routine for fGetToken() */
+
+#define MAXTOKEN 100
+
+char *pgm = "gettoken";
+
+main(argc,argv)
+ int argc;
+ char **argv;
+{
+ char *p;
+ int type;
+ FILE *fp;
+
+ if (--argc) {
+ fp = fopen(*++argv,"ra");
+ if (fp == (FILE *)NULL) {
+ fprintf(stderr,"can\'t open \"%s\"\n",*argv);
+ }
+ } else
+ fp = stdin;
+
+ p = malloc(MAXTOKEN);
+ while (type = fGetToken(fp,p,MAXTOKEN)) {
+ switch(type) {
+ case GTOK_BAD_QSTRING:
+ printf("BAD QSTRING!\t");
+ break;
+ case GTOK_EOF:
+ printf("EOF!\t");
+ break;
+ case GTOK_QSTRING:
+ printf("QSTRING\t");
+ break;
+ case GTOK_STRING:
+ printf("STRING\t");
+ break;
+ case GTOK_NUMBER:
+ printf("NUMBER\t");
+ break;
+ case GTOK_PUNK:
+ printf("PUNK\t");
+ break;
+ case GTOK_WHITE:
+ printf("WHITE\t");
+ break;
+ default:
+ printf("HUH?\t");
+ break;
+ }
+ if (*p=='\n')
+ printf("\\n\n");
+ else
+ printf("%s\n",p);
+ }
+ exit(0);
+}
+#endif
+
+#ifdef KVTEST
+
+main(argc,argv)
+ int argc;
+ char **argv;
+{
+ int rc,ch;
+ FILE *fp;
+ char key[MAXKEY],valu[MAXVALUE];
+ char *filename;
+
+ if (argc != 2) {
+ fprintf(stderr,"usage: test <filename>\n");
+ exit(1);
+ }
+
+ if (!(fp=fopen(*++argv,"r"))) {
+ fprintf(stderr,"can\'t open input file \"%s\"\n",filename);
+ exit(1);
+ }
+ filename = *argv;
+
+ while ((rc=fGetKeywordValue(fp,key,MAXKEY,valu,MAXVALUE))!=KV_EOF){
+
+ switch (rc) {
+
+ case KV_EOL:
+ printf("%s, line %d: nada mas.\n",filename,LineNbr-1);
+ break;
+
+ case KV_SYNTAX:
+ printf("%s, line %d: syntax error: %s\n",
+ filename,LineNbr,ErrorMsg);
+ while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+ break;
+
+ case KV_OKAY:
+ printf("%s, line %d: okay, %s=\"%s\"\n",
+ filename,LineNbr,key,valu);
+ break;
+
+ default:
+ printf("panic: bad return (%d) from fGetKeywordValue\n",rc);
+ break;
+ }
+ }
+ printf("EOF");
+ fclose(fp);
+ exit(0);
+}
+#endif
+
+#ifdef PSTEST
+
+parmtable kparm[] = {
+ /* keyword, default, found value */
+ { "user", "", (char *)NULL },
+ { "realm", "Athena", (char *)NULL },
+ { "instance", "", (char *)NULL }
+};
+
+main(argc,argv)
+ int argc;
+ char **argv;
+{
+ int rc,i,ch;
+ FILE *fp;
+ char *filename;
+
+ if (argc != 2) {
+ fprintf(stderr,"usage: test <filename>\n");
+ exit(1);
+ }
+
+ if (!(fp=fopen(*++argv,"r"))) {
+ fprintf(stderr,"can\'t open input file \"%s\"\n",filename);
+ exit(1);
+ }
+ filename = *argv;
+
+ while ((rc=fGetParameterSet(fp,kparm,PARMCOUNT(kparm))) != PS_EOF) {
+
+ switch (rc) {
+
+ case PS_BAD_KEYWORD:
+ printf("%s, line %d: %s\n",filename,LineNbr,ErrorMsg);
+ while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+ break;
+
+ case PS_SYNTAX:
+ printf("%s, line %d: syntax error: %s\n",
+ filename,LineNbr,ErrorMsg);
+ while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') );
+ break;
+
+ case PS_OKAY:
+ printf("%s, line %d: valid parameter set found:\n",
+ filename,LineNbr-1);
+ for (i=0; i<PARMCOUNT(kparm); i++) {
+ printf("\t%s = \"%s\"\n",kparm[i].keyword,
+ (kparm[i].value ? kparm[i].value
+ : kparm[i].defvalue));
+ }
+ break;
+
+ default:
+ printf("panic: bad return (%d) from fGetParameterSet\n",rc);
+ break;
+ }
+ FreeParameterSet(kparm,PARMCOUNT(kparm));
+ }
+ printf("EOF");
+ fclose(fp);
+ exit(0);
+}
+#endif
diff --git a/src/lib/krb4/krb_err.et b/src/lib/krb4/krb_err.et
new file mode 100644
index 0000000000..7ee5dd5f9d
--- /dev/null
+++ b/src/lib/krb4/krb_err.et
@@ -0,0 +1,256 @@
+# Copyright 1987,1988 Massachusetts Institute of Technology
+#
+# For copying and distribution information, see the file
+# "mit-copyright.h".
+#
+#
+ error_table krb
+
+ ec KRBET_KSUCCESS,
+ "Kerberos successful"
+
+ ec KRBET_KDC_NAME_EXP,
+ "Kerberos principal expired"
+
+ ec KRBET_KDC_SERVICE_EXP,
+ "Kerberos service expired"
+
+ ec KRBET_KDC_AUTH_EXP,
+ "Kerberos auth expired"
+
+ ec KRBET_KDC_PKT_VER,
+ "Incorrect kerberos master key version"
+
+ ec KRBET_KDC_P_MKEY_VER,
+ "Incorrect kerberos master key version"
+
+ ec KRBET_KDC_S_MKEY_VER,
+ "Incorrect kerberos master key version"
+
+ ec KRBET_KDC_BYTE_ORDER,
+ "Kerberos error: byte order unknown"
+
+ ec KRBET_KDC_PR_UNKNOWN,
+ "Kerberos principal unknown"
+
+ ec KRBET_KDC_PR_N_UNIQUE,
+ "Kerberos principal not unique"
+
+ ec KRBET_KDC_NULL_KEY,
+ "Kerberos principal has null key"
+
+ ec KRBET_KRB_RES11,
+ "Reserved 11"
+
+ ec KRBET_KRB_RES12,
+ "Reserved 12"
+
+ ec KRBET_KRB_RES13,
+ "Reserved 13"
+
+ ec KRBET_KRB_RES14,
+ "Reserved 14"
+
+ ec KRBET_KRB_RES15,
+ "Reserved 15"
+
+ ec KRBET_KRB_RES16,
+ "Reserved 16"
+
+ ec KRBET_KRB_RES17,
+ "Reserved 17"
+
+ ec KRBET_KRB_RES18,
+ "Reserved 18"
+
+ ec KRBET_KRB_RES19,
+ "Reserved 19"
+
+ ec KRBET_KDC_GEN_ERR,
+ "Generic error from Kerberos KDC"
+
+ ec KRBET_GC_TKFIL,
+ "Can't read Kerberos ticket file"
+
+ ec KRBET_GC_NOTKT,
+ "Can't find Kerberos ticket or TGT"
+
+ ec KRBET_KRB_RES23,
+ "Reserved 23"
+
+ ec KRBET_KRB_RES24,
+ "Reserved 24"
+
+ ec KRBET_KRB_RES25,
+ "Reserved 25"
+
+ ec KRBET_MK_AP_TGTEXP,
+ "Kerberos TGT Expired"
+
+ ec KRBET_KRB_RES27,
+ "Reserved 27"
+
+ ec KRBET_KRB_RES28,
+ "Reserved 28"
+
+ ec KRBET_KRB_RES29,
+ "Reserved 29"
+
+ ec KRBET_KRB_RES30,
+ "Reserved 30"
+
+ ec KRBET_RD_AP_UNDEC,
+ "Kerberos error: Can't decode authenticator"
+
+ ec KRBET_RD_AP_EXP,
+ "Kerberos ticket expired"
+
+ ec KRBET_RD_AP_NYV,
+ "Kerberos ticket not yet valid"
+
+ ec KRBET_RD_AP_REPEAT,
+ "Kerberos error: Repeated request"
+
+ ec KRBET_RD_AP_NOT_US,
+ "The kerberos ticket isn't for us"
+
+ ec KRBET_RD_AP_INCON,
+ "Kerberos request inconsistent"
+
+ ec KRBET_RD_AP_TIME,
+ "Kerberos error: time is out of bounds"
+
+ ec KRBET_RD_AP_BADD,
+ "Kerberos error: incorrect net address"
+
+ ec KRBET_RD_AP_VERSION,
+ "Kerberos protocol version mismatch"
+
+ ec KRBET_RD_AP_MSG_TYPE,
+ "Kerberos error: invalid msg type"
+
+ ec KRBET_RD_AP_MODIFIED,
+ "Kerberos error: message stream modified"
+
+ ec KRBET_RD_AP_ORDER,
+ "Kerberos error: message out of order"
+
+ ec KRBET_RD_AP_UNAUTHOR,
+ "Kerberos error: unauthorized request"
+
+ ec KRBET_KRB_RES44,
+ "Reserved 44"
+
+ ec KRBET_KRB_RES45,
+ "Reserved 45"
+
+ ec KRBET_KRB_RES46,
+ "Reserved 46"
+
+ ec KRBET_KRB_RES47,
+ "Reserved 47"
+
+ ec KRBET_KRB_RES48,
+ "Reserved 48"
+
+ ec KRBET_KRB_RES49,
+ "Reserved 49"
+
+ ec KRBET_KRB_RES50,
+ "Reserved 50"
+
+ ec KRBET_GT_PW_NULL,
+ "Kerberos error: current PW is null"
+
+ ec KRBET_GT_PW_BADPW,
+ "Kerberos error: Incorrect current password"
+
+ ec KRBET_GT_PW_PROT,
+ "Kerberos protocol error"
+
+ ec KRBET_GT_PW_KDCERR,
+ "Error returned by Kerberos KDC"
+
+ ec KRBET_GT_PW_NULLTKT,
+ "Null Kerberos ticket returned by KDC"
+
+ ec KRBET_SKDC_RETRY,
+ "Kerberos error: Retry count exceeded"
+
+ ec KRBET_SKDC_CANT,
+ "Kerberos error: Can't send request"
+
+ ec KRBET_KRB_RES58,
+ "Reserved 58"
+
+ ec KRBET_KRB_RES59,
+ "Reserved 59"
+
+ ec KRBET_KRB_RES60,
+ "Reserved 60"
+
+ ec KRBET_INTK_W_NOTALL,
+ "Kerberos error: not all tickets returned"
+
+ ec KRBET_INTK_BADPW,
+ "Kerberos error: incorrect password"
+
+ ec KRBET_INTK_PROT,
+ "Kerberos error: Protocol Error"
+
+ ec KRBET_KRB_RES64,
+ "Reserved 64"
+
+ ec KRBET_KRB_RES65,
+ "Reserved 65"
+
+ ec KRBET_KRB_RES66,
+ "Reserved 66"
+
+ ec KRBET_KRB_RES67,
+ "Reserved 67"
+
+ ec KRBET_KRB_RES68,
+ "Reserved 68"
+
+ ec KRBET_KRB_RES69,
+ "Reserved 69"
+
+ ec KRBET_INTK_ERR,
+ "Other error"
+
+ ec KRBET_AD_NOTGT,
+ "Don't have Kerberos ticket-granting ticket"
+
+ ec KRBET_KRB_RES72,
+ "Reserved 72"
+
+ ec KRBET_KRB_RES73,
+ "Reserved 73"
+
+ ec KRBET_KRB_RES74,
+ "Reserved 74"
+
+ ec KRBET_KRB_RES75,
+ "Reserved 75"
+
+ ec KRBET_NO_TKT_FIL,
+ "You have no tickets cached"
+
+ ec KRBET_TKT_FIL_ACC,
+ "Couldn't access ticket file"
+
+ ec KRBET_TKT_FIL_LCK,
+ "Couldn't lock ticket file"
+
+ ec KRBET_TKT_FIL_FMT,
+ "Bad ticket file format"
+
+ ec KRBET_TKT_FIL_INI,
+ "tf_init not called first"
+
+ ec KRBET_KNAME_FMT,
+ "Bad Kerberos name format"
+
+ end
+
diff --git a/src/lib/krb4/kuserok.c b/src/lib/krb4/kuserok.c
new file mode 100644
index 0000000000..ef22b4a47b
--- /dev/null
+++ b/src/lib/krb4/kuserok.c
@@ -0,0 +1,231 @@
+/*
+ * kuserok.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * kuserok: check if a kerberos principal has
+ * access to a local account
+ */
+
+#include "mit-copyright.h"
+
+#include "krb.h"
+#include <stdio.h>
+#include <pwd.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <string.h>
+#ifdef USE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef __SCO__
+/* just for F_OK for sco */
+#include <sys/unistd.h>
+#endif
+
+#ifdef hpux
+#define seteuid(e) setresuid(-1,e,-1)
+#define setegid(e) setresgid(-1,e,-1)
+#endif
+
+#define OK 0
+#define NOTOK 1
+#define MAX_USERNAME 10
+
+/*
+ * Given a Kerberos principal "kdata", and a local username "luser",
+ * determine whether user is authorized to login according to the
+ * authorization file ("~luser/.klogin" by default). Returns OK
+ * if authorized, NOTOK if not authorized.
+ *
+ * If there is no account for "luser" on the local machine, returns
+ * NOTOK. If there is no authorization file, and the given Kerberos
+ * name "kdata" translates to the same name as "luser" (using
+ * krb_kntoln()), returns OK. Otherwise, if the authorization file
+ * can't be accessed, returns NOTOK. Otherwise, the file is read for
+ * a matching principal name, instance, and realm. If one is found,
+ * returns OK, if none is found, returns NOTOK.
+ *
+ * The file entries are in the format:
+ *
+ * name.instance@realm
+ *
+ * one entry per line.
+ *
+ * The ATHENA_COMPAT code supports old-style Athena ~luser/.klogin
+ * file entries. See the file "kparse.c".
+ */
+
+#if defined(ATHENA_COMPAT) || defined(ATHENA_OLD_KLOGIN)
+
+#include <kparse.h>
+
+/*
+ * The parmtable defines the keywords we will recognize with their
+ * default values, and keeps a pointer to the found value. The found
+ * value should be filled in with strsave(), since FreeParameterSet()
+ * will release memory for all non-NULL found strings.
+ *
+*** NOTE WELL! ***
+ *
+ * The table below is very nice, but we cannot hard-code a default for the
+ * realm: we have to get the realm via krb_get_lrealm(). Even though the
+ * default shows as "from krb_get_lrealm, below", it gets changed in
+ * kuserok to whatever krb_get_lrealm() tells us. That code assumes that
+ * the realm will be the entry number in the table below, so if you
+ * change the order of the entries below, you have to change the
+ * #definition of REALM_SCRIPT to reflect it.
+ */
+#define REALM_SUBSCRIPT 1
+parmtable kparm[] = {
+
+/* keyword default found value */
+{"user", "", (char *) NULL},
+{"realm", "see krb_get_lrealm, below", (char *) NULL},
+{"instance", "", (char *) NULL},
+};
+#define KPARMS kparm,PARMCOUNT(kparm)
+#endif
+
+kuserok(kdata, luser)
+ AUTH_DAT *kdata;
+ char *luser;
+{
+ struct stat sbuf;
+ struct passwd *pwd;
+ char pbuf[MAXPATHLEN];
+ int isok = NOTOK, rc;
+ FILE *fp;
+ char kuser[MAX_USERNAME];
+ char principal[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
+ char linebuf[BUFSIZ];
+ char *newline;
+ int gobble;
+#if defined(ATHENA_COMPAT) || defined(ATHENA_OLD_KLOGIN)
+ char local_realm[REALM_SZ];
+#endif
+
+ /* no account => no access */
+ if ((pwd = getpwnam(luser)) == NULL) {
+ return(NOTOK);
+ }
+ (void) strcpy(pbuf, pwd->pw_dir);
+ (void) strcat(pbuf, "/.klogin");
+
+ if (access(pbuf, F_OK)) { /* not accessible */
+ /*
+ * if he's trying to log in as himself, and there is no .klogin file,
+ * let him. To find out, call
+ * krb_kntoln to convert the triple in kdata to a name which we can
+ * string compare.
+ */
+ if (!krb_kntoln(kdata, kuser) && (strcmp(kuser, luser) == 0)) {
+ return(OK);
+ }
+ }
+ /* open ~/.klogin */
+ if ((fp = fopen(pbuf, "r")) == NULL) {
+ /* however, root might not have enough access, so temporarily switch
+ * over to the user's uid, try the access again, and switch back
+ */
+ if(getuid() == 0) {
+ uid_t old_euid = geteuid();
+ seteuid(pwd->pw_uid);
+ fp = fopen(pbuf, "r");
+ seteuid(old_euid);
+ if ((fp) == NULL) {
+ return(NOTOK);
+ }
+ } else {
+ return(NOTOK);
+ }
+ }
+ /*
+ * security: if the user does not own his own .klogin file,
+ * do not grant access
+ */
+ if (fstat(fileno(fp), &sbuf)) {
+ fclose(fp);
+ return(NOTOK);
+ }
+ /*
+ * however, allow root to own the .klogin file, to allow creative
+ * access management schemes.
+ */
+ if (sbuf.st_uid && (sbuf.st_uid != pwd->pw_uid)) {
+ fclose(fp);
+ return(NOTOK);
+ }
+
+#if defined(ATHENA_COMPAT) || defined(ATHENA_OLD_KLOGIN)
+ /* Accept old-style .klogin files */
+
+ /*
+ * change the default realm from the hard-coded value to the
+ * accepted realm that Kerberos specifies.
+ */
+ rc = krb_get_lrealm(local_realm, 1);
+ if (rc == KSUCCESS)
+ kparm[REALM_SUBSCRIPT].defvalue = local_realm;
+ else
+ return (rc);
+
+ /* check each line */
+ while ((isok != OK) && (rc = fGetParameterSet(fp, KPARMS)) != PS_EOF) {
+ switch (rc) {
+ case PS_BAD_KEYWORD:
+ case PS_SYNTAX:
+ while (((gobble = fGetChar(fp)) != EOF) && (gobble != '\n'));
+ break;
+
+ case PS_OKAY:
+ isok = (ParmCompare(KPARMS, "user", kdata->pname) ||
+ ParmCompare(KPARMS, "instance", kdata->pinst) ||
+ ParmCompare(KPARMS, "realm", kdata->prealm));
+ break;
+
+ default:
+ break;
+ }
+ FreeParameterSet(kparm, PARMCOUNT(kparm));
+ }
+ /* reset the stream for parsing new-style names, if necessary */
+ rewind(fp);
+#endif
+
+ /* check each line */
+ while ((isok != OK) && (fgets(linebuf, BUFSIZ, fp) != NULL)) {
+ /* null-terminate the input string */
+ linebuf[BUFSIZ-1] = '\0';
+ newline = NULL;
+ /* nuke the newline if it exists */
+ if (newline = strchr(linebuf, '\n'))
+ *newline = '\0';
+
+ /* Default the fields (default realm is filled in later) */
+ principal[0] = '\0';
+ inst[0] = '\0';
+ realm[0] = '\0';
+ rc = kname_parse(principal, inst, realm, linebuf);
+ if (rc == KSUCCESS) {
+ if (realm[0] == '\0') {
+ rc = krb_get_lrealm(realm, 1);
+ if (rc != KSUCCESS)
+ goto nextline;
+ }
+ isok = (strncmp(kdata->pname, principal, ANAME_SZ) ||
+ strncmp(kdata->pinst, inst, INST_SZ) ||
+ strncmp(kdata->prealm, realm, REALM_SZ));
+ }
+ nextline:
+ /* clean up the rest of the line if necessary */
+ if (!newline)
+ while (((gobble = getc(fp)) != EOF) && gobble != '\n');
+ }
+ fclose(fp);
+ return(isok);
+}
diff --git a/src/lib/krb4/log.c b/src/lib/krb4/log.c
new file mode 100644
index 0000000000..7244a60b65
--- /dev/null
+++ b/src/lib/krb4/log.c
@@ -0,0 +1,128 @@
+/*
+ * log.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#ifdef KRB_CRYPT_DEBUG
+/* This file used to contain log() and set_logfile(). If you define
+ KRB_CRYPT_DEBUG, you'll need to define those to point to krb_log and
+ krb_set_logfile, or change all the invokers. */
+#endif
+
+#include "mit-copyright.h"
+#ifdef NEED_TIME_H
+#include <time.h>
+#endif
+#ifndef VMS
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+
+#include "krb.h"
+#include <klog.h>
+
+static char *log_name = KRBLOG;
+static is_open;
+
+/*
+ * This file contains three logging routines: set_logfile()
+ * to determine the file that log entries should be written to;
+ * and log() and new_log() to write log entries to the file.
+ */
+
+/*
+ * krb_log() is used to add entries to the logfile (see krb_set_logfile()
+ * below). Note that it is probably not portable since it makes
+ * assumptions about what the compiler will do when it is called
+ * with less than the correct number of arguments which is the
+ * way it is usually called.
+ *
+ * The log entry consists of a timestamp and the given arguments
+ * printed according to the given "format".
+ *
+ * The log file is opened and closed for each log entry.
+ *
+ * The return value is undefined.
+ */
+
+/* should be in a header */
+char *month_sname();
+
+/*VARARGS1 */
+void krb_log(format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0)
+ char *format;
+ char *a1,*a2,*a3,*a4,*a5,*a6,*a7,*a8,*a9,*a0;
+{
+ FILE *logfile;
+ time_t now;
+ struct tm *tm;
+
+ if ((logfile = fopen(log_name,"a")) == NULL)
+ return;
+
+ (void) time(&now);
+ tm = localtime(&now);
+
+ fprintf(logfile,"%2d-%s-%02d %02d:%02d:%02d ",tm->tm_mday,
+ month_sname(tm->tm_mon + 1),tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ fprintf(logfile,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0);
+ fprintf(logfile,"\n");
+ (void) fclose(logfile);
+ return;
+}
+
+/*
+ * krb_set_logfile() changes the name of the file to which
+ * messages are logged. If krb_set_logfile() is not called,
+ * the logfile defaults to KRBLOG, defined in "krb.h".
+ */
+
+krb_set_logfile(filename)
+ char *filename;
+{
+ log_name = filename;
+ is_open = 0;
+}
+
+#if 0
+/*
+ * new_log() appends a log entry containing the give time "t" and the
+ * string "string" to the logfile (see set_logfile() above). The file
+ * is opened once and left open. The routine returns 1 on failure, 0
+ * on success.
+ */
+
+krb_new_log(t,string)
+ long t;
+ char *string;
+{
+ static FILE *logfile;
+
+ struct tm *tm;
+
+ if (!is_open) {
+ if ((logfile = fopen(log_name,"a")) == NULL) return(1);
+ is_open = 1;
+ }
+
+ if (t) {
+ tm = localtime(&t);
+
+ fprintf(logfile,"\n%2d-%s-%02d %02d:%02d:%02d %s",tm->tm_mday,
+ month_sname(tm->tm_mon + 1),tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec, string);
+ }
+ else {
+ fprintf(logfile,"\n%20s%s","",string);
+ }
+
+ (void) fflush(logfile);
+ return(0);
+}
+#endif
diff --git a/src/lib/krb4/mac_glue.c b/src/lib/krb4/mac_glue.c
new file mode 100644
index 0000000000..ce3a6523f1
--- /dev/null
+++ b/src/lib/krb4/mac_glue.c
@@ -0,0 +1,49 @@
+/*
+ * mac_glue.c
+ *
+ * Copyright 1989 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Macintosh ooperating system interface for Kerberos.
+ */
+
+#include "mit-copyright.h"
+#define DEFINE_SOCKADDR /* For struct hostent, <netdb.h>, etc */
+#include "krb.h"
+
+/* Mac Cincludes */
+#include <string.h>
+#include <stddef.h>
+
+/* FIXME! swab should be swapping, but for initial test, don't bother. */
+
+void swab(char *from, char *to, int nbytes) {}
+
+mymemset( void *s, register int c, register size_t n )
+{
+ // written because memset doesn't work in think C (ARGGGG!!!!!!)
+ register char *j = s;
+ while( n-- )
+ *j++ = c;
+}
+
+int INTERFACE
+krb_start_session (x)
+ char *x;
+{
+ return KSUCCESS;
+}
+
+int INTERFACE
+krb_end_session (x)
+ char *x;
+{
+ return KSUCCESS;
+}
+
+/* FIXME: These stubs should go away. */
+int read() {return 0;}
+int write () {return 0;}
+int krb_ignore_ip_address = 0;
diff --git a/src/lib/krb4/mac_store.c b/src/lib/krb4/mac_store.c
new file mode 100644
index 0000000000..262ba58bd5
--- /dev/null
+++ b/src/lib/krb4/mac_store.c
@@ -0,0 +1,731 @@
+/*
+ * mac_store.c
+ *
+ * Kerberos configuration store
+ * Originally coded by Tim Miller / Brown University as KRB_Store.c
+ * Mods 1/92 By Peter Bosanko
+ *
+ * Modified May-June 1994 by Julia Menapace and John Gilmore
+ * of Cygnus Support.
+ *
+ * This file incorporates replacements for the Unix files
+ * g_admhst.c, g_krbhst.c, realmofhost.c, and g_krbrlm.c.
+ */
+
+/* Headers from in_tkt.c, merged in by gnu FIXME */
+#include <types.h>
+
+/* Headers from store.c from KClient */
+#include <string.h>
+#include <traps.h>
+#include <gestaltEqu.h>
+#include <Folders.h>
+#include <Resources.h>
+#include <Memory.h>
+#include <Files.h>
+
+#include "krb.h"
+#include "mac_store.h" /* includes memcache.h */
+#include "krb_driver.h"
+
+#define prefname "\pKerberos Client Preferences"
+const OSType preftype = 'PREF';
+const OSType prefcrea = 'krbL';
+const OSType unametype = 'UNam';
+const OSType lrealmtype = 'LRlm';
+const OSType templatetype = 'TMPL';
+const OSType realmmaptype = 'RMap';
+const OSType servermaptype = 'SMap';
+#define kNumTemplates 4
+#define kFirstTemplate 128
+#define kMapResNum 1024
+
+
+/* Lower level routines and data structures */
+
+
+/* Need to check this in each high-level routine, and call init_store
+ if not set. */
+static int initialized_store = 0;
+
+static char fLRealm[REALM_SZ] = "";
+static Handle fRealmMap = 0;
+static Handle fServerMap = 0;
+static short fPrefVRefNum;
+static long fPrefDirID;
+OSErr fConstructErr = -1;
+
+/* Current default user name (for prompts, etc). */
+
+static char gUserName[MAX_K_NAME_SZ];
+
+
+/* Routines for dealing with the realm versus host database */
+
+/*
+ * krb_get_admhst
+ *
+ * Given a Kerberos realm, find a host on which the Kerberos database
+ * administration server can be found.
+ *
+ * krb_get_admhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer n, and
+ * returns (in h) the nth administrative host entry from the configuration
+ * file (KRB_CONF, defined in "krb.h") associated with the specified realm.
+ * If ATHENA_CONF_FALLBACK is defined, also look in old location.
+ *
+ * On error, get_admhst returns KFAILURE. If all goes well, the routine
+ * returns KSUCCESS.
+ *
+ * For the format of the KRB_CONF file, see comments describing the routine
+ * krb_get_krbhst().
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * a Kerberos admin server. In the long run, this functionality will be
+ * provided by a nameserver. (HAH!)
+ */
+int
+krb_get_admhst (h, r, n)
+ char *h;
+ char *r;
+ int n;
+{
+ if (!initialized_store)
+ if (init_store())
+ return KFAILURE;
+ if(GetNthServer(n, r, 1, h)) return KFAILURE;
+ else return KSUCCESS;
+}
+
+/*
+ * Given a Kerberos realm, find a host on which the Kerberos authenti-
+ * cation server can be found.
+ *
+ * krb_get_krbhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer, n, and
+ * returns (in h) the nth entry from the configuration information
+ * associated with the specified realm.
+ *
+ * If no info is found, krb_get_krbhst returns KFAILURE. If n=1 and the
+ * configuration file does not exist, krb_get_krbhst will return KRB_HOST
+ * (defined in "krb.h"). If all goes well, the routine returnes
+ * KSUCCESS.
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * kerberos. In the long run, this functionality will be provided by a
+ * nameserver. (AH SO!)
+ */
+int krb_get_krbhst(h, r, n)
+ char *h;
+ char *r;
+ int n;
+{
+ if (!initialized_store)
+ if (init_store())
+ return KFAILURE;
+ if (GetNthServer(n, r, 0, h)) return KFAILURE;
+ else return KSUCCESS;
+}
+
+
+/*
+ * krb_get_lrealm takes a pointer to a string, and a number, n. It fills
+ * in the string, r, with the name of the local realm specified in
+ * the local Kerberos configuration.
+ * It returns 0 (KSUCCESS) on success, and KFAILURE on failure. If the
+ * config info does not exist, and if n=1, a successful return will occur
+ * with r = KRB_REALM (also defined in "krb.h"). [FIXME -- not implem.]
+ *
+ * NOTE: for archaic & compatibility reasons, this routine will only return
+ * valid results when n = 1.
+ */
+
+int krb_get_lrealm(char *r, int n)
+{
+ if (!initialized_store)
+ if (init_store())
+ return KFAILURE;
+ if (n != 1)
+ return KFAILURE;
+ if (GetLocalRealm(r))
+ return KFAILURE;
+ return KSUCCESS;
+}
+
+
+/*
+ * krb_realmofhost.
+ * Given a fully-qualified domain-style primary host name,
+ * return the name of the Kerberos realm for the host.
+ * If the hostname contains no discernable domain, or an error occurs,
+ * return the local realm name, as supplied by get_krbrlm().
+ * If the hostname contains a domain, but no translation is found,
+ * the hostname's domain is converted to upper-case and returned.
+ *
+ * In the database,
+ * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU)
+ * host names should be in the usual form (e.g. FOO.BAR.BAZ)
+ */
+
+char *krb_realmofhost(char *host)
+{
+ static char realm[REALM_SZ];
+
+ if (!initialized_store)
+ if (init_store())
+ return 0;
+
+ /* Store realm string through REALM pointer arg */
+ GetRealm(host, realm);
+ return realm;
+}
+
+
+char * INTERFACE
+krb_get_default_user (void)
+{
+ if (!initialized_store)
+ if (init_store())
+ return 0;
+
+ return gUserName;
+}
+
+
+int INTERFACE
+krb_set_default_user (uName)
+ char* uName;
+{
+ if (!initialized_store)
+ if (init_store())
+ return KFAILURE;
+
+ if( strcmp( gUserName, uName ) != 0 ) {
+ strcpy( gUserName, uName );
+ if (WriteUser() != 0)
+ return KFAILURE;
+ }
+ return KSUCCESS;
+}
+
+
+
+void GetPrefsFolder(short *vRefNumP, long *dirIDP)
+{
+ Boolean hasFolderMgr = false;
+ long feature;
+/*
+ FIXME Error: Ô_GestaltDispatchÕ has not been declared - not needed now? - jcm
+ if (TrapAvailable(_GestaltDispatch))
+*/
+ if (Gestalt(gestaltFindFolderAttr, &feature) == noErr) hasFolderMgr = true;
+ if (!hasFolderMgr) {
+ GetSystemFolder(vRefNumP, dirIDP);
+ return;
+ }
+ else {
+ if (FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, vRefNumP, dirIDP) != noErr) {
+ *vRefNumP = 0;
+ *dirIDP = 0;
+ }
+ }
+ }
+
+
+/*
+ init_store() is used to initialize the config store. It opens the
+ driver preferences file and reads the local realm, user name, and
+ realm and server maps from resources in the prefs file into driver
+ storage. If the preferences file doesn't exist, init_store creates it.
+ Returns 0 on success, or 1 if something goes wrong.
+ */
+int
+init_store()
+{
+ short refnum;
+ Handle temp;
+ int hasPrefFile;
+
+ /* If a prefs file exists, load from it, otherwise load defaults from self */
+ GetPrefsFolder(&fPrefVRefNum, &fPrefDirID);
+ refnum = HOpenResFile(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname, fsRdPerm);
+ hasPrefFile = (refnum != -1); // did we open it?
+
+ temp = GetResource(lrealmtype, kMapResNum);
+ if(ResError() || !temp) {
+ if(refnum != -1) CloseResFile(refnum);
+ fConstructErr = cKrbCorruptedFile;
+ return 1;
+ }
+ strcpy(fLRealm, *temp);
+ ReleaseResource(temp);
+
+ temp = GetResource(unametype, kMapResNum);
+ if(ResError() || !temp) {
+ if(refnum != -1) CloseResFile(refnum);
+ fConstructErr = cKrbCorruptedFile;
+ return 1;
+ }
+ strcpy(gUserName, *temp);
+ ReleaseResource(temp);
+
+ fRealmMap = GetResource(realmmaptype, kMapResNum);
+ if(ResError() || !fRealmMap) {
+ if(refnum != -1) CloseResFile(refnum);
+ *fLRealm = 0;
+ fConstructErr = cKrbCorruptedFile;
+ return 1;
+ }
+ DetachResource(fRealmMap);
+
+ fServerMap = GetResource(servermaptype, kMapResNum);
+ if(ResError() || !fServerMap) {
+ if(refnum != -1) CloseResFile(refnum);
+ *fLRealm = 0;
+ DisposeHandle(fRealmMap);
+ fRealmMap = 0;
+ fConstructErr = cKrbCorruptedFile;
+ return 1;
+ }
+ DetachResource(fServerMap);
+
+ if(refnum != -1) CloseResFile(refnum);
+ fConstructErr = noErr;
+
+ if (!hasPrefFile) {
+ fConstructErr = CreatePrefFile(); // make prefs file if we need to
+ }
+
+ initialized_store = 1;
+ return 0;
+}
+
+
+/****************Private routines******************/
+
+OSErr OpenPrefsFile(short *refnum)
+{
+ *refnum = HOpenResFile(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname, fsRdWrPerm);
+
+ if(ResError()) { /* doesn't exist, create it */
+ FInfo fndrinfo;
+
+ HCreateResFile(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname);
+ if(ResError()) {
+ return ResError();
+ }
+ *refnum = HOpenResFile(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname, fsRdWrPerm);
+ if(ResError()) {
+ return ResError();
+ }
+ HGetFInfo(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname, &fndrinfo);
+ fndrinfo.fdCreator = prefcrea;
+ fndrinfo.fdType = preftype;
+ HSetFInfo(fPrefVRefNum, fPrefDirID, (unsigned char *)prefname, &fndrinfo);
+ }
+
+ return noErr;
+ }
+
+
+
+OSErr CreatePrefFile()
+{
+ short refnum, i;
+ OSErr err;
+ Handle tmpls[ kNumTemplates ];
+
+ // Get all the templates for ResEdit
+ for( i = 0; i < kNumTemplates; i++ ) {
+ tmpls[i] = GetResource( templatetype, kFirstTemplate + i );
+ if( ResError() || !tmpls[i] ) return cKrbCorruptedFile;
+ }
+
+ err = OpenPrefsFile( &refnum );
+ if( err ) return err;
+
+ // write out the templates
+ for( i = 0; i < kNumTemplates && !err; i++ ) {
+ short tmplid;
+ ResType theType;
+ Str255 resName;
+
+ GetResInfo( tmpls[i], &tmplid, &theType, resName );
+ err = WritePref( refnum, tmpls[i], templatetype, tmplid, resName );
+ ReleaseResource( tmpls[i] );
+ }
+
+ if( !err )
+ err = WritePref( refnum, fRealmMap, realmmaptype, kMapResNum, "\p" );
+ if( !err )
+ err = WritePref( refnum, fServerMap, servermaptype, kMapResNum, "\p" );
+ if( !err )
+ err = WritePrefStr( refnum, fLRealm, lrealmtype, kMapResNum, "\p" );
+ if( !err )
+ err = WritePrefStr( refnum, gUserName, unametype, kMapResNum, "\p" );
+
+ CloseResFile( refnum );
+ if( !err ) err = ResError();
+ return err;
+}
+
+OSErr WriteUser()
+{
+ short refnum;
+ OSErr err;
+
+ err = OpenPrefsFile( &refnum );
+ if( err ) return err;
+
+ err = WritePrefStr( refnum, gUserName, unametype, kMapResNum, "\p" );
+
+ CloseResFile( refnum );
+ if( !err ) err = ResError();
+ return err;
+}
+
+OSErr WritePref( short refnum, Handle dataHandle, OSType mapType, short resID, Str255 resName )
+{
+ OSErr err;
+ Handle resHandle;
+
+ resHandle = Get1Resource( mapType, resID );
+ if( !resHandle ) { // create a new resource:
+ resHandle = dataHandle;
+ err = HandToHand( &resHandle ); // copy the data handle
+ if( err != noErr ) return err;
+
+ AddResource( resHandle, mapType, resID, resName );
+ if( ( err = ResError() ) != noErr ) {
+ DisposHandle( resHandle );
+ return err;
+ }
+ SetResAttrs( resHandle, resSysHeap | GetResAttrs( resHandle ) );
+ }
+ else { /* modify an existing resource: */
+ Size handleSize = GetHandleSize( dataHandle );
+ SetHandleSize( resHandle, handleSize );
+ if( ( err = MemError() ) != noErr ) {
+ ReleaseResource( resHandle );
+ return err;
+ }
+ BlockMove( *dataHandle, *resHandle, handleSize );
+ ChangedResource( resHandle );
+ if( ( err = ResError() ) != noErr ) {
+ ReleaseResource( resHandle );
+ return err;
+ }
+ }
+
+ UpdateResFile( refnum );
+ err = ResError();
+ ReleaseResource( resHandle );
+ return err;
+}
+
+OSErr WritePrefStr( short refnum, char *dataString, OSType mapType, short resID, Str255 resName )
+{
+ OSErr err;
+ Handle dataHandle;
+
+ err = PtrToHand( dataString, &dataHandle, strlen( dataString ) + 1 );
+ if( err == noErr ) {
+ err = WritePref( refnum, dataHandle, mapType, resID, resName );
+ DisposHandle( dataHandle );
+ }
+ return err;
+}
+
+OSErr WriteRealmMap()
+{
+ short refnum;
+ OSErr err;
+
+ err = OpenPrefsFile( &refnum );
+ if( err ) return err;
+
+ err = WritePref( refnum, fRealmMap, realmmaptype, kMapResNum, "\p" );
+
+ CloseResFile( refnum );
+ if( !err ) err = ResError();
+ return err;
+}
+
+OSErr WriteServerMap()
+{
+ short refnum;
+ OSErr err;
+
+ err = OpenPrefsFile(&refnum);
+ if( err ) return err;
+
+ err = WritePref( refnum, fServerMap, servermaptype, kMapResNum,"\p" );
+
+ CloseResFile( refnum );
+ if( !err ) err = ResError();
+ return err;
+}
+
+OSErr GetLocalRealm(char *lrealm)
+{
+ if (!initialized_store)
+ init_store();
+
+ strcpy(lrealm, fLRealm);
+ return noErr;
+ }
+
+OSErr SetLocalRealm( const char *lrealm )
+{
+ short refnum;
+ OSErr err;
+
+ if (!initialized_store)
+ init_store();
+
+ strcpy( fLRealm, (char *) lrealm );
+
+ err = OpenPrefsFile( &refnum );
+ if( err ) return err;
+
+ err = WritePrefStr( refnum, fLRealm, lrealmtype, kMapResNum, "\p" );
+
+ CloseResFile( refnum );
+ if( !err ) err = ResError();
+ return err;
+}
+
+OSErr GetRealm(const char *host, char *realm)
+{
+ int numrealms;
+ char *curnetorhost, *currealm;
+ char *domain;
+
+ if (!initialized_store)
+ init_store();
+
+ numrealms = *((short *)*fRealmMap);
+ GetLocalRealm(realm);
+
+ domain = strchr( host, '.');
+ if(!domain) return noErr;
+
+ curnetorhost = (*fRealmMap) + 2;
+ currealm = strchr(curnetorhost, '\0') + 1;
+ for( ; numrealms > 0; numrealms--) {
+ if(!strcasecmp(curnetorhost, host)) {
+ strcpy(realm, currealm);
+ return noErr;
+ }
+ if(!strcasecmp(curnetorhost, domain)) {
+ strcpy(realm, currealm);
+ }
+
+ if(numrealms > 1) {
+ curnetorhost = strchr(currealm, '\0') + 1;
+ currealm = strchr(curnetorhost, '\0') + 1;
+ }
+ }
+
+ return noErr;
+ }
+
+OSErr AddRealmMap(const char *netorhost, const char *realm)
+{
+ int numrealms;
+ char *curptr;
+
+ SetHandleSize(fRealmMap, strlen(netorhost)+1 + strlen(realm)+1 +
+ GetHandleSize(fRealmMap));
+ if(MemError()) return MemError();
+
+ numrealms = ++(*((short *)*fRealmMap));
+
+ for(curptr = (*fRealmMap)+2; numrealms > 1; numrealms--) {
+ curptr = strchr(curptr, '\0') + 1;
+ curptr = strchr(curptr, '\0') + 1;
+ }
+
+ strcpy(curptr, netorhost);
+ curptr = strchr(curptr, '\0') + 1;
+ strcpy(curptr, realm);
+
+ return WriteRealmMap();
+ }
+
+OSErr DeleteRealmMap(const char *netorhost)
+{
+ int numrealms = *((short *)*fRealmMap);
+ char *curptr, *fromptr, *nextptr;
+
+ for(curptr = (*fRealmMap)+2; numrealms > 0; numrealms--) {
+ if(!strcasecmp(curptr, netorhost)) break; /* got it! */
+
+ curptr = strchr(curptr, '\0') + 1;
+ curptr = strchr(curptr, '\0') + 1;
+ }
+
+ if(numrealms == 0) return cKrbMapDoesntExist;
+
+ *(short*)*fRealmMap -= 1;
+
+ if(numrealms > 1) {
+ fromptr = strchr(curptr, '\0') + 1;
+ fromptr = strchr(fromptr, '\0') + 1;
+ }
+
+ for( ; numrealms > 1; numrealms--) {
+ nextptr = strchr(fromptr, '\0') + 1;
+ strcpy(curptr, fromptr);
+ curptr = strchr(curptr, '\0') + 1;
+ fromptr = nextptr;
+
+ nextptr = strchr(fromptr, '\0') + 1;
+ strcpy(curptr, fromptr);
+ curptr = strchr(curptr, '\0') + 1;
+ fromptr = nextptr;
+ }
+
+ SetHandleSize(fRealmMap, curptr-(*fRealmMap));
+ if(MemError()) return MemError();
+ return WriteRealmMap();
+ }
+
+OSErr GetNthRealmMap(const int n, char *netorhost, char *realm)
+{
+ int i;
+ char *curptr;
+
+ if(n > *(short*)*fRealmMap) return cKrbMapDoesntExist;
+
+ for(curptr = (*fRealmMap) + 2, i = 1; i < n; i++) {
+ curptr = strchr(curptr, '\0') + 1;
+ curptr = strchr(curptr, '\0') + 1;
+ }
+
+ strcpy(netorhost, curptr);
+ curptr = strchr(curptr, '\0') + 1;
+ strcpy(realm, curptr);
+
+ return noErr;
+ }
+
+OSErr GetNthServer(const int n, const char *realm, const int mustadmin,
+ char *server)
+{
+ int numservers = *(short*)*fServerMap, i = 0;
+ char *currealm, *curserver;
+
+ currealm = (*fServerMap) + 2;
+ curserver = strchr(currealm, '\0') + 1 + 1;
+ for( ; numservers > 0; numservers--) {
+ if(!strcmp(currealm, realm)) {
+ if(!mustadmin || *(curserver-1)) i++;
+ if(i >= n) {
+ strcpy(server, curserver);
+ return noErr;
+ }
+ }
+
+ if(numservers > 1) {
+ currealm = strchr(curserver, '\0') + 1;
+ curserver = strchr(currealm, '\0') + 1 + 1;
+ }
+ }
+
+ return cKrbMapDoesntExist;
+ }
+
+OSErr AddServerMap(const char *realm, const char *server,
+ const int isadmin)
+{
+ int numservers;
+ char *curptr;
+
+ SetHandleSize(fServerMap, strlen(realm)+1 + 1 + strlen(server)+1 +
+ GetHandleSize(fServerMap));
+ if(MemError()) return MemError();
+
+ numservers = ++(*((short *)*fServerMap));
+
+ for(curptr = (*fServerMap)+2; numservers > 1; numservers--) {
+ curptr = strchr(curptr, '\0') + 1 + 1;
+ curptr = strchr(curptr, '\0') + 1;
+ }
+
+ strcpy(curptr, realm);
+ curptr = strchr(curptr, '\0') + 1;
+ *curptr = (char) isadmin;
+ curptr++;
+ strcpy(curptr, server);
+
+ return WriteServerMap();
+ }
+
+OSErr DeleteServerMap(const char *realm, const char *server)
+{
+ int numservers = *((short *)*fServerMap);
+ char *curptr, *fromptr, *nextptr;
+
+ for(curptr = (*fServerMap)+2; numservers > 0; numservers--) {
+ if(!strcmp(curptr, realm)) {
+ nextptr = strchr(curptr, '\0') + 1 + 1;
+ if(!strcasecmp(nextptr, server)) {
+ break; /* got it! */
+ }
+ }
+
+ curptr = strchr(curptr, '\0') + 1 + 1;
+ curptr = strchr(curptr, '\0') + 1;
+ }
+
+ if(numservers == 0) return cKrbMapDoesntExist;
+
+ *(short*)*fServerMap -= 1;
+
+ if(numservers > 1) {
+ fromptr = strchr(curptr, '\0') + 1 + 1;
+ fromptr = strchr(fromptr, '\0') + 1;
+ }
+
+ for( ; numservers > 1; numservers--) {
+ nextptr = strchr(fromptr, '\0') + 1;
+ strcpy(curptr, fromptr);
+ curptr = strchr(curptr, '\0') + 1;
+ fromptr = nextptr;
+
+ *curptr = *fromptr;
+ curptr++;
+ fromptr++;
+
+ nextptr = strchr(fromptr, '\0') + 1;
+ strcpy(curptr, fromptr);
+ curptr = strchr(curptr, '\0') + 1;
+ fromptr = nextptr;
+ }
+
+ SetHandleSize(fServerMap, curptr-(*fServerMap));
+ if(MemError()) return MemError();
+ return WriteServerMap();
+ }
+
+OSErr GetNthServerMap(const int n, char *realm, char *server, int *admin)
+{
+ int i;
+ char *curptr;
+
+ if(n > *(short*)*fServerMap) return cKrbMapDoesntExist;
+
+ for(curptr = (*fServerMap) + 2, i = 1; i < n; i++) {
+ curptr = strchr(curptr, '\0') + 1 + 1;
+ curptr = strchr(curptr, '\0') + 1;
+ }
+
+ strcpy(realm, curptr);
+ curptr = strchr(curptr, '\0') + 1;
+ *admin = *curptr;
+ curptr++;
+ strcpy(server, curptr);
+
+ return noErr;
+}
diff --git a/src/lib/krb4/mac_store.h b/src/lib/krb4/mac_store.h
new file mode 100644
index 0000000000..b1652dc556
--- /dev/null
+++ b/src/lib/krb4/mac_store.h
@@ -0,0 +1,56 @@
+/*
+ store.h
+ Kerberos credential store
+ Originally coded by Tim Miller / Brown University
+ Mods 1/92 By Peter Bosanko
+
+ Modified May 1994 by Julia Menapace and John Gilmore, Cygnus
+ Support.
+*/
+
+#include "memcache.h"
+
+extern OSErr fConstructErr;
+
+ OSErr CreatePrefFile();
+ OSErr WriteUser(); /* saves gUserName to prefs file */
+
+ /* Used internally... */
+ OSErr WritePref(short refnum, Handle dataHandle, OSType mapType, short resID,
+ Str255 resName);
+ OSErr WritePrefStr(short refnum, char *dataString, OSType mapType, short resID,
+ Str255 resName);
+
+ /*** Realm info routines: ***/
+ OSErr GetLocalRealm(char *lrealm); /* stuffs local realm in lrealm */
+ OSErr SetLocalRealm(const char *lrealm); /* sets local realm */
+
+ OSErr GetRealm(const char *host, char *realm); /* yields realm for given
+ host's net name */
+ OSErr AddRealmMap(const char *netorhost, const char *realm); /* says hosts
+ with this name or in this domain (if
+ begins with period) map to this realm
+ (provided no more specific map is
+ found) */
+ OSErr DeleteRealmMap(const char *netorhost); /* deletes realm map for the
+ net or net hostname */
+ OSErr GetNthRealmMap(const int n, char *netorhost, char *realm); /* yields
+ the Nth mapping of a net or host to
+ a kerberos realm */
+
+ OSErr GetNthServer(const int n, const char *realm, const int mustadmin,
+ char *server); /* yields Nth (administrating if
+ mustadmin is true) server for
+ the given realm */
+ OSErr AddServerMap(const char *realm, const char *server,
+ const int isadmin); /* says this server services this
+ realm (administratively if isadmin) */
+ OSErr DeleteServerMap(const char *realm, const char *server); /* deletes
+ the map of this realm to this server */
+ OSErr GetNthServerMap(const int n, char *realm, char *server, int *admin);
+ /* yields Nth realm-server mapping */
+
+ OSErr OpenPrefsFile(short *refnum); /* open (create if necessary) prefs file
+ for writing */
+ OSErr WriteRealmMap();
+ OSErr WriteServerMap();
diff --git a/src/lib/krb4/mac_stubs.c b/src/lib/krb4/mac_stubs.c
new file mode 100644
index 0000000000..b83e92d10f
--- /dev/null
+++ b/src/lib/krb4/mac_stubs.c
@@ -0,0 +1,526 @@
+/*
+ * mac_stubs.c
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Macintosh oopserating system stub interface for Kerberos.
+ * Applications call these routines, which then call the driver to do the work.
+ */
+
+#define DEFINE_SOCKADDR /* For struct hostent, <netdb.h>, etc */
+#include "krb.h"
+#include "krb_driver.h" /* Mac driver interface */
+
+#include <string.h>
+#include <stddef.h>
+#include <Files.h>
+#include <Devices.h>
+
+/* We export the driver reference under the name mac_stubs_kdriver,
+ but for convenience throughout this code, we call it "kdriver",
+ which was its name when it was static. */
+short mac_stubs_kdriver = 0; /* .Kerberos driver ref */
+#define kdriver mac_stubs_kdriver
+
+ParamBlockRec pb[1];
+struct krbHiParmBlock khipb[1];
+struct krbParmBlock klopb[1];
+
+short lowcall (long cscode, krbParmBlock *klopb, short kdriver)
+{
+ short s;
+ ParamBlockRec pb;
+
+ memset (&pb, 0, sizeof(ParamBlockRec));
+ *(long *)pb.cntrlParam.csParam = (long)klopb;
+ pb.cntrlParam.ioCompletion = nil;
+ pb.cntrlParam.ioCRefNum = kdriver;
+ pb.cntrlParam.csCode = cscode;
+
+ if (s = PBControl(&pb, false))
+ return KFAILURE;
+ if (s = pb.cntrlParam.ioResult)
+ return -(s - cKrbKerberosErrBlock); /* Restore krb err code from driver err */
+
+ return KSUCCESS;
+}
+
+
+short hicall (long cscode, krbHiParmBlock *khipb, short kdriver)
+{
+ short s;
+ ParamBlockRec pb;
+ memset(&pb, 0, sizeof(ParamBlockRec));
+ *(long *)pb.cntrlParam.csParam = (long)khipb;
+ pb.cntrlParam.ioCompletion = nil;
+ pb.cntrlParam.ioCRefNum = kdriver;
+
+ pb.cntrlParam.csCode = cscode;
+ if (s = PBControl(&pb, false))
+ return KFAILURE;
+ if (s = pb.cntrlParam.ioResult)
+ return -(s - cKrbKerberosErrBlock); /* Restore krb err code from driver err */
+
+ return KSUCCESS;
+}
+
+
+int INTERFACE
+krb_start_session (x)
+ char *x;
+{
+ short s;
+
+ /*
+ * Open the .Kerberos driver if not already open
+ */
+ if (!kdriver) {
+ s = OpenDriver("\p.Kerberos", &kdriver);
+ if (s) {
+ return KFAILURE; /* Improve this error code */
+ }
+ }
+
+ return KSUCCESS;
+}
+
+
+int INTERFACE
+krb_end_session (x)
+ char *x;
+{
+ short s;
+
+#if 0 /* This driver doesn't want to be closed. FIXME, is this OK? */
+ if (kdriver) {
+ s = CloseDriver(kdriver);
+ if (s)
+ return KFAILURE;
+ kdriver = 0;
+ }
+#endif
+ return KSUCCESS;
+}
+
+
+char * INTERFACE
+krb_realmofhost (host)
+ char *host;
+{
+ short s;
+ ParamBlockRec pb;
+ static char realm[REALM_SZ];
+
+ memset(klopb, 0, sizeof(*klopb));
+ klopb->host = host;
+ klopb->uRealm = realm;
+
+ /* FIXME jcm - no error handling for return value of lowcall in krb_realmofhost */
+ s = lowcall (cKrbGetRealm , klopb, kdriver);
+
+ return realm;
+}
+
+int INTERFACE
+krb_get_lrealm (realm, n)
+ char *realm;
+ int n;
+{
+ short s;
+ ParamBlockRec pb;
+
+ if (n != 1)
+ return KFAILURE;
+
+ memset(klopb, 0, sizeof(*klopb));
+ klopb->uRealm = realm;
+
+ s = lowcall (cKrbGetLocalRealm, klopb, kdriver);
+ return s;
+
+}
+
+
+int INTERFACE
+kname_parse (name, instance, realm, fullname)
+ char *name, *instance, *realm, *fullname;
+{
+ short s;
+ ParamBlockRec pb;
+
+ memset(klopb, 0, sizeof(*klopb));
+ klopb->uName = name;
+ klopb->uInstance = instance;
+ klopb->uRealm = realm;
+ klopb->fullname = fullname;
+
+ s = lowcall (cKrbKnameParse, klopb, kdriver);
+ return s;
+}
+
+const char* INTERFACE
+krb_get_err_text (error_code)
+ int error_code;
+{
+ short s;
+
+ memset(klopb, 0, sizeof(*klopb));
+ klopb->admin = error_code;
+ s = lowcall (cKrbGetErrText, klopb, kdriver);
+ if (s != KSUCCESS)
+ return "Error in get_err_text";
+ return klopb->uName;
+}
+
+
+int INTERFACE
+krb_get_pw_in_tkt(user,instance,realm,service,sinstance,life,password)
+ char *user, *instance, *realm, *service, *sinstance;
+ int life;
+ char *password;
+{
+ short s;
+
+ memset(klopb, 0, sizeof(*klopb));
+ klopb->uName = user;
+ klopb->uInstance = instance;
+ klopb->uRealm = realm;
+ klopb->sName = service;
+ klopb->sInstance = sinstance;
+ klopb->admin = life;
+ klopb->fullname = password;
+
+ s = lowcall (cKrbGetPwInTkt, klopb, kdriver);
+ return s;
+}
+
+
+/* FIXME: For now, we handle the preauth version exactly the same
+ as the non-preauth. */
+krb_get_pw_in_tkt_preauth(user,instance,realm,service,sinstance,life,password)
+ char *user, *instance, *realm, *service, *sinstance;
+ int life;
+ char *password;
+{
+ short s;
+
+ memset(klopb, 0, sizeof(*klopb));
+ klopb->uName = user;
+ klopb->uInstance = instance;
+ klopb->uRealm = realm;
+ klopb->sName = service;
+ klopb->sInstance = sinstance;
+ klopb->admin = life;
+ klopb->fullname = password;
+
+ s = lowcall (cKrbGetPwInTkt, klopb, kdriver);
+ return s;
+}
+
+
+
+char* INTERFACE
+krb_get_default_user (void)
+{
+ short s;
+ static char return_name[MAX_K_NAME_SZ];
+
+ memset(khipb, 0, sizeof(*khipb));
+ khipb->user = return_name;
+ s = hicall (cKrbGetUserName, khipb, kdriver);
+ if (s != KSUCCESS)
+ return 0;
+ return return_name;
+}
+
+
+int INTERFACE
+krb_set_default_user (uName)
+ char* uName;
+{
+ short s;
+
+ memset(khipb, 0, sizeof(*khipb));
+ khipb->user = uName;
+ s = hicall (cKrbSetUserName, khipb, kdriver);
+ return s;
+}
+
+int INTERFACE
+krb_get_cred (name, instance, realm, cr)
+ char *name;
+ char *instance;
+ char *realm;
+ CREDENTIALS *cr;
+{
+ short s;
+
+ memset(klopb, 0, sizeof(*klopb));
+
+ strcpy(cr->service, name);
+ strcpy(cr->instance, instance);
+ strcpy(cr->realm, realm);
+
+ klopb->cred = cr;
+
+ s = lowcall (cKrbGetCredentials, klopb, kdriver);
+ return s;
+}
+
+int INTERFACE
+krb_save_credentials (sname, sinstance, srealm, session,
+ lifetime, kvno,ticket, issue_date)
+ char *sname; /* service name */
+ char *sinstance; /* service instance */
+ char *srealm; /* service realm */
+ C_Block session; /* Session key */
+ int lifetime; /* Lifetime */
+ int kvno; /* Key version number */
+ KTEXT ticket; /* The ticket itself */
+ long issue_date; /* The issue time */
+
+{
+ short s;
+ CREDENTIALS cr;
+
+ strcpy(cr.service, sname);
+ strcpy(cr.instance, sinstance);
+ strcpy(cr.realm, srealm);
+ memcpy(cr.session, session, sizeof(C_Block));
+ cr.lifetime = lifetime;
+ cr.kvno = kvno;
+ cr.ticket_st = *ticket;
+ cr.issue_date = issue_date;
+
+ memset(klopb, 0, sizeof(*klopb));
+ klopb->cred = &cr;
+
+ s = lowcall (cKrbAddCredentials, klopb, kdriver);
+ return s;
+}
+
+
+int INTERFACE
+krb_delete_cred (sname, sinstance, srealm)
+ char *sname;
+ char *sinstance;
+ char *srealm;
+{
+ short s;
+
+ memset(klopb, 0, sizeof(*klopb));
+
+ klopb->sName = sname;
+ klopb->sInstance = sinstance;
+ klopb->sRealm = srealm;
+
+ s = lowcall (cKrbDeleteCredentials, klopb, kdriver);
+ return s;
+}
+
+int INTERFACE
+dest_tkt (cachename)
+ char *cachename; /* This parameter is ignored. */
+{
+ short s;
+
+ memset(klopb, 0, sizeof(*klopb));
+ s = lowcall (cKrbDeleteAllSessions, klopb, kdriver);
+ return s;
+}
+
+/*
+ * returns service name, service instance and realm of the nth credential.
+ * credential numbering is 1 based.
+ */
+
+int INTERFACE
+krb_get_nth_cred (sname, sinstance, srealm, n)
+ char *sname;
+ char *sinstance;
+ char *srealm;
+ int n;
+{
+ short s;
+
+ memset(klopb, 0, sizeof(*klopb));
+
+ klopb->sName = sname;
+ klopb->sInstance = sinstance;
+ klopb->sRealm = srealm;
+ klopb->itemNumber = &n;
+
+ s = lowcall (cKrbGetNthCredentials, klopb, kdriver);
+ return s;
+}
+
+/*
+ * Return the number of credentials in the current credential cache (ticket cache).
+ * On error, returns -1.
+ */
+int INTERFACE
+krb_get_num_cred ()
+{
+ int s;
+ int n;
+
+ memset(klopb, 0, sizeof(*klopb));
+ klopb->itemNumber = &n;
+
+ s = lowcall (cKrbGetNumCredentials, klopb, kdriver);
+ if (s)
+ return -1;
+ return *(klopb->itemNumber);
+}
+
+
+
+/* GetNthRealmMap
+ yields the Nth mapping of a net or host to a Kerberos realm
+ -> itemNumber which mapping, traditionally the first
+ -> host host or net
+ -> uRealm pointer to buffer that will receive realm name
+*/
+
+OSErr INTERFACE
+GetNthRealmMap(n, netorhost, realm)
+ int n;
+ char *netorhost;
+ char *realm;
+{
+ int s;
+ memset(klopb, 0, sizeof(*klopb));
+ klopb->itemNumber = &n;
+ klopb->host = netorhost;
+ klopb->uRealm = realm;
+
+ s = lowcall (cKrbGetNthRealmMap, klopb, kdriver);
+ return s;
+}
+
+/* GetNthServerMap
+ yields Nth realm-server mapping
+ -> itemNumber which mapping should be returned
+ -> uRealm pointer to buffer that will receive realm name
+ -> host pointer to buffer that will receive server name
+ -> admin pointer to admin flag
+ */
+
+OSErr INTERFACE
+GetNthServerMap(n, realm, server, admin)
+ int n;
+ char *realm;
+ char *server;
+ int *admin;
+{
+ int s;
+ memset(klopb, 0, sizeof(*klopb));
+ klopb->itemNumber = &n;
+ klopb->uRealm = realm;
+ klopb->host = server;
+ klopb->adminReturn = admin;
+
+ s = lowcall (cKrbGetNthServerMap, klopb, kdriver);
+ return s;
+}
+
+
+
+/* krb_get_ticket_for_service
+ * Gets a ticket and returns it to application in buf
+ -> service Formal Kerberos name of service
+ -> buf Buffer to receive ticket
+ -> checksum checksum for this service
+ <-> buflen length of ticket buffer (must be at least
+ 1258 bytes)
+ <- sessionKey for internal use
+ <- schedule for internal use
+
+ * Result is:
+ * GC_NOTKT if there is no matching TGT in the cache
+ * MK_AP_TGTEXP if the matching TGT is expired
+ * Other errors possible. These could cause a dialogue with the user
+ * to get a new TGT.
+ */
+
+int INTERFACE
+krb_get_ticket_for_service (serviceName, buf, buflen, checksum, sessionKey,
+ schedule, version, includeVersion)
+ char *serviceName;
+ char *buf;
+ unsigned KRB4_32 *buflen;
+ int checksum;
+ des_cblock sessionKey;
+ Key_schedule schedule;
+ char *version;
+ int includeVersion;
+{
+ short s;
+
+ if (includeVersion)
+ return KFAILURE; /* Not implmented in the kclient driver iface */
+
+ memset(khipb, 0, sizeof(*khipb));
+ khipb->service = serviceName;
+ khipb->buf = buf;
+ khipb->buflen = *buflen;
+ khipb->checksum = checksum;
+
+ s = hicall (cKrbGetTicketForService, khipb, kdriver);
+ /* These are ARRAYS in the hiparmblock, for some reason! */
+ memcpy (sessionKey, khipb->sessionKey, sizeof (khipb[0].sessionKey));
+ memcpy (schedule, khipb->schedule, sizeof (khipb[0].schedule));
+ *buflen = khipb->buflen;
+ return s;
+}
+
+
+/* krb_get_tf_fullname -- return name, instance and realm of the
+ principal in the current ticket file. The ticket file name is not
+ currently used for anything since there is only one credentials
+ cache/ticket file
+*/
+
+int INTERFACE
+krb_get_tf_fullname (tktfile, name, instance, realm)
+ char *tktfile;
+ char *name;
+ char *instance;
+ char *realm;
+
+{
+ short s;
+ memset (klopb, 0, sizeof(*klopb));
+ klopb->fullname = tktfile;
+ klopb->uName = name;
+ klopb->uInstance = instance;
+ klopb->uRealm = realm;
+
+ s = lowcall (cKrbGetTfFullname, klopb, kdriver);
+ return s;
+}
+
+
+
+#if 0
+ xbzero(khipb, sizeof(krbHiParmBlock));
+ khipb->service = (char *)cannon;
+ khipb->buf = (char *)buf; /* where to build it */
+ khipb->checksum = 0;
+ khipb->buflen = sizeof(buf);
+ if (s = hicall(cKrbGetTicketForService, khipb, kdriver))
+ return s;
+ xbcopy(khipb->sessionKey, sessionKey, sizeof(sessionKey)); /* save the session key */
+ /*
+ * cKrbGetTicketForService put a longword buffer length into the buffer
+ * which we don't want, so we ignore it.
+ * Make room for first 3 bytes which preceed the auth data.
+ */
+ cp = &buf[4-3]; /* skip long, make room for 3 bytes */
+ cp[0] = tp[0]; /* copy type and modifier */
+ cp[1] = tp[1];
+ cp[2] = KRB_AUTH; /* suboption command */
+ len = khipb->buflen - sizeof(long) + 3; /* data - 4 + 3 */
+
+#endif /* 0 */
diff --git a/src/lib/krb4/mac_time.c b/src/lib/krb4/mac_time.c
new file mode 100644
index 0000000000..91f09e5aa7
--- /dev/null
+++ b/src/lib/krb4/mac_time.c
@@ -0,0 +1,151 @@
+/*
+ * mac_time.c
+ * (Originally time_stuff.c)
+ *
+ * Copyright 1989 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Macintosh ooperating system interface for Kerberos.
+ */
+
+#include "mit-copyright.h"
+#define DEFINE_SOCKADDR /* For struct hostent, <netdb.h>, etc */
+#define NEED_TIME_H
+#include "krb.h"
+#include "des.h"
+#include "AddressXlation.h" /* for ip_addr */
+
+#include <script.h> /* Defines MachineLocation, used by getTimeZoneOffset */
+#include <ToolUtils.h> /* Defines BitTst(), called by getTimeZoneOffset() */
+#include <OSUtils.h> /* Defines GetDateTime */
+
+/* Mac Cincludes */
+#include <string.h>
+#include <stddef.h>
+
+
+ /*******************************
+ The Unix epoch is 1/1/70, the Mac epoch is 1/1/04.
+
+ 70 - 4 = 66 year differential
+
+ Thus the offset is:
+
+ (66 yrs) * (365 days/yr) * (24 hours/day) * (60 mins/hour) * (60 secs/min)
+ plus
+ (17 leap days) * (24 hours/day) * (60 mins/hour) * (60 secs/min)
+
+ Don't forget the offset from GMT.
+ *******************************/
+
+
+/* returns the offset in hours between the mac local time and the GMT */
+
+unsigned KRB_INT32
+getTimeZoneOffset()
+{
+ MachineLocation macLocation;
+ long gmtDelta;
+
+ macLocation.gmtFlags.gmtDelta=0L;
+ ReadLocation(&macLocation);
+ gmtDelta=macLocation.gmtFlags.gmtDelta & 0x00FFFFFF;
+ if (BitTst((void *)&gmtDelta,23L)) gmtDelta |= 0xFF000000;
+ gmtDelta /= 3600L;
+ return(gmtDelta);
+}
+
+
+/* Returns the GMT in seconds using the Unix epoch, ie. Net time */
+
+unsigned KRB_INT32 gettimeofdaynet_no_offset()
+{
+ time_t the_time;
+
+ GetDateTime (&the_time);
+ the_time = the_time -
+ ((66 * 365 * 24 * 60 * 60) +
+ (17 * 24 * 60 * 60) +
+ (getTimeZoneOffset() * 60 * 60));
+ return the_time;
+}
+
+
+
+int
+gettimeofdaynet (struct timeval *tp, struct timezone *tz)
+{
+ tp->tv_sec = gettimeofdaynet_no_offset();
+ return 0;
+}
+
+
+#if 0
+
+int
+gettimeofdaynet (struct timeval *tp, struct timezone *tz)
+{
+ int result;
+
+ if (!net_got_offset)
+ result = get_net_offset();
+ else result = 0;
+
+ time ((time_t *) &(tp->tv_sec));
+
+ tp->tv_sec = tp->tv_sec - (66 * 365 * 24 * 60 * 60
+ + 17 * 60 * 60 * 24) + net_offset;
+
+ return (result);
+}
+
+
+#define TIME_PORT 37
+#define TM_OFFSET 2208988800
+
+/*
+ *
+ * get_net_offset () -- Use UDP time protocol to figure out the
+ * offset between what the Mac thinks the time is an what
+ * the network thinks.
+ *
+ */
+int
+get_net_offset()
+{
+ time_t tv;
+ char buf[512],ts[256];
+ long *nettime;
+ int attempts, cc, time_port;
+ long unixtime;
+ char realm[REALM_SZ];
+ ip_addr fromaddr;
+ unsigned short fromport;
+ int result;
+
+ nettime = (long *)buf;
+ time_port = TIME_PORT;
+
+ cc = sizeof(buf);
+ result = hosts_send_recv(ts, 1, buf, &cc, "", time_port);
+ time (&tv);
+
+ if (result!=KSUCCESS || cc<4) {
+ net_offset = 0;
+ if (!result) result = 100;
+ return result;
+ }
+
+ unixtime = (long) ntohl(*nettime) - TM_OFFSET;
+
+ tv -= 66 * 365 * 24 * 60 * 60
+ + 17 * 60 * 60 * 24; /* Convert to unix time w/o offset */
+ net_offset = unixtime - tv;
+ net_got_offset = 1;
+
+ return 0;
+}
+
+#endif
diff --git a/src/lib/krb4/macsock.c b/src/lib/krb4/macsock.c
new file mode 100644
index 0000000000..e62e663470
--- /dev/null
+++ b/src/lib/krb4/macsock.c
@@ -0,0 +1,484 @@
+/*
+ * macsock.c
+ *
+ * Macintosh socket implementation using MacTCP.
+ *
+ * This only implements what's needed for Cygnus Kerberos -- a warped
+ * subset of UDP.
+ *
+ * Written by John Gilmore, Cygnus Support, June 1994.
+ * Adapted from:
+ Interface into the UDP class.
+ Written by Timothy Miller for Brown University.
+ */
+
+/* C includes */
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+/* Mac includes */
+#include <Memory.h>
+#include <Devices.h>
+#include <errno.h> /* For ENOMEM */
+
+#ifndef ENOMEM /* Think C <errno.h> doesn't have ENOMEM */
+#define ENOMEM ENOSPC
+#endif
+
+/* Our own include file */
+#include "macsock.h"
+
+/* Kerberos:source:lib:kerb - MacTCP headers from KClient */
+#include "MacTCPCommonTypes.h"
+#include "UDPPB.h"
+#include "AddressXlation.h" /* MacTCP Domain name resolver decls */
+
+/* This WinSock-ism is just too ugly to use everywhere. */
+#define SOCKET_SET_ERRNO WSASetLastError
+
+/* Description of our WinSock implementation... */
+struct WSAData macsock_data = {
+ 0x0101, /* wVersion = 1.1 */
+ 0x0101, /* wHighVersion = 1.1 */
+ "Mac Sockets implemented on top of MacTCP, by John Gilmore of\
+Cygnus Support (email info@cygnus.com).",
+ "It only implements a small subset of UDP for now.",
+ 107, /* iMaxSockets, arbitrary number */
+ UDPbuflen, /* iMaxUDPDg, max datagram size */
+ 0 /* lpVendorInfo, nonexistent */
+};
+
+/* This variable implements a kludge in which select() always says that
+ sockets are ready for I/O, but recvfrom() actually implements the
+ timeout that select() had requested. This hack happens to work
+ for Kerberos, which is all that we care about right now. */
+static struct timeval last_timeout;
+
+
+/* Forward declarations of static functions */
+
+static pascal void DNRresultproc(struct hostInfo *hinfo, char *userdata);
+
+
+/* Start using sockets */
+int
+WSAStartup(WORD wVersionRequested, WSADATA *data)
+{
+ if (LOBYTE (wVersionRequested) < 1 ||
+ (LOBYTE (wVersionRequested) == 1 && HIBYTE (wVersionRequested) < 1))
+ return WSAVERNOTSUPPORTED;
+ if (data)
+ *data = macsock_data;
+ return 0;
+}
+
+/* Finish using sockets */
+int
+WSACleanup()
+{
+ return 0;
+}
+
+/* Get a particular socket */
+SOCKET
+socket(af, type, protocol)
+ int af;
+ int type;
+ int protocol;
+{
+ SOCKET theUDP;
+ short refNum;
+ UDPiopb pb;
+ OSErr err;
+
+ if (af != AF_INET) {
+ SOCKET_SET_ERRNO (EINVAL);
+ return INVALID_SOCKET;
+ }
+ if (type != SOCK_DGRAM) {
+ SOCKET_SET_ERRNO (EINVAL);
+ return INVALID_SOCKET;
+ }
+ if (protocol != 0) {
+ SOCKET_SET_ERRNO (EINVAL);
+ return INVALID_SOCKET;
+ }
+
+ theUDP = malloc (sizeof (*theUDP));
+ if (theUDP == 0) {
+ SOCKET_SET_ERRNO (ENOMEM);
+ return INVALID_SOCKET;
+ }
+
+ err = OpenDriver( "\p.IPP", &refNum );
+ if (err) {
+ free (theUDP);
+ SOCKET_SET_ERRNO (EIO);
+ return INVALID_SOCKET;
+ }
+ theUDP->fMacTCPRef = refNum;
+
+ /* Set up param blocks and create the socket (called a
+ stream by MacTCP). */
+ pb.ioCRefNum = theUDP->fMacTCPRef;
+ pb.csCode = UDPCreate;
+ pb.csParam.create.rcvBuff = theUDP->fRecvBuf;
+ pb.csParam.create.rcvBuffLen = UDPbuflen;
+ pb.csParam.create.notifyProc = NULL;
+ pb.csParam.create.localPort = 0;
+
+ err = PBControl( (ParamBlockRec *) &pb, false );
+ if (err) {
+ free (theUDP);
+ SOCKET_SET_ERRNO (EIO);
+ return INVALID_SOCKET;
+ }
+ theUDP->fStream = (unsigned long)pb.udpStream;
+
+ return theUDP;
+}
+
+/* Finish using a particular socket. */
+int
+closesocket (theUDP)
+ SOCKET theUDP;
+{
+ UDPiopb pb;
+
+ if (theUDP->fStream) {
+ pb.ioCRefNum = theUDP->fMacTCPRef;
+ pb.csCode = UDPRelease;
+ pb.udpStream = (StreamPtr) theUDP->fStream;
+
+ (void) PBControl( (ParamBlockRec *) &pb, false );
+ }
+
+ free(theUDP);
+ return 0;
+}
+
+
+/* Bind a socket to a particular address.
+ In our case, this is just a no-op for bug-compatability with
+ the FTP Software WINSOCK library. */
+int
+bind (s, name, namelen)
+ SOCKET s;
+ const struct sockaddr *name;
+ int namelen;
+{
+ if (name->sin_family != AF_INET) {
+ SOCKET_SET_ERRNO (EINVAL);
+ return SOCKET_ERROR;
+ }
+#if 0
+ if (namelen != sizeof (struct sockaddr_in)) {
+ SOCKET_SET_ERRNO (EINVAL);
+ return SOCKET_ERROR;
+ }
+ if (name->sin_addr.s_addr != INADDR_ANY) {
+ SOCKET_SET_ERRNO (EINVAL);
+ return SOCKET_ERROR;
+ }
+#endif
+ /* OK, then, it's a no-op. */
+ s - s; /* lint */
+ return 0;
+}
+
+
+/* Send a packet to a UDP peer. */
+int
+sendto (theUDP, buf, len, flags, to_param, tolen)
+ SOCKET theUDP;
+ const char *buf;
+ const int len;
+ int flags;
+ const struct sockaddr *to_param;
+ int tolen;
+{
+ OSErr err;
+ /* really 1 wds + extra space for terminating null */
+ wdsEntry wds[2];
+ UDPiopb pb;
+ struct sockaddr_in *to = (struct sockaddr_in *)to_param;
+
+ if (tolen != sizeof (struct sockaddr_in)) {
+ SOCKET_SET_ERRNO (EINVAL);
+ return SOCKET_ERROR;
+ }
+ if (to->sin_family != AF_INET) {
+ SOCKET_SET_ERRNO (EINVAL);
+ return SOCKET_ERROR;
+ }
+
+ wds[0].length = len;
+ wds[0].ptr = (char *) buf;
+ wds[1].length = 0;
+
+ pb.ioCRefNum = theUDP->fMacTCPRef;
+ pb.csCode = UDPWrite;
+ pb.udpStream = (StreamPtr) theUDP->fStream;
+ pb.csParam.send.remotePort = to->sin_port;
+ pb.csParam.send.wdsPtr = (Ptr) wds;
+ pb.csParam.send.checkSum = 1; // TRUE
+ pb.csParam.send.sendLength = 0; // reserved
+ pb.csParam.send.remoteHost = to->sin_addr.s_addr;
+
+ err = PBControl( (ParamBlockRec *) &pb, false );
+ if (err != noErr) {
+ SOCKET_SET_ERRNO (EIO);
+ return SOCKET_ERROR;
+ }
+ return len;
+}
+
+/* Select for sockets that are ready for I/O.
+ This version just remembers the timeout for a future receive...
+ It always reports that one socket is ready for I/O.
+ */
+int
+select (nfds, readfds, writefds, exceptfds, timeout)
+ int nfds;
+ fd_set *readfds;
+ fd_set *writefds;
+ fd_set *exceptfds;
+ const struct timeval *timeout;
+{
+ if (timeout)
+ last_timeout = *timeout;
+ return 1; /* Claim that a single FD is ready */
+ /* Note that readfd, writefds, and exceptfds still have all
+ of their current values, indicating that they're all ready
+ for I/O. */
+}
+
+
+/* Receive a packet from a UDP peer. */
+int
+recvfrom (theUDP, buf, len, flags, from_param, fromlen)
+ SOCKET theUDP;
+ char *buf;
+ int len;
+ int flags;
+ struct sockaddr *from_param;
+ int *fromlen;
+{
+ OSErr err;
+ UDPiopb pb;
+ int packet_len;
+ struct sockaddr_in *from = (struct sockaddr_in *)from_param;
+
+ if (*fromlen < sizeof (*from)) {
+ SOCKET_SET_ERRNO (EINVAL);
+ return SOCKET_ERROR;
+ }
+
+ pb.ioCRefNum = theUDP->fMacTCPRef;
+ pb.csCode = UDPRead;
+ pb.udpStream = (StreamPtr) theUDP->fStream;
+ pb.csParam.receive.timeOut = last_timeout.tv_sec;
+ pb.csParam.receive.secondTimeStamp = 0; // reserved
+
+ err = PBControl( (ParamBlockRec *) &pb, false );
+ if( err ) {
+ SOCKET_SET_ERRNO (EIO);
+ return SOCKET_ERROR;
+ }
+
+ packet_len = pb.csParam.receive.rcvBuffLen;
+ if( len > packet_len )
+ len = packet_len; /* only move as much as we got */
+ BlockMove( pb.csParam.receive.rcvBuff, buf, len );
+ *fromlen = sizeof (*from);
+ from->sin_family = AF_INET;
+ from->sin_port = pb.csParam.receive.remotePort;
+ from->sin_addr.s_addr = pb.csParam.receive.remoteHost;
+
+ if( pb.csParam.receive.rcvBuffLen ) {
+ pb.csCode = UDPBfrReturn;
+ err = PBControl( (ParamBlockRec *) &pb, false );
+ }
+
+ if (len < packet_len) {
+ /* Only got first part of packet, rest was dropped. */
+ SOCKET_SET_ERRNO (EMSGSIZE);
+ return SOCKET_ERROR;
+ }
+ return len;
+}
+
+
+
+/*
+ Interface UNIX routine inet_ntoa with mac equivalent.
+
+ The input argument is a struct containing the internet address.
+ struct type defined in config-mac.h
+
+ The routine inet_ntoa() returns a pointer to a string in the
+ base 256 notation ``d.d.d.d''
+*/
+
+
+char*
+inet_ntoa(struct in_addr ina) {
+ OSErr err;
+#define max_addr_str 16
+ char addrStr[max_addr_str];
+
+ err = AddrToStr(ina.s_addr, addrStr);
+ return addrStr;
+
+}
+
+/* Static variables which provide space for the last result from getXbyY. */
+
+static struct hostInfo host;
+static char * ipaddr_ptrs[NUM_ALT_ADDRS+1];
+static struct hostent result;
+
+/*
+ Performs a domain name resolution of host, returning an IP address for it,
+ or 0 if any error occurred.
+
+ FIXME -- this routine has the potential to go asynchronous, but it
+ loops until the asynchronous call to MacTCP finishes.
+ */
+
+struct hostent *
+gethostbyname (char *hostname)
+{
+ OSErr err;
+ char done = false;
+ int i;
+
+ if (err = OpenResolver(NULL))
+ return(0); // make sure resolver is open
+ err = StrToAddr(hostname, &host, DNRresultproc, &done);
+
+ if (err == cacheFault) {
+ while(!done) ; /* LOOP UNTIL CALLBACK IS RUN */
+ err = host.rtnCode; /* Pick up final result code */
+ }
+
+ if (err != noErr) {
+ return 0;
+ }
+
+ /* Build result in hostent structure, which we will return to caller. */
+
+ result.h_name = host.cname;
+ result.h_aliases = 0; /* We don't know about aliases. */
+ result.h_addrtype = AF_INET;
+ result.h_length = sizeof (host.addr[0]); /* Length of each address */
+ result.h_addr_list = ipaddr_ptrs;
+ for (i = 0; i < NUM_ALT_ADDRS; i++)
+ if (host.addr[i] != 0) /* Assume addrs terminated with 0 addr */
+ ipaddr_ptrs[i] = (char*) &host.addr[i]; /* Point at good IP addresses */
+ else
+ break; /* Quit when we see first zero address */
+ ipaddr_ptrs[i] = 0;
+
+ return &result;
+}
+
+/* Does a reverse DNS lookup of addr, to find the canonical name of its host.
+ FIXME, set errno for failures. */
+
+struct hostent *
+gethostbyaddr (char *addr, int len, int type)
+{
+ OSErr err;
+ char done = false;
+ ip_addr macaddr;
+
+ if (type != AF_INET)
+ return 0; /* We only do Internet addresses */
+ if (len != sizeof (ip_addr))
+ return 0; /* We only handle IP addrs *this* long... */
+ memcpy ((void *)&macaddr, (void *)addr, (size_t)len);
+
+ if (err = OpenResolver(NULL))
+ return 0; // make sure resolver is open
+ err = AddrToName(macaddr, &host, DNRresultproc, &done);
+
+ if (err == cacheFault) {
+ while(!done) ; /* LOOP UNTIL CALLBACK IS RUN */
+ err = host.rtnCode; /* Pick up final result code */
+ }
+
+ if (err != noErr) {
+ /* Set errno? FIXME. */
+ return 0;
+ }
+
+ /* Build result in hostent structure, which we will return to caller. */
+
+ result.h_name = host.cname;
+ result.h_aliases = 0; /* We don't know about aliases. */
+ result.h_addrtype = AF_INET;
+ result.h_length = sizeof (host.addr[0]); /* Length of each address */
+ result.h_addr_list = 0; /* MacTCP doesn't give us this info on addr->name */
+
+ return &result;
+}
+
+/* Tell calling program that the asynchronous operation has finished.
+ FIXME, this will require significant work if we support async calls to
+ Kerberos in the future. */
+static pascal void
+DNRresultproc(struct hostInfo *hinfo, char *userdata)
+{
+ *userdata = true;
+}
+
+#if 0
+/* FIXME: THIS WAS A STAB AT GETHOSTNAME, which I abandoned for lack of need,
+ and since the required header files didn't seem to be handy.
+ -- gnu@cygnus.com june94 */
+/*
+ * gethostname
+ *
+ * Gets our own host name, by getting our IP address and asking what name
+ * corresponds. There seems to be no better way in MacTCP to do this.
+ */
+ int
+ gethostname(name, namelen)
+ char *name;
+ int namelen;
+{
+ ip_addr ourAddress;
+ SOCKET sock;
+ struct IPParamBlock pb;
+ struct hostent *host;
+ struct sockaddr_in hostaddr;
+
+ sock = socket (AF_INET, SOCK_DGRAM, 0);
+ if (!sock)
+ return -1;
+ pb.ioCRefNum = sock->fMacTCPRef;
+ pb.csCode = ipctlGetAddr;
+ err = PBControl( (ParamBlockRec *) &pb, false );
+ if (err) {
+ free (theUDP);
+ SOCKET_SET_ERRNO (EIO);
+ return -1;
+ }
+
+
+ pb.csParam.xxxx
+
+ host = gethostbyaddr (&hostaddr, sizeof (hostaddr), AF_INET);
+ if (!host)
+ return -1;
+ len = strlen (host->h_name);
+ if (len > namelen)
+ return -1;
+ memcpy (name, host->h_name, len+1);
+ return 0;
+}
+
+#endif
diff --git a/src/lib/krb4/memcache.c b/src/lib/krb4/memcache.c
new file mode 100644
index 0000000000..3e622eb10c
--- /dev/null
+++ b/src/lib/krb4/memcache.c
@@ -0,0 +1,867 @@
+/*
+ * memcache.c
+ *
+ * Kerberos credential cache
+ * Originally coded by Tim Miller / Brown University as KRB_Store.c
+ * Mods 1/92 By Peter Bosanko
+ *
+ * Modified May-June 1994 by Julia Menapace and John Gilmore
+ * of Cygnus Support.
+ *
+ * This file incorporates replacements for the Unix files
+ * in_tkt.c, dest_tkt.c, tf_util.c, and tkt_string.c.
+ */
+
+#ifdef _WINDOWS
+#include <windows.h>
+#include <malloc.h> /* REQUIRED for near/far declarations */
+#endif
+
+#ifndef unix
+#ifdef _AIX
+#define unix
+#endif
+#endif
+
+#ifdef unix
+
+/* Unix interface to memory cache Mac functions. */
+
+#include <stdio.h>
+#include <errno.h>
+#ifdef POSIX
+#include <stdlib.h>
+#else
+extern char *malloc (), *realloc ();
+#endif
+
+#define _nmalloc malloc
+#define _nfree free
+#define _nrealloc realloc
+#define NPSTR char *
+#define OFFSETOF(x) x
+
+typedef int OSErr;
+#define noErr 0
+#define memFullErr ENOMEM
+
+#endif /* unix */
+
+#include "krb.h"
+#include "memcache.h"
+
+/* Lower level data structures */
+
+static int fNumSessions = 0;
+static Session **fSessions = 0;
+
+#ifndef _WINDOWS
+#define change_cache()
+#endif
+
+#if defined (_WINDOWS) || defined (unix)
+/* Fake Mac handles up for general use. */
+#define Handle char **
+#define Size int
+
+static OSErr memerror = noErr;
+
+/*
+ * Simulates Macintosh routine by allocating a block of memory
+ * and a pointer to that block of memory. If the requested block
+ * size is 0, then we just allocate the indirect pointer and 0
+ * it, otherwise we allocate an indirect pointer and place a pointer
+ * to the actual allocated block in the indirect pointer location.
+ */
+Handle
+NewHandleSys(s)
+ int s;
+{
+ Handle h;
+
+ h = (char **) _nmalloc(sizeof(char *));
+
+ if (h == NULL) {
+ memerror = memFullErr;
+ return (NULL);
+ }
+
+ if (s > 0) {
+ *h = _nmalloc(s);
+
+ if (*h == NULL) {
+ _nfree((NPSTR) OFFSETOF(h));
+ memerror = memFullErr;
+ return (NULL);
+ }
+ }
+ else
+ *h = NULL;
+
+ memerror = noErr;
+
+ return h;
+}
+
+/*
+ * Frees allocated indirect pointer and the block of memory it points
+ * to. If the indirect pointer is NULL, then the block is considered
+ * to have 0 length.
+ */
+void
+DisposHandle(h)
+ Handle h;
+{
+ if (*h != NULL)
+ _nfree((NPSTR) OFFSETOF(*h));
+
+ _nfree((NPSTR) OFFSETOF(h));
+}
+
+/*
+ * Resizes a block of memory pointed to by and indirect pointer. The
+ * indirect pointer is updated when the block of memory is reallocated.
+ * If the indirect pointer is 0, then the block of memory is allocated
+ * rather than reallocated. If the size requested is 0, then the block
+ * is deallcated rather than reallocated.
+ */
+void
+SetHandleSize(h, s)
+ Handle h;
+ int s;
+{
+ if (*h != NULL) {
+ if (s > 0) {
+ *h = _nrealloc((NPSTR) OFFSETOF(*h), s);
+
+ if (*h == NULL) {
+ memerror = memFullErr;
+ return;
+ }
+ }
+ else {
+ _nfree((NPSTR) OFFSETOF(*h));
+ *h = NULL;
+ }
+ }
+
+ else {
+ if (s > 0) {
+ *h = _nmalloc(s);
+
+ if (*h == NULL) {
+ memerror = memFullErr;
+ return;
+ }
+ }
+ }
+
+ memerror = noErr;
+}
+
+OSErr
+MemError()
+{
+ return memerror;
+}
+
+#endif /* Windows || unix */
+
+#ifdef _WINDOWS
+
+/*
+ * change_cache should be called after the cache changes.
+ * If the session count is > 0 it forces the DLL to stay in
+ * memory even after the calling program exits providing cross
+ * session ticket cacheing. Also a notification message is
+ * is posted out to all top level Windows so that they may
+ * recheck the cache based on the changes made. The
+ * krb_get_notifcation_message routine will return the
+ * current notificaiton message for the system which an
+ * application can expect to get.
+ */
+void
+change_cache()
+{
+ char fname[260];
+ static BOOL locked = FALSE;
+
+ if (fNumSessions > 0 && !locked) {
+ GetModuleFileName(get_lib_instance(), fname, sizeof(fname));
+ LoadLibrary(fname);
+ locked = TRUE;
+ }
+
+ else if (fNumSessions == 0 && locked) {
+ FreeLibrary(get_lib_instance());
+ locked = FALSE;
+ }
+
+ SendMessage(HWND_BROADCAST, krb_get_notification_message(), 0, 0);
+}
+
+
+/*
+ * Returns a system wide unique notification message. This
+ * message will be broadcast to all top level windows when
+ * the credential cache changes.
+ */
+unsigned int INTERFACE
+krb_get_notification_message(void)
+{
+ static UINT message = 0;
+
+ if (message == 0)
+ message = RegisterWindowMessage(WM_KERBEROS_CHANGED);
+
+ return message;
+}
+
+
+#endif /* Windows */
+
+
+#include "krb_driver.h"
+
+/* The low level routines in this file are capable of storing
+ tickets for multiple "sessions", each led by a different
+ ticket-granting ticket. For now, since the top level code
+ doesn't know how to handle that, we are short-cutting all
+ that with a fixed top level identifying tag for the (one)
+ session supported.
+
+ FIXME jcm - Force one named cache for now for compatibility with
+ Cygnus source tree. Figure out later how to access the multiple
+ cache functionality in KClient.
+ */
+
+char uname[] = "Fixed User";
+char uinstance[] = "Fixed Instance";
+char urealm[] = "Fixed Realm";
+
+static char curr_auth_uname [ANAME_SZ];
+static char curr_auth_uinst [INST_SZ];
+
+
+/*
+ in_tkt() is used to initialize the ticket cache.
+ It inits the driver's credentials storage, by deleting any tickets.
+ in_tkt() returns KSUCCESS on success, or KFAILURE if something goes wrong.
+
+ User name, instance and realm are not currently being stored in
+ the credentials cache because currently we are forcing a single
+ named cache by using a fixed user name,inst,and realm in the
+ memcache accessor routines.
+
+ FIXME jcm - needed while stubbing out multi-caching with fixed
+ user etc... Store currently authenticated user name and instance
+ in this file. We will use this information to fill out the p_user
+ and p_inst fields in the credential.
+
+ FIXME jcm - more kludges: make sure default user name matches the
+ current credentials cache. Telnet asks for default user name. It
+ may have last been set to another user name programmatically or
+ via ResEdit.
+
+ */
+int INTERFACE
+in_tkt(pname,pinst)
+ char *pname;
+ char *pinst;
+{
+ int retval;
+
+ strncpy (curr_auth_uname, pname, ANAME_SZ);
+ strncpy (curr_auth_uinst, pinst, INST_SZ);
+
+ krb_set_default_user (pname);
+
+ retval = dest_tkt();
+ if (!retval)
+ return retval;
+ else
+ return KSUCCESS;
+
+}
+
+/*
+ * dest_tkt() is used to destroy the ticket store upon logout.
+ * If the ticket file does not exist, dest_tkt() returns RET_TKFIL.
+ * Otherwise the function returns RET_OK on success, KFAILURE on
+ * failure.
+ *
+ */
+int INTERFACE
+dest_tkt()
+{
+ /*
+ FIXME jcm - Force one named cache for now for
+ compatibility with Cygnus source tree. Figure out
+ later how to access the multiple cache functionality in
+ KClient.
+ */
+ OSErr err;
+
+ err = DeleteSession(uname, uinstance, urealm);
+
+ change_cache();
+
+ switch(err) {
+ case noErr:
+ return RET_OK;
+ case cKrbSessDoesntExist:
+ return RET_TKFIL;
+ default:
+ return KFAILURE;
+ }
+ }
+
+
+int dest_all_tkts()
+{
+ int i=0;
+ char name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
+ int ndeletes=0;
+ int err=0;
+
+ (void) GetNumSessions(&i);
+ if(!i) return RET_TKFIL;
+
+ for( ; i; i--) {
+ if(!GetNthSession(i, name, inst, realm)) {
+ if (err = DeleteSession(name, inst, realm))
+ break;
+ ndeletes++;
+ }
+ else {
+ err = KFAILURE;
+ break;
+ }
+ }
+
+ if (ndeletes > 0)
+ change_cache();
+
+ if (err)
+ return KFAILURE;
+ else
+ return KSUCCESS;
+ }
+
+
+/* krb_get_tf_realm -- return the realm of the current ticket file. */
+int
+krb_get_tf_realm (tktfile, lrealm)
+ char *tktfile;
+ char *lrealm; /* Result stored through here */
+{
+
+ return krb_get_tf_fullname(tktfile, (char*) 0, (char*) 0 , lrealm);
+}
+
+
+/* krb_get_tf_fullname -- return name, instance and realm of the
+principal in the current ticket file. */
+int INTERFACE
+krb_get_tf_fullname (tktfile, name, instance, realm)
+ char *tktfile;
+ char *name;
+ char *instance;
+ char *realm;
+
+{
+ OSErr err;
+
+/*
+ Explaining this ugly hack:
+ uname, uinstance, and urealm in the session record are "fixed"
+ to short circuit multicache functionality, yielding only one
+ session/cache for all cases. This was done under protest to remain
+ API compatable with UNIX. The principal's and service realm are
+ always the same and are stored in the same field of the credential.
+ Principal's name and instance are stored neither in the session
+ record or the credentials cache but in the file static variables
+ curr_auth_uname, and curr_auth_uinst as set by in_tkt from its
+ arguments pname and pinst.
+
+ FIXME for multiple sessions -- keep track of which one is
+ the "current" session, as picked by the user. tktfile not
+ used for anything right now...
+*/
+
+ err = GetNthCredentials(uname, uinstance, urealm, name,
+ instance, realm, 1);
+
+ if (err != noErr)
+ return NO_TKT_FIL;
+
+ if (name)
+ strcpy(name, curr_auth_uname);
+ if (instance)
+ strcpy(instance, curr_auth_uinst);
+
+ return KSUCCESS;
+
+}
+
+
+/*
+ * krb_get_cred takes a service name, instance, and realm, and a
+ * structure of type CREDENTIALS to be filled in with ticket
+ * information. It then searches the ticket file for the appropriate
+ * ticket and fills in the structure with the corresponding
+ * information from the file. If successful, it returns KSUCCESS.
+ * On failure it returns a Kerberos error code.
+ */
+int INTERFACE
+krb_get_cred (service, instance, realm, c)
+ char *service; /* Service name */
+ char *instance; /* Instance */
+ char *realm; /* Authorization domain */
+ CREDENTIALS *c; /* Credentials struct */
+{
+ strcpy(c->service, service);
+ strcpy(c->instance, instance);
+ strcpy(c->realm, realm);
+
+ /*
+ FIXME jcm - Force one named cache for now for
+ compatibility with Cygnus source tree. Figure out
+ later how to access the multiple cache functionality
+ from KClient.
+ */
+
+ switch(GetCredentials(uname, uinstance, urealm, c)) {
+ case noErr:
+ return KSUCCESS;
+ case cKrbCredsDontExist:
+ case cKrbSessDoesntExist:
+ return GC_NOTKT;
+ default:
+ return KFAILURE;
+ }
+}
+
+/*
+ * This routine takes a ticket and associated info and
+ * stores them in the ticket cache. The peer
+ * routine for extracting a ticket and associated info from the
+ * ticket cache is krb_get_cred(). When changes are made to
+ * this routine, the corresponding changes should be made
+ * in krb_get_cred() as well.
+ *
+ * Returns KSUCCESS if all goes well, otherwise KFAILURE.
+ */
+
+int INTERFACE
+krb_save_credentials(sname, sinst, srealm, session,
+ lifetime, kvno, ticket, issue_date)
+
+ char* sname; /* Service name */
+ char* sinst; /* Instance */
+ char* srealm; /* Auth domain */
+ C_Block session; /* Session key */
+ int lifetime; /* Lifetime */
+ int kvno; /* Key version number */
+ KTEXT ticket; /* The ticket itself */
+ long issue_date; /* The issue time */
+{
+ CREDENTIALS cr;
+
+ strcpy(cr.service, sname);
+ strcpy(cr.instance, sinst);
+ strcpy(cr.realm, srealm);
+ memcpy((void*)cr.session, (void*)session, sizeof(C_Block));
+ cr.lifetime = lifetime;
+ cr.kvno = kvno;
+ cr.ticket_st = *ticket;
+ cr.issue_date = issue_date;
+ strcpy(cr.pname, curr_auth_uname); /* FIXME for mult sessions */
+ strcpy(cr.pinst, curr_auth_uinst); /* FIXME for mult sessions */
+
+ if(AddCredentials(uname, uinstance, urealm, &cr)) return KFAILURE;
+ change_cache();
+ return KSUCCESS;
+}
+
+int INTERFACE
+krb_delete_cred (sname, sinstance, srealm)
+ char *sname;
+ char *sinstance;
+ char *srealm;
+{
+
+ if (DeleteCredentials (uname, uinstance, urealm, sname, sinstance, srealm))
+ return KFAILURE;
+
+ change_cache();
+
+ return KSUCCESS;
+
+ /*
+ FIXME jcm - translate better between KClient internal OSErr errors
+ (eg. cKrbCredsDontExist) and kerberos error codes (eg. GC_NOTKT)
+ */
+}
+
+int INTERFACE
+krb_get_nth_cred (sname, sinstance, srealm, n)
+ char *sname;
+ char *sinstance;
+ char *srealm;
+ int n;
+{
+ if (GetNthCredentials(uname, uinstance, urealm, sname, sinstance, srealm, n))
+ return KFAILURE;
+ else
+ return KSUCCESS;
+}
+
+/*
+ * Return the number of credentials in the current credential cache (ticket cache).
+ * On error, returns -1.
+ */
+int INTERFACE
+krb_get_num_cred ()
+{
+ int n;
+ int s;
+
+ s = GetNumCredentials(uname, uinstance, urealm, &n);
+ if (s) return -1;
+ else return n;
+}
+
+
+
+/* Lower level routines */
+
+OSErr GetNumSessions(n)
+ int *n;
+{
+ *n = fNumSessions;
+ return 0;
+ }
+
+/* n starts at 1, not 0 */
+OSErr
+GetNthSession(n, name, instance, realm)
+ const int n;
+ char *name;
+ char *instance;
+ char *realm;
+{
+ Session *sptr;
+
+ if(n > fNumSessions || !fSessions) return cKrbSessDoesntExist;
+
+ sptr = (*fSessions) + n-1;
+ if (name) strcpy(name, sptr->name);
+ if (instance) strcpy(instance, sptr->instance);
+ if (realm) strcpy(realm, sptr->realm);
+
+ return noErr;
+ }
+
+OSErr DeleteSession(name, instance, realm)
+ const char *name;
+ const char *instance;
+ const char *realm;
+{
+ int i;
+ Session *sptr;
+ Handle creds;
+
+ if(!fNumSessions || !fSessions) return cKrbSessDoesntExist;
+
+ sptr = *fSessions;
+
+ for(i = 0; i < fNumSessions; i++) {
+ if(!strcmp(sptr[i].name, name) &&
+ !strcmp(sptr[i].instance, instance) &&
+ !strcmp(sptr[i].realm, realm)) {
+ break;
+ }
+ }
+
+ if(i == fNumSessions) return cKrbSessDoesntExist;
+
+ fNumSessions--;
+
+ creds = (Handle) sptr[i].creds;
+
+ for( ; i < fNumSessions; i++) {
+ strcpy(sptr[i].name, sptr[i+1].name);
+ strcpy(sptr[i].instance, sptr[i+1].instance);
+ strcpy(sptr[i].realm, sptr[i+1].realm);
+ }
+
+ SetHandleSize((Handle) fSessions, fNumSessions * sizeof(Session));
+ if(creds) DisposHandle(creds);
+
+ return MemError();
+ }
+
+OSErr GetCredentials(name, instance, realm, cr)
+ const char *name;
+ const char *instance;
+ const char *realm;
+ CREDENTIALS *cr;
+{
+ int i;
+ Session *sptr;
+ CREDENTIALS *cptr;
+
+ if(!fNumSessions || !fSessions) return cKrbSessDoesntExist;
+
+ sptr = *fSessions;
+
+ for(i = 0; i < fNumSessions; i++) {
+ if(!strcmp(sptr[i].name, name) &&
+ !strcmp(sptr[i].instance, instance) &&
+ !strcmp(sptr[i].realm, realm)) {
+ break;
+ }
+ }
+
+ if(i == fNumSessions) return cKrbSessDoesntExist;
+
+ sptr = sptr + i;
+
+ if(!sptr->numcreds || !sptr->creds) return cKrbCredsDontExist;
+
+ cptr = *(sptr->creds);
+
+ for(i = 0; i < sptr->numcreds; i++) {
+ if(!strcmp(cptr[i].service, cr->service) &&
+ !strcmp(cptr[i].instance, cr->instance) &&
+ !strcmp(cptr[i].realm, cr->realm)) {
+ break;
+ }
+ }
+
+ if(i == sptr->numcreds) return cKrbCredsDontExist;
+
+ *cr = cptr[i];
+ return noErr;
+ }
+
+OSErr AddCredentials(name, instance, realm, cr)
+ const char *name;
+ const char *instance;
+ const char *realm;
+ const CREDENTIALS *cr;
+{
+ Session *sptr;
+ Handle creds;
+ int i, thesess;
+ CREDENTIALS *cptr;
+
+ /* find the appropriate session, or create it if it doesn't exist */
+ if(!fSessions) {
+ fSessions = (Session**) NewHandleSys(0);
+ if(MemError()) return MemError();
+ fNumSessions = 0;
+ }
+
+ sptr = *fSessions;
+
+ for(thesess = 0; thesess < fNumSessions; thesess++) {
+ if(!strcmp(sptr[thesess].name, name) &&
+ !strcmp(sptr[thesess].instance, instance) &&
+ !strcmp(sptr[thesess].realm, realm)) {
+ break;
+ }
+ }
+
+ sptr = (*fSessions) + thesess;
+
+ if(thesess == fNumSessions) { /* doesn't exist, create it */
+ fNumSessions++;
+ SetHandleSize((Handle) fSessions, fNumSessions * sizeof(Session));
+ if(MemError()) return MemError();
+
+ /* fSessions may have been moved, so redereference */
+ sptr = (*fSessions) + thesess;
+ strcpy(sptr->name, (char *)name);
+ strcpy(sptr->instance, (char *)instance);
+ strcpy(sptr->realm, (char *)realm);
+ sptr->numcreds = 0;
+ sptr->creds = 0;
+ }
+
+ /* if the session has no assoc creds, create storage for them so rest of algorithm
+ doesn't break */
+ if(!sptr->numcreds || !sptr->creds) {
+ creds = NewHandleSys((Size) 0);
+ if(MemError()) return MemError();
+
+ /* rederef */
+ sptr = (*fSessions) + thesess;
+ sptr->creds = (CREDENTIALS **)creds;
+ sptr->numcreds = 0;
+ }
+
+ /* find creds if we already have an instance of them, or create a new slot for them
+ if we don't */
+ cptr = *(sptr->creds);
+
+ for(i = 0; i < sptr->numcreds; i++) {
+ if(!strcmp(cptr[i].service, cr->service) &&
+ !strcmp(cptr[i].instance, cr->instance) &&
+ !strcmp(cptr[i].realm, cr->realm)) {
+ break;
+ }
+ }
+
+ if(i == sptr->numcreds) {
+ sptr->numcreds++;
+ SetHandleSize((Handle)sptr->creds, sptr->numcreds * sizeof(CREDENTIALS));
+ if(MemError()) return MemError();
+
+ /* rederef */
+ sptr = (*fSessions) + thesess;
+ cptr = *(sptr->creds);
+ }
+
+ /* store them (possibly replacing previous creds if they already exist) */
+ cptr[i] = *cr;
+ return noErr;
+ }
+
+OSErr
+DeleteCredentials (uname, uinst, urealm, sname, sinst, srealm)
+ const char *uname;
+ const char *uinst;
+ const char *urealm;
+ const char *sname;
+ const char *sinst;
+ const char *srealm;
+{
+ int i;
+ Session *sptr;
+ CREDENTIALS *cptr;
+
+ if(!fNumSessions || !fSessions) return cKrbSessDoesntExist;
+
+ sptr = *fSessions;
+
+ for(i = 0; i < fNumSessions; i++) {
+ if(!strcmp(sptr[i].name, uname) &&
+ !strcmp(sptr[i].instance, uinstance) &&
+ !strcmp(sptr[i].realm, urealm)) {
+ break;
+ }
+ }
+
+ if(i == fNumSessions) return cKrbSessDoesntExist;
+
+ sptr = sptr + i;
+
+ if(!sptr->numcreds || !sptr->creds) return cKrbCredsDontExist;
+
+ cptr = *(sptr->creds);
+
+ for(i = 0; i < sptr->numcreds; i++) {
+ if(!strcmp(cptr[i].service, sname) &&
+ !strcmp(cptr[i].instance, sinst) &&
+ !strcmp(cptr[i].realm, srealm)) {
+ break;
+ }
+ }
+
+ if(i == sptr->numcreds) return cKrbCredsDontExist;
+
+ sptr->numcreds--;
+
+ for( ; i < sptr->numcreds; i++) {
+ cptr[i] = cptr[i+1];
+ }
+
+ SetHandleSize((Handle) sptr->creds, sptr->numcreds * sizeof(CREDENTIALS));
+
+ return MemError();
+ }
+
+OSErr GetNumCredentials(name, instance, realm, n)
+ const char *name;
+ const char *instance;
+ const char *realm;
+ int *n;
+{
+ int i;
+ Session *sptr;
+
+ if(!fNumSessions || !fSessions) {
+ *n = 0;
+ return cKrbSessDoesntExist;
+ }
+
+ sptr = *fSessions;
+
+ for(i = 0; i < fNumSessions; i++) {
+ if(!strcmp(sptr[i].name, name) &&
+ !strcmp(sptr[i].instance, instance) &&
+ !strcmp(sptr[i].realm, realm)) {
+ break;
+ }
+ }
+
+ if(i == fNumSessions) {
+ *n = 0;
+ return cKrbCredsDontExist;
+ }
+
+ *n = sptr[i].numcreds;
+ return noErr;
+ }
+
+/* returns service name, service instance and realm of the nth credential. */
+/* n starts at 1, not 0 */
+OSErr
+GetNthCredentials(uname, uinstance, urealm, sname, sinst, srealm, n)
+ const char *uname;
+ const char *uinstance;
+ const char *urealm;
+ char *sname;
+ char *sinst;
+ char *srealm;
+ const int n;
+{
+ int i;
+ Session *sptr;
+ CREDENTIALS *cptr;
+
+ if(!fNumSessions || !fSessions) return cKrbSessDoesntExist;
+
+ sptr = *fSessions;
+
+ for(i = 0; i < fNumSessions; i++) {
+ if(!strcmp(sptr[i].name, uname) &&
+ !strcmp(sptr[i].instance, uinstance) &&
+ !strcmp(sptr[i].realm, urealm)) {
+ break;
+ }
+ }
+
+ if(i == fNumSessions) return cKrbSessDoesntExist;
+
+ sptr = (*fSessions) + i;
+
+ if(n > sptr->numcreds || !sptr->creds) return cKrbCredsDontExist;
+
+ cptr = (*(sptr->creds)) + n-1;
+
+ /*
+ check for null pointers cuz. some callers don't provide
+ storage for all this info, eg. Kerb_get_tf_fullname.
+ */
+
+ if (sname)
+ strcpy(sname, cptr->service);
+ if (sinst)
+ strcpy(sinst, cptr->instance);
+ if (srealm)
+ strcpy(srealm, cptr->realm);
+ return noErr;
+}
diff --git a/src/lib/krb4/memcache.h b/src/lib/krb4/memcache.h
new file mode 100644
index 0000000000..4126e115fd
--- /dev/null
+++ b/src/lib/krb4/memcache.h
@@ -0,0 +1,50 @@
+/*
+ memcache.h
+ Kerberos credential store in memory
+ Originally coded by Tim Miller / Brown University
+ Mods 1/92 By Peter Bosanko
+
+ Modified May-June 1994 by Julia Menapace and John Gilmore,
+ Cygnus Support.
+*/
+
+struct Session {
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+ char realm[REALM_SZ];
+ int numcreds;
+ CREDENTIALS **creds;
+};
+typedef struct Session Session;
+
+OSErr GetNumSessions PROTOTYPE ((int *n));
+OSErr GetNthSession PROTOTYPE ((const int n, char *name,
+ char *instance, char *realm));
+OSErr DeleteSession PROTOTYPE ((const char *name,
+ const char *instance,
+ const char *realm));
+
+OSErr GetCredentials PROTOTYPE ((const char *name,
+ const char *instance,
+ const char *realm,
+ CREDENTIALS *cr));
+ /* name, instance, and realm of service wanted should be
+ set in *cr before calling */
+OSErr AddCredentials PROTOTYPE ((const char *name,
+ const char *instance,
+ const char *realm,
+ const CREDENTIALS *cr));
+OSErr DeleteCredentials PROTOTYPE ((const char *uname,
+ const char *uinst,
+ const char *urealm,
+ const char *sname,
+ const char *sinst,
+ const char *srealm));
+OSErr GetNumCredentials PROTOTYPE ((const char *name,
+ const char *instance,
+ const char *realm, int *n));
+OSErr GetNthCredentials PROTOTYPE ((const char *uname,
+ const char *uinst,
+ const char *urealm, char *sname,
+ char *sinst, char *srealm,
+ const int n));
diff --git a/src/lib/krb4/mk_auth.c b/src/lib/krb4/mk_auth.c
new file mode 100644
index 0000000000..60444dcf16
--- /dev/null
+++ b/src/lib/krb4/mk_auth.c
@@ -0,0 +1,218 @@
+/*
+ * mk_auth.c
+ *
+ * CopKRB4_32right 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Derived from sendauth.c by John Gilmore, 10 October 1994.
+ */
+
+#include "mit-copyright.h"
+
+#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */
+#include "krb.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */
+/*
+ * If the protocol changes, you will need to change the version string
+ * and make appropriate changes in recvauth.c and sendauth.c.
+ */
+
+/*
+ * This file contains two routines: krb_mk_auth() and krb_check_auth().
+ *
+ * krb_mk_auth() packages a ticket for transmission to an application
+ * server.
+ *
+ * krb_krb_check_auth() validates a mutual-authentication response from
+ * the application server.
+ *
+ * These routines are portable versions that implement a protocol
+ * compatible with the original Unix "sendauth".
+ */
+
+/*
+ * The first argument to krb_mk_auth() contains a bitfield of
+ * options (the options are defined in "krb.h"):
+ *
+ * KOPT_DONT_CANON Don't canonicalize instance as a hostname.
+ * (If this option is not chosen, krb_get_phost()
+ * is called to canonicalize it.)
+ *
+ * KOPT_DONT_MK_REQ Don't request server ticket from Kerberos.
+ * A ticket must be supplied in the "ticket"
+ * argument.
+ * (If this option is not chosen, and there
+ * is no ticket for the given server in the
+ * ticket cache, one will be fetched using
+ * krb_mk_req() and returned in "ticket".)
+ *
+ * KOPT_DO_MUTUAL Do mutual authentication, requiring that the
+ * receiving server return the checksum+1 encrypted
+ * in the session key. The mutual authentication
+ * is done using krb_mk_priv() on the other side
+ * (see "recvauth.c") and krb_rd_priv() on this
+ * side.
+ *
+ * The "ticket" argument is used to store the new ticket
+ * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is
+ * chosen, the ticket must be supplied in the "ticket" argument.
+ * The "service", "inst", and "realm" arguments identify the ticket.
+ * If "realm" is null, the local realm is used.
+ *
+ * The following argument is only needed if the KOPT_DO_MUTUAL option
+ * is chosen:
+ *
+ * The "checksum" argument is a number that the server will add 1 to
+ * to authenticate itself back to the client.
+ *
+ * The application protocol version number (of up to KRB_SENDAUTH_VLEN
+ * characters) is passed in "version".
+ *
+ * The ticket is packaged into a message in the buffer pointed to by
+ * the argument "buf".
+ *
+ * If all goes well, KSUCCESS is returned, otherwise some error code.
+ *
+ * The format of the message packaged to send to the application server is:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * KRB_SENDAUTH_VLEN KRB_SENDAUTH_VER sendauth protocol
+ * bytes version number
+ *
+ * KRB_SENDAUTH_VLEN version application protocol
+ * bytes version number
+ *
+ * 4 bytes ticket->length length of ticket
+ *
+ * ticket->length ticket->dat ticket itself
+ */
+
+/*
+ * Build a "sendauth" packet compatible with Unix sendauth/recvauth.
+ */
+int INTERFACE
+krb_mk_auth(options, ticket, service, inst, realm, checksum, version, buf)
+ long options; /* bit-pattern of options */
+ KTEXT ticket; /* where to put ticket (return); or
+ supplied in case of KOPT_DONT_MK_REQ */
+ char *service; /* service name */
+ char *inst; /* instance (OUTPUT canonicalized) */
+ char *realm; /* realm */
+ unsigned KRB4_32 checksum; /* checksum to include in request */
+ char *version; /* version string */
+ KTEXT buf; /* Output buffer to fill */
+{
+ int rem, i;
+ char krb_realm[REALM_SZ];
+ KRB4_32 tkt_len;
+
+ rem=KSUCCESS;
+
+ /* get current realm if not passed in */
+ if (!realm) {
+ rem = krb_get_lrealm(krb_realm,1);
+ if (rem != KSUCCESS)
+ return(rem);
+ realm = krb_realm;
+ }
+
+ if (!(options & KOPT_DONT_CANON))
+ (void) strncpy(inst, krb_get_phost(inst), INST_SZ);
+
+ /* get the ticket if desired */
+ if (!(options & KOPT_DONT_MK_REQ)) {
+ rem = krb_mk_req(ticket, service, inst, realm, checksum);
+ if (rem != KSUCCESS)
+ return(rem);
+ }
+
+#ifdef ATHENA_COMPAT
+ /* this is only for compatibility with old servers */
+ if (options & KOPT_DO_OLDSTYLE) {
+ (void) sprintf(buf->dat,"%d ",ticket->length);
+ (void) write(fd, buf, strlen(buf));
+ (void) write(fd, (char *) ticket->dat, ticket->length);
+ return(rem);
+ }
+#endif /* ATHENA_COMPAT */
+
+ /* zero the buffer */
+ (void) memset(buf->dat, 0, MAX_KTXT_LEN);
+
+ /* insert version strings */
+ (void) strncpy((char *)buf->dat, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN);
+ (void) strncpy((char *)buf->dat+KRB_SENDAUTH_VLEN, version,
+ KRB_SENDAUTH_VLEN);
+
+ /* increment past vers strings */
+ i = 2*KRB_SENDAUTH_VLEN;
+
+ /* put ticket length into buffer */
+ tkt_len = htonl((unsigned KRB4_32) ticket->length);
+ (void) memcpy(buf->dat+i, (char *) &tkt_len, sizeof(tkt_len));
+ i += sizeof(tkt_len);
+
+ /* put ticket into buffer */
+ (void) memcpy(buf->dat+i, (char *) ticket->dat, ticket->length);
+ i += ticket->length;
+
+ buf->length = i;
+ return KSUCCESS;
+}
+
+
+
+/*
+ * For mutual authentication using mk_auth, check the server's response
+ * to validate that we're really talking to the server which holds the
+ * key that we obtained from the Kerberos key server.
+ *
+ * The "buf" argument is the response we received from the app server.
+ * The "checksum" argument is a number that the server has added 1 to
+ * to authenticate itself back to the client (us); the "msg_data" argument
+ * returns the returned mutual-authentication message from the server
+ * (i.e., the checksum+1); "session" holds the
+ * session key of the server, extracted from the ticket file, for use
+ * in decrypting the mutual authentication message from the server;
+ * and "schedule" returns the key schedule for that decryption. The
+ * the local and server addresses are given in "laddr" and "faddr".
+ */
+int INTERFACE
+krb_check_auth (buf, checksum, msg_data, session, schedule, laddr, faddr)
+ KTEXT buf; /* The response we read from app server */
+ unsigned KRB4_32 checksum; /* checksum we included in request */
+ MSG_DAT *msg_data; /* mutual auth MSG_DAT (return) */
+ C_Block session; /* credentials (input) */
+ Key_schedule schedule; /* key schedule (return) */
+ struct sockaddr_in *laddr; /* local address */
+ struct sockaddr_in *faddr; /* address of foreign host on fd */
+{
+ int cc;
+ unsigned KRB4_32 cksum;
+
+ /* decrypt it */
+#ifndef NOENCRYPTION
+ key_sched(session, schedule);
+#endif /* !NOENCRYPTION */
+ if (cc = krb_rd_priv(buf->dat, buf->length, schedule,
+ (C_Block *)session, faddr, laddr, msg_data))
+ return(cc);
+
+ /* fetch the (incremented) checksum that we supplied in the request */
+ (void) memcpy((char *)&cksum, (char *)msg_data->app_data,
+ sizeof(cksum));
+ cksum = ntohl(cksum);
+
+ /* if it doesn't match, fail -- reply wasn't from our real server. */
+ if (cksum != checksum + 1)
+ return(KFAILURE); /* XXX */
+ return(KSUCCESS);
+}
diff --git a/src/lib/krb4/mk_err.c b/src/lib/krb4/mk_err.c
new file mode 100644
index 0000000000..830ee716b9
--- /dev/null
+++ b/src/lib/krb4/mk_err.c
@@ -0,0 +1,59 @@
+/*
+ * mk_err.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+/*
+ * This routine creates a general purpose error reply message. It
+ * doesn't use KTEXT because application protocol may have long
+ * messages, and may want this part of buffer contiguous to other
+ * stuff.
+ *
+ * The error reply is built in "p", using the error code "e" and
+ * error text "e_string" given. The length of the error reply is
+ * returned.
+ *
+ * The error reply is in the following format:
+ *
+ * unsigned char KRB_PROT_VERSION protocol version no.
+ * unsigned char AUTH_MSG_APPL_ERR message type
+ * (least significant
+ * bit of above) HOST_BYTE_ORDER local byte order
+ * 4 bytes e given error code
+ * string e_string given error text
+ */
+
+long INTERFACE
+krb_mk_err(p,e,e_string)
+ u_char *p; /* Where to build error packet */
+ KRB4_32 e; /* Error code */
+ char *e_string; /* Text of error */
+{
+ u_char *start;
+
+ start = p;
+
+ /* Create fixed part of packet */
+ *p++ = (unsigned char) KRB_PROT_VERSION;
+ *p = (unsigned char) AUTH_MSG_APPL_ERR;
+ *p++ |= HOST_BYTE_ORDER;
+
+ /* Add the basic info */
+ memcpy((char *)p, (char *)&e, 4); /* err code */
+ p += sizeof(e);
+ (void) strcpy((char *)p,e_string); /* err text */
+ p += strlen(e_string);
+
+ /* And return the length */
+ return p-start;
+}
diff --git a/src/lib/krb4/mk_preauth.c b/src/lib/krb4/mk_preauth.c
new file mode 100644
index 0000000000..3f48307475
--- /dev/null
+++ b/src/lib/krb4/mk_preauth.c
@@ -0,0 +1,78 @@
+/* mk_preauth.c */
+/* part of Cygnus Network Security */
+/* Copyright 1994 Cygnus Support */
+/*
+ * 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.
+ * Cygnus Support makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+
+/* Define a couple of function types including parameters. These
+ are needed on MS-Windows to convert arguments of the function pointers
+ to the proper FAR types during calls. These definitions are found in
+ <krb-sed.h> but the code is too opaque unless they are also here. */
+#ifndef KEY_PROC_TYPE_DEFINED
+typedef int (*key_proc_type) PROTOTYPE ((char *, char *, char *,
+ char *, C_Block));
+#endif
+
+int
+krb_mk_preauth(preauth_p, preauth_len,
+ key_proc,aname,inst,realm,password,key)
+ char **preauth_p;
+ int *preauth_len;
+ key_proc_type key_proc;
+ char *aname;
+ char *inst;
+ char *realm;
+ char *password;
+ C_Block key;
+{
+#ifdef NOENCRYPTION
+ *preauth_len = strlen(aname)+1; /* include the trailing 0 */
+ *preauth_p = malloc(*preauth_len);
+ strcpy(*preauth_p, aname); /* this will copy the trailing 0 */
+#else
+ des_key_schedule key_s;
+ int sl = strlen(aname);
+#endif
+
+ (*key_proc)(aname,inst,realm,password,key);
+
+#ifndef NOENCRYPTION
+ /*
+ * preauth_len is set to a length greater than sl + 1
+ * and a multpile of 8
+ */
+ *preauth_len = (((sl + 1) / 8) + 1) * 8;
+ /* allocate memory for preauth_p and fill it with 0 */
+ *preauth_p = (char*) malloc(*preauth_len);
+ /* create the key schedule */
+ if (des_key_sched(key, key_s)) {
+ return 1;
+ }
+ /*
+ * encrypt aname using key_s as the key schedule and key as the
+ * initialization vector.
+ */
+ des_pcbc_encrypt((des_cblock *) aname, (des_cblock *) *preauth_p,
+ (long) (sl + 1), key_s, (des_cblock *) key, DES_ENCRYPT);
+#endif
+ return 0;
+}
+
+void
+krb_free_preauth(preauth_p, preauth_len)
+ char *preauth_p;
+ int preauth_len;
+{
+ free(preauth_p);
+ return;
+}
diff --git a/src/lib/krb4/mk_priv.c b/src/lib/krb4/mk_priv.c
new file mode 100644
index 0000000000..72fff70071
--- /dev/null
+++ b/src/lib/krb4/mk_priv.c
@@ -0,0 +1,205 @@
+/*
+ * mk_priv.c
+ *
+ * CopKRB4_32right 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * This routine constructs a Kerberos 'private msg', i.e.
+ * cryptographically sealed with a private session key.
+ *
+ * Returns either < 0 ===> error, or resulting size of message
+ *
+ * Steve Miller Project Athena MIT/DEC
+ */
+
+#include "mit-copyright.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */
+#include "krb.h"
+#include "prot.h"
+#include "des.h"
+#include "lsb_addr_cmp.h"
+
+extern int krb_debug;
+
+/*
+ * krb_mk_priv() constructs an AUTH_MSG_PRIVATE message. It takes
+ * some user data "in" of "length" bytes and creates a packet in "out"
+ * consisting of the user data, a timestamp, and the sender's network
+ * address.
+#ifndef NOENCRYTION
+ * The packet is encrypted by pcbc_encrypt(), using the given
+ * "key" and "schedule".
+#endif
+ * The length of the resulting packet "out" is
+ * returned.
+ *
+ * It is similar to krb_mk_safe() except for the additional key
+ * schedule argument "schedule" and the fact that the data is encrypted
+ * rather than appended with a checksum. Also, the protocol version
+ * number is "private_msg_ver", defined in krb_rd_priv.c, rather than
+ * KRB_PROT_VERSION, defined in "krb.h".
+ *
+ * The "out" packet consists of:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * 1 byte private_msg_ver protocol version number
+ * 1 byte AUTH_MSG_PRIVATE | message type plus local
+ * HOST_BYTE_ORDER byte order in low bit
+ *
+#ifdef NOENCRYPTION
+ * 4 bytes c_length length of data
+#else
+ * 4 bytes c_length length of encrypted data
+ *
+ * ===================== begin encrypt ================================
+#endif
+ *
+ * 4 bytes length length of user data
+ * length in user data
+ * 1 byte msg_time_5ms timestamp milliseconds
+ * 4 bytes sender->sin.addr.s_addr sender's IP address
+ *
+ * 4 bytes msg_time_sec or timestamp seconds with
+ * -msg_time_sec direction in sign bit
+ *
+ * 0<=n<=7 bytes pad to 8 byte multiple zeroes
+#ifndef NOENCRYPTION
+ * (done by pcbc_encrypt())
+ *
+ * ======================= end encrypt ================================
+#endif
+ */
+
+long INTERFACE
+krb_mk_priv(in,out,length,schedule,key,sender,receiver)
+ u_char *in; /* application data */
+ u_char *out; /* put msg here, leave room for
+ * header! breaks if in and out
+ * (header stuff) overlap */
+ unsigned KRB4_32 length; /* of in data */
+ Key_schedule schedule; /* precomputed key schedule */
+ C_Block *key; /* encryption key for seed and ivec */
+ struct sockaddr_in *sender; /* sender address */
+ struct sockaddr_in *receiver; /* receiver address */
+{
+ register u_char *p,*q;
+ u_char *c_length_ptr;
+ extern int private_msg_ver; /* in krb_rd_priv.c */
+
+ unsigned KRB4_32 c_length;
+ u_char msg_time_5ms;
+ unsigned KRB4_32 msg_time_sec;
+ unsigned KRB4_32 msg_time_usec;
+
+ /*
+ * get the current time to use instead of a sequence #, since
+ * process lifetime may be shorter than the lifetime of a session
+ * key.
+ */
+ msg_time_sec = TIME_GMT_UNIXSEC_US (&msg_time_usec);
+ msg_time_5ms = msg_time_usec/5000; /* 5ms quanta */
+
+ p = out;
+
+ *p++ = private_msg_ver?private_msg_ver:KRB_PROT_VERSION;
+ *p++ = AUTH_MSG_PRIVATE | HOST_BYTE_ORDER;
+
+ /* calculate cipher length */
+ c_length_ptr = p;
+ p += sizeof(c_length);
+
+#ifndef NOENCRYPTION
+ /* start for encrypted stuff */
+#endif
+ q = p;
+
+ /* stuff input length */
+ memcpy((char *)p, (char *)&length, sizeof(length));
+ p += sizeof(length);
+
+#ifdef NOENCRYPTION
+ /* make all the stuff contiguous for checksum */
+#else
+ /* make all the stuff contiguous for checksum and encryption */
+#endif
+ memcpy((char *)p, (char *)in, (int) length);
+ p += length;
+
+ /* stuff time 5ms */
+ memcpy((char *)p, (char *)&msg_time_5ms, sizeof(msg_time_5ms));
+ p += sizeof(msg_time_5ms);
+
+ /* stuff source address */
+ memcpy((char *)p, (char *)&sender->sin_addr.s_addr,
+ sizeof(sender->sin_addr.s_addr));
+ p += sizeof(sender->sin_addr.s_addr);
+
+ /*
+ * direction bit is the sign bit of the timestamp. Ok
+ * until 2038??
+ */
+ /* For compatibility with broken old code, compares are done in VAX
+ byte order (LSBFIRST) */
+ if (lsb_net_ulong_less(sender->sin_addr.s_addr, /* src < recv */
+ receiver->sin_addr.s_addr)==-1)
+ msg_time_sec = -msg_time_sec;
+ else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==0)
+ if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port) == -1)
+ msg_time_sec = -msg_time_sec;
+ /* stuff time sec */
+ memcpy((char *)p, (char *)&msg_time_sec, sizeof(msg_time_sec));
+ p += sizeof(msg_time_sec);
+
+ /*
+ * All that for one tiny bit! Heaven help those that talk to
+ * themselves.
+ */
+
+#ifdef notdef
+ /*
+ * calculate the checksum of the length, address, sequence, and
+ * inp data
+ */
+ cksum = quad_cksum(q,NULL,p-q,0,key);
+ DEB (("\ncksum = %u",cksum));
+ /* stuff checksum */
+ memcpy((char *) p, (char *) &cksum, sizeof(cksum));
+ p += sizeof(cksum);
+#endif
+
+#ifdef NOENCRYPTION
+ /*
+ * All the data have been assembled, compute length
+ */
+#else
+ /*
+ * All the data have been assembled, compute length and encrypt
+ * starting with the length, data, and timestamps use the key as
+ * an ivec.
+ */
+#endif
+
+ c_length = p - q;
+ c_length = ((c_length + sizeof(C_Block) -1)/sizeof(C_Block)) *
+ sizeof(C_Block);
+ /* stuff the length */
+ memcpy((char *)c_length_ptr, (char *) &c_length, sizeof(c_length));
+
+#ifndef NOENCRYPTION
+ /* pcbc encrypt, pad as needed, use key as ivec */
+ pcbc_encrypt((C_Block *) q,(C_Block *) q, (long) (p-q), schedule,
+ key, ENCRYPT);
+#endif /* NOENCRYPTION */
+
+ return (q - out + c_length); /* resulting size */
+}
diff --git a/src/lib/krb4/mk_req.c b/src/lib/krb4/mk_req.c
new file mode 100644
index 0000000000..0cb953fc53
--- /dev/null
+++ b/src/lib/krb4/mk_req.c
@@ -0,0 +1,214 @@
+/*
+ * mk_req.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#define DEFINE_SOCKADDR
+#include "mit-copyright.h"
+#include "krb.h"
+#include "prot.h"
+#include "des.h"
+#include <string.h>
+
+extern int krb_ap_req_debug;
+static int lifetime = 255; /* Default based on the TGT */
+
+/*
+ * krb_mk_req takes a text structure in which an authenticator is to
+ * be built, the name of a service, an instance, a realm,
+ * and a checksum. It then retrieves a ticket for
+ * the desired service and creates an authenticator in the text
+ * structure passed as the first argument. krb_mk_req returns
+ * KSUCCESS on success and a Kerberos error code on failure.
+ *
+ * The peer procedure on the other end is krb_rd_req. When making
+ * any changes to this routine it is important to make corresponding
+ * changes to krb_rd_req.
+ *
+ * The authenticator consists of the following:
+ *
+ * authent->dat
+ *
+ * unsigned char KRB_PROT_VERSION protocol version no.
+ * unsigned char AUTH_MSG_APPL_REQUEST message type
+ * (least significant
+ * bit of above) HOST_BYTE_ORDER local byte ordering
+ * unsigned char kvno from ticket server's key version
+ * string realm server's realm
+ * unsigned char tl ticket length
+ * unsigned char idl request id length
+ * text ticket->dat ticket for server
+ * text req_id->dat request id
+ *
+ * The ticket information is retrieved from the ticket cache or
+ * fetched from Kerberos. The request id (called the "authenticator"
+#ifdef NOENCRYPTION
+ * in the papers on Kerberos) contains the following:
+#else
+ * in the papers on Kerberos) contains information encrypted in the session
+ * key for the client and ticket-granting service: {req_id}Kc,tgs
+ * Before encryption, it contains the following:
+#endif
+ *
+ * req_id->dat
+ *
+ * string cr.pname {name, instance, and
+ * string cr.pinst realm of principal
+ * string myrealm making this request}
+ * 4 bytes checksum checksum argument given
+ * unsigned char time_usecs time (microseconds)
+ * 4 bytes time_secs time (seconds)
+ *
+ * req_id->length = 3 strings + 3 terminating nulls + 5 bytes for time,
+ * all rounded up to multiple of 8.
+ */
+
+int INTERFACE
+krb_mk_req(authent,service,instance,realm,checksum)
+ register KTEXT authent; /* Place to build the authenticator */
+ char *service; /* Name of the service */
+ char *instance; /* Service instance */
+ char *realm; /* Authentication domain of service */
+ KRB4_32 checksum; /* Checksum of data (optional) */
+{
+ KTEXT_ST req_st; /* Temp storage for req id */
+ KTEXT req_id = &req_st;
+ unsigned char *v = authent->dat; /* Prot version number */
+ unsigned char *t = (authent->dat+1); /* Message type */
+ unsigned char *kv = (authent->dat+2); /* Key version no */
+ unsigned char *tl; /* Tkt len */
+ unsigned char *idl; /* Reqid len */
+ CREDENTIALS cr; /* Credentials used by retr */
+ register KTEXT ticket = &(cr.ticket_st); /* Pointer to tkt_st */
+ int retval; /* Returned by krb_get_cred */
+ Key_schedule key_s;
+ char krb_realm[REALM_SZ]; /* Our local realm, if not specified */
+ char myrealm[REALM_SZ]; /* Realm of our TGT */
+ unsigned KRB4_32 time_secs;
+ unsigned KRB4_32 time_usecs;
+
+ /* The fixed parts of the authenticator */
+ *v = (unsigned char) KRB_PROT_VERSION;
+ *t = (unsigned char) AUTH_MSG_APPL_REQUEST;
+ *t |= HOST_BYTE_ORDER;
+
+ /* get current realm if not passed in */
+ if (!realm) {
+ retval = krb_get_lrealm(krb_realm,1);
+ if (retval != KSUCCESS)
+ return(retval);
+ realm = krb_realm;
+ }
+
+ tl = (authent->dat+4+strlen(realm)); /* Tkt len */
+ idl = (authent->dat+5+strlen(realm)); /* Reqid len */
+
+ /* Get the ticket and move it into the authenticator */
+ if (krb_ap_req_debug)
+ DEB (("Realm: %s\n",realm));
+ /*
+ * Determine realm of these tickets. We will send this to the
+ * KDC from which we are requesting tickets so it knows what to
+ * with our session key.
+ */
+ if ((retval = krb_get_tf_realm(TKT_FILE, myrealm)) != KSUCCESS)
+ return(retval);
+
+ retval = krb_get_cred(service,instance,realm,&cr);
+
+ if (retval == RET_NOTKT) {
+ if (retval = get_ad_tkt(service,instance,realm,lifetime))
+ return(retval);
+ if (retval = krb_get_cred(service,instance,realm,&cr))
+ return(retval);
+ }
+
+ if (retval != KSUCCESS) return (retval);
+
+ if (krb_ap_req_debug)
+ DEB (("%s %s %s %s %s\n", service, instance, realm,
+ cr.pname, cr.pinst));
+ *kv = (unsigned char) cr.kvno;
+ (void) strcpy((char *)(authent->dat+3),realm);
+ *tl = (unsigned char) ticket->length;
+ memcpy((char *)(authent->dat+6+strlen(realm)), (char *)(ticket->dat),
+ ticket->length);
+ authent->length = 6 + strlen(realm) + ticket->length;
+ if (krb_ap_req_debug)
+ DEB (("Ticket->length = %d\n",ticket->length));
+ if (krb_ap_req_debug)
+ DEB (("Issue date: %d\n",cr.issue_date));
+
+ /* Build request id */
+ (void) strcpy((char *)(req_id->dat),cr.pname); /* Auth name */
+ req_id->length = strlen(cr.pname)+1;
+ /* Principal's instance */
+ (void) strcpy((char *)(req_id->dat+req_id->length),cr.pinst);
+ req_id->length += strlen(cr.pinst)+1;
+ /* Authentication domain */
+ (void) strcpy((char *)(req_id->dat+req_id->length),myrealm);
+ req_id->length += strlen(myrealm)+1;
+ /* Checksum */
+ memcpy((char *)(req_id->dat+req_id->length), (char *)&checksum, 4);
+ req_id->length += 4;
+
+ /* Fill in the times on the request id */
+
+ time_secs = TIME_GMT_UNIXSEC_US (&time_usecs);
+ *(req_id->dat+(req_id->length)++) =
+ (unsigned char) time_usecs;
+ /* Time (coarse) */
+ memcpy((char *)(req_id->dat+req_id->length),
+ (char *) &time_secs , 4);
+ req_id->length += 4;
+
+ /* Fill to a multiple of 8 bytes for DES */
+ req_id->length = ((req_id->length+7)/8)*8;
+
+#ifndef NOENCRYPTION
+ /* Encrypt the request ID using the session key */
+ key_sched(cr.session,key_s);
+ pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat,
+ (long) req_id->length,key_s,(C_Block *) cr.session,1);
+ /* clean up */
+ memset((char *) key_s, 0, sizeof(key_s));
+#endif /* NOENCRYPTION */
+
+ /* Copy it into the authenticator */
+ memcpy((char *)(authent->dat+authent->length), (char *)(req_id->dat),
+ req_id->length);
+ authent->length += req_id->length;
+ /* And set the id length */
+ *idl = (unsigned char) req_id->length;
+ /* clean up */
+ memset((char *)req_id, 0, sizeof(*req_id));
+
+ if (krb_ap_req_debug)
+ DEB (("Authent->length = %d\n",authent->length));
+ if (krb_ap_req_debug)
+ DEB (("idl = %d, tl = %d\n",(int) *idl, (int) *tl));
+
+ return(KSUCCESS);
+}
+
+/*
+ * krb_set_lifetime sets the default lifetime for additional tickets
+ * obtained via krb_mk_req().
+ *
+ * It returns the previous value of the default lifetime.
+ */
+
+int
+krb_set_lifetime(newval)
+int newval;
+{
+ int olife = lifetime;
+
+ lifetime = newval;
+ return(olife);
+}
diff --git a/src/lib/krb4/mk_safe.c b/src/lib/krb4/mk_safe.c
new file mode 100644
index 0000000000..c3ed94d323
--- /dev/null
+++ b/src/lib/krb4/mk_safe.c
@@ -0,0 +1,154 @@
+/*
+ * mk_safe.c
+ *
+ * Copyright 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * This routine constructs a Kerberos 'safe msg', i.e. authenticated
+ * using a private session key to seed a checksum. Msg is NOT
+ * encrypted.
+ *
+ * Returns either <0 ===> error, or resulting size of message
+ *
+ * Steve Miller Project Athena MIT/DEC
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include <string.h>
+
+#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */
+#include "krb.h"
+#include "des.h"
+#include "prot.h"
+#include "lsb_addr_cmp.h"
+
+extern int krb_debug;
+
+/*
+ * krb_mk_safe() constructs an AUTH_MSG_SAFE message. It takes some
+ * user data "in" of "length" bytes and creates a packet in "out"
+ * consisting of the user data, a timestamp, and the sender's network
+ * address, followed by a checksum computed on the above, using the
+ * given "key". The length of the resulting packet is returned.
+ *
+ * The "out" packet consists of:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * 1 byte KRB_PROT_VERSION protocol version number
+ * 1 byte AUTH_MSG_SAFE | message type plus local
+ * HOST_BYTE_ORDER byte order in low bit
+ *
+ * ===================== begin checksum ================================
+ *
+ * 4 bytes length length of user data
+ * length in user data
+ * 1 byte msg_time_5ms timestamp milliseconds
+ * 4 bytes sender->sin.addr.s_addr sender's IP address
+ *
+ * 4 bytes msg_time_sec or timestamp seconds with
+ * -msg_time_sec direction in sign bit
+ *
+ * ======================= end checksum ================================
+ *
+ * 16 bytes big_cksum quadratic checksum of
+ * above using "key"
+ */
+
+long INTERFACE
+krb_mk_safe(in,out,length,key,sender,receiver)
+ u_char *in; /* application data */
+ u_char *out; /*
+ * put msg here, leave room for header!
+ * breaks if in and out (header stuff)
+ * overlap
+ */
+ unsigned KRB4_32 length; /* of in data */
+ C_Block *key; /* encryption key for seed and ivec */
+ struct sockaddr_in *sender; /* sender address */
+ struct sockaddr_in *receiver; /* receiver address */
+{
+ register u_char *p,*q;
+
+ unsigned KRB4_32 cksum;
+ unsigned KRB4_32 big_cksum[4];
+ unsigned KRB4_32 msg_secs;
+ unsigned KRB4_32 msg_usecs;
+ u_char msg_time_5ms;
+ KRB4_32 msg_time_sec;
+
+ /*
+ * get the current time to use instead of a sequence #, since
+ * process lifetime may be shorter than the lifetime of a session
+ * key.
+ */
+
+ msg_secs = TIME_GMT_UNIXSEC_US(&msg_usecs);
+ msg_time_sec = msg_secs;
+ msg_time_5ms = msg_usecs/5000; /* 5ms quanta */
+
+ p = out;
+
+ *p++ = KRB_PROT_VERSION;
+ *p++ = AUTH_MSG_SAFE | HOST_BYTE_ORDER;
+
+ q = p; /* start for checksum stuff */
+ /* stuff input length */
+ memcpy((char *)p, (char *)&length, sizeof(length));
+ p += sizeof(length);
+
+ /* make all the stuff contiguous for checksum */
+ memcpy((char *)p, (char *)in, (int) length);
+ p += length;
+
+ /* stuff time 5ms */
+ memcpy((char *)p, (char *)&msg_time_5ms, sizeof(msg_time_5ms));
+ p += sizeof(msg_time_5ms);
+
+ /* stuff source address */
+ memcpy((char *)p, (char *) &sender->sin_addr.s_addr,
+ sizeof(sender->sin_addr.s_addr));
+ p += sizeof(sender->sin_addr.s_addr);
+
+ /*
+ * direction bit is the sign bit of the timestamp. Ok until
+ * 2038??
+ */
+ /* For compatibility with broken old code, compares are done in VAX
+ byte order (LSBFIRST) */
+ if (lsb_net_ulong_less(sender->sin_addr.s_addr, /* src < recv */
+ receiver->sin_addr.s_addr)==-1)
+ msg_time_sec = -msg_time_sec;
+ else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==0)
+ if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port) == -1)
+ msg_time_sec = -msg_time_sec;
+ /*
+ * all that for one tiny bit! Heaven help those that talk to
+ * themselves.
+ */
+
+ /* stuff time sec */
+ memcpy((char *)p, (char *)&msg_time_sec, sizeof(msg_time_sec));
+ p += sizeof(msg_time_sec);
+
+#ifdef NOENCRYPTION
+ cksum = 0;
+ memset((char*) big_cksum, 0, sizeof(big_cksum));
+#else /* Do encryption */
+ /* calculate the checksum of length, timestamps, and input data */
+ cksum = quad_cksum(q,big_cksum,p-q,2,(C_Block*) key);
+#endif /* NOENCRYPTION */
+ DEB (("\ncksum = %u",cksum));
+
+ /* stuff checksum */
+ memcpy((char *)p, (char *)big_cksum, sizeof(big_cksum));
+ p += sizeof(big_cksum);
+
+ return ((long)(p - out)); /* resulting size */
+}
diff --git a/src/lib/krb4/month_sname.c b/src/lib/krb4/month_sname.c
new file mode 100644
index 0000000000..61a007ab73
--- /dev/null
+++ b/src/lib/krb4/month_sname.c
@@ -0,0 +1,28 @@
+/*
+ * month_sname.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "conf.h"
+
+/*
+ * Given an integer 1-12, month_sname() returns a string
+ * containing the first three letters of the corresponding
+ * month. Returns 0 if the argument is out of range.
+ */
+
+const char *month_sname(n)
+ int n;
+{
+ static const char name[][4] = {
+ "Jan","Feb","Mar","Apr","May","Jun",
+ "Jul","Aug","Sep","Oct","Nov","Dec"
+ };
+ return((n < 1 || n > 12) ? 0 : name [n-1]);
+}
diff --git a/src/lib/krb4/netread.c b/src/lib/krb4/netread.c
new file mode 100644
index 0000000000..91a868c86b
--- /dev/null
+++ b/src/lib/krb4/netread.c
@@ -0,0 +1,52 @@
+/*
+ * netread.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <errno.h>
+#define DEFINE_SOCKADDR
+#include "krb.h"
+#ifndef _WINDOWS
+extern int errno;
+#endif
+
+/*
+ * krb_net_read() reads from the file descriptor "fd" to the buffer
+ * "buf", until either 1) "len" bytes have been read or 2) cannot
+ * read anymore from "fd". It returns the number of bytes read
+ * or a read() error. (The calling interface is identical to
+ * read(2).)
+ *
+ * XXX must not use non-blocking I/O
+ */
+int
+krb_net_read(fd, buf, len)
+int fd;
+register char *buf;
+register int len;
+{
+ int cc, len2 = 0;
+
+ do {
+ cc = SOCKET_READ(fd, buf, len);
+ if (cc < 0)
+ {
+ if (SOCKET_ERRNO == SOCKET_EINTR)
+ continue;
+ return(cc); /* errno is already set */
+ }
+ else if (cc == 0) {
+ return(len2);
+ } else {
+ buf += cc;
+ len2 += cc;
+ len -= cc;
+ }
+ } while (len > 0);
+ return(len2);
+}
diff --git a/src/lib/krb4/netwrite.c b/src/lib/krb4/netwrite.c
new file mode 100644
index 0000000000..403ee4fb52
--- /dev/null
+++ b/src/lib/krb4/netwrite.c
@@ -0,0 +1,48 @@
+/*
+ * netwrite.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <errno.h>
+#define DEFINE_SOCKADDR
+#include "krb.h"
+#ifndef _WINDOWS
+extern int errno;
+#endif
+
+/*
+ * krb_net_write() writes "len" bytes from "buf" to the file
+ * descriptor "fd". It returns the number of bytes written or
+ * a write() error. (The calling interface is identical to
+ * write(2).)
+ *
+ * XXX must not use non-blocking I/O
+ */
+int
+krb_net_write(fd, buf, len)
+int fd;
+register char *buf;
+int len;
+{
+ int cc;
+ register int wrlen = len;
+ do {
+ cc = SOCKET_WRITE(fd, buf, wrlen);
+ if (cc < 0)
+ {
+ if (SOCKET_ERRNO == SOCKET_EINTR)
+ continue;
+ return(cc);
+ }
+ else {
+ buf += cc;
+ wrlen -= cc;
+ }
+ } while (wrlen > 0);
+ return(len);
+}
diff --git a/src/lib/krb4/one.c b/src/lib/krb4/one.c
new file mode 100644
index 0000000000..358bb782ea
--- /dev/null
+++ b/src/lib/krb4/one.c
@@ -0,0 +1,20 @@
+/*
+ * one.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "conf.h"
+
+/*
+ * definition of variable set to 1.
+ * used in krb_conf.h to determine host byte order.
+ */
+
+#ifndef HOST_BYTE_ORDER
+const int krbONE = 1;
+#endif
diff --git a/src/lib/krb4/pkt_cipher.c b/src/lib/krb4/pkt_cipher.c
new file mode 100644
index 0000000000..29123480e0
--- /dev/null
+++ b/src/lib/krb4/pkt_cipher.c
@@ -0,0 +1,35 @@
+/*
+ * pkt_cipher.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <string.h>
+#include "krb.h"
+#include "prot.h"
+
+
+/*
+ * This routine takes a reply packet from the Kerberos ticket-granting
+ * service and returns a pointer to the beginning of the ciphertext in it.
+ *
+ * See "prot.h" for packet format.
+ */
+
+KTEXT
+pkt_cipher(packet)
+ KTEXT packet;
+{
+ unsigned char *ptr = pkt_a_realm(packet) + 6
+ + strlen((char *)pkt_a_realm(packet));
+ /* Skip a few more fields */
+ ptr += 3 + 4; /* add 4 for exp_date */
+
+ /* And return the pointer */
+ return((KTEXT) ptr);
+}
diff --git a/src/lib/krb4/pkt_clen.c b/src/lib/krb4/pkt_clen.c
new file mode 100644
index 0000000000..99a712b8d3
--- /dev/null
+++ b/src/lib/krb4/pkt_clen.c
@@ -0,0 +1,49 @@
+/*
+ * pkt_clen.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <string.h>
+#include "krb.h"
+#include "prot.h"
+
+extern int krb_debug;
+int swap_bytes;
+
+/*
+ * Given a pointer to an AUTH_MSG_KDC_REPLY packet, return the length of
+ * its ciphertext portion. The external variable "swap_bytes" is assumed
+ * to have been set to indicate whether or not the packet is in local
+ * byte order. pkt_clen() takes this into account when reading the
+ * ciphertext length out of the packet.
+ */
+
+pkt_clen(pkt)
+ KTEXT pkt;
+{
+ static unsigned short temp,temp2;
+ int clen = 0;
+
+ /* Start of ticket list */
+ unsigned char *ptr = pkt_a_realm(pkt) + 10
+ + strlen((char *)pkt_a_realm(pkt));
+
+ /* Finally the length */
+ memcpy((char *)&temp, (char *)(++ptr), 2); /* alignment */
+ if (swap_bytes) {
+ /* assume a short is 2 bytes?? */
+ swab((char *)&temp,(char *)&temp2,2);
+ temp = temp2;
+ }
+
+ clen = (int) temp;
+
+ DEB (("Clen is %d\n",clen));
+ return(clen);
+}
diff --git a/src/lib/krb4/put_svc_key.c b/src/lib/krb4/put_svc_key.c
new file mode 100644
index 0000000000..e3b05cc270
--- /dev/null
+++ b/src/lib/krb4/put_svc_key.c
@@ -0,0 +1,93 @@
+/* lib/krb/put_svc_key.c */
+/* Copyright 1994 Cygnus Support */
+/* Mark W. Eichin */
+/*
+ * 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.
+ * Cygnus Support makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/*
+ * put_svc_key is a simple version of what 'ksrvutil add' provides, for some
+ * circumstances when service keys are distributed by applictions.
+ *
+ * Caveats: currently uses UNIX I/O (open, read) rather than stdio - this
+ * should be fixed.
+ * It could probably be made more general (and then actually be used
+ * by ksrvutil.) This version supports just enough to be useful.
+ */
+
+#include "krb.h"
+#include <string.h>
+#include <sys/file.h>
+#include <stdio.h>
+#ifdef NEED_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#endif
+#ifdef HAS_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define KEYSZ sizeof(C_Block)
+/* strict put_svc_key.
+ The srvtab must already exist;
+ The key (exact match) must already be in the file;
+ version numbers are not checked.
+ */
+put_svc_key(sfile,name,inst,realm,newvno,key)
+ char *sfile;
+ char *name;
+ char *inst;
+ char *realm;
+ int newvno;
+ char *key;
+{
+ int fd;
+ char fname[SNAME_SZ], finst[INST_SZ], frlm[REALM_SZ];
+ unsigned char fvno;
+ char fkey[KEYSZ];
+
+ if (!sfile)
+ sfile = KEYFILE;
+
+ if ((fd = open(sfile, O_RDWR)) < 0)
+ return KFAILURE;
+
+ while(getst(fd,fname,SNAME_SZ) > 0) {
+ getst(fd,finst,INST_SZ);
+ getst(fd,frlm,REALM_SZ);
+ if (!strcmp(fname,name)
+ && !strcmp(finst,inst)
+ && !strcmp(frlm,realm)) {
+ /* all matched, so write new data */
+ fvno = newvno;
+ lseek(fd,0,SEEK_CUR);
+ if (write(fd,&fvno,1) != 1) {
+ close(fd);
+ return KFAILURE;
+ }
+ if (write(fd,key,KEYSZ) != KEYSZ) {
+ close(fd);
+ return KFAILURE;
+ }
+ close(fd);
+ return KSUCCESS;
+ }
+ if (read(fd,&fvno,1) != 1) {
+ close(fd);
+ return KFAILURE;
+ }
+ if (read(fd,&fkey,KEYSZ) != KEYSZ) {
+ close(fd);
+ return KFAILURE;
+ }
+ }
+ /* never found it */
+ close(fd);
+ return KFAILURE;
+}
diff --git a/src/lib/krb4/rd_err.c b/src/lib/krb4/rd_err.c
new file mode 100644
index 0000000000..2b105a01f8
--- /dev/null
+++ b/src/lib/krb4/rd_err.c
@@ -0,0 +1,69 @@
+/*
+ * rd_err.c
+ *
+ * Copyright 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Steve Miller Project Athena MIT/DEC
+ */
+
+#include "mit-copyright.h"
+
+#include <string.h>
+
+#include "krb.h"
+#include "prot.h"
+
+/*
+ * Given an AUTH_MSG_APPL_ERR message, "in" and its length "in_length",
+ * return the error code from the message in "code" and the text in
+ * "m_data" as follows:
+ *
+ * m_data->app_data points to the error text
+ * m_data->app_length points to the length of the error text
+ *
+ * If all goes well, return RD_AP_OK. If the version number
+ * is wrong, return RD_AP_VERSION, and if it's not an AUTH_MSG_APPL_ERR
+ * type message, return RD_AP_MSG_TYPE.
+ *
+ * The AUTH_MSG_APPL_ERR message format can be found in mk_err.c
+ */
+
+int INTERFACE
+krb_rd_err(in,in_length,code,m_data)
+ u_char *in; /* pointer to the msg received */
+ u_long in_length; /* of in msg */
+ long *code; /* received error code */
+ MSG_DAT *m_data;
+{
+ register u_char *p;
+ int swap_bytes = 0;
+ p = in; /* beginning of message */
+
+ if (*p++ != KRB_PROT_VERSION)
+ return(RD_AP_VERSION);
+ if (((*p) & ~1) != AUTH_MSG_APPL_ERR)
+ return(RD_AP_MSG_TYPE);
+ if ((*p++ & 1) != HOST_BYTE_ORDER)
+ swap_bytes++;
+
+ /* safely get code */
+ {
+ unsigned KRB4_32 raw_code;
+
+ memcpy((char *)&raw_code, (char *)p, sizeof(raw_code));
+ if (swap_bytes)
+ swap_u_long(raw_code);
+ p += sizeof(raw_code); /* skip over */
+ *code = raw_code;
+ }
+
+ m_data->app_data = p; /* we're now at the error text
+ * message */
+ m_data->app_length = in_length;
+
+ return(RD_AP_OK); /* OK == 0 */
+}
diff --git a/src/lib/krb4/rd_preauth.c b/src/lib/krb4/rd_preauth.c
new file mode 100644
index 0000000000..65c2dcc719
--- /dev/null
+++ b/src/lib/krb4/rd_preauth.c
@@ -0,0 +1,58 @@
+/* rd_preauth.c */
+/* part of Cygnus Network Security */
+/* Copyright 1994 Cygnus Support */
+/*
+ * 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.
+ * Cygnus Support makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "krb.h"
+#include "krb_db.h"
+#include "prot.h"
+#include "des.h"
+/* #define KERB_ERR_PREAUTH_SHORT 11 */
+/* #define KERB_ERR_PREAUTH_MISMATCH 12 */
+
+
+int
+krb_rd_preauth(pkt,preauth_p,preauth_len,auth_pr,key)
+ KTEXT pkt;
+ char *preauth_p;
+ int preauth_len;
+ Principal *auth_pr;
+ des_cblock key;
+{
+ int st;
+ char *name_p;
+
+ name_p = auth_pr->name;
+
+#ifndef NOENCRYPTION
+ /* Decrypt preauth_p using key as the key and initialization vector. */
+ /* check preauth_len */
+ if ((((strlen(name_p) + 1) / 8) + 1) *8 != preauth_len)
+ return KERB_ERR_PREAUTH_SHORT;
+ else {
+ des_key_schedule key_s;
+
+ if (des_key_sched(key, key_s)) {
+ return 1;
+ }
+ des_pcbc_encrypt((des_cblock *) preauth_p, (des_cblock *) preauth_p,
+ (long) preauth_len, key_s, (des_cblock *) key,
+ DES_DECRYPT);
+ }
+#endif /* R3_NO_MODIFICATIONS */
+
+ /* since the preauth data has the trailing 0, this just works */
+ st = strcmp(preauth_p, name_p);
+ if (st)
+ return KERB_ERR_PREAUTH_MISMATCH;
+ return 0;
+}
diff --git a/src/lib/krb4/rd_priv.c b/src/lib/krb4/rd_priv.c
new file mode 100644
index 0000000000..7c4f613a42
--- /dev/null
+++ b/src/lib/krb4/rd_priv.c
@@ -0,0 +1,217 @@
+/*
+ * rd_priv.c
+ *
+ * CopKRB4_32right 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * This routine dissects a a Kerberos 'private msg', decrypting it,
+ * checking its integrity, and returning a pointer to the application
+ * data contained and its length.
+ *
+ * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...). If
+ * the return value is RD_AP_TIME, then either the times are too far
+ * out of synch, OR the packet was modified.
+ *
+ * Steve Miller Project Athena MIT/DEC
+ */
+
+#include "mit-copyright.h"
+
+/* system include files */
+#include <stdio.h>
+#include <string.h>
+
+/* application include files */
+#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */
+#include "krb.h"
+#include "prot.h"
+#include "des.h"
+#include "lsb_addr_cmp.h"
+
+extern int krb_debug;
+
+/* This one is exported, for use by krb_mk_priv. */
+int private_msg_ver = KRB_PROT_VERSION;
+
+/*
+#ifdef NOENCRPYTION
+ * krb_rd_priv() checks the integrity of an
+#else
+ * krb_rd_priv() decrypts and checks the integrity of an
+#endif
+ * AUTH_MSG_PRIVATE message. Given the message received, "in",
+ * the length of that message, "in_length", the key "schedule"
+#ifdef NOENCRYPTION
+ * and "key", and the network addresses of the
+#else
+ * and "key" to decrypt with, and the network addresses of the
+#endif
+ * "sender" and "receiver" of the message, krb_rd_safe() returns
+ * RD_AP_OK if the message is okay, otherwise some error code.
+ *
+ * The message data retrieved from "in" are returned in the structure
+#ifdef NOENCRYPTION
+ * "m_data". The pointer to the application data
+#else
+ * "m_data". The pointer to the decrypted application data
+#endif
+ * (m_data->app_data) refers back to the appropriate place in "in".
+ *
+ * See the file "mk_priv.c" for the format of the AUTH_MSG_PRIVATE
+ * message. The structure containing the extracted message
+ * information, MSG_DAT, is defined in "krb.h".
+ */
+
+long INTERFACE
+krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data)
+ u_char *in; /* pointer to the msg received */
+ unsigned KRB4_32 in_length; /* length of "in" msg */
+ Key_schedule schedule; /* precomputed key schedule */
+ C_Block *key; /* encryption key for seed and ivec */
+ struct sockaddr_in *sender;
+ struct sockaddr_in *receiver;
+ MSG_DAT *m_data; /*various input/output data from msg */
+{
+ register u_char *p,*q;
+ unsigned KRB4_32 src_addr;
+ unsigned KRB4_32 c_length;
+ int swap_bytes;
+ unsigned KRB4_32 t_local;
+ KRB4_32 delta_t; /* Difference between timestamps */
+
+ p = in; /* beginning of message */
+ swap_bytes = 0;
+
+ if (*p++ != KRB_PROT_VERSION && *(p-1) != 3)
+ return RD_AP_VERSION;
+ private_msg_ver = *(p-1);
+ if (((*p) & ~1) != AUTH_MSG_PRIVATE)
+ return RD_AP_MSG_TYPE;
+ if ((*p++ & 1) != HOST_BYTE_ORDER)
+ swap_bytes++;
+
+ /* get cipher length */
+ memcpy((char *)&c_length, (char *)p, sizeof(c_length));
+ if (swap_bytes)
+ swap_u_long(c_length);
+ p += sizeof(c_length);
+ /* check for rational length so we don't go comatose */
+ if (VERSION_SZ + MSG_TYPE_SZ + c_length > in_length)
+ return RD_AP_MODIFIED;
+
+#ifndef NOENCRYPTION
+ /*
+ * decrypt to obtain length, timestamps, app_data, and checksum
+ * use the session key as an ivec
+ */
+#endif
+
+ q = p; /* mark start of encrypted stuff */
+
+#ifndef NOENCRYPTION
+ /* pcbc decrypt, use key as ivec */
+ pcbc_encrypt((C_Block *) q,(C_Block *) q, (long) c_length,
+ schedule,key,DECRYPT);
+#endif
+
+ /* safely get application data length */
+ memcpy((char *)&(m_data->app_length), (char *) p,
+ sizeof(m_data->app_length));
+ if (swap_bytes)
+ swap_u_long(m_data->app_length);
+ p += sizeof(m_data->app_length); /* skip over */
+
+ if (m_data->app_length + sizeof(c_length) + sizeof(in_length) +
+ sizeof(m_data->time_sec) + sizeof(m_data->time_5ms) +
+ sizeof(src_addr) + VERSION_SZ + MSG_TYPE_SZ
+ > in_length)
+ return RD_AP_MODIFIED;
+
+#ifndef NOENCRYPTION
+ /* we're now at the decrypted application data */
+#endif
+ m_data->app_data = p;
+
+ p += m_data->app_length;
+
+ /* safely get time_5ms */
+ memcpy((char *)&(m_data->time_5ms), (char *) p,
+ sizeof(m_data->time_5ms));
+ /* don't need to swap-- one byte for now */
+ p += sizeof(m_data->time_5ms);
+
+ /* safely get src address */
+ memcpy((char *)&src_addr, (char *) p, sizeof(src_addr));
+ /* don't swap, net order always */
+ p += sizeof(src_addr);
+
+ if (!krb_ignore_ip_address && src_addr != (u_long) sender->sin_addr.s_addr)
+ return RD_AP_MODIFIED;
+
+ /* safely get time_sec */
+ memcpy((char *)&(m_data->time_sec), (char *) p,
+ sizeof(m_data->time_sec));
+ if (swap_bytes) swap_u_long(m_data->time_sec);
+
+ p += sizeof(m_data->time_sec);
+
+ /* check direction bit is the sign bit */
+ /* For compatibility with broken old code, compares are done in VAX
+ byte order (LSBFIRST) */
+ /* However, if we don't have good ip addresses anyhow, just clear
+ the bit. This makes it harder to detect replay of sent packets
+ back to the receiver, but most higher level protocols can deal
+ with that more directly. */
+ if (krb_ignore_ip_address) {
+ if (m_data->time_sec <0)
+ m_data->time_sec = -m_data->time_sec;
+ } else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==-1)
+ /* src < recv */
+ m_data->time_sec = - m_data->time_sec;
+ else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==0)
+ if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port)==-1)
+ /* src < recv */
+ m_data->time_sec = - m_data->time_sec;
+ /*
+ * all that for one tiny bit!
+ * Heaven help those that talk to themselves.
+ */
+
+ /* check the time integrity of the msg */
+ t_local = TIME_GMT_UNIXSEC;
+ delta_t = t_local - m_data->time_sec;
+ if (delta_t < 0) delta_t = -delta_t; /* Absolute value of difference */
+ if (delta_t > CLOCK_SKEW) {
+ return(RD_AP_TIME); /* XXX should probably be better
+ code */
+ }
+ DEB (("\ndelta_t = %d",delta_t));
+
+ /*
+ * caller must check timestamps for proper order and
+ * replays, since server might have multiple clients
+ * each with its own timestamps and we don't assume
+ * tightly synchronized clocks.
+ */
+
+#ifdef notdef
+ memcpy((char *)&cksum, (char *) p, sizeof(cksum));
+ if (swap_bytes) swap_u_long(cksum)
+ /*
+ * calculate the checksum of the length, sequence,
+ * and input data, on the sending byte order!!
+ */
+ calc_cksum = quad_cksum(q,NULL,p-q,0,key);
+
+ DEB (("\ncalc_cksum = %u, received cksum = %u",
+ calc_cksum, cksum));
+ if (cksum != calc_cksum)
+ return RD_AP_MODIFIED;
+#endif
+ return RD_AP_OK; /* OK == 0 */
+}
diff --git a/src/lib/krb4/rd_req.c b/src/lib/krb4/rd_req.c
new file mode 100644
index 0000000000..07347b9055
--- /dev/null
+++ b/src/lib/krb4/rd_req.c
@@ -0,0 +1,358 @@
+/*
+ * rd_req.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "des.h"
+#include "krb.h"
+#include "prot.h"
+#include <string.h>
+
+extern int krb_ap_req_debug;
+
+/* declared in krb.h */
+int krb_ignore_ip_address = 0;
+
+/*
+ * Keep the following information around for subsequent calls
+ * to this routine by the same server using the same key.
+ */
+
+static Key_schedule serv_key; /* Key sched to decrypt ticket */
+static C_Block ky; /* Initialization vector */
+static int st_kvno; /* version number for this key */
+static char st_rlm[REALM_SZ]; /* server's realm */
+static char st_nam[ANAME_SZ]; /* service name */
+static char st_inst[INST_SZ]; /* server's instance */
+
+/*
+ * This file contains two functions. krb_set_key() takes a DES
+ * key or password string and returns a DES key (either the original
+ * key, or the password converted into a DES key) and a key schedule
+ * for it.
+ *
+ * krb_rd_req() reads an authentication request and returns information
+ * about the identity of the requestor, or an indication that the
+ * identity information was not authentic.
+ */
+
+/*
+ * krb_set_key() takes as its first argument either a DES key or a
+ * password string. The "cvt" argument indicates how the first
+ * argument "key" is to be interpreted: if "cvt" is null, "key" is
+ * taken to be a DES key; if "cvt" is non-null, "key" is taken to
+ * be a password string, and is converted into a DES key using
+ * string_to_key(). In either case, the resulting key is returned
+ * in the external static variable "ky". A key schedule is
+ * generated for "ky" and returned in the external static variable
+ * "serv_key".
+ *
+ * This routine returns the return value of des_key_sched.
+ *
+ * krb_set_key() needs to be in the same .o file as krb_rd_req() so that
+ * the key set by krb_set_key() is available in private storage for
+ * krb_rd_req().
+ */
+
+int
+krb_set_key(key,cvt)
+ char *key;
+ int cvt;
+{
+#ifdef NOENCRYPTION
+ memset(ky, 0, sizeof(ky));
+ return KSUCCESS;
+#else /* Encrypt */
+ if (cvt)
+ string_to_key(key,ky);
+ else
+ memcpy((char *)ky, key, 8);
+ return(des_key_sched(ky,serv_key));
+#endif /* NOENCRYPTION */
+}
+
+
+/*
+ * krb_rd_req() takes an AUTH_MSG_APPL_REQUEST or
+ * AUTH_MSG_APPL_REQUEST_MUTUAL message created by krb_mk_req(),
+ * checks its integrity and returns a judgement as to the requestor's
+ * identity.
+ *
+ * The "authent" argument is a pointer to the received message.
+ * The "service" and "instance" arguments name the receiving server,
+ * and are used to get the service's ticket to decrypt the ticket
+ * in the message, and to compare against the server name inside the
+ * ticket. "from_addr" is the network address of the host from which
+ * the message was received; this is checked against the network
+ * address in the ticket. If "from_addr" is zero, the check is not
+ * performed. "ad" is an AUTH_DAT structure which is
+ * filled in with information about the sender's identity according
+ * to the authenticator and ticket sent in the message. Finally,
+ * "fn" contains the name of the file containing the server's key.
+ * (If "fn" is NULL, the server's key is assumed to have been set
+ * by krb_set_key(). If "fn" is the null string ("") the default
+ * file KEYFILE, defined in "krb.h", is used.)
+ *
+ * krb_rd_req() returns RD_AP_OK if the authentication information
+ * was genuine, or one of the following error codes (defined in
+ * "krb.h"):
+ *
+ * RD_AP_VERSION - wrong protocol version number
+ * RD_AP_MSG_TYPE - wrong message type
+ * RD_AP_UNDEC - couldn't decipher the message
+ * RD_AP_INCON - inconsistencies found
+ * RD_AP_BADD - wrong network address
+ * RD_AP_TIME - client time (in authenticator)
+ * too far off server time
+ * RD_AP_NYV - Kerberos time (in ticket) too
+ * far off server time
+ * RD_AP_EXP - ticket expired
+ *
+ * For the message format, see krb_mk_req().
+ *
+ * Mutual authentication is not implemented.
+ */
+
+int INTERFACE
+krb_rd_req(authent,service,instance,from_addr,ad,fn)
+ register KTEXT authent; /* The received message */
+ char *service; /* Service name */
+ char *instance; /* Service instance */
+ long from_addr; /* Net address of originating host */
+ AUTH_DAT *ad; /* Structure to be filled in */
+ char *fn; /* Filename to get keys from */
+{
+ KTEXT_ST ticket; /* Temp storage for ticket */
+ KTEXT tkt = &ticket;
+ KTEXT_ST req_id_st; /* Temp storage for authenticator */
+ register KTEXT req_id = &req_id_st;
+
+ char realm[REALM_SZ]; /* Realm of issuing kerberos */
+ Key_schedule seskey_sched; /* Key sched for session key */
+ unsigned char skey[KKEY_SZ]; /* Session key from ticket */
+ char sname[SNAME_SZ]; /* Service name from ticket */
+ char iname[INST_SZ]; /* Instance name from ticket */
+ char r_aname[ANAME_SZ]; /* Client name from authenticator */
+ char r_inst[INST_SZ]; /* Client instance from authenticator */
+ char r_realm[REALM_SZ]; /* Client realm from authenticator */
+ unsigned int r_time_ms; /* Fine time from authenticator */
+ unsigned KRB4_32 r_time_sec; /* Coarse time from authenticator */
+ register char *ptr; /* For stepping through */
+ unsigned KRB4_32 t_local; /* Local time on our side of the protocol */
+ KRB4_32 delta_t; /* Time in authenticator minus local time */
+ KRB4_32 tkt_age; /* Age of ticket */
+ int swap_bytes; /* Need to swap bytes? */
+ int mutual; /* Mutual authentication requested? */
+ unsigned char s_kvno; /* Version number of the server's key
+ Kerberos used to encrypt ticket */
+ int status;
+
+ if (authent->length <= 0)
+ return(RD_AP_MODIFIED);
+
+ ptr = (char *) authent->dat;
+
+ /* get msg version, type and byte order, and server key version */
+
+ /* check version */
+ if (KRB_PROT_VERSION != (unsigned int) *ptr++)
+ return(RD_AP_VERSION);
+
+ /* byte order */
+ swap_bytes = 0;
+ if ((*ptr & 1) != HOST_BYTE_ORDER)
+ swap_bytes++;
+
+ /* check msg type */
+ mutual = 0;
+ switch (*ptr++ & ~1) {
+ case AUTH_MSG_APPL_REQUEST:
+ break;
+ case AUTH_MSG_APPL_REQUEST_MUTUAL:
+ mutual++;
+ break;
+ default:
+ return(RD_AP_MSG_TYPE);
+ }
+
+#ifdef lint
+ /* XXX mutual is set but not used; why??? */
+ /* this is a crock to get lint to shut up */
+ if (mutual)
+ mutual = 0;
+#endif /* lint */
+ s_kvno = *ptr++; /* get server key version */
+ (void) strcpy(realm,ptr); /* And the realm of the issuing KDC */
+ ptr += strlen(ptr) + 1; /* skip the realm "hint" */
+
+ /*
+ * If "fn" is NULL, key info should already be set; don't
+ * bother with ticket file. Otherwise, check to see if we
+ * already have key info for the given server and key version
+ * (saved in the static st_* variables). If not, go get it
+ * from the ticket file. If "fn" is the null string, use the
+ * default ticket file.
+ */
+ if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance) ||
+ strcmp(st_rlm,realm) || (st_kvno != s_kvno))) {
+ if (*fn == 0) fn = KEYFILE;
+ st_kvno = s_kvno;
+#ifndef NOENCRYPTION
+ if (read_service_key(service,instance,realm,(int) s_kvno,
+ fn,(char *)skey))
+ return(RD_AP_UNDEC);
+ if (status = krb_set_key((char *)skey,0))
+ return(status);
+#endif /* !NOENCRYPTION */
+ (void) strcpy(st_rlm,realm);
+ (void) strcpy(st_nam,service);
+ (void) strcpy(st_inst,instance);
+ }
+
+ /* Get ticket from authenticator */
+ tkt->length = (int) *ptr++;
+ if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length)
+ return(RD_AP_MODIFIED);
+ memcpy((char *)(tkt->dat), ptr+1, tkt->length);
+
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_ap_req_debug)
+ log("ticket->length: %d",tkt->length);
+ if (krb_ap_req_debug)
+ log("authent->length: %d", authent->length);
+#endif
+
+#ifndef NOENCRYPTION
+ /* Decrypt and take apart ticket */
+#endif
+
+ if (decomp_ticket(tkt,&ad->k_flags,ad->pname,ad->pinst,ad->prealm,
+ &(ad->address),ad->session, &(ad->life),
+ &(ad->time_sec),sname,iname,ky,serv_key)) {
+#ifdef KRB_CRYPT_DEBUG
+ log("Can't decode ticket");
+#endif
+ return(RD_AP_UNDEC);
+ }
+
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_ap_req_debug) {
+ log("Ticket Contents.");
+ log(" Aname: %s%s%s@%s",ad->pname,
+ ((int)*(ad->pinst) ? "." : ""), ad->pinst,
+ ((int)*(ad->prealm) ? ad->prealm : "Athena"));
+ log(" Service: %s%s%s",sname,((int)*iname ? "." : ""),iname);
+ log(" sname=%s, sinst=%s", sname, iname);
+ }
+#endif
+
+ /* Extract the authenticator */
+ req_id->length = (int) *(ptr++);
+ if ((req_id->length + (ptr + tkt->length - (char *) authent->dat)) >
+ authent->length)
+ return(RD_AP_MODIFIED);
+ memcpy((char *)(req_id->dat), ptr + tkt->length, req_id->length);
+
+#ifndef NOENCRYPTION
+ /* And decrypt it with the session key from the ticket */
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_ap_req_debug) log("About to decrypt authenticator");
+#endif
+ key_sched(ad->session,seskey_sched);
+ pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat,
+ (long) req_id->length, seskey_sched,&ad->session,DES_DECRYPT);
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_ap_req_debug) log("Done.");
+#endif
+#endif /* NOENCRYPTION */
+
+#define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED);
+
+ ptr = (char *) req_id->dat;
+ (void) strcpy(r_aname,ptr); /* Authentication name */
+ ptr += strlen(r_aname)+1;
+ check_ptr();
+ (void) strcpy(r_inst,ptr); /* Authentication instance */
+ ptr += strlen(r_inst)+1;
+ check_ptr();
+ (void) strcpy(r_realm,ptr); /* Authentication name */
+ ptr += strlen(r_realm)+1;
+ check_ptr();
+ memcpy((char *)&ad->checksum, ptr, 4); /* Checksum */
+ ptr += 4;
+ check_ptr();
+ if (swap_bytes) swap_u_long(ad->checksum);
+ r_time_ms = *(ptr++); /* Time (fine) */
+#ifdef lint
+ /* XXX r_time_ms is set but not used. why??? */
+ /* this is a crock to get lint to shut up */
+ if (r_time_ms)
+ r_time_ms = 0;
+#endif /* lint */
+ check_ptr();
+ /* assume sizeof(r_time_sec) == 4 ?? */
+ memcpy((char *)&r_time_sec, ptr, 4); /* Time (coarse) */
+ if (swap_bytes) swap_u_long(r_time_sec);
+
+ /* Check for authenticity of the request */
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_ap_req_debug)
+ log("Pname: %s %s",ad->pname,r_aname);
+#endif
+ if (strcmp(ad->pname,r_aname) != 0)
+ return(RD_AP_INCON);
+ if (strcmp(ad->pinst,r_inst) != 0)
+ return(RD_AP_INCON);
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_ap_req_debug)
+ log("Realm: %s %s",ad->prealm,r_realm);
+#endif
+ if ((strcmp(ad->prealm,r_realm) != 0))
+ return(RD_AP_INCON);
+
+ /* check the time integrity of the msg */
+ t_local = TIME_GMT_UNIXSEC;
+ delta_t = t_local - r_time_sec;
+ if (delta_t < 0) delta_t = -delta_t; /* Absolute value of difference */
+ if (delta_t > CLOCK_SKEW) {
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_ap_req_debug)
+ log("Time out of range: %d - %d = %d",
+ time_secs, r_time_sec, delta_t);
+#endif
+ return(RD_AP_TIME);
+ }
+
+ /* Now check for expiration of ticket */
+
+ tkt_age = t_local - ad->time_sec;
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_ap_req_debug)
+ log("Time: %d Issue Date: %d Diff: %d Life %x",
+ time_secs, ad->time_sec, tkt_age, ad->life);
+#endif
+ if (t_local < ad->time_sec) {
+ if ((ad->time_sec - t_local) > CLOCK_SKEW)
+ return(RD_AP_NYV);
+ }
+ else if ((t_local - ad->time_sec) > 5 * 60 * ad->life)
+ return(RD_AP_EXP);
+
+#ifdef KRB_CRYPT_DEBUG
+ if (krb_ap_req_debug)
+ log("Address: %d %d",ad->address,from_addr);
+#endif
+ if (!krb_ignore_ip_address && from_addr && (ad->address != from_addr))
+ return(RD_AP_BADD);
+
+ /* All seems OK */
+ ad->reply.length = 0;
+
+ return(RD_AP_OK);
+}
diff --git a/src/lib/krb4/rd_safe.c b/src/lib/krb4/rd_safe.c
new file mode 100644
index 0000000000..e1ea236ad1
--- /dev/null
+++ b/src/lib/krb4/rd_safe.c
@@ -0,0 +1,196 @@
+/*
+ * rd_safe.c
+ *
+ * CopKRB4_32right 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * This routine dissects a a Kerberos 'safe msg', checking its
+ * integrity, and returning a pointer to the application data
+ * contained and its length.
+ *
+ * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...)
+ *
+ * Steve Miller Project Athena MIT/DEC
+ */
+
+#include "mit-copyright.h"
+
+/* system include files */
+#include <stdio.h>
+#include <string.h>
+
+/* application include files */
+#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */
+#include "krb.h"
+#include "prot.h"
+#include "des.h"
+#include "lsb_addr_cmp.h"
+
+extern int krb_debug;
+
+/*
+ * krb_rd_safe() checks the integrity of an AUTH_MSG_SAFE message.
+ * Given the message received, "in", the length of that message,
+ * "in_length", the "key" to compute the checksum with, and the
+ * network addresses of the "sender" and "receiver" of the message,
+ * krb_rd_safe() returns RD_AP_OK if message is okay, otherwise
+ * some error code.
+ *
+ * The message data retrieved from "in" is returned in the structure
+ * "m_data". The pointer to the application data (m_data->app_data)
+ * refers back to the appropriate place in "in".
+ *
+ * See the file "mk_safe.c" for the format of the AUTH_MSG_SAFE
+ * message. The structure containing the extracted message
+ * information, MSG_DAT, is defined in "krb.h".
+ */
+
+long INTERFACE
+krb_rd_safe(in,in_length,key,sender,receiver,m_data)
+ u_char *in; /* pointer to the msg received */
+ unsigned KRB4_32 in_length; /* length of "in" msg */
+ C_Block *key; /* encryption key for seed and ivec */
+ struct sockaddr_in *sender; /* sender's address */
+ struct sockaddr_in *receiver; /* receiver's address -- me */
+ MSG_DAT *m_data; /* where to put message information */
+{
+ unsigned KRB4_32 calc_cksum[4];
+ unsigned KRB4_32 big_cksum[4];
+ int swap_bytes;
+
+ u_char *p,*q;
+ unsigned KRB4_32 src_addr; /* Can't send structs since no
+ * guarantees on size */
+ unsigned KRB4_32 t_local; /* Local time in our machine */
+ KRB4_32 delta_t; /* Difference between timestamps */
+
+ /* Be very conservative */
+ if (sizeof(src_addr) != sizeof(struct in_addr)) {
+#ifdef DEBUG
+ fprintf(stderr,"\n\
+krb_rd_safe protocol err sizeof(u_long) != sizeof(struct in_addr)");
+#endif
+ return RD_AP_VERSION;
+ }
+
+ p = in; /* beginning of message */
+ swap_bytes = 0;
+
+ if (*p++ != KRB_PROT_VERSION) return RD_AP_VERSION;
+ if (((*p) & ~1) != AUTH_MSG_SAFE) return RD_AP_MSG_TYPE;
+ if ((*p++ & 1) != HOST_BYTE_ORDER) swap_bytes++;
+
+ q = p; /* mark start of cksum stuff */
+
+ /* safely get length */
+ memcpy((char *)&(m_data->app_length), (char *)p,
+ sizeof(m_data->app_length));
+ if (swap_bytes) swap_u_long(m_data->app_length);
+ p += sizeof(m_data->app_length); /* skip over */
+
+ if (m_data->app_length + sizeof(in_length)
+ + sizeof(m_data->time_sec) + sizeof(m_data->time_5ms)
+ + sizeof(big_cksum) + sizeof(src_addr)
+ + VERSION_SZ + MSG_TYPE_SZ > in_length)
+ return(RD_AP_MODIFIED);
+
+ m_data->app_data = p; /* we're now at the application data */
+
+ /* skip app data */
+ p += m_data->app_length;
+
+ /* safely get time_5ms */
+ memcpy((char *)&(m_data->time_5ms), (char *)p,
+ sizeof(m_data->time_5ms));
+
+ /* don't need to swap-- one byte for now */
+ p += sizeof(m_data->time_5ms);
+
+ /* safely get src address */
+ memcpy((char *)&src_addr, (char *)p, sizeof(src_addr));
+
+ /* don't swap, net order always */
+ p += sizeof(src_addr);
+
+ if (!krb_ignore_ip_address && src_addr != (u_long) sender->sin_addr.s_addr)
+ return RD_AP_MODIFIED;
+
+ /* safely get time_sec */
+ memcpy((char *)&(m_data->time_sec), (char *)p,
+ sizeof(m_data->time_sec));
+ if (swap_bytes)
+ swap_u_long(m_data->time_sec);
+ p += sizeof(m_data->time_sec);
+
+ /* check direction bit is the sign bit */
+ /* For compatibility with broken old code, compares are done in VAX
+ byte order (LSBFIRST) */
+ /* However, if we don't have good ip addresses anyhow, just clear
+ the bit. This makes it harder to detect replay of sent packets
+ back to the receiver, but most higher level protocols can deal
+ with that more directly. */
+ if (krb_ignore_ip_address) {
+ if (m_data->time_sec <0)
+ m_data->time_sec = -m_data->time_sec;
+ } else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==-1)
+ /* src < recv */
+ m_data->time_sec = - m_data->time_sec;
+ else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
+ receiver->sin_addr.s_addr)==0)
+ if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port)==-1)
+ /* src < recv */
+ m_data->time_sec = - m_data->time_sec;
+
+ /*
+ * All that for one tiny bit! Heaven help those that talk to
+ * themselves.
+ */
+
+ /* check the time integrity of the msg */
+ t_local = TIME_GMT_UNIXSEC;
+ delta_t = t_local - m_data->time_sec;
+ if (delta_t < 0) delta_t = -delta_t; /* Absolute value of difference */
+ if (delta_t > CLOCK_SKEW) {
+ return(RD_AP_TIME); /* XXX should probably be better
+ code */
+ }
+
+ /*
+ * caller must check timestamps for proper order and replays, since
+ * server might have multiple clients each with its own timestamps
+ * and we don't assume tightly synchronized clocks.
+ */
+
+ memcpy((char *)big_cksum, (char *)p, sizeof(big_cksum));
+ if (swap_bytes) {
+ /* swap_u_16(big_cksum); */
+ unsigned long tt, *bb;
+ bb = (unsigned long*)big_cksum;
+ tt = bb[0]; swap_u_long(tt); bb[0] = tt;
+ tt = bb[1]; swap_u_long(tt); bb[1] = tt;
+ tt = bb[2]; swap_u_long(tt); bb[2] = tt;
+ tt = bb[3]; swap_u_long(tt); bb[3] = tt;
+ }
+
+#ifdef NOENCRYPTION
+ memset(calc_cksum, 0, sizeof(calc_cksum));
+#else /* Do encryption */
+ /* calculate the checksum of the length, timestamps, and
+ * input data, on the sending byte order !! */
+ quad_cksum(q,calc_cksum,p-q,2,key);
+#endif /* NOENCRYPTION */
+
+ DEB (("\n0: calc %l big %lx\n1: calc %lx big %lx\n2: calc %lx big %lx\n3: calc %lx big %lx\n",
+ calc_cksum[0], big_cksum[0],
+ calc_cksum[1], big_cksum[1],
+ calc_cksum[2], big_cksum[2],
+ calc_cksum[3], big_cksum[3]));
+ if (memcmp((char *)big_cksum,(char *)calc_cksum,sizeof(big_cksum)))
+ return(RD_AP_MODIFIED);
+
+ return(RD_AP_OK); /* OK == 0 */
+}
diff --git a/src/lib/krb4/rd_svc_key.c b/src/lib/krb4/rd_svc_key.c
new file mode 100644
index 0000000000..cd457eb423
--- /dev/null
+++ b/src/lib/krb4/rd_svc_key.c
@@ -0,0 +1,206 @@
+/*
+ * rd_svc_key.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include "krb.h"
+#include <stdio.h>
+#include <string.h>
+
+/*
+ * The private keys for servers on a given host are stored in a
+ * "srvtab" file (typically "/etc/srvtab"). This routine extracts
+ * a given server's key from the file.
+ *
+ * read_service_key() takes the server's name ("service"), "instance",
+ * and "realm" and a key version number "kvno", and looks in the given
+ * "file" for the corresponding entry, and if found, returns the entry's
+ * key field in "key".
+ *
+ * If "instance" contains the string "*", then it will match
+ * any instance, and the chosen instance will be copied to that
+ * string. For this reason it is important that the there is enough
+ * space beyond the "*" to receive the entry.
+ *
+ * If "kvno" is 0, it is treated as a wild card and the first
+ * matching entry regardless of the "vno" field is returned.
+ *
+ * This routine returns KSUCCESS on success, otherwise KFAILURE.
+ *
+ * The format of each "srvtab" entry is as follows:
+ *
+ * Size Variable Field in file
+ * ---- -------- -------------
+ * string serv server name
+ * string inst server instance
+ * string realm server realm
+ * 1 byte vno server key version #
+ * 8 bytes key server's key
+ * ... ... ...
+ */
+
+#ifdef __i960__
+/* special hack to use a global srvtab variable... */
+#define open vxworks_srvtab_open
+#define close vxworks_srvtab_close
+#define getst vxworks_srvtab_getst
+#define read vxworks_srvtab_read
+
+extern char *vxworks_srvtab_base;
+char *vxworks_srvtab_ptr;
+int vxworks_srvtab_getchar(s)
+ char *s;
+{
+ int tmp1;
+ if(vxworks_srvtab_ptr >= (vxworks_srvtab_base + strlen(vxworks_srvtab_base)))
+ return 0;
+
+ sscanf(vxworks_srvtab_ptr, "%2x", &tmp1);
+
+ *s = tmp1;
+ vxworks_srvtab_ptr+=2;
+ return 1;
+}
+
+int vxworks_srvtab_getst(fd,s,n)
+ int fd;
+ register char *s;
+ int n;
+{
+ register count = n;
+ while (vxworks_srvtab_getchar(s) && --count)
+ if (*s++ == '\0')
+ return (n - count);
+ *s = '\0';
+ return (n - count);
+}
+
+int vxworks_srvtab_open(s, n, m)
+ char *s;
+ int n, m;
+{
+ vxworks_srvtab_ptr = vxworks_srvtab_base;
+ return 1;
+}
+
+int vxworks_srvtab_close(fd)
+ int fd;
+{
+ vxworks_srvtab_ptr = 0;
+ return 0;
+}
+
+int vxworks_srvtab_read(fd, s, n)
+ int fd;
+ char *s;
+ int n;
+{
+ int count = n;
+ /* we want to get exactly n chars. */
+ while(vxworks_srvtab_getchar(s) && --count)
+ s++;
+ return (n-count);
+}
+#endif
+
+int read_service_key(service,instance,realm,kvno,file,key)
+ char *service; /* Service Name */
+ char *instance; /* Instance name or "*" */
+ char *realm; /* Realm */
+ int kvno; /* Key version number */
+ char *file; /* Filename */
+ char *key; /* Pointer to key to be filled in */
+{
+ return get_service_key(service,instance,realm,&kvno,file,key);
+}
+
+/* kvno is passed by reference, so that if it is zero, and we find a match,
+ the match gets written back into *kvno so the caller can find it.
+ */
+int get_service_key(service,instance,realm,kvno,file,key)
+ char *service; /* Service Name */
+ char *instance; /* Instance name or "*" */
+ char *realm; /* Realm */
+ int *kvno; /* Key version number */
+ char *file; /* Filename */
+ char *key; /* Pointer to key to be filled in */
+{
+ char serv[SNAME_SZ];
+ char inst[INST_SZ];
+ char rlm[REALM_SZ];
+ unsigned char vno; /* Key version number */
+ int wcard;
+ char krb_realm[REALM_SZ];
+
+ int stab, open();
+
+ if (!file)
+ file = KEYFILE;
+
+ if ((stab = open(file, 0, 0)) < 0)
+ return(KFAILURE);
+
+ wcard = (instance[0] == '*') && (instance[1] == '\0');
+ /* get current realm if not passed in */
+ if (!realm) {
+ int rem;
+
+ rem = krb_get_lrealm(krb_realm,1);
+ if (rem != KSUCCESS)
+ return(rem);
+ realm = krb_realm;
+ }
+
+ while(getst(stab,serv,SNAME_SZ) > 0) { /* Read sname */
+ (void) getst(stab,inst,INST_SZ); /* Instance */
+ (void) getst(stab,rlm,REALM_SZ); /* Realm */
+ /* Vers number */
+ if (read(stab,(char *)&vno,1) != 1) {
+ close(stab);
+ return(KFAILURE);
+ }
+ /* Key */
+ if (read(stab,key,8) != 8) {
+ close(stab);
+ return(KFAILURE);
+ }
+ /* Is this the right service */
+ if (strcmp(serv,service))
+ continue;
+ /* How about instance */
+ if (!wcard && strcmp(inst,instance))
+ continue;
+ if (wcard)
+ (void) strncpy(instance,inst,INST_SZ);
+ /* Is this the right realm */
+#if defined(ATHENA_COMPAT) || defined(ATHENA_OLD_SRVTAB)
+ /* XXX For backward compatibility: if keyfile says "Athena"
+ and caller wants "ATHENA.MIT.EDU", call it a match */
+ if (strcmp(rlm,realm) &&
+ (strcmp(rlm,"Athena") ||
+ strcmp(realm,"ATHENA.MIT.EDU")))
+ continue;
+#else /* ! ATHENA_COMPAT */
+ if (strcmp(rlm,realm))
+ continue;
+#endif /* ATHENA_COMPAT */
+
+ /* How about the key version number */
+ if (*kvno && *kvno != (int) vno)
+ continue;
+
+ (void) close(stab);
+ *kvno = vno;
+ return(KSUCCESS);
+ }
+
+ /* Can't find the requested service */
+ (void) close(stab);
+ return(KFAILURE);
+}
diff --git a/src/lib/krb4/realmofhost.c b/src/lib/krb4/realmofhost.c
new file mode 100644
index 0000000000..2114b516a1
--- /dev/null
+++ b/src/lib/krb4/realmofhost.c
@@ -0,0 +1,141 @@
+/*
+ * realmofhost.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * routine to convert hostname into realm name.
+ */
+
+#include "mit-copyright.h"
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <netdb.h> /* For struct hostent, gethostbyname, etc */
+#include <sys/param.h> /* For MAXHOSTNAMELEN */
+#ifdef POSIX
+#include <stdlib.h>
+#else
+extern char *malloc();
+#endif
+#define DEFINE_SOCKADDR /* Ask for MAXHOSTNAMELEN */
+#include "krb.h"
+
+/*
+ * krb_realmofhost.
+ * Given a fully-qualified domain-style primary host name,
+ * return the name of the Kerberos realm for the host.
+ * If the hostname contains no discernable domain, or an error occurs,
+ * return the local realm name, as supplied by get_krbrlm().
+ * If the hostname contains a domain, but no translation is found,
+ * the hostname's domain is converted to upper-case and returned.
+ *
+ * The format of each line of the translation file is:
+ * domain_name kerberos_realm
+ * -or-
+ * host_name kerberos_realm
+ *
+ * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU)
+ * host names should be in the usual form (e.g. FOO.BAR.BAZ)
+ */
+
+static char ret_realm[REALM_SZ+1];
+
+char * INTERFACE
+krb_realmofhost(host)
+char *host;
+{
+ char *domain;
+ FILE *trans_file;
+ FILE *krb__get_realmsfile();
+ char trans_host[MAXHOSTNAMELEN+1];
+ char trans_realm[REALM_SZ+1];
+ int retval;
+ struct hostent *h;
+ char *lhost;
+
+ /* First, canonicalize it. This is in case the caller
+ didn't have a fully qualified domain name. */
+ if ((h=gethostbyname(host)) == NULL)
+ lhost = host;
+ else {
+ lhost = h->h_name;
+#ifdef DO_REVERSE_RESOLVE
+ if (h->h_addr_list != NULL && h->h_addr_list[0] != NULL) {
+ char *rev_addr; int rev_type, rev_len;
+
+ rev_type = h->h_addrtype;
+ rev_len = h->h_length;
+ rev_addr = malloc(rev_len);
+ if (rev_addr != NULL) {
+ memcpy(rev_addr, h->h_addr_list[0], rev_len);
+ h = gethostbyaddr(rev_addr, rev_len, rev_type);
+ free(rev_addr);
+ if (h == NULL)
+ lhost = host;
+ else
+ lhost = h->h_name;
+ }
+ }
+#endif
+ }
+
+ domain = strchr(lhost, '.');
+
+ /* prepare default */
+ if (domain) {
+ char *cp;
+
+ /* If the domain is just below the top, e.g., CYGNUS.COM,
+ then we special-case it; if someone really wants a
+ realm called COM they will just have to specify it
+ properly. */
+ if (((cp = strchr(domain+1, '.')) == (char *) 0)
+ /* Handle root domain properly (COM.): */
+ || (*(cp + 1) == '\0'))
+ domain = lhost - 1; /* -1 fakes "period" before domain */
+
+ strncpy(ret_realm, domain+1, REALM_SZ);
+ ret_realm[REALM_SZ] = '\0';
+ /* Upper-case realm */
+ for (cp = ret_realm; *cp; cp++)
+ if (islower(*cp))
+ *cp = toupper(*cp);
+ } else {
+ krb_get_lrealm(ret_realm, 1);
+ }
+
+ if ((trans_file = krb__get_realmsfile()) == (FILE *) 0)
+ /* krb_errno = KRB_NO_TRANS */
+ return(ret_realm);
+
+ /* loop while not exact match, and more entries to read */
+ while (1) {
+ if ((retval = fscanf(trans_file, "%s %s",
+ trans_host, trans_realm)) != 2) {
+ if (retval == EOF)
+ break;
+ continue; /* ignore broken lines */
+ }
+ trans_host[MAXHOSTNAMELEN] = '\0';
+ trans_realm[REALM_SZ] = '\0';
+ if (trans_host[0] == '.') {
+ /* want domain match only */
+ if (domain && !strcasecmp (trans_host, domain)) {
+ /* got domain match, save for later */
+ (void) strcpy (ret_realm, trans_realm);
+ continue;
+ }
+ } else {
+ /* want exact match of hostname */
+ if (!strcasecmp (trans_host, lhost)) {
+ (void) strcpy (ret_realm, trans_realm);
+ break;
+ }
+ }
+ }
+ fclose (trans_file);
+ return ret_realm;
+}
diff --git a/src/lib/krb4/recvauth.c b/src/lib/krb4/recvauth.c
new file mode 100644
index 0000000000..a7fd9b4568
--- /dev/null
+++ b/src/lib/krb4/recvauth.c
@@ -0,0 +1,282 @@
+/*
+ * recvauth.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+
+#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */
+#include "krb.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
+ chars */
+
+/*
+ * If the protocol changes, you will need to change the version string
+ * and make appropriate changes in krb_sendauth.c
+ * be sure to support old versions of krb_sendauth!
+ */
+
+extern int errno;
+
+/*
+ * krb_recvauth() reads (and optionally responds to) a message sent
+ * using krb_sendauth(). The "options" argument is a bit-field of
+ * selected options (see "sendauth.c" for options description).
+ * The only option relevant to krb_recvauth() is KOPT_DO_MUTUAL
+ * (mutual authentication requested). The "fd" argument supplies
+ * a file descriptor to read from (and write to, if mutual authenti-
+ * cation is requested).
+ *
+ * Part of the received message will be a Kerberos ticket sent by the
+ * client; this is read into the "ticket" argument. The "service" and
+ * "instance" arguments supply the server's Kerberos name. If the
+ * "instance" argument is the string "*", it is treated as a wild card
+ * and filled in during the krb_rd_req() call (see read_service_key()).
+ *
+ * The "faddr" and "laddr" give the sending (client) and receiving
+ * (local server) network addresses. ("laddr" may be left NULL unless
+ * mutual authentication is requested, in which case it must be set.)
+ *
+ * The authentication information extracted from the message is returned
+ * in "kdata". The "filename" argument indicates the file where the
+ * server's key can be found. (It is passed on to krb_rd_req().) If
+ * left null, the default "/etc/srvtab" will be used.
+ *
+ * If mutual authentication is requested, the session key schedule must
+ * be computed in order to reply; this schedule is returned in the
+ * "schedule" argument. A string containing the application version
+ * number from the received message is returned in "version", which
+ * should be large enough to hold a KRB_SENDAUTH_VLEN-character string.
+ *
+ * See krb_sendauth() for the format of the received client message.
+ *
+ * This routine supports another client format, for backward
+ * compatibility, consisting of:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * string tmp_buf, tkt_len length of ticket, in
+ * ascii
+ *
+ * char ' ' (space char) separator
+ *
+ * tkt_len ticket->dat the ticket
+ *
+ * This old-style version does not support mutual authentication.
+ *
+ * krb_recvauth() first reads the protocol version string from the
+ * given file descriptor. If it doesn't match the current protocol
+ * version (KRB_SENDAUTH_VERS), the old-style format is assumed. In
+ * that case, the string of characters up to the first space is read
+ * and interpreted as the ticket length, then the ticket is read.
+ *
+ * If the first string did match KRB_SENDAUTH_VERS, krb_recvauth()
+ * next reads the application protocol version string. Then the
+ * ticket length and ticket itself are read.
+ *
+ * The ticket is decrypted and checked by the call to krb_rd_req().
+ * If no mutual authentication is required, the result of the
+ * krb_rd_req() call is retured by this routine. If mutual authenti-
+ * cation is required, a message in the following format is returned
+ * on "fd":
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * 4 bytes tkt_len length of ticket or -1
+ * if error occurred
+ *
+ * priv_len tmp_buf "private" message created
+ * by krb_mk_priv() which
+ * contains the incremented
+ * checksum sent by the client
+ * encrypted in the session
+ * key. (This field is not
+ * present in case of error.)
+ *
+ * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some
+ * other error code is returned.
+ */
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif /* max */
+
+int INTERFACE
+krb_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata,
+ filename, schedule, version)
+long options; /* bit-pattern of options */
+int fd; /* file descr. to read from */
+KTEXT ticket; /* storage for client's ticket */
+char *service; /* service expected */
+char *instance; /* inst expected (may be filled in) */
+struct sockaddr_in *faddr; /* address of foreign host on fd */
+struct sockaddr_in *laddr; /* local address */
+AUTH_DAT *kdata; /* kerberos data (returned) */
+char *filename; /* name of file with service keys */
+Key_schedule schedule; /* key schedule (return) */
+char *version; /* version string (filled in) */
+{
+
+ int i, cc, old_vers = 0;
+ char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */
+ char *cp;
+ int rem;
+ KRB4_32 tkt_len, priv_len;
+ unsigned KRB4_32 cksum;
+ u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)];
+
+ /* read the protocol version number */
+ if (krb_net_read(fd, krb_vers, KRB_SENDAUTH_VLEN) !=
+ KRB_SENDAUTH_VLEN)
+ return(errno);
+ krb_vers[KRB_SENDAUTH_VLEN] = '\0';
+
+ /* check version string */
+ if (strcmp(krb_vers,KRB_SENDAUTH_VERS)) {
+ /* Assume the old version of sendkerberosdata: send ascii
+ length, ' ', and ticket. */
+ if (options & KOPT_DO_MUTUAL)
+ return(KFAILURE); /* XXX can't do old style with mutual auth */
+ old_vers = 1;
+
+ /* copy what we have read into tmp_buf */
+ (void) memcpy((char *) tmp_buf, krb_vers, KRB_SENDAUTH_VLEN);
+
+ /* search for space, and make it a null */
+ for (i = 0; i < KRB_SENDAUTH_VLEN; i++)
+ if (tmp_buf[i]== ' ') {
+ tmp_buf[i] = '\0';
+ /* point cp to the beginning of the real ticket */
+ cp = (char *) &tmp_buf[i+1];
+ break;
+ }
+
+ if (i == KRB_SENDAUTH_VLEN)
+ /* didn't find the space, keep reading to find it */
+ for (; i<20; i++) {
+ if (read(fd, (char *)&tmp_buf[i], 1) != 1) {
+ return(KFAILURE);
+ }
+ if (tmp_buf[i] == ' ') {
+ tmp_buf[i] = '\0';
+ /* point cp to the beginning of the real ticket */
+ cp = (char *) &tmp_buf[i+1];
+ break;
+ }
+ }
+
+ tkt_len = (KRB4_32) atoi((char *) tmp_buf);
+
+ /* sanity check the length */
+ /* These conditions make sure that cp got initialized */
+ if ((i==20)||(tkt_len<=0)||(tkt_len>MAX_KTXT_LEN))
+ return(KFAILURE);
+
+ if (i < KRB_SENDAUTH_VLEN) {
+ /* since we already got the space, and part of the ticket,
+ we read fewer bytes to get the rest of the ticket */
+ if (krb_net_read(fd, (char *)(tmp_buf+KRB_SENDAUTH_VLEN),
+ (int) (tkt_len - KRB_SENDAUTH_VLEN + 1 + i))
+ != (int)(tkt_len - KRB_SENDAUTH_VLEN + 1 + i))
+ return(errno);
+ } else {
+ if (krb_net_read(fd, (char *)(tmp_buf+i), (int)tkt_len) !=
+ (int) tkt_len)
+ return(errno);
+ }
+ ticket->length = tkt_len;
+ /* copy the ticket into the struct */
+ (void) memcpy((char *) ticket->dat, cp, ticket->length);
+
+ } else {
+ /* read the application version string */
+ if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) !=
+ KRB_SENDAUTH_VLEN)
+ return(errno);
+ version[KRB_SENDAUTH_VLEN] = '\0';
+
+ /* get the length of the ticket */
+ if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) !=
+ sizeof(tkt_len))
+ return(errno);
+
+ /* sanity check */
+ ticket->length = ntohl((unsigned KRB4_32)tkt_len);
+ if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) {
+ if (options & KOPT_DO_MUTUAL) {
+ rem = KFAILURE;
+ goto mutual_fail;
+ } else
+ return(KFAILURE); /* XXX there may still be junk on the fd? */
+ }
+
+ /* read the ticket */
+ if (krb_net_read(fd, (char *) ticket->dat, ticket->length)
+ != ticket->length)
+ return(errno);
+ }
+ /*
+ * now have the ticket. decrypt it to get the authenticated
+ * data.
+ */
+ rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr,
+ kdata,filename);
+
+ if (old_vers) return(rem); /* XXX can't do mutual with old client */
+
+ /* if we are doing mutual auth, compose a response */
+ if (options & KOPT_DO_MUTUAL) {
+ if (rem != KSUCCESS)
+ /* the krb_rd_req failed */
+ goto mutual_fail;
+
+ /* add one to the (formerly) sealed checksum, and re-seal it
+ for return to the client */
+ cksum = kdata->checksum + 1;
+ cksum = htonl(cksum);
+#ifndef NOENCRYPTION
+ key_sched(kdata->session,schedule);
+#endif /* !NOENCRYPTION */
+ priv_len = krb_mk_priv((unsigned char *)&cksum,
+ tmp_buf,
+ (unsigned KRB4_32) sizeof(cksum),
+ schedule,
+ &kdata->session,
+ laddr,
+ faddr);
+ if (priv_len < 0) {
+ /* re-sealing failed; notify the client */
+ rem = KFAILURE; /* XXX */
+mutual_fail:
+ priv_len = -1;
+ tkt_len = htonl((unsigned KRB4_32) priv_len);
+ /* a length of -1 is interpreted as an authentication
+ failure by the client */
+ if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
+ != sizeof(tkt_len))
+ return(cc);
+ return(rem);
+ } else {
+ /* re-sealing succeeded, send the private message */
+ tkt_len = htonl((unsigned KRB4_32)priv_len);
+ if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
+ != sizeof(tkt_len))
+ return(cc);
+ if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len))
+ != (int) priv_len)
+ return(cc);
+ }
+ }
+ return(rem);
+}
diff --git a/src/lib/krb4/ren-cyg.sh b/src/lib/krb4/ren-cyg.sh
new file mode 100644
index 0000000000..d3d31a9d41
--- /dev/null
+++ b/src/lib/krb4/ren-cyg.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# Rename Kerberos Cygnus V4 filenames to proposed names
+# for converting old trees.
+awk '/^@ / { if ($6 != "")
+ if ($6 != $4)
+ print "mv " $6 " " $4
+ else ;
+ else if ($2 != $4 && $2 != "-")
+ print "mv " $2 " " $4
+ }
+ ' <ren.msg | grep -v '(gone)' | sh -x
diff --git a/src/lib/krb4/ren-pc.bat b/src/lib/krb4/ren-pc.bat
new file mode 100644
index 0000000000..e25755fdb1
--- /dev/null
+++ b/src/lib/krb4/ren-pc.bat
@@ -0,0 +1,29 @@
+rename crerrep.c cr_err_repl.c
+rename crauthre.c cr_auth_repl.c
+rename cr_death.c cr_death_pkt.c
+rename crticket.c cr_tkt.c
+rename decomtkt.c decomp_tkt.c
+rename getadtkt.c g_ad_tkt.c
+rename getadmhs.c g_admhst.c
+rename get_cred.c g_cred.c
+rename getintkt.c g_pw_in_tkt.c
+rename getkrbhs.c g_krbhst.c
+rename getphost.c g_phost.c
+rename getpwtkt.c g_pw_tkt.c
+rename get_req.c g_request.c
+rename g_svctkt.c g_svc_in_tkt.c
+rename gettfnam.c g_tf_fname.c
+rename gettfrlm.c g_tf_realm.c
+rename getrealm.c realmofhost.c
+rename k_gethst.c gethostname.c
+rename knm_pars.c kname_parse.c
+rename k_errtxt.c err_txt.c
+rename k_gettkt.c g_in_tkt.c
+rename mth_snam.c month_sname.c
+rename pkt_ciph.c pkt_cipher.c
+rename rdservky.c rd_svc_key.c
+rename savecred.c save_creds.c
+rename send_kdc.c send_to_kdc.c
+rename s_cascmp.c strcasecmp.c
+rename tkt_strg.c tkt_string.c
+rename util.c ad_print.c
diff --git a/src/lib/krb4/ren-pc.sh b/src/lib/krb4/ren-pc.sh
new file mode 100644
index 0000000000..bea2beb01a
--- /dev/null
+++ b/src/lib/krb4/ren-pc.sh
@@ -0,0 +1,7 @@
+# Rename Kerberos V4 MIT PC-port filenames to proposed names
+# for converting old PC trees on Unix systems.
+awk '/^@ / {
+ if ($3 != $4 && $3 != "-")
+ print "mv " $3 " " $4
+ }
+ ' <ren.msg | grep -v '(gone)' | sh -x
diff --git a/src/lib/krb4/ren-pl10.sh b/src/lib/krb4/ren-pl10.sh
new file mode 100644
index 0000000000..d72a72c509
--- /dev/null
+++ b/src/lib/krb4/ren-pl10.sh
@@ -0,0 +1,7 @@
+# Rename Kerberos V4 pl10 filenames to proposed names
+# for converting old trees.
+awk '/^@ / {
+ if ($2 != $4 && $2 != "-")
+ print "mv " $2 " " $4
+ }
+ ' <ren.msg | grep -v '(gone)' | sh -x
diff --git a/src/lib/krb4/ren.msg b/src/lib/krb4/ren.msg
new file mode 100644
index 0000000000..45b404afab
--- /dev/null
+++ b/src/lib/krb4/ren.msg
@@ -0,0 +1,117 @@
+Subject: Kerberos file renaming for short DOS names
+Date: Tue, 19 Apr 1994 13:34:28 -0700
+From: John Gilmore <gnu@cygnus.com>
+
+[edited since sending, to bring it up to date with what actually happened.]
+
+I'd like to come up with some file naming and configuration
+conventions that will work in DOS, Unix, and Mac environments. At
+Cygnus, we are creating a single freely available K4 source tree that
+works on many Unixes, Windows, and Mac. It currently works on Unixes.
+(To get a copy, send mail to info@cygnus.com requesting our Kerberos
+release. It's in a hidden FTP location due to export control.)
+
+I diffed the current MIT release of Kerberos for PC and Windows
+against the V4 patchlevel 10 release, and identified some 30 files in
+lib/krb that have been renamed between Unix and PC. Comparing source
+trees becomes much more painful when files are renamed. If we don't
+come to sync on the file names, it will be very hard to collaborate,
+which would make more work for all of us.
+
+My plan, which we have used successfully in the GNU software, is to
+make sure that all filenames are unique if you take the first 8 chars
+and the first 3 after the dot. No files have more than a single dot
+in them. We don't restrict file names to just 8.3 characters, since
+doing so would impact readability for the (99.9%) of the developers
+who are on Unix or Mac, where long file names are fine.
+
+There's an additional complication that names longer than 14
+characters present problems to old System V Unix and to `ar' on Unix.
+DJ Delorie's excellent `doschk' program points out all these problems.
+(prep.ai.mit.edu:/pub/gnu/doschk-1.1.tar.gz).
+
+Here's my proposal for the lib/krb directory. In general, I tried to
+regularize the names, turning get_ into g_, removing krb_, turning
+reply into repl, turning ticket into tkt, keeping all file names
+unique across the various libraries, and making a file name more like
+the function name contained in it when there were conflicts. Some
+resulting truncated names are more readable than in the current MIT K4
+PC, some are less readable -- but the overall advantage is that the
+new names should be acceptable to Unix/Mac developers, while the old
+ones weren't.
+
+ MIT K4 patch10 MIT K4 PC PROPOSED NAME (trunc to 8.3) old Cyg
+$1 $2 $3 $4 $5 $6
+
+@ add_ticket.c (gone) add_tkt.c add_tkt.c
+@ - - ChangeLog changelo
+@ cr_err_reply.c crerrep.c cr_err_repl.c cr_err_r.c
+@ create_auth_reply.c crauthre.c cr_auth_repl.c cr_auth_.c cr_auth_reply.c
+@ create_ciph.c cr_ciph.c cr_ciph.c cr_ciph.c
+@ create_death_packet.c cr_death.c cr_death_pkt.c cr_death.c cr_death_pkt.c
+@ create_ticket.c crticket.c cr_tkt.c cr_tkt.c
+@ debug_decl.c debug.c debug.c debug.c
+@ decomp_ticket.c decomtkt.c decomp_tkt.c decomp_t.c
+@ - - DNR.c dnr.c
+@ extract_ticket.c ext_tkt.c ext_tkt.c ext_tkt.c extract_tkt.c
+@ - - g_cnffile.c g_cnffil.c
+@ get_ad_tkt.c getadtkt.c g_ad_tkt.c g_ad_tkt.c
+@ get_admhst.c getadmhs.c g_admhst.c g_admhst.c
+@ get_cred.c get_cred.c g_cred.c g_cred.c
+@ get_in_tkt.c getintkt.c g_pw_in_tkt.c g_pw_in_.c
+@ get_krbhst.c getkrbhs.c g_krbhst.c g_krbhst.c
+@ get_krbrlm.c g_krbrlm.c g_krbrlm.c g_krbrlm.c
+@ get_phost.c getphost.c g_phost.c g_phost.c
+@ get_pw_tkt.c getpwtkt.c g_pw_tkt.c g_pw_tkt.c
+@ get_request.c get_req.c (gone) (gone)
+@ get_svc_in_tkt.c g_svctkt.c g_svc_in_tkt.c g_svc_in.c get_svc_in.c
+@ get_tf_fullname.c gettfnam.c g_tf_fname.c g_tf_fna.c get_tf_fname.c
+@ get_tf_realm.c gettfrlm.c g_tf_realm.c g_tf_rea.c
+@ - - g_tkt_svc.c g_tkt_sv.c
+@ getrealm.c getrealm.c realmofhost.c realmofh.c
+@ k_gethostname.c k_gethst.c gethostname.c gethostn.c
+@ kname_parse.c knm_pars.c kname_parse.c kname_pa.c
+@ krb_err_txt.c k_errtxt.c err_txt.c err_txt.c
+@ krb_get_in_tkt.c k_gettkt.c g_in_tkt.c g_in_tkt.c krb_get_in.c
+@ - - mac_store.c mac_stor.c
+@ - - mac_store.h mac_stor.h
+@ - - mac_stubs.c mac_stub.c
+@ - - Makefile.in makefile.in
+@ - - mk_preauth.c mk_preau.c
+@ month_sname.c mth_snam.c month_sname.c month_sn.c
+@ pkt_cipher.c pkt_ciph.c pkt_cipher.c pkt_ciph.c
+@ - - Password.c password.c
+@ - - rd_preauth.c rd_preau.c
+@ - - put_svc_key.c put_svc_.c
+@ read_service_key.c rdservky.c rd_svc_key.c rd_svc_k.c read_svc_key.c
+@ save_credentials.c savecred.c save_creds.c save_cre.c save_creds.c
+@ send_to_kdc.c send_kdc.c send_to_kdc.c send_to_.c
+@ strcasecmp.c s_cascmp.c strcasecmp.c strcasec.c
+@ tkt_string.c tkt_strg.c tkt_string.c tkt_stri.c
+@ - - unix_glue.c unix_glu.c
+@ util.c util.c ad_print.c ad_print.c
+@ - - win_store.c win_stor.c
+# Cleanup for simplified sed scripts that use this table
+@sed s/tf_ad_print\./tf_util\./g
+
+I've supplied Unix shell scripts in the distribution for moving:
+ren-pl10.sh V4 pl10 filenames to proposed names for converting old trees
+ren-pc.sh V4 MIT PC names to proposed names for converting old trees
+ren2long.sh truncated names to proposed names for moving DOS->unix
+ren2dos.sh proposed names to truncated names for unix->DOS names
+
+There's also shell scripts to produce sed scripts for converting Makefiles
+and documentation. You use them like:
+ ./sed-pl10.sh >/tmp/sed
+ sed -f /tmp/sed <Makefile >newMakefile
+sed-pl10.sh V4 pl10 filenames to proposed names for converting old trees
+sed-pc.sh V4 MIT PC names to proposed names for converting old trees
+
+I'll also supply a DOS script for moving:
+ren-pc.bat V4 MIT PC names to proposed names for converting old trees
+
+And an MPW script for moving
+ren-pl10.mpw V4 pl10 filenames to proposed names for converting old trees
+
+ John Gilmore
+ Cygnus Support
diff --git a/src/lib/krb4/ren2dos.sh b/src/lib/krb4/ren2dos.sh
new file mode 100644
index 0000000000..3989e2c6e9
--- /dev/null
+++ b/src/lib/krb4/ren2dos.sh
@@ -0,0 +1,7 @@
+# Rename Unix filenames to DOS-truncated filenames for KRB library.
+# for converting Unix distributions to DOS distributions
+awk '/^@ / {
+ if ($4 != $5)
+ print "mv " $4 " " $5
+ }
+ ' <ren.msg | sh -x
diff --git a/src/lib/krb4/ren2long.sh b/src/lib/krb4/ren2long.sh
new file mode 100644
index 0000000000..7d1a25966f
--- /dev/null
+++ b/src/lib/krb4/ren2long.sh
@@ -0,0 +1,7 @@
+# Rename DOS-truncated filenames to Unix filenames for KRB library.
+# for converting DOS distributions to Unix distributions
+awk '/^@ / {
+ if ($4 != $5)
+ print "mv " $5 " " $4
+ }
+ ' <ren.msg | sh -x
diff --git a/src/lib/krb4/save_creds.c b/src/lib/krb4/save_creds.c
new file mode 100644
index 0000000000..d8a89cdcfa
--- /dev/null
+++ b/src/lib/krb4/save_creds.c
@@ -0,0 +1,54 @@
+/*
+ * save_creds.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include "krb.h"
+
+/*
+ * This routine takes a ticket and associated info and calls
+ * tf_save_cred() to store them in the ticket cache. The peer
+ * routine for extracting a ticket and associated info from the
+ * ticket cache is krb_get_cred(). When changes are made to
+ * this routine, the corresponding changes should be made
+ * in krb_get_cred() as well.
+ *
+ * Returns KSUCCESS if all goes well, otherwise an error returned
+ * by the tf_init() or tf_save_cred() routines.
+ *
+ * This used to just be called save_credentials, but when we formalized
+ * the DOS/Mac interface, we created and exported krb_save_credentials
+ * to avoid namespace pollution.
+ */
+
+int INTERFACE
+krb_save_credentials(service, instance, realm, session, lifetime, kvno,
+ ticket, issue_date)
+ char *service; /* Service name */
+ char *instance; /* Instance */
+ char *realm; /* Auth domain */
+ C_Block session; /* Session key */
+ int lifetime; /* Lifetime */
+ int kvno; /* Key version number */
+ KTEXT ticket; /* The ticket itself */
+ long issue_date; /* The issue time */
+{
+ int tf_status; /* return values of the tf_util calls */
+
+ /* Open and lock the ticket file for writing */
+ if ((tf_status = tf_init(TKT_FILE, W_TKT_FIL)) != KSUCCESS)
+ return(tf_status);
+
+ /* Save credentials by appending to the ticket file */
+ tf_status = tf_save_cred(service, instance, realm, session,
+ lifetime, kvno, ticket, issue_date);
+ (void) tf_close();
+ return (tf_status);
+}
diff --git a/src/lib/krb4/sed-cyg.sh b/src/lib/krb4/sed-cyg.sh
new file mode 100644
index 0000000000..3859df1383
--- /dev/null
+++ b/src/lib/krb4/sed-cyg.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+# Produce a sed script for converting Kerberos Cygnus V4 filenames to proposed
+# names -- for converting old makefiles and doc.
+# We fix any "oldfoo." into "newfoo." including .c and .o and .h files.
+awk '/^@ / { if ($6 != "")
+ if ($6 != $4)
+ print "s/" $6 "/" $4 "/g"
+ else ;
+ else if ($2 != $4 && $2 != "-")
+ print "s/" $2 "/" $4 "/g"
+ }
+ /^@sed / { print $2 }
+ ' <ren.msg | grep -v '(gone)' | sed 's/\.c/\\./g'
diff --git a/src/lib/krb4/sed-pc.sh b/src/lib/krb4/sed-pc.sh
new file mode 100644
index 0000000000..a222dca3ff
--- /dev/null
+++ b/src/lib/krb4/sed-pc.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# Produce a sed script for converting Kerberos V4 MIT PC filenames to proposed
+# names -- for converting old makefiles and doc.
+# We fix any "oldfoo." into "newfoo." including .c and .o and .h files.
+awk '/^@ / {
+ if ($3 != $4)
+ print "s/" $3 "/" $4 "/g"
+ }
+ /^@sed / { print $2 }
+ ' <ren.msg | grep -v '(gone)' | sed 's/\.c/\\./g'
+
diff --git a/src/lib/krb4/sed-pl10.sh b/src/lib/krb4/sed-pl10.sh
new file mode 100644
index 0000000000..a6ab27c969
--- /dev/null
+++ b/src/lib/krb4/sed-pl10.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+# Produce a sed script for converting Kerberos V4 pl10 filenames to proposed
+# names -- for converting old makefiles and doc.
+# We fix any "oldfoo." into "newfoo." including .c and .o and .h files.
+awk '/^@ / {
+ if ($2 != $4)
+ print "s/" $2 "/" $4 "/g"
+ }
+ /^@sed / { print $2 }
+ ' <ren.msg | sed 's/\.c/\\./g'
diff --git a/src/lib/krb4/send_to_kdc.c b/src/lib/krb4/send_to_kdc.c
new file mode 100644
index 0000000000..f6bec2881e
--- /dev/null
+++ b/src/lib/krb4/send_to_kdc.c
@@ -0,0 +1,388 @@
+/*
+ * send_to_kdc.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+
+#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */
+#include "krb.h"
+#include "krbports.h"
+#include "prot.h"
+#include <stdio.h>
+#include <string.h>
+
+#define S_AD_SZ sizeof(struct sockaddr_in)
+
+#ifdef POSIX
+#include <stdlib.h>
+#else
+extern char *malloc(), *calloc(), *realloc();
+#endif
+
+static int cached_krb_udp_port = 0;
+static int cached_krbsec_udp_port = 0;
+
+static int
+send_recv PROTOTYPE ((KTEXT pkt, KTEXT rpkt, SOCKET f,
+ struct sockaddr_in *_to, struct hostent *addrs));
+
+
+#ifdef DEBUG
+static char *prog = "send_to_kdc";
+#endif
+
+/*
+ * send_to_kdc() sends a message to the Kerberos authentication
+ * server(s) in the given realm and returns the reply message.
+ * The "pkt" argument points to the message to be sent to Kerberos;
+ * the "rpkt" argument will be filled in with Kerberos' reply.
+ * The "realm" argument indicates the realm of the Kerberos server(s)
+ * to transact with. If the realm is null, the local realm is used.
+ *
+ * If more than one Kerberos server is known for a given realm,
+ * different servers will be queried until one of them replies.
+ * Several attempts (retries) are made for each server before
+ * giving up entirely.
+ *
+ * The following results can be returned:
+ *
+ * KSUCCESS - an answer was received from a Kerberos host
+ *
+ * SKDC_CANT - can't get local realm
+ * - can't find "kerberos" in /etc/services database
+ * - can't open socket
+ * - can't bind socket
+ * - all ports in use
+ * - couldn't find any Kerberos host
+ *
+ * SKDC_RETRY - couldn't get an answer from any Kerberos server,
+ * after several retries
+ */
+
+send_to_kdc(pkt,rpkt,realm)
+ KTEXT pkt;
+ KTEXT rpkt;
+ char *realm;
+{
+ int i;
+ SOCKET f;
+ int no_host; /* was a kerberos host found? */
+ int retry;
+ int n_hosts;
+ int retval;
+ struct sockaddr_in to;
+ struct hostent FAR *farkedhost;
+ struct hostent *host, *hostlist;
+ char *cp;
+ char krbhst[MAXHOSTNAMELEN];
+ char lrealm[REALM_SZ];
+ char *scol;
+ int krb_udp_port = 0;
+ int krbsec_udp_port = 0;
+ int default_port;
+
+ /*
+ * If "realm" is non-null, use that, otherwise get the
+ * local realm.
+ */
+ if (realm)
+ (void) strcpy(lrealm, realm);
+ else
+ if (krb_get_lrealm(lrealm,1)) {
+ DEB (("%s: can't get local realm\n", prog));
+ return(SKDC_CANT);
+ }
+ DEB (("lrealm is %s\n", lrealm));
+
+ if (SOCKET_INITIALIZE()) {
+ DEB (("%s: can't initialize sockets library\n",prog));
+ return (SKDC_CANT);
+ }
+ /* from now on, exit through rtn label for cleanup */
+
+ /* The first time, decide what port to use for the KDC. */
+ if (cached_krb_udp_port == 0) {
+ register struct servent FAR *sp;
+ if (sp = getservbyname("kerberos","udp"))
+ cached_krb_udp_port = sp->s_port;
+ else
+ cached_krb_udp_port = htons(KERBEROS_PORT); /* kerberos/udp */
+ DEB (("cached_krb_udp_port is %d\n", cached_krb_udp_port));
+ }
+ /* If kerberos/udp isn't 750, try using kerberos-sec/udp (or 750)
+ as a fallback. */
+ if (cached_krbsec_udp_port == 0 &&
+ cached_krb_udp_port != htons(KERBEROS_PORT)) {
+ register struct servent FAR *sp;
+ if (sp = getservbyname("kerberos-sec","udp"))
+ cached_krbsec_udp_port = sp->s_port;
+ else
+ cached_krbsec_udp_port = htons(KERBEROS_PORT); /* kerberos/udp */
+ DEB (("cached_krbsec_udp_port is %d\n", cached_krbsec_udp_port));
+ }
+
+ memset((char *)&to, 0, S_AD_SZ);
+ hostlist = (struct hostent *) malloc(sizeof(struct hostent));
+ if (!hostlist) {
+ retval = /*errno */SKDC_CANT;
+ goto rtn_clean; /* Run SOCKET_CLEANUP then return. */
+ }
+ hostlist->h_name = 0; /* so it gets properly freed at "rtn" */
+
+ f = socket(AF_INET, SOCK_DGRAM, 0);
+ if (f == INVALID_SOCKET) {
+ DEB (("%s: Can't open socket\n", prog));
+ retval = /*errno */SKDC_CANT;
+ goto rtn_clean; /* Run SOCKET_CLEANUP then return. */
+ }
+
+/*
+** FIXME! FTP Software's WINSOCK implmentation insists that
+** a socket be bound before it can receive datagrams.
+** This is outside specs. Since it shouldn't hurt any
+** other implementations we'll go ahead and do it for
+** now.
+*/
+ {
+ struct sockaddr_in from;
+ memset ((char *)&from, 0, S_AD_SZ);
+ from.sin_family = AF_INET;
+ from.sin_addr.s_addr = INADDR_ANY;
+ if ( bind(f, (struct sockaddr *)&from, S_AD_SZ) == SOCKET_ERROR ) {
+ DEB (("%s : Can't bind\n", prog));
+ retval = SKDC_CANT;
+ goto rtn;
+ }
+ }
+/* End of kludge (FIXME) for FTP Software WinSock stack. */
+
+ no_host = 1;
+ default_port = 0;
+ /* get an initial allocation */
+ n_hosts = 0;
+ for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) {
+#ifdef DEBUG
+ if (krb_debug) {
+ DEB (("Getting host entry for %s...",krbhst));
+ (void) fflush(stdout);
+ }
+#endif
+ if (0 != (scol = strchr(krbhst,':'))) {
+ krb_udp_port = htons(atoi(scol+1));
+ *scol = 0;
+ if (krb_udp_port == 0) {
+#ifdef DEBUG
+ if (krb_debug) {
+ DEB (("bad port number %s\n",scol+1));
+ (void) fflush(stdout);
+ }
+#endif
+ continue;
+ }
+ krbsec_udp_port = 0;
+ } else {
+ krb_udp_port = cached_krb_udp_port;
+ krbsec_udp_port = cached_krbsec_udp_port;
+ default_port = 1;
+ }
+ farkedhost = gethostbyname(krbhst);
+#ifdef DEBUG
+ if (krb_debug) {
+ DEB (("%s.\n", farkedhost ? "Got it" : "Didn't get it"));
+ (void) fflush(stdout);
+ }
+#endif
+ if (!farkedhost)
+ continue;
+ no_host = 0; /* found at least one */
+ n_hosts++;
+ /* preserve host network address to check later
+ * (would be better to preserve *all* addresses,
+ * take care of that later)
+ */
+ hostlist = (struct hostent *)
+ realloc((char *)hostlist,
+ (unsigned)
+ sizeof(struct hostent)*(n_hosts+1));
+ if (!hostlist) {
+ retval = /*errno */SKDC_CANT;
+ goto rtn;
+ }
+ hostlist[n_hosts-1] = *farkedhost; /* Copy into array */
+ memset((char *)&hostlist[n_hosts], 0, sizeof(struct hostent));
+ host = &hostlist[n_hosts-1];
+ cp = malloc((unsigned)host->h_length);
+ if (!cp) {
+ retval = /*errno */SKDC_CANT;
+ goto rtn;
+ }
+ _fmemcpy(cp, host->h_addr, host->h_length);
+
+/* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2
+ (or worse) only return one name ... */
+#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
+ host->h_addr_list = (char **)malloc(sizeof(char *));
+ if (!host->h_addr_list) {
+ retval = /*errno */SKDC_CANT;
+ goto rtn;
+ }
+#endif /* ULTRIX022 || SunOS */
+ host->h_addr = cp;
+ to.sin_family = host->h_addrtype;
+ memcpy((char *)&to.sin_addr, host->h_addr,
+ host->h_length);
+ to.sin_port = krb_udp_port;
+ if (send_recv(pkt, rpkt, f, &to, hostlist)) {
+ retval = KSUCCESS;
+ goto rtn;
+ }
+ if (krbsec_udp_port) {
+ to.sin_port = krbsec_udp_port;
+ if (send_recv(pkt, rpkt, f, &to, hostlist)) {
+ retval = KSUCCESS;
+ goto rtn;
+ }
+ }
+ DEB (("Timeout, error, or wrong descriptor\n"));
+ }
+ if (no_host) {
+ DEB (("%s: can't find any Kerberos host.\n", prog));
+ retval = SKDC_CANT;
+ goto rtn;
+ }
+
+ /* retry each host in sequence */
+ for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) {
+ for (host = hostlist; host->h_name != (char *)NULL; host++) {
+ to.sin_family = host->h_addrtype;
+ memcpy((char *)&to.sin_addr, host->h_addr,
+ host->h_length);
+ if (send_recv(pkt, rpkt, f, &to, hostlist)) {
+ retval = KSUCCESS;
+ goto rtn;
+ }
+ }
+ }
+ retval = SKDC_RETRY;
+rtn:
+ (void) closesocket (f);
+rtn_clean:
+ SOCKET_CLEANUP(); /* Done with using sockets for awhile */
+ if (hostlist) {
+ register struct hostent *hp;
+ for (hp = hostlist; hp->h_name; hp++)
+#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
+ if (hp->h_addr_list) {
+#endif /* ULTRIX022 || SunOS */
+ if (hp->h_addr)
+ free(hp->h_addr);
+#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40))
+ free((char *)hp->h_addr_list);
+ }
+#endif /* ULTRIX022 || SunOS */
+ free((char *)hostlist);
+ }
+ return(retval);
+}
+
+/*
+ * try to send out and receive message.
+ * return 1 on success, 0 on failure
+ */
+
+static int
+send_recv(pkt,rpkt,f,_to,addrs)
+ KTEXT pkt;
+ KTEXT rpkt;
+ SOCKET f;
+ struct sockaddr_in *_to;
+ struct hostent *addrs;
+{
+ fd_set readfds;
+ register struct hostent *hp;
+ struct sockaddr_in from;
+ int sin_size;
+ int numsent;
+ int selresult;
+ int recvresult;
+ struct timeval timeout;
+
+#ifdef DEBUG
+ if (krb_debug) {
+ if (_to->sin_family == AF_INET) {
+ printf("Sending message to ");
+ far_fputs (inet_ntoa(_to->sin_addr), stdout);
+ printf("...");
+ } else
+ printf("Sending message...");
+ (void) fflush(stdout);
+ }
+#endif
+ if ((numsent = sendto(f,(char *)(pkt->dat), pkt->length, 0,
+ (struct sockaddr *)_to,
+ S_AD_SZ)) != pkt->length) {
+ DEB (("sent only %d/%d\n",numsent, pkt->length));
+ return 0;
+ }
+#ifdef DEBUG
+ if (krb_debug) {
+ printf("Sent\nWaiting for reply...");
+ (void) fflush(stdout);
+ }
+#endif
+ FD_ZERO(&readfds);
+ FD_SET(f, &readfds);
+ SOCKET_SET_ERRNO (0);
+
+ /* select - either recv is ready, or timeout */
+ /* see if timeout or error or wrong descriptor */
+ /* Need to fill in the timeout structure each time, because on some
+ systems -- e.g., Linux -- the timeout will be modified in place
+ by the select syscall. */
+ timeout.tv_sec = CLIENT_KRB_TIMEOUT;
+ timeout.tv_usec = 0;
+ selresult = select(SOCKET_NFDS(f), &readfds, (fd_set *)0, (fd_set *)0,
+ &timeout);
+ if (selresult != 1 || !FD_ISSET(f, &readfds)) {
+#ifdef DEBUG
+ if (krb_debug) {
+ fprintf(stderr, "select failed: selresult=%d, readfds=%x, errno=%d",
+ selresult, readfds, SOCKET_ERRNO);
+ perror("");
+ }
+#endif
+ return 0;
+ }
+
+ sin_size = sizeof(from);
+ recvresult = recvfrom(f, (char *)(rpkt->dat), sizeof(rpkt->dat), 0,
+ (struct sockaddr *)&from, &sin_size);
+ if (recvresult < 0) {
+ DEB (("Recvfrom error %d\n", SOCKET_ERRNO));
+ return 0;
+ }
+#ifdef DEBUG
+ if (krb_debug) {
+ printf("received packet from ");
+ far_fputs (inet_ntoa(from.sin_addr), stdout);
+ printf("\n");
+ fflush(stdout);
+ }
+#endif
+ for (hp = addrs; hp->h_name != (char *)NULL; hp++) {
+ if (!memcmp(hp->h_addr, (char *)&from.sin_addr.s_addr,
+ hp->h_length)) {
+ DEB (("Received it\n"));
+ return 1;
+ }
+ DEB (("packet not from %x\n", hp->h_addr));
+ }
+ DEB (("%s: received packet from wrong host! (%x)\n",
+ "send_to_kdc(send_rcv)", from.sin_addr.s_addr));
+ return 0;
+}
diff --git a/src/lib/krb4/sendauth.c b/src/lib/krb4/sendauth.c
new file mode 100644
index 0000000000..8d079f9107
--- /dev/null
+++ b/src/lib/krb4/sendauth.c
@@ -0,0 +1,278 @@
+/*
+ * sendauth.c
+ *
+ * CoKRB4_32yright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ */
+
+#include "mit-copyright.h"
+
+#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */
+#include "krb.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */
+/*
+ * If the protocol changes, you will need to change the version string
+ * and make appropriate changes in krb_recvauth.c
+ */
+
+/*
+ * This file contains two routines: krb_sendauth() and krb_sendsrv().
+ *
+ * krb_sendauth() transmits a ticket over a file descriptor for a
+ * desired service, instance, and realm, doing mutual authentication
+ * with the server if desired.
+ *
+ * Most of the real work of krb_sendauth() has been moved into mk_auth.c
+ * for portability; sendauth takes a Unix file descriptor as argument,
+ * which doesn't work on other operating systems.
+ *
+ * krb_sendsvc() sends a service name to a remote knetd server, and is
+ * only for Athena compatability.
+ */
+
+/*
+ * The first argument to krb_sendauth() contains a bitfield of
+ * options (the options are defined in "krb.h"):
+ *
+ * KOPT_DONT_CANON Don't canonicalize instance as a hostname.
+ * (If this option is not chosen, krb_get_phost()
+ * is called to canonicalize it.)
+ *
+ * KOPT_DONT_MK_REQ Don't request server ticket from Kerberos.
+ * A ticket must be supplied in the "ticket"
+ * argument.
+ * (If this option is not chosen, and there
+ * is no ticket for the given server in the
+ * ticket cache, one will be fetched using
+ * krb_mk_req() and returned in "ticket".)
+ *
+ * KOPT_DO_MUTUAL Do mutual authentication, requiring that the
+ * receiving server return the checksum+1 encrypted
+ * in the session key. The mutual authentication
+ * is done using krb_mk_priv() on the other side
+ * (see "recvauth.c") and krb_rd_priv() on this
+ * side.
+ *
+ * The "fd" argument is a file descriptor to write to the remote
+ * server on. The "ticket" argument is used to store the new ticket
+ * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is
+ * chosen, the ticket must be supplied in the "ticket" argument.
+ * The "service", "inst", and "realm" arguments identify the ticket.
+ * If "realm" is null, the local realm is used.
+ *
+ * The following arguments are only needed if the KOPT_DO_MUTUAL option
+ * is chosen:
+ *
+ * The "checksum" argument is a number that the server will add 1 to
+ * to authenticate itself back to the client; the "msg_data" argument
+ * holds the returned mutual-authentication message from the server
+ * (i.e., the checksum+1); the "cred" structure is used to hold the
+ * session key of the server, extracted from the ticket file, for use
+ * in decrypting the mutual authentication message from the server;
+ * and "schedule" holds the key schedule for that decryption. The
+ * the local and server addresses are given in "laddr" and "faddr".
+ *
+ * The application protocol version number (of up to KRB_SENDAUTH_VLEN
+ * characters) is passed in "version".
+ *
+ * If all goes well, KSUCCESS is returned, otherwise some error code.
+ *
+ * The format of the message sent to the server is:
+ *
+ * Size Variable Field
+ * ---- -------- -----
+ *
+ * KRB_SENDAUTH_VLEN KRB_SENDAUTH_VER sendauth protocol
+ * bytes version number
+ *
+ * KRB_SENDAUTH_VLEN version application protocol
+ * bytes version number
+ *
+ * 4 bytes ticket->length length of ticket
+ *
+ * ticket->length ticket->dat ticket itself
+ */
+
+/*
+ * XXX: Note that krb_rd_priv() is coded in such a way that
+ * "msg_data->app_data" will be pointing into "packet", which
+ * will disappear when krb_sendauth() returns.
+ *
+ * See FIXME KLUDGE code in appl/bsd/kcmd.c.
+ */
+KRB4_32 __krb_sendauth_hidden_tkt_len;
+#define raw_tkt_len __krb_sendauth_hidden_tkt_len
+
+
+/*
+ * Read a server's sendauth response out of a file descriptor.
+ * Returns a Kerberos error code.
+ *
+ * Note sneaky code using raw_tkt_len to stash away a bit of info
+ * for use by appl/bsd/kcmd.c. Now that krb_net_rd_sendauth is
+ * a separate function, kcmd should call it directly to get this
+ * sneaky info.
+ */
+int
+krb_net_rd_sendauth (fd, reply, raw_len)
+ int fd; /* file descriptor to write onto */
+ KTEXT reply; /* Where we put the reply message */
+ char *raw_len; /* Where to read the length field info */
+{
+ KRB4_32 tkt_len;
+ int got;
+
+ reply->length = 0; /* Nothing read from net yet */
+ reply->mbz = 0;
+
+ /* get the length of the reply */
+ reread:
+ got = krb_net_read(fd, raw_len, sizeof(KRB4_32));
+ if (got != sizeof(KRB4_32))
+ return KFAILURE;
+
+ /* Here's an amazing hack. If we are contacting an rlogin server,
+ and it is running on a Sun4, and it was compiled with the wrong
+ shared libary version, it will print an ld.so warning message
+ when it starts up. We just ignore any such message and keep
+ going. This doesn't affect security: we just require the
+ ticket to follow the warning message. */
+ if ((*(unsigned long *)raw_len
+ == (('l' << 24) | ('d' << 16) | ('.' << 8) | 's'))) {
+ char c;
+
+ while (krb_net_read(fd, &c, 1) == 1 && c != '\n')
+ ;
+ goto reread;
+ }
+
+ tkt_len = ntohl(*(unsigned long *)raw_len);
+
+ /* if the length is negative, the server failed to recognize us. */
+ if ((tkt_len < 0) || (tkt_len > sizeof(reply->dat)))
+ return KFAILURE; /* XXX */
+ /* read the reply... */
+ got = krb_net_read(fd, (char *)reply->dat, (int) tkt_len);
+ if (got != (int) tkt_len)
+ return KFAILURE;
+
+ reply->length = tkt_len;
+ reply->mbz = 0;
+ return KSUCCESS;
+}
+
+
+/*
+ * krb_sendauth
+ *
+ * The original routine, provided on Unix.
+ * Obtains a service ticket using the ticket-granting ticket,
+ * uses it to stuff an authorization request down a Unix socket to the
+ * end-user application server, sucks a response out of the socket,
+ * and decodes it to verify mutual authentication.
+ */
+int
+krb_sendauth(options, fd, ticket, service, inst, realm, checksum,
+ msg_data, cred, schedule, laddr, faddr, version)
+ long options; /* bit-pattern of options */
+ int fd; /* file descriptor to write onto */
+ KTEXT ticket; /* where to put ticket (return); or
+ supplied in case of KOPT_DONT_MK_REQ */
+ char *service, *inst, *realm; /* service name, instance, realm */
+ unsigned KRB4_32 checksum; /* checksum to include in request */
+ MSG_DAT *msg_data; /* mutual auth MSG_DAT (return) */
+ CREDENTIALS *cred; /* credentials (return) */
+ Key_schedule schedule; /* key schedule (return) */
+ struct sockaddr_in *laddr; /* local address */
+ struct sockaddr_in *faddr; /* address of foreign host on fd */
+ char *version; /* version string */
+{
+ int rem, cc;
+ char srv_inst[INST_SZ];
+ char krb_realm[REALM_SZ];
+ KTEXT_ST packet[1]; /* Re-use same one for msg and reply */
+
+ /* get current realm if not passed in */
+ if (!realm) {
+ rem = krb_get_lrealm(krb_realm,1);
+ if (rem != KSUCCESS)
+ return(rem);
+ realm = krb_realm;
+ }
+
+ /* copy instance into local storage, so mk_auth can canonicalize */
+ (void) strncpy(srv_inst, inst, INST_SZ);
+ rem = krb_mk_auth (options, ticket, service, srv_inst, realm, checksum,
+ version, packet);
+ if (rem != KSUCCESS)
+ return rem;
+
+#ifdef ATHENA_COMPAT
+ /* this is only for compatibility with old servers */
+ if (options & KOPT_DO_OLDSTYLE) {
+ (void) sprintf(buf,"%d ",ticket->length);
+ (void) write(fd, buf, strlen(buf));
+ (void) write(fd, (char *) ticket->dat, ticket->length);
+ return(rem);
+ }
+#endif /* ATHENA_COMPAT */
+
+ /* write the request to the server */
+ if ((cc = krb_net_write(fd, packet->dat, packet->length)) != packet->length)
+ return(cc);
+
+ /* mutual authentication, if desired */
+ if (options & KOPT_DO_MUTUAL) {
+ /* get credentials so we have service session
+ key for decryption below */
+ if (cc = krb_get_cred(service, srv_inst, realm, cred))
+ return(cc);
+
+ /* Get the reply out of the socket. */
+ cc = krb_net_rd_sendauth (fd, packet, (char *)&raw_tkt_len);
+ if (cc != KSUCCESS)
+ return cc;
+
+ /* Check the reply to verify that server is really who we expect. */
+ cc = krb_check_auth (packet, checksum,
+ msg_data, cred->session, schedule, laddr, faddr);
+ if (cc != KSUCCESS)
+ return cc;
+ }
+ return(KSUCCESS);
+}
+
+
+#ifdef ATHENA_COMPAT
+/*
+ * krb_sendsvc
+ */
+
+int
+krb_sendsvc(fd, service)
+ int fd;
+ char *service;
+{
+ /* write the service name length and then the service name to
+ the fd */
+ KRB4_32 serv_length;
+ int cc;
+
+ serv_length = htonl((unsigned long)strlen(service));
+ if ((cc = krb_net_write(fd, (char *) &serv_length,
+ sizeof(serv_length)))
+ != sizeof(serv_length))
+ return(cc);
+ if ((cc = krb_net_write(fd, service, strlen(service)))
+ != strlen(service))
+ return(cc);
+ return(KSUCCESS);
+}
+#endif /* ATHENA_COMPAT */
diff --git a/src/lib/krb4/setenv.c b/src/lib/krb4/setenv.c
new file mode 100644
index 0000000000..76a2a615b4
--- /dev/null
+++ b/src/lib/krb4/setenv.c
@@ -0,0 +1,164 @@
+/*
+ * 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 "conf.h"
+#include <stdio.h>
+#include <string.h>
+
+/*
+ * setenv --
+ * Set the value of the environmental variable "name" to be
+ * "value". If rewrite is set, replace any current value.
+ */
+int 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);
+ memcpy(P, environ, 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.
+ */
+
+#ifndef HAVE_GETENV
+#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));
+}
+#endif
+/*
+ * _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);
+}
diff --git a/src/lib/krb4/stime.c b/src/lib/krb4/stime.c
new file mode 100644
index 0000000000..f90fbc566a
--- /dev/null
+++ b/src/lib/krb4/stime.c
@@ -0,0 +1,40 @@
+/*
+ * stime.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#define DEFINE_SOCKADDR
+#define NEED_TIME_H
+#include "krb.h"
+#include <stdio.h> /* for sprintf() */
+
+/*
+ * Given a pointer to a long containing the number of seconds
+ * since the beginning of time (midnight 1 Jan 1970 GMT), return
+ * a string containing the local time in the form:
+ *
+ * "25-Jan-88 10:17:56"
+ */
+
+char *krb_stime(t)
+ long *t;
+{
+ static char st[40];
+ static time_t adjusted_time;
+ struct tm *tm;
+ char *month_sname();
+
+ adjusted_time = *t - CONVERT_TIME_EPOCH;
+ tm = localtime(&adjusted_time);
+ (void) sprintf(st,"%2d-%s-%02d %02d:%02d:%02d",tm->tm_mday,
+ month_sname(tm->tm_mon + 1),tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ return st;
+}
+
diff --git a/src/lib/krb4/strcasecmp.c b/src/lib/krb4/strcasecmp.c
new file mode 100644
index 0000000000..31bf0afbff
--- /dev/null
+++ b/src/lib/krb4/strcasecmp.c
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison. The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char charmap[] = {
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+ '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+ '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+ '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+ '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+ '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+ '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+ '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+ '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+ '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+ '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+strcasecmp(s1, s2)
+ char *s1, *s2;
+{
+ register unsigned char *cm = charmap,
+ *us1 = (unsigned char *)s1,
+ *us2 = (unsigned char *)s2;
+
+ while (cm[*us1] == cm[*us2++])
+ if (*us1++ == '\0')
+ return(0);
+ return(cm[*us1] - cm[*--us2]);
+}
+
+strncasecmp(s1, s2, n)
+ char *s1, *s2;
+ register int n;
+{
+ register unsigned char *cm = charmap,
+ *us1 = (unsigned char *)s1,
+ *us2 = (unsigned char *)s2;
+
+ while (--n >= 0 && cm[*us1] == cm[*us2++])
+ if (*us1++ == '\0')
+ return(0);
+ return(n < 0 ? 0 : cm[*us1] - cm[*--us2]);
+}
diff --git a/src/lib/krb4/swab.c b/src/lib/krb4/swab.c
new file mode 100644
index 0000000000..e07b28b434
--- /dev/null
+++ b/src/lib/krb4/swab.c
@@ -0,0 +1,18 @@
+/* simple implementation of swab. */
+
+swab(from,to,nbytes)
+ char *from;
+ char *to;
+ int nbytes;
+{
+ char tmp;
+ while ( (nbytes-=2) >= 0 ) {
+ tmp = from[1];
+ to[1] = from[0];
+ to[0] = tmp;
+ to++; to++;
+ from++; from++;
+ }
+}
+
+
diff --git a/src/lib/krb4/tf_shm.c b/src/lib/krb4/tf_shm.c
new file mode 100644
index 0000000000..bd08f7f722
--- /dev/null
+++ b/src/lib/krb4/tf_shm.c
@@ -0,0 +1,171 @@
+/*
+ * tf_shm.c
+ *
+ * Copyright 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ *
+ * Shared memory segment functions for session keys. Derived from code
+ * contributed by Dan Kolkowitz (kolk@jessica.stanford.edu).
+ */
+
+#include "mit-copyright.h"
+
+#include <stdio.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "krb.h"
+#include "des.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define MAX_BUFF sizeof(des_cblock)*1000 /* room for 1k keys */
+
+extern int krb_debug;
+
+/*
+ * krb_create_shmtkt:
+ *
+ * create a shared memory segment for session keys, leaving its id
+ * in the specified filename.
+ */
+
+int
+krb_shm_create(file_name)
+char *file_name;
+{
+ int retval;
+ int shmid;
+ struct shmid_ds shm_buf;
+ FILE *sfile;
+ uid_t me, metoo, getuid(), geteuid();
+
+ (void) krb_shm_dest(file_name); /* nuke it if it exists...
+ this cleans up to make sure we
+ don't slowly lose memory. */
+
+ shmid = shmget((long)IPC_PRIVATE,MAX_BUFF, IPC_CREAT);
+ if (shmid == -1) {
+ if (krb_debug)
+ perror("krb_shm_create shmget");
+ return(KFAILURE); /* XXX */
+ }
+ me = getuid();
+ metoo = geteuid();
+ /*
+ * now set up the buffer so that we can modify it
+ */
+ shm_buf.shm_perm.uid = me;
+ shm_buf.shm_perm.gid = getgid();
+ shm_buf.shm_perm.mode = 0600;
+ if (shmctl(shmid,IPC_SET,&shm_buf) < 0) { /*can now map it */
+ if (krb_debug)
+ perror("krb_shm_create shmctl");
+ (void) shmctl(shmid, IPC_RMID, 0);
+ return(KFAILURE); /* XXX */
+ }
+#if !defined(_AIX)
+ (void) shmctl(shmid, SHM_LOCK, 0); /* attempt to lock-in-core */
+#endif
+ /* arrange so the file is owned by the ruid
+ (swap real & effective uid if necessary). */
+ if (me != metoo) {
+ if (setreuid(metoo, me) < 0) {
+ /* can't switch??? barf! */
+ if (krb_debug)
+ perror("krb_shm_create: setreuid");
+ (void) shmctl(shmid, IPC_RMID, 0);
+ return(KFAILURE);
+ } else
+ if (krb_debug)
+ printf("swapped UID's %d and %d\n",metoo,me);
+ }
+ if ((sfile = fopen(file_name,"w")) == 0) {
+ if (krb_debug)
+ perror("krb_shm_create file");
+ (void) shmctl(shmid, IPC_RMID, 0);
+ return(KFAILURE); /* XXX */
+ }
+ if (fchmod(fileno(sfile),0600) < 0) {
+ if (krb_debug)
+ perror("krb_shm_create fchmod");
+ (void) shmctl(shmid, IPC_RMID, 0);
+ return(KFAILURE); /* XXX */
+ }
+ if (me != metoo) {
+ if (setreuid(me, metoo) < 0) {
+ /* can't switch??? barf! */
+ if (krb_debug)
+ perror("krb_shm_create: setreuid2");
+ (void) shmctl(shmid, IPC_RMID, 0);
+ return(KFAILURE);
+ } else
+ if (krb_debug)
+ printf("swapped UID's %d and %d\n",me,metoo);
+ }
+
+ (void) fprintf(sfile,"%d",shmid);
+ (void) fflush(sfile);
+ (void) fclose(sfile);
+ return(KSUCCESS);
+}
+
+
+/*
+ * krb_is_diskless:
+ *
+ * check / to see if file .diskless exists. If so it is diskless.
+ * Do it this way now to avoid dependencies on a particular routine.
+ * Choose root file system since that will be private to the client.
+ */
+
+int krb_is_diskless()
+{
+ struct stat buf;
+ if (stat("/.diskless",&buf) < 0)
+ return(0);
+ else return(1);
+}
+
+/*
+ * krb_shm_dest: destroy shared memory segment with session keys, and remove
+ * file pointing to it.
+ */
+
+int krb_shm_dest(file)
+char *file;
+{
+ int shmid;
+ FILE *sfile;
+ struct stat st_buf;
+
+ if (stat(file,&st_buf) == 0) {
+ /* successful stat */
+ if ((sfile = fopen(file,"r")) == 0) {
+ if (krb_debug)
+ perror("cannot open shared memory file");
+ return(KFAILURE); /* XXX */
+ }
+ if (fscanf(sfile,"%d",&shmid) == 1) {
+ if (shmctl(shmid,IPC_RMID,0) != 0) {
+ if (krb_debug)
+ perror("krb_shm_dest: cannot delete shm segment");
+ (void) fclose(sfile);
+ return(KFAILURE); /* XXX */
+ }
+ } else {
+ if (krb_debug)
+ fprintf(stderr, "bad format in shmid file\n");
+ (void) fclose(sfile);
+ return(KFAILURE); /* XXX */
+ }
+ (void) fclose(sfile);
+ (void) unlink(file);
+ return(KSUCCESS);
+ } else
+ return(RET_TKFIL); /* XXX */
+}
+
+
+
diff --git a/src/lib/krb4/tf_util.c b/src/lib/krb4/tf_util.c
new file mode 100644
index 0000000000..717f2dae25
--- /dev/null
+++ b/src/lib/krb4/tf_util.c
@@ -0,0 +1,630 @@
+/*
+ * tf_util.c
+ *
+ * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+
+#include "krb.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+
+#ifdef TKT_SHMEM
+#include <sys/param.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* TKT_SHMEM */
+
+#define TOO_BIG -1
+#define TF_LCK_RETRY ((unsigned)2) /* seconds to sleep before
+ * retry if ticket file is
+ * locked */
+extern int errno;
+extern int krb_debug;
+
+#ifdef TKT_SHMEM
+char *krb_shm_addr;
+static char *tmp_shm_addr;
+static const char krb_dummy_skey[8];
+
+char *shmat();
+#endif /* TKT_SHMEM */
+
+#ifdef NEED_UTIMES
+
+#include <sys/time.h>
+#include <unistd.h>
+#ifdef __SCO__
+#include <utime.h>
+#endif
+#ifdef __svr4__
+#include <utime.h>
+#endif
+int utimes(path, times)
+ char* path;
+ struct timeval times[2];
+{
+ struct utimbuf tv;
+ tv.actime = times[0].tv_sec;
+ tv.modtime = times[1].tv_sec;
+ return utime(path,&tv);
+}
+#endif
+#ifndef LOCK_SH
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* don't block when locking */
+#define LOCK_UN 8 /* unlock */
+#endif
+#ifdef POSIX
+#include <fcntl.h>
+
+/*
+ * This function emulates a subset of flock()
+ */
+int emul_flock(fd, cmd)
+ int fd, cmd;
+{
+ struct flock f;
+
+ memset(&f, 0, sizeof (f));
+
+ if (cmd & LOCK_UN)
+ f.l_type = F_UNLCK;
+ if (cmd & LOCK_SH)
+ f.l_type = F_RDLCK;
+ if (cmd & LOCK_EX)
+ f.l_type = F_WRLCK;
+
+ return fcntl(fd, (cmd & LOCK_NB) ? F_SETLK : F_SETLKW, &f);
+}
+
+#define flock(f,c) emul_flock(f,c)
+#endif
+
+
+/*
+ * fd must be initialized to something that won't ever occur as a real
+ * file descriptor. Since open(2) returns only non-negative numbers as
+ * valid file descriptors, and tf_init always stuffs the return value
+ * from open in here even if it is an error flag, we must
+ * a. Initialize fd to a negative number, to indicate that it is
+ * not initially valid.
+ * b. When checking for a valid fd, assume that negative values
+ * are invalid (ie. when deciding whether tf_init has been
+ * called.)
+ * c. In tf_close, be sure it gets reinitialized to a negative
+ * number.
+ */
+static int fd = -1;
+static int curpos; /* Position in tfbfr */
+static int lastpos; /* End of tfbfr */
+static char tfbfr[BUFSIZ]; /* Buffer for ticket data */
+
+static tf_gets(), tf_read();
+
+/*
+ * This file contains routines for manipulating the ticket cache file.
+ *
+ * The ticket file is in the following format:
+ *
+ * principal's name (null-terminated string)
+ * principal's instance (null-terminated string)
+ * CREDENTIAL_1
+ * CREDENTIAL_2
+ * ...
+ * CREDENTIAL_n
+ * EOF
+ *
+ * Where "CREDENTIAL_x" consists of the following fixed-length
+ * fields from the CREDENTIALS structure (see "krb.h"):
+ *
+ * char service[ANAME_SZ]
+ * char instance[INST_SZ]
+ * char realm[REALM_SZ]
+ * C_Block session
+ * int lifetime
+ * int kvno
+ * KTEXT_ST ticket_st
+ * long issue_date
+ *
+ * Short description of routines:
+ *
+ * tf_init() opens the ticket file and locks it.
+ *
+ * tf_get_pname() returns the principal's name.
+ *
+ * tf_get_pinst() returns the principal's instance (may be null).
+ *
+ * tf_get_cred() returns the next CREDENTIALS record.
+ *
+ * tf_save_cred() appends a new CREDENTIAL record to the ticket file.
+ *
+ * tf_close() closes the ticket file and releases the lock.
+ *
+ * tf_gets() returns the next null-terminated string. It's an internal
+ * routine used by tf_get_pname(), tf_get_pinst(), and tf_get_cred().
+ *
+ * tf_read() reads a given number of bytes. It's an internal routine
+ * used by tf_get_cred().
+ */
+
+/*
+ * tf_init() should be called before the other ticket file routines.
+ * It takes the name of the ticket file to use, "tf_name", and a
+ * read/write flag "rw" as arguments.
+ *
+ * It tries to open the ticket file, checks the mode, and if everything
+ * is okay, locks the file. If it's opened for reading, the lock is
+ * shared. If it's opened for writing, the lock is exclusive.
+ *
+ * Returns KSUCCESS if all went well, otherwise one of the following:
+ *
+ * NO_TKT_FIL - file wasn't there
+ * TKT_FIL_ACC - file was in wrong mode, etc.
+ * TKT_FIL_LCK - couldn't lock the file, even after a retry
+ */
+
+int tf_init(tf_name, rw)
+ char *tf_name;
+ int rw;
+{
+ int wflag;
+ uid_t me, getuid();
+ struct stat stat_buf;
+#ifdef TKT_SHMEM
+ char shmidname[MAXPATHLEN];
+ FILE *sfp;
+ int shmid;
+#endif
+
+ switch (rw) {
+ case R_TKT_FIL:
+ wflag = 0;
+ break;
+ case W_TKT_FIL:
+ wflag = 1;
+ break;
+ default:
+ if (krb_debug) fprintf(stderr, "tf_init: illegal parameter\n");
+ return TKT_FIL_ACC;
+ }
+
+ /* If ticket cache selector is null, use default cache. */
+ if (tf_name == 0)
+ tf_name = tkt_string();
+
+ if (lstat(tf_name, &stat_buf) < 0)
+ switch (errno) {
+ case ENOENT:
+ return NO_TKT_FIL;
+ default:
+ return TKT_FIL_ACC;
+ }
+ me = getuid();
+ if ((stat_buf.st_uid != me && me != 0) ||
+ ((stat_buf.st_mode & S_IFMT) != S_IFREG))
+ return TKT_FIL_ACC;
+#ifdef TKT_SHMEM
+ (void) strcpy(shmidname, tf_name);
+ (void) strcat(shmidname, ".shm");
+ if (stat(shmidname,&stat_buf) < 0)
+ return(TKT_FIL_ACC);
+ if ((stat_buf.st_uid != me && me != 0) ||
+ ((stat_buf.st_mode & S_IFMT) != S_IFREG))
+ return TKT_FIL_ACC;
+#endif /* TKT_SHMEM */
+
+ /*
+ * If "wflag" is set, open the ticket file in append-writeonly mode
+ * and lock the ticket file in exclusive mode. If unable to lock
+ * the file, sleep and try again. If we fail again, return with the
+ * proper error message.
+ */
+
+ curpos = sizeof(tfbfr);
+
+#ifdef TKT_SHMEM
+ sfp = fopen(shmidname, "r"); /* only need read/write on the
+ actual tickets */
+ if (sfp == 0)
+ return TKT_FIL_ACC;
+ shmid = -1;
+ {
+ char buf[BUFSIZ];
+ int val; /* useful for debugging fscanf */
+ /* We provide our own buffer here since some STDIO libraries
+ barf on unbuffered input with fscanf() */
+
+ setbuf(sfp, buf);
+ if ((val = fscanf(sfp,"%d",&shmid)) != 1) {
+ (void) fclose(sfp);
+ return TKT_FIL_ACC;
+ }
+ if (shmid < 0) {
+ (void) fclose(sfp);
+ return TKT_FIL_ACC;
+ }
+ (void) fclose(sfp);
+ }
+ /*
+ * global krb_shm_addr is initialized to 0. Ultrix bombs when you try and
+ * attach the same segment twice so we need this check.
+ */
+ if (!krb_shm_addr) {
+ if ((krb_shm_addr = shmat(shmid,0,0)) == -1){
+ if (krb_debug)
+ fprintf(stderr,
+ "cannot attach shared memory for segment %d\n",
+ shmid);
+ krb_shm_addr = 0; /* reset so we catch further errors */
+ return TKT_FIL_ACC;
+ }
+ }
+ tmp_shm_addr = krb_shm_addr;
+#endif /* TKT_SHMEM */
+
+ if (wflag) {
+ fd = open(tf_name, O_RDWR, 0600);
+ if (fd < 0) {
+ return TKT_FIL_ACC;
+ }
+ if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
+ sleep(TF_LCK_RETRY);
+ if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
+ (void) close(fd);
+ fd = -1;
+ return TKT_FIL_LCK;
+ }
+ }
+ return KSUCCESS;
+ }
+ /*
+ * Otherwise "wflag" is not set and the ticket file should be opened
+ * for read-only operations and locked for shared access.
+ */
+
+ fd = open(tf_name, O_RDONLY, 0600);
+ if (fd < 0) {
+ return TKT_FIL_ACC;
+ }
+ if (flock(fd, LOCK_SH | LOCK_NB) < 0) {
+ sleep(TF_LCK_RETRY);
+ if (flock(fd, LOCK_SH | LOCK_NB) < 0) {
+ (void) close(fd);
+ fd = -1;
+ return TKT_FIL_LCK;
+ }
+ }
+ return KSUCCESS;
+}
+
+/*
+ * tf_get_pname() reads the principal's name from the ticket file. It
+ * should only be called after tf_init() has been called. The
+ * principal's name is filled into the "p" parameter. If all goes well,
+ * KSUCCESS is returned. If tf_init() wasn't called, TKT_FIL_INI is
+ * returned. If the name was null, or EOF was encountered, or the name
+ * was longer than ANAME_SZ, TKT_FIL_FMT is returned.
+ */
+
+int tf_get_pname(p)
+ char *p;
+{
+ if (fd < 0) {
+ if (krb_debug)
+ fprintf(stderr, "tf_get_pname called before tf_init.\n");
+ return TKT_FIL_INI;
+ }
+ if (tf_gets(p, ANAME_SZ) < 2) /* can't be just a null */
+ return TKT_FIL_FMT;
+ return KSUCCESS;
+}
+
+/*
+ * tf_get_pinst() reads the principal's instance from a ticket file.
+ * It should only be called after tf_init() and tf_get_pname() have been
+ * called. The instance is filled into the "inst" parameter. If all
+ * goes well, KSUCCESS is returned. If tf_init() wasn't called,
+ * TKT_FIL_INI is returned. If EOF was encountered, or the instance
+ * was longer than ANAME_SZ, TKT_FIL_FMT is returned. Note that the
+ * instance may be null.
+ */
+
+int tf_get_pinst(inst)
+ char *inst;
+{
+ if (fd < 0) {
+ if (krb_debug)
+ fprintf(stderr, "tf_get_pinst called before tf_init.\n");
+ return TKT_FIL_INI;
+ }
+ if (tf_gets(inst, INST_SZ) < 1)
+ return TKT_FIL_FMT;
+ return KSUCCESS;
+}
+
+/*
+ * tf_get_cred() reads a CREDENTIALS record from a ticket file and fills
+ * in the given structure "c". It should only be called after tf_init(),
+ * tf_get_pname(), and tf_get_pinst() have been called. If all goes well,
+ * KSUCCESS is returned. Possible error codes are:
+ *
+ * TKT_FIL_INI - tf_init wasn't called first
+ * TKT_FIL_FMT - bad format
+ * EOF - end of file encountered
+ */
+
+int tf_get_cred(c)
+ CREDENTIALS *c;
+{
+ KTEXT ticket = &c->ticket_st; /* pointer to ticket */
+ int k_errno;
+
+ if (fd < 0) {
+ if (krb_debug)
+ fprintf(stderr, "tf_get_cred called before tf_init.\n");
+ return TKT_FIL_INI;
+ }
+ if ((k_errno = tf_gets(c->service, SNAME_SZ)) < 2)
+ switch (k_errno) {
+ case TOO_BIG:
+ case 1: /* can't be just a null */
+ tf_close();
+ return TKT_FIL_FMT;
+ case 0:
+ return EOF;
+ }
+ if ((k_errno = tf_gets(c->instance, INST_SZ)) < 1)
+ switch (k_errno) {
+ case TOO_BIG:
+ return TKT_FIL_FMT;
+ case 0:
+ return EOF;
+ }
+ if ((k_errno = tf_gets(c->realm, REALM_SZ)) < 2)
+ switch (k_errno) {
+ case TOO_BIG:
+ case 1: /* can't be just a null */
+ tf_close();
+ return TKT_FIL_FMT;
+ case 0:
+ return EOF;
+ }
+ if (
+ tf_read((char *) (c->session), KEY_SZ) < 1 ||
+ tf_read((char *) &(c->lifetime), sizeof(c->lifetime)) < 1 ||
+ tf_read((char *) &(c->kvno), sizeof(c->kvno)) < 1 ||
+ tf_read((char *) &(ticket->length), sizeof(ticket->length))
+ < 1 ||
+ /* don't try to read a silly amount into ticket->dat */
+ ticket->length > MAX_KTXT_LEN ||
+ tf_read((char *) (ticket->dat), ticket->length) < 1 ||
+ tf_read((char *) &(c->issue_date), sizeof(c->issue_date)) < 1
+ ) {
+ tf_close();
+ return TKT_FIL_FMT;
+ }
+#ifdef TKT_SHMEM
+ memcpy(c->session, tmp_shm_addr, KEY_SZ);
+ tmp_shm_addr += KEY_SZ;
+#endif /* TKT_SHMEM */
+ return KSUCCESS;
+}
+
+/*
+ * tf_close() closes the ticket file and sets "fd" to -1. If "fd" is
+ * not a valid file descriptor, it just returns. It also clears the
+ * buffer used to read tickets.
+ *
+ * The return value is not defined.
+ */
+
+tf_close()
+{
+ if (!(fd < 0)) {
+#ifdef TKT_SHMEM
+ if (shmdt(krb_shm_addr)) {
+ /* what kind of error? */
+ if (krb_debug)
+ fprintf(stderr, "shmdt 0x%x: errno %d",krb_shm_addr, errno);
+ } else {
+ krb_shm_addr = 0;
+ }
+#endif /* TKT_SHMEM */
+ (void) flock(fd, LOCK_UN);
+ (void) close(fd);
+ fd = -1; /* see declaration of fd above */
+ }
+ memset(tfbfr, 0, sizeof(tfbfr));
+}
+
+/*
+ * tf_gets() is an internal routine. It takes a string "s" and a count
+ * "n", and reads from the file until either it has read "n" characters,
+ * or until it reads a null byte. When finished, what has been read exists
+ * in "s". If it encounters EOF or an error, it closes the ticket file.
+ *
+ * Possible return values are:
+ *
+ * n the number of bytes read (including null terminator)
+ * when all goes well
+ *
+ * 0 end of file or read error
+ *
+ * TOO_BIG if "count" characters are read and no null is
+ * encountered. This is an indication that the ticket
+ * file is seriously ill.
+ */
+
+static int
+tf_gets(s, n)
+ register char *s;
+ int n;
+{
+ register int count;
+
+ if (fd < 0) {
+ if (krb_debug)
+ fprintf(stderr, "tf_gets called before tf_init.\n");
+ return TKT_FIL_INI;
+ }
+ for (count = n - 1; count > 0; --count) {
+ if (curpos >= sizeof(tfbfr)) {
+ lastpos = read(fd, tfbfr, sizeof(tfbfr));
+ curpos = 0;
+ }
+ if (curpos == lastpos) {
+ tf_close();
+ return 0;
+ }
+ *s = tfbfr[curpos++];
+ if (*s++ == '\0')
+ return (n - count);
+ }
+ tf_close();
+ return TOO_BIG;
+}
+
+/*
+ * tf_read() is an internal routine. It takes a string "s" and a count
+ * "n", and reads from the file until "n" bytes have been read. When
+ * finished, what has been read exists in "s". If it encounters EOF or
+ * an error, it closes the ticket file.
+ *
+ * Possible return values are:
+ *
+ * n the number of bytes read when all goes well
+ *
+ * 0 on end of file or read error
+ */
+
+static int
+tf_read(s, n)
+ register char *s;
+ register int n;
+{
+ register int count;
+
+ for (count = n; count > 0; --count) {
+ if (curpos >= sizeof(tfbfr)) {
+ lastpos = read(fd, tfbfr, sizeof(tfbfr));
+ curpos = 0;
+ }
+ if (curpos == lastpos) {
+ tf_close();
+ return 0;
+ }
+ *s++ = tfbfr[curpos++];
+ }
+ return n;
+}
+
+char *tkt_string();
+
+/*
+ * tf_save_cred() appends an incoming ticket to the end of the ticket
+ * file. You must call tf_init() before calling tf_save_cred().
+ *
+ * The "service", "instance", and "realm" arguments specify the
+ * server's name; "session" contains the session key to be used with
+ * the ticket; "kvno" is the server key version number in which the
+ * ticket is encrypted, "ticket" contains the actual ticket, and
+ * "issue_date" is the time the ticket was requested (local host's time).
+ *
+ * Returns KSUCCESS if all goes well, TKT_FIL_INI if tf_init() wasn't
+ * called previously, and KFAILURE for anything else that went wrong.
+ */
+
+int tf_save_cred(service, instance, realm, session, lifetime, kvno,
+ ticket, issue_date)
+ char *service; /* Service name */
+ char *instance; /* Instance */
+ char *realm; /* Auth domain */
+ C_Block session; /* Session key */
+ int lifetime; /* Lifetime */
+ int kvno; /* Key version number */
+ KTEXT ticket; /* The ticket itself */
+ long issue_date; /* The issue time */
+{
+
+ off_t lseek();
+ int count; /* count for write */
+#ifdef TKT_SHMEM
+ int *skey_check;
+#endif /* TKT_SHMEM */
+
+ if (fd < 0) { /* fd is ticket file as set by tf_init */
+ if (krb_debug)
+ fprintf(stderr, "tf_save_cred called before tf_init.\n");
+ return TKT_FIL_INI;
+ }
+ /* Find the end of the ticket file */
+ (void) lseek(fd, (off_t)0, 2);
+#ifdef TKT_SHMEM
+ /* scan to end of existing keys: pick first 'empty' slot.
+ we assume that no real keys will be completely zero (it's a weak
+ key under DES) */
+
+ skey_check = (int *) krb_shm_addr;
+
+ while (*skey_check && *(skey_check+1))
+ skey_check += 2;
+ tmp_shm_addr = (char *)skey_check;
+#endif /* TKT_SHMEM */
+
+ /* Write the ticket and associated data */
+ /* Service */
+ count = strlen(service) + 1;
+ if (write(fd, service, count) != count)
+ goto bad;
+ /* Instance */
+ count = strlen(instance) + 1;
+ if (write(fd, instance, count) != count)
+ goto bad;
+ /* Realm */
+ count = strlen(realm) + 1;
+ if (write(fd, realm, count) != count)
+ goto bad;
+ /* Session key */
+#ifdef TKT_SHMEM
+ memcpy(tmp_shm_addr, session, 8);
+ tmp_shm_addr+=8;
+ if (write(fd,krb_dummy_skey,8) != 8)
+ goto bad;
+#else /* ! TKT_SHMEM */
+ if (write(fd, (char *) session, 8) != 8)
+ goto bad;
+#endif /* TKT_SHMEM */
+ /* Lifetime */
+ if (write(fd, (char *) &lifetime, sizeof(int)) != sizeof(int))
+ goto bad;
+ /* Key vno */
+ if (write(fd, (char *) &kvno, sizeof(int)) != sizeof(int))
+ goto bad;
+ /* Tkt length */
+ if (write(fd, (char *) &(ticket->length), sizeof(int)) !=
+ sizeof(int))
+ goto bad;
+ /* Ticket */
+ count = ticket->length;
+ if (write(fd, (char *) (ticket->dat), count) != count)
+ goto bad;
+ /* Issue date */
+ if (write(fd, (char *) &issue_date, sizeof(long))
+ != sizeof(long))
+ goto bad;
+
+ /* Actually, we should check each write for success */
+ return (KSUCCESS);
+bad:
+ return (KFAILURE);
+}
diff --git a/src/lib/krb4/tkt_string.c b/src/lib/krb4/tkt_string.c
new file mode 100644
index 0000000000..aac6ec467f
--- /dev/null
+++ b/src/lib/krb4/tkt_string.c
@@ -0,0 +1,71 @@
+/*
+ * tkt_string.c
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include "mit-copyright.h"
+#include <stdio.h>
+#include "krb.h"
+#include <string.h>
+#include <sys/param.h>
+
+char *getenv();
+
+/*
+ * This routine is used to generate the name of the file that holds
+ * the user's cache of server tickets and associated session keys.
+ *
+ * If it is set, krb_ticket_string contains the ticket file name.
+ * Otherwise, the filename is constructed as follows:
+ *
+ * If it is set, the environment variable "KRBTKFILE" will be used as
+ * the ticket file name. Otherwise TKT_ROOT (defined in "krb.h") and
+ * the user's uid are concatenated to produce the ticket file name
+ * (e.g., "/tmp/tkt123"). A pointer to the string containing the ticket
+ * file name is returned.
+ */
+
+static char krb_ticket_string[MAXPATHLEN];
+
+char *tkt_string()
+{
+ char *env;
+ uid_t getuid();
+
+ if (!*krb_ticket_string) {
+ if (env = getenv("KRBTKFILE")) {
+ (void) strncpy(krb_ticket_string, env,
+ sizeof(krb_ticket_string)-1);
+ krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
+ } else {
+ /* 32 bits of signed integer will always fit in 11 characters
+ (including the sign), so no need to worry about overflow */
+ (void) sprintf(krb_ticket_string, "%s%d",TKT_ROOT,getuid());
+ }
+ }
+ return krb_ticket_string;
+}
+
+/*
+ * This routine is used to set the name of the file that holds the user's
+ * cache of server tickets and associated session keys.
+ *
+ * The value passed in is copied into local storage.
+ *
+ * NOTE: This routine should be called during initialization, before other
+ * Kerberos routines are called; otherwise tkt_string() above may be called
+ * and return an undesired ticket file name until this routine is called.
+ */
+
+void
+krb_set_tkt_string(val)
+char *val;
+{
+ (void) strncpy(krb_ticket_string, val, sizeof(krb_ticket_string)-1);
+ krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
+}
diff --git a/src/lib/krb4/unix_glue.c b/src/lib/krb4/unix_glue.c
new file mode 100644
index 0000000000..eeafdb9d7e
--- /dev/null
+++ b/src/lib/krb4/unix_glue.c
@@ -0,0 +1,39 @@
+/*
+ * unix_glue.c
+ *
+ * Glue code for pasting Kerberos into the Unix environment.
+ *
+ * Originally written by John Gilmore, Cygnus Support, May '94.
+ * Public Domain.
+ */
+
+#include "krb.h"
+#include <sys/time.h>
+
+/* Start and end Kerberos library access. On Unix, this is a No-op. */
+int INTERFACE
+krb_start_session (x)
+ char *x;
+{
+ return KSUCCESS;
+}
+
+int INTERFACE
+krb_end_session (x)
+ char *x;
+{
+ return KSUCCESS;
+}
+
+char FAR * INTERFACE
+krb_get_default_user ()
+{
+ return 0; /* FIXME */
+}
+
+int INTERFACE
+krb_set_default_user (x)
+ char *x;
+{
+ return KFAILURE; /* FIXME */
+}
diff --git a/src/lib/krb4/unix_time.c b/src/lib/krb4/unix_time.c
new file mode 100644
index 0000000000..736f496083
--- /dev/null
+++ b/src/lib/krb4/unix_time.c
@@ -0,0 +1,26 @@
+/*
+ * unix_time.c
+ *
+ * Glue code for pasting Kerberos into the Unix environment.
+ *
+ * Originally written by John Gilmore, Cygnus Support, May '94.
+ * Public Domain.
+ */
+
+#include "krb.h"
+#include <sys/time.h>
+
+/* Time handling. Translate Unix time calls into Kerberos cnternal
+ procedure calls. See ../../include/cc-unix.h. */
+
+unsigned KRB4_32
+unix_time_gmt_unixsec (usecptr)
+ unsigned KRB4_32 *usecptr;
+{
+ struct timeval now;
+
+ (void) gettimeofday (&now, (struct timezone *)0);
+ if (usecptr)
+ *usecptr = now.tv_usec;
+ return now.tv_sec;
+}
diff --git a/src/lib/krb4/vmslink.com b/src/lib/krb4/vmslink.com
new file mode 100644
index 0000000000..95cabfe1d8
--- /dev/null
+++ b/src/lib/krb4/vmslink.com
@@ -0,0 +1,79 @@
+$ write sys$output "start of run"
+$ cc /decc /inc=inc /debug=all des.c
+$ cc /decc /inc=inc /debug=all d3des.c
+$ cc /decc /inc=inc /debug=all cbc.c
+$ cc /decc /inc=([],inc) /debug=all qcksum.c
+$ cc /decc /inc=([],inc) /debug=all str2key.c
+$ cc /decc /inc=([],inc) /debug=all parity.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all ad_print.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all add_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all cr_auth_repl.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all cr_ciph.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all cr_death_pkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all cr_err_repl.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all cr_tkt.c
+$ write sys$output "begin d"
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all debug.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all decomp_tkt.c
+stat $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all dest_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all err_txt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all ext_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all fakeenv.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all fgetst.c
+$ write sys$output "begin g"
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_ad_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_admhst.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_cnffile.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_cred.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_in_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_krbhst.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_krbrlm.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_phost.c
+sgtty $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_pw_in_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_pw_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_request.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_svc_in_tkt.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_tf_fname.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all g_tf_realm.c
+$ write sys$output "end g_"
+$ cc/decc/inc=inc /define=("HOST_BYTE_ORDER=1",BSD42) /debug=all gethostname.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all getst.c
+stat $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all in_tkt.c
+$ cc/decc/inc=inc /define=("HOST_BYTE_ORDER=1",NEED_TIME_H) /debug=all klog.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all kname_parse.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all kntoln.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all kparse.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all krbglue.c
+stat $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all kuserok.c
+$ write sys$output "end k"
+$ cc/decc/inc=inc /define=("HOST_BYTE_ORDER=1",NEED_TIME_H) /debug=all log.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all mk_err.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all mk_preauth.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all mk_priv.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all mk_req.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all mk_safe.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all month_sname.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all netread.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all netwrite.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all pkt_cipher.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all pkt_clen.c
+$ write sys$output "begin rd"
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_err.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_preauth.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_priv.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_req.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_safe.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all rd_svc_key.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all realmofhost.c
+$ write sys$output "begin recv"
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all recvauth.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all save_creds.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all send_to_kdc.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all sendauth.c
+$ cc/decc/inc=inc /define=("HOST_BYTE_ORDER=1",NEED_TIME_H) /debug=all stime.c
+stat $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all tf_shm.c
+stat $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all tf_util.c
+MAXPATHLEN $ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all tkt_string.c
+$ cc/decc/inc=inc /define="HOST_BYTE_ORDER=1" /debug=all vmsswab.c
+$ library /create /list libkrb *.obj
+
diff --git a/src/lib/krb4/vmsswab.c b/src/lib/krb4/vmsswab.c
new file mode 100644
index 0000000000..019580882e
--- /dev/null
+++ b/src/lib/krb4/vmsswab.c
@@ -0,0 +1,34 @@
+/* Copyright 1994 Cygnus Support */
+/* Mark W. Eichin */
+/*
+ * 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.
+ * Cygnus Support makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+/* VMS doesn't have swab, but everything else does */
+/* so make this available anyway ... someday it might go
+ into the VMS makefile fragment, but for now it is only
+ referenced by l.com. */
+
+swab(from,to,nbytes)
+ char *from;
+ char *to;
+ int nbytes;
+{
+ char tmp;
+
+ while ( (nbytes-=2) >= 0 ) {
+ tmp = from[1];
+ to[1] = from[0];
+ to[0] = tmp;
+ to++; to++;
+ from++; from++;
+ }
+}
+
diff --git a/src/lib/krb4/win_glue.c b/src/lib/krb4/win_glue.c
new file mode 100644
index 0000000000..de8b62015f
--- /dev/null
+++ b/src/lib/krb4/win_glue.c
@@ -0,0 +1,117 @@
+/*
+ * win-glue.c
+ *
+ * Glue code for pasting Kerberos into the Windows environment.
+ *
+ * Originally written by John Gilmore, Cygnus Support, May '94.
+ * Public Domain.
+ */
+
+#define DEFINE_SOCKADDR
+#include "krb.h"
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <windows.h>
+
+static HINSTANCE hlibinstance;
+
+/*
+ * WinSock support.
+ *
+ * Do the WinSock initialization call, keeping all the hair here.
+ *
+ * This routine is called by SOCKET_INITIALIZE in include/c-windows.h.
+ * The code is pretty much copied from winsock.txt from winsock-1.1,
+ * available from:
+ * ftp://sunsite.unc.edu/pub/micro/pc-stuff/ms-windows/winsock/winsock-1.1
+ */
+int
+win_socket_initialize()
+{
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = 0x0101; /* We need version 1.1 */
+
+ err = WSAStartup (wVersionRequested, &wsaData);
+ if (err != 0)
+ return err; /* Library couldn't initialize */
+
+ if (wVersionRequested != wsaData.wVersion) {
+ /* DLL couldn't support our version of the spec */
+ WSACleanup ();
+ return -104; /* FIXME -- better error? */
+ }
+
+ return 0;
+}
+
+/*
+ * We needed a way to print out what might be FAR pointers on Windows,
+ * but might be ordinary pointers on real machines. Printf modifiers
+ * scattered through the code don't cut it,
+ * since they might break on real machines. Microloss
+ * didn't provide a function to print a char FAR *, so we wrote one.
+ * It gets #define'd to fputs on real machines.
+ */
+int
+far_fputs(string, stream)
+ char FAR *string;
+ FILE *stream;
+{
+ return fprintf(stream, "%Fs", string);
+}
+
+
+BOOL CALLBACK
+LibMain(hInst, wDataSeg, cbHeap, CmdLine)
+ HINSTANCE hInst;
+ WORD wDataSeg;
+ WORD cbHeap;
+ LPSTR CmdLine;
+{
+ hlibinstance = hInst;
+
+ return 1;
+}
+
+
+int CALLBACK __export
+WEP(nParam)
+ int nParam;
+{
+ return 1;
+}
+
+
+HINSTANCE
+get_lib_instance()
+{
+ return hlibinstance;
+}
+
+
+int INTERFACE
+krb_start_session(x)
+ char *x;
+{
+ return KSUCCESS;
+}
+
+int INTERFACE
+krb_end_session(x)
+ char *x;
+{
+ return KSUCCESS;
+}
+
+void
+krb_set_tkt_string(val)
+char *val;
+{
+}
+
+/* FIXME -- Mark... */
+int krb_ignore_ip_address = 0;
diff --git a/src/lib/krb4/win_store.c b/src/lib/krb4/win_store.c
new file mode 100644
index 0000000000..914ba77413
--- /dev/null
+++ b/src/lib/krb4/win_store.c
@@ -0,0 +1,115 @@
+/*
+ * win_store.c
+ *
+ * Kerberos configuration storage management routines.
+ *
+ * Originally coded by John Rivlin / Fusion Software, Inc.
+ *
+ * This file incorporates replacements for the following Unix files:
+ * g_cnffil.c
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "krb.h"
+
+/*
+ * Returns an open file handle to the configuration file. This
+ * file was called "krb.conf" on Unix. Here we search for the entry
+ * "krb.conf=" in the "[FILES]" section of the "kerberos.ini" file
+ * located in the Windows directory. If the entry doesn't exist in
+ * the kerberos.ini file, then "krb.con" in the Windows directory is
+ * used in its place.
+ */
+FILE*
+krb__get_cnffile()
+{
+ FILE *cnffile = 0;
+ char cnfname[FILENAME_MAX];
+ char defname[FILENAME_MAX];
+ UINT rc;
+
+ rc = GetWindowsDirectory(defname, sizeof(defname));
+ assert(rc > 0);
+
+ strcat(defname, "\\");
+
+ strcat(defname, DEF_KRB_CONF);
+
+ GetPrivateProfileString(INI_FILES, INI_KRB_CONF, defname,
+ cnfname, sizeof(cnfname), KERBEROS_INI);
+
+ cnffile = fopen(cnfname, "r");
+
+ return cnffile;
+}
+
+
+/*
+ * Returns an open file handle to the realms file. This
+ * file was called "krb.realms" on Unix. Here we search for the entry
+ * "krb.realms=" in the "[FILES]" section of the "kerberos.ini" file
+ * located in the Windows directory. If the entry doesn't exist in
+ * the kerberos.ini file, then "krb.rea" in the Windows directory is
+ * used in its place.
+ */
+FILE*
+krb__get_realmsfile()
+{
+ FILE *realmsfile = 0;
+ char realmsname[FILENAME_MAX];
+ char defname[FILENAME_MAX];
+ UINT rc;
+
+ rc = GetWindowsDirectory(defname, sizeof(defname));
+ assert(rc > 0);
+
+ strcat(defname, "\\");
+
+ strcat(defname, DEF_KRB_REALMS);
+
+ GetPrivateProfileString(INI_FILES, INI_KRB_REALMS, defname,
+ realmsname, sizeof(realmsname), KERBEROS_INI);
+
+ realmsfile = fopen(realmsname, "r");
+
+ return realmsfile;
+}
+
+
+/*
+ * Returns the current default user. This information is stored in
+ * the [DEFAULTS] section of the "kerberos.ini" file located in the
+ * Windows directory.
+ */
+char FAR * INTERFACE
+krb_get_default_user()
+{
+ static char username[ANAME_SZ];
+
+ GetPrivateProfileString(INI_DEFAULTS, INI_USER, "",
+ username, sizeof(username), KERBEROS_INI);
+
+ return username;
+}
+
+
+/*
+ * Sets the default user name stored in the "kerberos.ini" file.
+ */
+int INTERFACE
+krb_set_default_user(username)
+ char *username;
+{
+ BOOL rc;
+
+ rc = WritePrivateProfileString(INI_DEFAULTS, INI_USER,
+ username, KERBEROS_INI);
+
+ if (rc)
+ return KSUCCESS;
+ else
+ return KFAILURE;
+}
diff --git a/src/lib/krb4/win_time.c b/src/lib/krb4/win_time.c
new file mode 100644
index 0000000000..9022d1b9a2
--- /dev/null
+++ b/src/lib/krb4/win_time.c
@@ -0,0 +1,103 @@
+/*
+ * win_time.c
+ *
+ * Glue code for pasting Kerberos into the Windows environment.
+ *
+ * Originally written by John Gilmore, Cygnus Support, May '94.
+ * Public Domain.
+ */
+
+#define DEFINE_SOCKADDR
+#include "krb.h"
+
+#include <sys/types.h>
+#include <time.h>
+#include <sys/timeb.h>
+#include <stdio.h>
+#include <windows.h>
+#include <dos.h>
+
+/*
+ * Time handling. Translate Unix time calls into Kerberos internal
+ * procedure calls. See ../../include/c-win.h.
+ *
+ * Due to the fact that DOS time can be unreliable we have reverted
+ * to using the AT hardware clock and converting it to Unix time.
+ */
+
+unsigned KRB_INT32
+win_time_gmt_unixsec (usecptr)
+ unsigned KRB_INT32 *usecptr;
+{
+ struct tm tm;
+ union _REGS inregs;
+ union _REGS outregs;
+ struct _timeb now;
+ time_t time;
+
+ _ftime(&now);
+
+ #if 0
+ if (usecptr)
+ *usecptr = now.millitm * 1000;
+ #endif
+
+ /* Get time from AT hardware clock INT 0x1A, AH=2 */
+ memset(&inregs, 0, sizeof(inregs));
+ inregs.h.ah = 2;
+
+ _int86(0x1a, &inregs, &outregs);
+
+ /* 0x13 = decimal 13, hence the decoding below */
+ tm.tm_sec = 10 * ((outregs.h.dh & 0xF0) >> 4) + (outregs.h.dh & 0x0F);
+ tm.tm_min = 10 * ((outregs.h.cl & 0xF0) >> 4) + (outregs.h.cl & 0x0F);
+ tm.tm_hour = 10 * ((outregs.h.ch & 0xF0) >> 4) + (outregs.h.ch & 0x0F);
+
+ /* Get date from AT hardware clock INT 0x1A, AH=4 */
+ memset(&inregs, 0, sizeof(inregs));
+ inregs.h.ah = 4;
+
+ _int86(0x1a, &inregs, &outregs);
+
+ tm.tm_mday = 10 * ((outregs.h.dl & 0xF0) >> 4) + (outregs.h.dl & 0x0F);
+ tm.tm_mon = 10 * ((outregs.h.dh & 0xF0) >> 4) + (outregs.h.dh & 0x0F) - 1;
+ tm.tm_year = 10 * ((outregs.h.cl & 0xF0) >> 4) + (outregs.h.cl & 0x0F);
+ tm.tm_year += 100 * ((10 * (outregs.h.ch & 0xF0) >> 4)
+ + (outregs.h.ch & 0x0F) - 19);
+
+ tm.tm_wday = 0;
+ tm.tm_yday = 0;
+ tm.tm_isdst = now.dstflag;
+
+ time = mktime(&tm);
+
+ if (usecptr)
+ *usecptr = 0;
+
+ return time + CONVERT_TIME_EPOCH;
+}
+
+
+/*
+ * This routine figures out the current time epoch and returns the
+ * conversion factor. It exists because
+ * Microloss screwed the pooch on the time() and _ftime() calls in
+ * its release 7.0 libraries. They changed the epoch to Dec 31, 1899!
+ * Idiots... We try to cope.
+ */
+
+static struct tm jan_1_70 = {0, 0, 0, 1, 0, 70};
+static long epoch = 0;
+static int epoch_set = 0;
+
+long
+win_time_get_epoch()
+{
+
+ if (!epoch_set) {
+ epoch = - mktime (&jan_1_70); /* Seconds til 1970 localtime */
+ epoch += timezone; /* Seconds til 1970 GMT */
+ epoch_set = 1;
+ }
+ return epoch;
+}
diff --git a/src/lib/krb4/winsock.def b/src/lib/krb4/winsock.def
new file mode 100644
index 0000000000..cada779858
--- /dev/null
+++ b/src/lib/krb4/winsock.def
@@ -0,0 +1,90 @@
+;
+; File: winsock.def
+; System: MS-Windows 3.x
+; Summary: Module definition file for Windows Sockets DLL.
+;
+; This file is from
+; ftp://sunsite.unc.edu/pub/micro/pc-stuff/ms-windows/winsock/winsock-1.1
+; except that we made all the routine names uppercase, to match what
+; MicroSoft C does when you declare an interface routine PASCAL
+; (the way all these routines are declared in .../include/winsock.h).
+;
+
+LIBRARY WINSOCK ; Application's module name
+
+DESCRIPTION 'BSD Socket API for Windows'
+
+EXETYPE WINDOWS ; required for all windows applications
+
+STUB 'WINSTUB.EXE' ; generates error message if application
+ ; is run without Windows
+
+;CODE can be FIXED in memory because of potential upcalls
+CODE PRELOAD FIXED
+
+;DATA must be SINGLE and at a FIXED location since this is a DLL
+DATA PRELOAD FIXED SINGLE
+
+HEAPSIZE 1024
+STACKSIZE 16384
+
+; All functions that will be called by any Windows routine
+; must be exported. Any additional exports beyond those defined
+; here must have ordinal numbers 1000 or above.
+
+EXPORTS
+ ACCEPT @1
+ BIND @2
+ CLOSESOCKET @3
+ CONNECT @4
+ GETPEERNAME @5
+ GETSOCKNAME @6
+ GETSOCKOPT @7
+ HTONL @8
+ HTONS @9
+ INET_ADDR @10
+ INET_NTOA @11
+ IOCTLSOCKET @12
+ LISTEN @13
+ NTOHL @14
+ NTOHS @15
+ RECV @16
+ RECVFROM @17
+ SELECT @18
+ SEND @19
+ SENDTO @20
+ SETSOCKOPT @21
+ SHUTDOWN @22
+ SOCKET @23
+
+ GETHOSTBYADDR @51
+ GETHOSTBYNAME @52
+ GETPROTOBYNAME @53
+ GETPROTOBYNUMBER @54
+ GETSERVBYNAME @55
+ GETSERVBYPORT @56
+ GETHOSTNAME @57
+
+ WSAASYNCSELECT @101
+ WSAASYNCGETHOSTBYADDR @102
+ WSAASYNCGETHOSTBYNAME @103
+ WSAASYNCGETPROTOBYNUMBER @104
+ WSAASYNCGETPROTOBYNAME @105
+ WSAASYNCGETSERVBYPORT @106
+ WSAASYNCGETSERVBYNAME @107
+ WSACANCELASYNCREQUEST @108
+ WSASETBLOCKINGHOOK @109
+ WSAUNHOOKBLOCKINGHOOK @110
+ WSAGETLASTERROR @111
+ WSASETLASTERROR @112
+ WSACANCELBLOCKINGCALL @113
+ WSAISBLOCKING @114
+ WSASTARTUP @115
+ WSACLEANUP @116
+
+ __WSAFDISSET @151
+
+ WEP @500 RESIDENTNAME
+
+;eof
+