From f487a0a0f51ce55e769b2c6766662307dab9df0f Mon Sep 17 00:00:00 2001 From: Mark Eichin Date: Thu, 27 Apr 1995 15:51:19 +0000 Subject: [PATCH] add CNS V4 library to tree for compatibility use. Installs as libkrb4.a git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5537 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb4/ChangeLog | 1135 +++++++++++++++++++++++++++++++++++ src/lib/krb4/DNR.c | 309 ++++++++++ src/lib/krb4/Makefile.in | 264 ++++++++ src/lib/krb4/Password.c | 433 +++++++++++++ src/lib/krb4/TAGS | 546 +++++++++++++++++ src/lib/krb4/ad_print.c | 66 ++ src/lib/krb4/configure.in | 17 + src/lib/krb4/cr_auth_repl.c | 112 ++++ src/lib/krb4/cr_ciph.c | 108 ++++ src/lib/krb4/cr_death_pkt.c | 59 ++ src/lib/krb4/cr_err_repl.c | 90 +++ src/lib/krb4/cr_tkt.c | 133 ++++ src/lib/krb4/debug.c | 15 + src/lib/krb4/decomp_tkt.c | 160 +++++ src/lib/krb4/dest_tkt.c | 94 +++ src/lib/krb4/err_txt.c | 294 +++++++++ src/lib/krb4/fakeenv.c | 88 +++ src/lib/krb4/fgetst.c | 35 ++ src/lib/krb4/g_ad_tkt.c | 241 ++++++++ src/lib/krb4/g_admhst.c | 77 +++ src/lib/krb4/g_cnffile.c | 53 ++ src/lib/krb4/g_cred.c | 58 ++ src/lib/krb4/g_in_tkt.c | 387 ++++++++++++ src/lib/krb4/g_krbhst.c | 93 +++ src/lib/krb4/g_krbrlm.c | 60 ++ src/lib/krb4/g_phost.c | 75 +++ src/lib/krb4/g_pw_in_tkt.c | 342 +++++++++++ src/lib/krb4/g_pw_tkt.c | 67 +++ src/lib/krb4/g_svc_in_tkt.c | 133 ++++ src/lib/krb4/g_tf_fname.c | 67 +++ src/lib/krb4/g_tf_realm.c | 29 + src/lib/krb4/g_tkt_svc.c | 173 ++++++ src/lib/krb4/gethostname.c | 30 + src/lib/krb4/getst.c | 33 + src/lib/krb4/in_tkt.c | 159 +++++ src/lib/krb4/kerberos.def | 68 +++ src/lib/krb4/klog.c | 109 ++++ src/lib/krb4/kname_parse.c | 230 +++++++ src/lib/krb4/kntoln.c | 56 ++ src/lib/krb4/kparse.c | 766 +++++++++++++++++++++++ src/lib/krb4/krb_err.et | 256 ++++++++ src/lib/krb4/kuserok.c | 231 +++++++ src/lib/krb4/log.c | 128 ++++ src/lib/krb4/mac_glue.c | 49 ++ src/lib/krb4/mac_store.c | 731 ++++++++++++++++++++++ src/lib/krb4/mac_store.h | 56 ++ src/lib/krb4/mac_stubs.c | 526 ++++++++++++++++ src/lib/krb4/mac_time.c | 151 +++++ src/lib/krb4/macsock.c | 484 +++++++++++++++ src/lib/krb4/memcache.c | 867 ++++++++++++++++++++++++++ src/lib/krb4/memcache.h | 50 ++ src/lib/krb4/mk_auth.c | 218 +++++++ src/lib/krb4/mk_err.c | 59 ++ src/lib/krb4/mk_preauth.c | 78 +++ src/lib/krb4/mk_priv.c | 205 +++++++ src/lib/krb4/mk_req.c | 214 +++++++ src/lib/krb4/mk_safe.c | 154 +++++ src/lib/krb4/month_sname.c | 28 + src/lib/krb4/netread.c | 52 ++ src/lib/krb4/netwrite.c | 48 ++ src/lib/krb4/one.c | 20 + src/lib/krb4/pkt_cipher.c | 35 ++ src/lib/krb4/pkt_clen.c | 49 ++ src/lib/krb4/put_svc_key.c | 93 +++ src/lib/krb4/rd_err.c | 69 +++ src/lib/krb4/rd_preauth.c | 58 ++ src/lib/krb4/rd_priv.c | 217 +++++++ src/lib/krb4/rd_req.c | 358 +++++++++++ src/lib/krb4/rd_safe.c | 196 ++++++ src/lib/krb4/rd_svc_key.c | 206 +++++++ src/lib/krb4/realmofhost.c | 141 +++++ src/lib/krb4/recvauth.c | 282 +++++++++ src/lib/krb4/ren-cyg.sh | 11 + src/lib/krb4/ren-pc.bat | 29 + src/lib/krb4/ren-pc.sh | 7 + src/lib/krb4/ren-pl10.sh | 7 + src/lib/krb4/ren.msg | 117 ++++ src/lib/krb4/ren2dos.sh | 7 + src/lib/krb4/ren2long.sh | 7 + src/lib/krb4/save_creds.c | 54 ++ src/lib/krb4/sed-cyg.sh | 13 + src/lib/krb4/sed-pc.sh | 11 + src/lib/krb4/sed-pl10.sh | 10 + src/lib/krb4/send_to_kdc.c | 388 ++++++++++++ src/lib/krb4/sendauth.c | 278 +++++++++ src/lib/krb4/setenv.c | 164 +++++ src/lib/krb4/stime.c | 40 ++ src/lib/krb4/strcasecmp.c | 83 +++ src/lib/krb4/swab.c | 18 + src/lib/krb4/tf_shm.c | 171 ++++++ src/lib/krb4/tf_util.c | 630 +++++++++++++++++++ src/lib/krb4/tkt_string.c | 71 +++ src/lib/krb4/unix_glue.c | 39 ++ src/lib/krb4/unix_time.c | 26 + src/lib/krb4/vmslink.com | 79 +++ src/lib/krb4/vmsswab.c | 34 ++ src/lib/krb4/win_glue.c | 117 ++++ src/lib/krb4/win_store.c | 115 ++++ src/lib/krb4/win_time.c | 103 ++++ src/lib/krb4/winsock.def | 90 +++ 100 files changed, 16292 insertions(+) create mode 100644 src/lib/krb4/ChangeLog create mode 100644 src/lib/krb4/DNR.c create mode 100644 src/lib/krb4/Makefile.in create mode 100644 src/lib/krb4/Password.c create mode 100644 src/lib/krb4/TAGS create mode 100644 src/lib/krb4/ad_print.c create mode 100644 src/lib/krb4/configure.in create mode 100644 src/lib/krb4/cr_auth_repl.c create mode 100644 src/lib/krb4/cr_ciph.c create mode 100644 src/lib/krb4/cr_death_pkt.c create mode 100644 src/lib/krb4/cr_err_repl.c create mode 100644 src/lib/krb4/cr_tkt.c create mode 100644 src/lib/krb4/debug.c create mode 100644 src/lib/krb4/decomp_tkt.c create mode 100644 src/lib/krb4/dest_tkt.c create mode 100644 src/lib/krb4/err_txt.c create mode 100644 src/lib/krb4/fakeenv.c create mode 100644 src/lib/krb4/fgetst.c create mode 100644 src/lib/krb4/g_ad_tkt.c create mode 100644 src/lib/krb4/g_admhst.c create mode 100644 src/lib/krb4/g_cnffile.c create mode 100644 src/lib/krb4/g_cred.c create mode 100644 src/lib/krb4/g_in_tkt.c create mode 100644 src/lib/krb4/g_krbhst.c create mode 100644 src/lib/krb4/g_krbrlm.c create mode 100644 src/lib/krb4/g_phost.c create mode 100644 src/lib/krb4/g_pw_in_tkt.c create mode 100644 src/lib/krb4/g_pw_tkt.c create mode 100644 src/lib/krb4/g_svc_in_tkt.c create mode 100644 src/lib/krb4/g_tf_fname.c create mode 100644 src/lib/krb4/g_tf_realm.c create mode 100644 src/lib/krb4/g_tkt_svc.c create mode 100644 src/lib/krb4/gethostname.c create mode 100644 src/lib/krb4/getst.c create mode 100644 src/lib/krb4/in_tkt.c create mode 100644 src/lib/krb4/kerberos.def create mode 100644 src/lib/krb4/klog.c create mode 100644 src/lib/krb4/kname_parse.c create mode 100644 src/lib/krb4/kntoln.c create mode 100644 src/lib/krb4/kparse.c create mode 100644 src/lib/krb4/krb_err.et create mode 100644 src/lib/krb4/kuserok.c create mode 100644 src/lib/krb4/log.c create mode 100644 src/lib/krb4/mac_glue.c create mode 100644 src/lib/krb4/mac_store.c create mode 100644 src/lib/krb4/mac_store.h create mode 100644 src/lib/krb4/mac_stubs.c create mode 100644 src/lib/krb4/mac_time.c create mode 100644 src/lib/krb4/macsock.c create mode 100644 src/lib/krb4/memcache.c create mode 100644 src/lib/krb4/memcache.h create mode 100644 src/lib/krb4/mk_auth.c create mode 100644 src/lib/krb4/mk_err.c create mode 100644 src/lib/krb4/mk_preauth.c create mode 100644 src/lib/krb4/mk_priv.c create mode 100644 src/lib/krb4/mk_req.c create mode 100644 src/lib/krb4/mk_safe.c create mode 100644 src/lib/krb4/month_sname.c create mode 100644 src/lib/krb4/netread.c create mode 100644 src/lib/krb4/netwrite.c create mode 100644 src/lib/krb4/one.c create mode 100644 src/lib/krb4/pkt_cipher.c create mode 100644 src/lib/krb4/pkt_clen.c create mode 100644 src/lib/krb4/put_svc_key.c create mode 100644 src/lib/krb4/rd_err.c create mode 100644 src/lib/krb4/rd_preauth.c create mode 100644 src/lib/krb4/rd_priv.c create mode 100644 src/lib/krb4/rd_req.c create mode 100644 src/lib/krb4/rd_safe.c create mode 100644 src/lib/krb4/rd_svc_key.c create mode 100644 src/lib/krb4/realmofhost.c create mode 100644 src/lib/krb4/recvauth.c create mode 100644 src/lib/krb4/ren-cyg.sh create mode 100644 src/lib/krb4/ren-pc.bat create mode 100644 src/lib/krb4/ren-pc.sh create mode 100644 src/lib/krb4/ren-pl10.sh create mode 100644 src/lib/krb4/ren.msg create mode 100644 src/lib/krb4/ren2dos.sh create mode 100644 src/lib/krb4/ren2long.sh create mode 100644 src/lib/krb4/save_creds.c create mode 100644 src/lib/krb4/sed-cyg.sh create mode 100644 src/lib/krb4/sed-pc.sh create mode 100644 src/lib/krb4/sed-pl10.sh create mode 100644 src/lib/krb4/send_to_kdc.c create mode 100644 src/lib/krb4/sendauth.c create mode 100644 src/lib/krb4/setenv.c create mode 100644 src/lib/krb4/stime.c create mode 100644 src/lib/krb4/strcasecmp.c create mode 100644 src/lib/krb4/swab.c create mode 100644 src/lib/krb4/tf_shm.c create mode 100644 src/lib/krb4/tf_util.c create mode 100644 src/lib/krb4/tkt_string.c create mode 100644 src/lib/krb4/unix_glue.c create mode 100644 src/lib/krb4/unix_time.c create mode 100644 src/lib/krb4/vmslink.com create mode 100644 src/lib/krb4/vmsswab.c create mode 100644 src/lib/krb4/win_glue.c create mode 100644 src/lib/krb4/win_store.c create mode 100644 src/lib/krb4/win_time.c create mode 100644 src/lib/krb4/winsock.def diff --git a/src/lib/krb4/ChangeLog b/src/lib/krb4/ChangeLog new file mode 100644 index 000000000..ecf35d82d --- /dev/null +++ b/src/lib/krb4/ChangeLog @@ -0,0 +1,1135 @@ +Tue Mar 28 09:19:23 1995 Mark Eichin + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 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 + + * 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 + + * 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 + + * 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 + + * memcache.c (unix): Define if _AIX is defined (AIX compiler does + not predefine unix). + +Fri Dec 16 18:57:40 1994 Ian Lance Taylor + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * in_tkt.c: Fix thinko in last change. + +Fri Nov 4 12:05:57 1994 Ian Lance Taylor + + * 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 + + * dest_tkt.c: Include "krb.h" before . + +Mon Oct 31 19:41:14 1994 Ian Lance Taylor + + * Makefile.in (CODE): Use Makefile.in instead of Imakefile. + +Fri Oct 28 15:21:56 1994 Ian Lance Taylor + + * 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 , declare + fStream as unsigned long. Cast it whenever we need it. This + removes the need to include MacTCP header files in . + * 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 + 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 and default MAXHOSTNAMELEN. + * dest_tkt.c, realmofhost.c, tf_shm.c: Remove RCS crud. + * rd_safe.c, tf_shm.c: Remove errno declaration, , etc. + * mk_priv.c: Comment changes. + * g_ad_tkt.c: Remove obsolete defn of . + +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 . 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 . + * rd_priv.c, mk_safe.c: Remove , 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 , 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, and errmsg as unused. + + * ad_print.c: Pull , which is now in . + * decomp_tkt.c: Add file name to title comments. + * fakeenv.c: Pull and . + * g_phost.c: Replace and with . + * ren.msg: Remove get_request.c (g_request.c), now gone. + * send_to_kdc.c: Pull . + * 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 + 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 + . + * cr_tkt.c, decomp_tkt.c: Pull . + * dest_tkt.c, in_tkt.c, mk_err.c: Pull + * g_ad_tkt.c: Pull , , RCS crud. + * g_cred.c: Pull RCS crud, add . + * g_in_tkt.c: Pull , , , RCS crud. + * g_tf_fname.c: Lint, pull RCS crud. + * kuserok.c: and . + * rd_err.c: Pull , , , . + * 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 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 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 000000000..4f49121ad --- /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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 000000000..6571db95b --- /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 000000000..b29663006 --- /dev/null +++ b/src/lib/krb4/Password.c @@ -0,0 +1,433 @@ +#include "kerberos.h" +#define KRB_DEFS +#include "krb_driver.h" + +#include +#include +#include +#include +#include +#include + +/* added for OpenInitRF.c + FIXME jcm - should check that they are not in c-mac + or other included file +*/ + +#include +#include +#include +#include +#include +#include + + +// #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 000000000..2ed539d8c --- /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 000000000..797293751 --- /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 + * . + * + * Miscellaneous debug printing utilities + */ + +#include "mit-copyright.h" +#define DEFINE_SOCKADDR /* Request definitions for sockets */ +#include "krb.h" +#include "des.h" +#include + +/* + * 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 000000000..8f10ace40 --- /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 000000000..5203506d3 --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include "prot.h" +#include + +/* + * 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 000000000..d15a4e0fd --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include "des.h" +#include + +/* + * 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 000000000..8daa2d688 --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include "prot.h" +#include + +/* + * 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 000000000..068d4e2ba --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include "prot.h" +#include + +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 000000000..39ed53859 --- /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 + * . + */ + +#include "mit-copyright.h" +#include "des.h" +#include "krb.h" +#include "prot.h" +#include + +/* + * 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 000000000..bd2ec904a --- /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 + * . + */ + +#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 000000000..5a9213b60 --- /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 + * . + */ + +#include "mit-copyright.h" +#include "des.h" +#include "krb.h" +#include "prot.h" +#include + +#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 000000000..1358322ed --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include +#include +#include +#ifdef TKT_SHMEM +#include +#endif +#include +#ifdef NEED_SYS_FCNTL_H +/* for sconix, to get O_RDWR */ +#include +#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 000000000..0b7697ea8 --- /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 + * . + */ + +#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 000000000..d4f4d7638 --- /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 +#include + +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 000000000..b5d8aa5cb --- /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 + * . + */ + +#include "mit-copyright.h" +#include + +/* + * 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 000000000..55a82bb71 --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include "des.h" +#include "prot.h" +#include + +#include + +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 000000000..68ac1f0da --- /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 + * . + */ + +#include "mit-copyright.h" +#include +#include "krb.h" +#include + +/* + * 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 000000000..b1d38efdf --- /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 's work for the Mac port, but + it solves a problem for now. */ + +#include +#include + +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 000000000..491861be6 --- /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 + * . + */ + +#include "mit-copyright.h" +#include +#include +#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 000000000..35abf2e90 --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include "des.h" +#include "prot.h" + +#include + +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 , 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 000000000..eaab28928 --- /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 + * . + */ + +#include "mit-copyright.h" +#include +#include "krb.h" +#include + +/* + * 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 000000000..f83beba36 --- /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 + * . + */ + +#include "mit-copyright.h" +#include +#include "krb.h" +#include + +/* + * 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 000000000..2e3d0402e --- /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 + * . + */ + +#include "mit-copyright.h" +#define DEFINE_SOCKADDR /* For struct hostent, , etc */ +#include "krb.h" + +#include +#include +#include +#include /* For struct hostent, gethostbyname, etc */ +#include /* 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 000000000..213540e69 --- /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 + * . + */ + +#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 +#ifdef BSDUNIX +#include +#include +#include +#include +#else +char *strcpy(); +int strcmp(); +#endif +#ifdef __svr4__ +#include +#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 000000000..faacab9d0 --- /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 + * . + */ + +#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 000000000..72fae3be7 --- /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 + * . + */ + +#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 000000000..9aef3cfdf --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include +#include /* 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 000000000..5de152849 --- /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 + * . + */ + +#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 000000000..a4f5c183c --- /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 +#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 000000000..cac202e3f --- /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 + * . + */ + +#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 000000000..3ff05bd31 --- /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 + * . + */ + +#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 000000000..4674f3116 --- /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 + * . + */ + +#include "mit-copyright.h" +#include +#include +#include "krb.h" +#include +#ifdef NEED_SYS_FCNTL_H +/* just for O_RDWR for sco */ +#include +#endif +#include +#ifdef TKT_SHMEM +#include +#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 000000000..f8124aa8c --- /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 000000000..9a65ae9ef --- /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 + * . + */ + +#include "mit-copyright.h" +#ifdef NEED_TIME_H +#include +#endif +#ifndef VMS +#include +#endif +#include + +#include "krb.h" +#include + +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 000000000..059d08428 --- /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 + * . + */ + +#include "mit-copyright.h" + +#include +#include "krb.h" +#include + +/* 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 000000000..8b6cdfe0e --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include + +/* + * 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 000000000..fb4f6e243 --- /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 + * . + * + * 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 +#include +#include +#include + +#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) { + 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\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 \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. + * + * kuserok: check if a kerberos principal has + * access to a local account + */ + +#include "mit-copyright.h" + +#include "krb.h" +#include +#include +#include +#include +#include +#include +#ifdef USE_UNISTD_H +#include +#endif +#ifdef __SCO__ +/* just for F_OK for sco */ +#include +#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 + +/* + * 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 000000000..7244a60b6 --- /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 + * . + */ + +#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 +#endif +#ifndef VMS +#include +#endif +#include + +#include "krb.h" +#include + +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 000000000..ce3a6523f --- /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 + * . + * + * Macintosh ooperating system interface for Kerberos. + */ + +#include "mit-copyright.h" +#define DEFINE_SOCKADDR /* For struct hostent, , etc */ +#include "krb.h" + +/* Mac Cincludes */ +#include +#include + +/* 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 000000000..262ba58bd --- /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 + +/* Headers from store.c from KClient */ +#include +#include +#include +#include +#include +#include +#include + +#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 000000000..b1652dc55 --- /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 000000000..b83e92d10 --- /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 + * . + * + * 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, , etc */ +#include "krb.h" +#include "krb_driver.h" /* Mac driver interface */ + +#include +#include +#include +#include + +/* 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 000000000..91f09e5aa --- /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 + * . + * + * Macintosh ooperating system interface for Kerberos. + */ + +#include "mit-copyright.h" +#define DEFINE_SOCKADDR /* For struct hostent, , etc */ +#define NEED_TIME_H +#include "krb.h" +#include "des.h" +#include "AddressXlation.h" /* for ip_addr */ + +#include /* Defines MachineLocation, used by getTimeZoneOffset */ +#include /* Defines BitTst(), called by getTimeZoneOffset() */ +#include /* Defines GetDateTime */ + +/* Mac Cincludes */ +#include +#include + + + /******************************* + 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 000000000..e62e66347 --- /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 +#include +#include +#include + +/* Mac includes */ +#include +#include +#include /* For ENOMEM */ + +#ifndef ENOMEM /* Think C 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 000000000..3e622eb10 --- /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 +#include /* REQUIRED for near/far declarations */ +#endif + +#ifndef unix +#ifdef _AIX +#define unix +#endif +#endif + +#ifdef unix + +/* Unix interface to memory cache Mac functions. */ + +#include +#include +#ifdef POSIX +#include +#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 000000000..4126e115f --- /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 000000000..60444dcf1 --- /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 + * . + * + * 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 +#include +#include + +#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 000000000..830ee716b --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include "prot.h" +#include + +/* + * 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 000000000..3f4830747 --- /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 + 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 000000000..72fff7007 --- /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 + * . + * + * 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 +#include + +#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 000000000..0cb953fc5 --- /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 + * . + */ + +#define DEFINE_SOCKADDR +#include "mit-copyright.h" +#include "krb.h" +#include "prot.h" +#include "des.h" +#include + +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 000000000..c3ed94d32 --- /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 + * . + * + * 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 +#include + +#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 000000000..61a007ab7 --- /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 + * . + */ + +#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 000000000..91a868c86 --- /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 + * . + */ + +#include "mit-copyright.h" +#include +#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 000000000..403ee4fb5 --- /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 + * . + */ + +#include "mit-copyright.h" +#include +#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 000000000..358bb782e --- /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 + * . + */ + +#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 000000000..29123480e --- /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 + * . + */ + +#include "mit-copyright.h" +#include +#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 000000000..99a712b8d --- /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 + * . + */ + +#include "mit-copyright.h" +#include +#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 000000000..e3b05cc27 --- /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 +#include +#include +#ifdef NEED_SYS_FCNTL_H +#include +#endif +#ifdef HAS_UNISTD_H +#include +#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 000000000..2b105a01f --- /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 + * . + * + * Steve Miller Project Athena MIT/DEC + */ + +#include "mit-copyright.h" + +#include + +#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 000000000..65c2dcc71 --- /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 000000000..7c4f613a4 --- /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 + * . + * + * 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 +#include + +/* 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 000000000..07347b905 --- /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 + * . + */ + +#include "mit-copyright.h" +#include "des.h" +#include "krb.h" +#include "prot.h" +#include + +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 000000000..e1ea236ad --- /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 + * . + * + * 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 +#include + +/* 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 000000000..cd457eb42 --- /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 + * . + */ + +#include "mit-copyright.h" +#include "krb.h" +#include +#include + +/* + * 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 000000000..2114b516a --- /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 + * . + * + * routine to convert hostname into realm name. + */ + +#include "mit-copyright.h" +#include +#include +#include +#include /* For struct hostent, gethostbyname, etc */ +#include /* For MAXHOSTNAMELEN */ +#ifdef POSIX +#include +#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 000000000..a7fd9b456 --- /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 + * . + */ + +#include "mit-copyright.h" + +#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */ +#include "krb.h" +#include +#include +#include + + +#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 000000000..d3d31a9d4 --- /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 + } + ' + +[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 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 000000000..3989e2c6e --- /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 + } + ' . + */ + +#include "mit-copyright.h" +#include +#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 000000000..3859df138 --- /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 } + ' . + */ + +#include "mit-copyright.h" + +#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */ +#include "krb.h" +#include "krbports.h" +#include "prot.h" +#include +#include + +#define S_AD_SZ sizeof(struct sockaddr_in) + +#ifdef POSIX +#include +#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 000000000..8d079f910 --- /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 + * . + * + */ + +#include "mit-copyright.h" + +#define DEFINE_SOCKADDR /* Ask for sockets declarations from krb.h. */ +#include "krb.h" +#include +#include +#include + +#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 000000000..76a2a615b --- /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 +#include + +/* + * 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 000000000..f90fbc566 --- /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 + * . + */ + +#include "mit-copyright.h" +#define DEFINE_SOCKADDR +#define NEED_TIME_H +#include "krb.h" +#include /* 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 000000000..31bf0afbf --- /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 000000000..e07b28b43 --- /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 000000000..bd08f7f72 --- /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 + * . + * + * Shared memory segment functions for session keys. Derived from code + * contributed by Dan Kolkowitz (kolk@jessica.stanford.edu). + */ + +#include "mit-copyright.h" + +#include +#include +#include +#include "krb.h" +#include "des.h" +#include +#include + +#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 000000000..717f2dae2 --- /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 + * . + */ + +#include "mit-copyright.h" + +#include "krb.h" + +#include +#include +#include +#include +#include + +#ifdef TKT_SHMEM +#include +#include +#include +#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 +#include +#ifdef __SCO__ +#include +#endif +#ifdef __svr4__ +#include +#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 + +/* + * 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 000000000..aac6ec467 --- /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 + * . + */ + +#include "mit-copyright.h" +#include +#include "krb.h" +#include +#include + +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 000000000..eeafdb9d7 --- /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 + +/* 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 000000000..736f49608 --- /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 + +/* 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 000000000..95cabfe1d --- /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 000000000..019580882 --- /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 000000000..de8b62015 --- /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 +#include +#include + +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 000000000..914ba7741 --- /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 +#include +#include + +#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 000000000..9022d1b9a --- /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 +#include +#include +#include +#include +#include + +/* + * 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 000000000..cada77985 --- /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 + -- 2.26.2