[23153] in Source-Commits

home help back first fref pref prev next nref lref last post

/svn/athena r22814 - in trunk/athena/lib/zephyr: . h h/zephyr lib server zhm

daemon@ATHENA.MIT.EDU (ghudson@MIT.EDU)
Thu Apr 3 13:52:35 2008

Date: Thu, 3 Apr 2008 13:51:49 -0400 (EDT)
From: ghudson@MIT.EDU
Message-Id: <200804031751.NAA06985@drugstore.mit.edu>
To: source-commits@MIT.EDU
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Author: ghudson
Date: 2008-04-03 13:51:46 -0400 (Thu, 03 Apr 2008)
New Revision: 22814

Added:
   trunk/athena/lib/zephyr/lib/ZCkZAut.c
   trunk/athena/lib/zephyr/lib/ZMakeZcode.c
   trunk/athena/lib/zephyr/lib/ZReadZcode.c
Modified:
   trunk/athena/lib/zephyr/configure.in
   trunk/athena/lib/zephyr/h/internal.h
   trunk/athena/lib/zephyr/h/zephyr/zephyr.h
   trunk/athena/lib/zephyr/lib/Makefile.in
   trunk/athena/lib/zephyr/lib/ZCkAuth.c
   trunk/athena/lib/zephyr/lib/ZFmtAuth.c
   trunk/athena/lib/zephyr/lib/ZFmtNotice.c
   trunk/athena/lib/zephyr/lib/ZFmtSmRaw.c
   trunk/athena/lib/zephyr/lib/ZGetSender.c
   trunk/athena/lib/zephyr/lib/ZInit.c
   trunk/athena/lib/zephyr/lib/ZMkAuth.c
   trunk/athena/lib/zephyr/lib/ZParseNot.c
   trunk/athena/lib/zephyr/lib/ZVariables.c
   trunk/athena/lib/zephyr/lib/Zinternal.c
   trunk/athena/lib/zephyr/server/bdump.c
   trunk/athena/lib/zephyr/server/client.c
   trunk/athena/lib/zephyr/server/dispatch.c
   trunk/athena/lib/zephyr/server/kstuff.c
   trunk/athena/lib/zephyr/server/main.c
   trunk/athena/lib/zephyr/server/realm.c
   trunk/athena/lib/zephyr/server/server.c
   trunk/athena/lib/zephyr/server/subscr.c
   trunk/athena/lib/zephyr/server/uloc.c
   trunk/athena/lib/zephyr/server/zserver.h
   trunk/athena/lib/zephyr/server/zsrv_conf.h
   trunk/athena/lib/zephyr/zhm/zhm_client.c
Log:
From Karl Ramm (incorporating work from Jeff Hutzelman and others):
Add krb5 support to Zephyr.


Modified: trunk/athena/lib/zephyr/configure.in
===================================================================
--- trunk/athena/lib/zephyr/configure.in	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/configure.in	2008-04-03 17:51:46 UTC (rev 22814)
@@ -37,7 +37,7 @@
 AC_HEADER_SYS_WAIT
 AC_CHECK_HEADERS(fcntl.h paths.h termios.h sgtty.h unistd.h malloc.h)
 AC_CHECK_HEADERS(sys/filio.h sys/ioctl.h sys/time.h sys/file.h sys/utsname.h)
-AC_CHECK_HEADERS(sys/select.h sys/msgbuf.h sys/cdefs.h)
+AC_CHECK_HEADERS(sys/select.h sys/msgbuf.h sys/cdefs.h krb5_err.h)
 
 if test "$no_x" != "yes"; then
 	XCLIENTS=xzwrite
@@ -86,12 +86,13 @@
 AC_SUBST(SLIB)
 
 ATHENA_KRB4
+ATHENA_KRB5
 ATHENA_HESIOD
 ATHENA_REGEXP
 ATHENA_ARES
 ATHENA_UTIL_COM_ERR
 ATHENA_UTIL_SS
-LIBS="$KRB4_LIBS $HESIOD_LIBS $LIBS"
+LIBS="$KRB5_LIBS $KRB4_LIBS $HESIOD_LIBS $LIBS"
 
 dnl Checks for library functions.
 AC_PROG_GCC_TRADITIONAL
@@ -100,7 +101,60 @@
 AC_FUNC_SETPGRP
 AC_CHECK_FUNCS(putenv strchr memcpy memmove waitpid getlogin strerror random)
 AC_CHECK_FUNCS(lrand48 gethostid getsid getpgid krb_get_err_text krb_log)
+AC_CHECK_FUNCS(krb5_free_data krb5_c_make_checksum krb5_cc_set_default_name)
 
+AC_MSG_CHECKING(for krb5_auth_con_getauthenticator taking double pointer)
+AC_CACHE_VAL(ac_cv_krb5_auth_con_getauthenticator_takes_double_pointer, [
+local_save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="${CPPFLAGS} ${KRB5_INC_FLAGS}"
+AC_TRY_COMPILE(
+[#define socklen_t int
+#define ssize_t int
+#include <krb5.h>
+krb5_error_code
+krb5_auth_con_getauthenticator(krb5_context context,
+                           krb5_auth_context auth_context,
+                           krb5_authenticator *authenticator);],
+[krb5_error_code foo = krb5_auth_con_getauthenticator(0, 0, 0);],
+ac_cv_krb5_auth_con_getauthenticator_takes_double_pointer=no,
+ac_cv_krb5_auth_con_getauthenticator_takes_double_pointer=yes)
+])
+CPPFLAGS="${local_save_CPPFLAGS}"
+if test "$ac_cv_krb5_auth_con_getauthenticator_takes_double_pointer" = yes; then
+        AC_DEFINE(KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER)dnl
+fi
+AC_MSG_RESULT($ac_cv_krb5_auth_con_getauthenticator_takes_double_pointer)
+
+AC_MSG_CHECKING(for enc_part2 in struct krb5_ticket)
+AC_CACHE_VAL(ac_cv_have_krb5_ticket_enc_part2, [
+local_save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="${CPPFLAGS} ${KRB5_INC_FLAGS}"
+AC_TRY_COMPILE(
+[#include <krb5.h>], [krb5_ticket _tkt; _tkt.enc_part2;],
+ac_cv_have_krb5_ticket_enc_part2=yes,
+ac_cv_have_krb5_ticket_enc_part2=no)
+])
+CPPFLAGS="${local_save_CPPFLAGS}"
+if test "$ac_cv_have_krb5_ticket_enc_part2" = yes; then
+	AC_DEFINE(HAVE_KRB5_TICKET_ENC_PART2)dnl
+fi
+AC_MSG_RESULT($ac_cv_have_krb5_ticket_enc_part2)
+
+AC_MSG_CHECKING(for enctype in struct krb5_keyblock)
+AC_CACHE_VAL(ac_cv_have_krb5_creds_keyblock_enctype, [
+local_save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="${CPPFLAGS} ${KRB5_INC_FLAGS}"
+AC_TRY_COMPILE(
+[#include <krb5.h>], [krb5_creds _creds; _creds.keyblock.enctype;],
+ac_cv_have_krb5_creds_keyblock_enctype=yes,
+ac_cv_have_krb5_creds_keyblock_enctype=no)
+])
+CPPFLAGS="${local_save_CPPFLAGS}"
+if test "$ac_cv_have_krb5_creds_keyblock_enctype" = yes; then
+	AC_DEFINE(HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE)dnl
+fi
+AC_MSG_RESULT($ac_cv_have_krb5_creds_keyblock_enctype)
+
 AC_CONFIG_HEADER(h/config.h)
 AC_OUTPUT(Makefile clients/Makefile clients/xzwrite/Makefile
 	  clients/zaway/Makefile clients/zctl/Makefile

Modified: trunk/athena/lib/zephyr/h/internal.h
===================================================================
--- trunk/athena/lib/zephyr/h/internal.h	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/h/internal.h	2008-04-03 17:51:46 UTC (rev 22814)
@@ -11,6 +11,10 @@
 #include <krb_err.h>
 #endif
 
+#ifdef HAVE_KRB5
+#include <krb5.h>
+#endif
+
 #ifdef HAVE_HESIOD
 #include <hesiod.h>
 #endif
@@ -34,6 +38,13 @@
 #define Z_NOTICETIMELIMIT	30	/* Time to wait for fragments */
 #define Z_INITFILTERSIZE	30	/* Starting size of uid filter */
 
+#define Z_AUTHMODE_NONE          0      /* no authentication */
+#define Z_AUTHMODE_KRB4          1      /* authenticate using Kerberos V4 */
+#define Z_AUTHMODE_KRB5          2      /* authenticate using Kerberos V5 */
+
+#define Z_KEYUSAGE_CLT_CKSUM  1027    /* client->server notice checksum */
+#define Z_KEYUSAGE_SRV_CKSUM  1029    /* server->client notice checksum */
+
 struct _Z_Hole {
     struct _Z_Hole	*next;
     int			first;
@@ -64,6 +75,11 @@
 extern int __HM_set;		/* 0 if dest addr set, 1 otherwise */
 extern int __Zephyr_server;	/* 0 if normal client, 1 if server or zhm */
 
+#ifdef HAVE_KRB5
+extern krb5_context Z_krb5_ctx;
+Code_t Z_krb5_lookup_cksumtype(krb5_enctype, krb5_cksumtype *);
+#endif
+
 extern ZLocations_t *__locate_list;
 extern int __locate_num;
 extern int __locate_next;
@@ -97,5 +113,48 @@
 			    int (*pred) __P((ZNotice_t *, void *)), void *arg,
 			    int timeout));
 
+
+Code_t Z_NewFormatHeader __P((ZNotice_t *, char *, int, int *, Z_AuthProc));
+Code_t Z_NewFormatAuthHeader __P((ZNotice_t *, char *, int, int *, Z_AuthProc));
+Code_t Z_NewFormatRawHeader __P((ZNotice_t *, char *, int, int *, char **, 
+                                 int *, char **, char **));
+Code_t Z_AsciiFormatRawHeader __P((ZNotice_t *, char *, int, int *, char **, 
+                                 int *, char **, char **));
+
+void Z_gettimeofday(struct _ZTimeval *ztv, struct timezone *tz);
+
+#ifdef HAVE_KRB5
+int ZGetCreds(krb5_creds **creds_out);
+int ZGetCredsRealm(krb5_creds **creds_out, char *realm);
+Code_t Z_Checksum(krb5_data *cksumbuf, krb5_keyblock *keyblock, krb5_cksumtype cksumtype, char **asn1_data, int *asn1_len);
+Code_t Z_ExtractEncCksum(krb5_keyblock *keyblock, krb5_enctype *enctype, krb5_cksumtype *cksumtype);
+int Z_krb5_verify_cksum(krb5_keyblock *keyblock, krb5_data *cksumbuf, krb5_cksumtype cksumtype, char *asn1_data, int asn1_len);
+Code_t Z_InsertZcodeChecksum(krb5_keyblock *keyblock, ZNotice_t *notice, 
+                             char *buffer,
+                             char *cksum_start, int cksum_len, 
+                             char *cstart, char *cend, int buffer_len,
+                             int *length_ajdust);
+#endif
+
+#ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
+#define Z_keydata(keyblock)	((keyblock)->contents)
+#define Z_keylen(keyblock)	((keyblock)->length)
+#define Z_credskey(creds)	(&(creds)->keyblock)
+#define Z_enctype(keyblock)	((keyblock)->enctype)
+#else
+#define Z_keydata(keyblock)	((keyblock)->keyvalue.data)
+#define Z_keylen(keyblock)	((keyblock)->keyvalue.length)
+#define Z_credskey(creds)	(&(creds)->session)
+#define Z_enctype(keyblock)	((keyblock)->keytype)
+#endif
+
+#ifdef HAVE_KRB5_TICKET_ENC_PART2
+#define Z_tktprincp(tkt)	((tkt)->enc_part2 != 0)
+#define Z_tktprinc(tkt)		((tkt)->enc_part2->client)
+#else
+#define	Z_tktprincp(tkt)	((tkt)->client != 0)
+#define Z_tktprinc(tkt)		((tkt)->client)
+#endif
+
 #endif /* __INTERNAL_H__ */
 

Modified: trunk/athena/lib/zephyr/h/zephyr/zephyr.h
===================================================================
--- trunk/athena/lib/zephyr/h/zephyr/zephyr.h	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/h/zephyr/zephyr.h	2008-04-03 17:51:46 UTC (rev 22814)
@@ -39,6 +39,7 @@
 #define	SERVER_SVCNAME		"zephyr-clt"
 #define SERVER_SERVICE		"zephyr"
 #define SERVER_INSTANCE		"zephyr"
+#define SERVER_KRB5_SERVICE     "zephyr"
 
 #define ZVERSIONHDR	"ZEPH"
 #define ZVERSIONMAJOR	0
@@ -62,14 +63,19 @@
 } ZNotice_Kind_t;
 extern ZCONST char *ZNoticeKinds[9];
 
+struct _ZTimeval {
+	int tv_sec;
+	int tv_usec;
+};
+
 /* Unique ID format */
 typedef struct _ZUnique_Id_t {
     struct	in_addr zuid_addr;
-    struct	timeval	tv;
+    struct	_ZTimeval	tv;
 } ZUnique_Id_t;
 
 /* Checksum */
-typedef unsigned long ZChecksum_t;
+typedef unsigned int ZChecksum_t;
 
 /* Notice definition */
 typedef struct _ZNotice_t {
@@ -78,7 +84,7 @@
     ZNotice_Kind_t	z_kind;
     ZUnique_Id_t	z_uid;
 #define z_sender_addr	z_uid.zuid_addr
-    struct		timeval z_time;
+    struct		_ZTimeval z_time;
     unsigned short	z_port;
     int			z_auth;
     int			z_checked_auth;
@@ -93,6 +99,7 @@
     char		*z_multinotice;
     ZUnique_Id_t	z_multiuid;
     ZChecksum_t		z_checksum;
+    char                *z_ascii_checksum;
     int			z_num_other_fields;
     char		*z_other_fields[Z_MAXOTHERFIELDS];
     caddr_t		z_message;
@@ -134,6 +141,8 @@
 /* Defines for ZFormatNotice, et al. */
 typedef Code_t (*Z_AuthProc) ZP((ZNotice_t*, char *, int, int *));
 Code_t ZMakeAuthentication ZP((ZNotice_t*, char *,int, int*));
+Code_t ZMakeZcodeAuthentication ZP((ZNotice_t*, char *,int, int*));
+Code_t ZMakeZcodeRealmAuthentication ZP((ZNotice_t*, char *,int, int*, char*));
 
 char *ZGetSender ZP((void));
 char *ZGetVariable ZP((char *));
@@ -147,6 +156,7 @@
 Code_t ZReadAscii ZP((char*, int, unsigned char*, int));
 Code_t ZReadAscii32 ZP((char *, int, unsigned long *));
 Code_t ZReadAscii16 ZP((char *, int, unsigned short *));
+Code_t ZReadZcode ZP((unsigned char*, unsigned char*, int, int *));
 Code_t ZSendPacket ZP((char*, int, int));
 Code_t ZSendList ZP((ZNotice_t*, char *[], int, Z_AuthProc));
 Code_t ZSrvSendList ZP((ZNotice_t*, char*[], int, Z_AuthProc, Code_t (*)()));
@@ -170,8 +180,12 @@
 Code_t ZMakeAscii ZP((char*, int, unsigned char*, int));
 Code_t ZMakeAscii32 ZP((char *, int, unsigned long));
 Code_t ZMakeAscii16 ZP((char *, int, unsigned int));
+Code_t ZMakeZcode ZP((char*, int, unsigned char*, int));
+Code_t ZMakeZcode32 ZP((char *, int, unsigned long));
 Code_t ZReceivePacket ZP((ZPacket_t, int*, struct sockaddr_in*));
 Code_t ZCheckAuthentication ZP((ZNotice_t*, struct sockaddr_in*));
+Code_t ZCheckZcodeAuthentication ZP((ZNotice_t*, struct sockaddr_in*));
+Code_t ZCheckZcodeRealmAuthentication ZP((ZNotice_t*, struct sockaddr_in*, char *realm));
 Code_t ZInitLocationInfo ZP((char *hostname, char *tty));
 Code_t ZSetLocation ZP((char *exposure));
 Code_t ZUnsetLocation ZP((void));
@@ -248,6 +262,7 @@
 #define	SRV_TIMEOUT		30
 
 #define ZAUTH (ZMakeAuthentication)
+#define ZCAUTH (ZMakeZcodeAuthentication)
 #define ZNOAUTH ((Z_AuthProc)0)
 
 /* Packet strings */

Modified: trunk/athena/lib/zephyr/lib/Makefile.in
===================================================================
--- trunk/athena/lib/zephyr/lib/Makefile.in	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/Makefile.in	2008-04-03 17:51:46 UTC (rev 22814)
@@ -37,7 +37,8 @@
 	ZPeekIfNot.lo ZPeekNot.lo ZPeekPkt.lo ZPending.lo ZReadAscii.lo \
 	ZRecvNot.lo ZRecvPkt.lo ZRetSubs.lo ZSendList.lo ZSendNot.lo \
 	ZSendPkt.lo ZSendRaw.lo ZSendRLst.lo ZSetDest.lo ZSetFD.lo ZSetSrv.lo \
-	ZSubs.lo ZVariables.lo ZWait4Not.lo Zinternal.lo
+	ZSubs.lo ZVariables.lo ZWait4Not.lo Zinternal.lo ZMakeZcode.lo \
+	ZReadZcode.lo ZCkZAut.lo
 
 .SUFFIXES: .lo
 

Modified: trunk/athena/lib/zephyr/lib/ZCkAuth.c
===================================================================
--- trunk/athena/lib/zephyr/lib/ZCkAuth.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/ZCkAuth.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -17,6 +17,10 @@
 
 #include <internal.h>
 
+#if defined(HAVE_KRB5) && !HAVE_KRB5_FREE_DATA
+#define krb5_free_data(ctx, dat) free((dat)->data)
+#endif
+
 /* Check authentication of the notice.
    If it looks authentic but fails the Kerberos check, return -1.
    If it looks authentic and passes the Kerberos check, return 1.
@@ -28,30 +32,49 @@
 Code_t ZCheckAuthentication(notice, from)
     ZNotice_t *notice;
     struct sockaddr_in *from;
-{	
-#ifdef HAVE_KRB4
+{
+#if 0
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
     int result;
     ZChecksum_t our_checksum;
+    C_Block *session;
+#ifdef HAVE_KRB5
+    krb5_creds *creds_out;
+#else
     CREDENTIALS cred;
-
+#endif
     /* If the value is already known, return it. */
     if (notice->z_checked_auth != ZAUTH_UNSET)
 	return (notice->z_checked_auth);
 
     if (!notice->z_auth)
 	return (ZAUTH_NO);
-	
+
+#ifdef HAVE_KRB5
+    result = ZGetCreds(&creds_out);
+    if (result)
+      return ZAUTH_NO;
+    /* HOLDING: creds_out */
+
+    if (creds_out->keyblock.enctype != ENCTYPE_DES_CBC_CRC)
+      return (ZAUTH_NO);
+    session = (C_Block *)creds_out->keyblock.contents;
+    
+#else
     if ((result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, 
 			       __Zephyr_realm, &cred)) != 0)
 	return (ZAUTH_NO);
 
+    session = (C_Block *)cred.session;
+#endif
+
 #ifdef NOENCRYPTION
     our_checksum = 0;
 #else
     our_checksum = des_quad_cksum(notice->z_packet, NULL, 
 				  notice->z_default_format+
 				  strlen(notice->z_default_format)+1-
-				  notice->z_packet, 0, cred.session);
+				  notice->z_packet, 0, session);
 #endif
     /* if mismatched checksum, then the packet was corrupted */
     return ((our_checksum == notice->z_checksum) ? ZAUTH_YES : ZAUTH_FAILED);
@@ -59,4 +82,7 @@
 #else
     return (notice->z_auth ? ZAUTH_YES : ZAUTH_NO);
 #endif
+#else
+    ZCheckZcodeAuthentication(notice, from);
+#endif
 } 

Added: trunk/athena/lib/zephyr/lib/ZCkZAut.c

Modified: trunk/athena/lib/zephyr/lib/ZFmtAuth.c
===================================================================
--- trunk/athena/lib/zephyr/lib/ZFmtAuth.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/ZFmtAuth.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -16,7 +16,7 @@
 
 #include <internal.h>
 
-#ifdef HAVE_KRB4
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
 Code_t ZFormatAuthenticNotice(notice, buffer, buffer_len, len, session)
     ZNotice_t *notice;
     register char *buffer;
@@ -62,3 +62,71 @@
     return (ZERR_NONE);
 }
 #endif
+
+#ifdef HAVE_KRB5
+Code_t ZFormatAuthenticNoticeV5(notice, buffer, buffer_len, len, keyblock)
+    ZNotice_t *notice;
+    register char *buffer;
+    register int buffer_len;
+    int *len;
+    krb5_keyblock *keyblock;
+{
+    ZNotice_t newnotice;
+    char *ptr;
+    int retval, hdrlen, hdr_adj;
+    krb5_enctype enctype;
+    krb5_cksumtype cksumtype;
+    int valid;
+    char *svcinst, *x, *y;
+    int key_len;
+    char *cksum_start, *cstart, *cend;
+    int cksum_len;
+    
+    key_len = Z_keylen(keyblock);
+    retval = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+    if (retval)
+         return (ZAUTH_FAILED);
+
+    if (key_len == 8 && (enctype == ENCTYPE_DES_CBC_CRC || 
+                         enctype == ENCTYPE_DES_CBC_MD4 ||
+                         enctype == ENCTYPE_DES_CBC_MD5)) {
+         C_Block tmp;
+         memcpy(&tmp, Z_keydata(keyblock), key_len);
+         return ZFormatAuthenticNotice(notice, buffer, buffer_len, len,
+                                       tmp);
+    }
+         
+    newnotice = *notice;
+    newnotice.z_auth = 1;
+    newnotice.z_authent_len = 0;
+    newnotice.z_ascii_authent = "";
+
+    if ((retval = Z_NewFormatRawHeader(&newnotice, buffer, buffer_len,
+                                       &hdrlen, 
+                                       &cksum_start, &cksum_len, &cstart, 
+                                       &cend)) != ZERR_NONE)
+	return (retval);
+     
+    retval = Z_InsertZcodeChecksum(keyblock, &newnotice, buffer, 
+                                   cksum_start, cksum_len, cstart, cend, 
+                                   buffer_len, &hdr_adj);
+     if (retval)
+          return retval;
+     
+     hdrlen += hdr_adj;
+     
+     ptr = buffer+hdrlen;
+
+     if (newnotice.z_message_len+hdrlen > buffer_len)
+          return (ZERR_PKTLEN);
+     
+     (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
+     
+     *len = hdrlen+newnotice.z_message_len;
+     
+     if (*len > Z_MAXPKTLEN)
+          return (ZERR_PKTLEN);
+     
+     return (ZERR_NONE);
+}
+#endif

Modified: trunk/athena/lib/zephyr/lib/ZFmtNotice.c
===================================================================
--- trunk/athena/lib/zephyr/lib/ZFmtNotice.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/ZFmtNotice.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -41,3 +41,29 @@
 
     return (ZERR_NONE);
 }
+
+Code_t ZNewFormatNotice(notice, buffer, ret_len, cert_routine)
+    register ZNotice_t *notice;
+    char **buffer;
+    int *ret_len;
+    Z_AuthProc cert_routine;
+{
+    char header[Z_MAXHEADERLEN];
+    int hdrlen;
+    Code_t retval;
+
+    if ((retval = Z_NewFormatHeader(notice, header, sizeof(header), &hdrlen, 
+				 cert_routine)) != ZERR_NONE)
+	return (retval);
+
+    *ret_len = hdrlen+notice->z_message_len;
+
+    /* Length can never be zero, don't have to worry about malloc(0). */
+    if (!(*buffer = (char *) malloc((unsigned)*ret_len)))
+	return (ENOMEM);
+
+    (void) memcpy(*buffer, header, hdrlen);
+    (void) memcpy(*buffer+hdrlen, notice->z_message, notice->z_message_len);
+
+    return (ZERR_NONE);
+}

Modified: trunk/athena/lib/zephyr/lib/ZFmtSmRaw.c
===================================================================
--- trunk/athena/lib/zephyr/lib/ZFmtSmRaw.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/ZFmtSmRaw.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -37,3 +37,26 @@
 
     return (ZERR_NONE);
 }
+
+Code_t ZNewFormatSmallRawNotice(notice, buffer, ret_len)
+     ZNotice_t *notice;
+     ZPacket_t buffer;
+     int *ret_len;
+{
+  Code_t retval;
+  int hdrlen;
+  
+  if ((retval = Z_AsciiFormatRawHeader(notice, buffer, Z_MAXHEADERLEN,
+                                       &hdrlen, NULL, NULL, NULL, NULL)) 
+      != ZERR_NONE)
+    return (retval);
+  
+  *ret_len = hdrlen+notice->z_message_len;
+  
+  if (*ret_len > Z_MAXPKTLEN)
+    return (ZERR_PKTLEN);
+  
+  (void) memcpy(buffer+hdrlen, notice->z_message, notice->z_message_len);
+  
+  return (ZERR_NONE);
+}

Modified: trunk/athena/lib/zephyr/lib/ZGetSender.c
===================================================================
--- trunk/athena/lib/zephyr/lib/ZGetSender.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/ZGetSender.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -22,31 +22,55 @@
 char *ZGetSender()
 {
     struct passwd *pw;
+    static char *sender = NULL;
+#ifdef HAVE_KRB5
+    krb5_ccache ccache;
+    krb5_principal principal;
+    char *prname;
+    int result;
+    char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; /*XXX*/
+#else    
 #ifdef HAVE_KRB4
     char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
-    static char sender[ANAME_SZ+INST_SZ+REALM_SZ+3] = "";
-#else
-    static char sender[128] = "";
+#endif 
 #endif
 
     /* Return it if already cached */
-    if (*sender)
+    if (sender)
 	return (sender);
 
+#ifdef HAVE_KRB5
+    result = krb5_cc_default(Z_krb5_ctx, &ccache);
+    if (!result) {
+      result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &principal);
+      if (!result) {
+	krb5_unparse_name(Z_krb5_ctx, principal, &prname);
+	sender = strdup(prname);
+	krb5_free_principal(Z_krb5_ctx, principal);
+	return sender;
+      }
+      krb5_cc_close(Z_krb5_ctx, ccache);
+    } 
+#else
 #ifdef HAVE_KRB4
     if (krb_get_tf_fullname((char *)TKT_FILE, pname, pinst, prealm) == KSUCCESS)
     {
-	(void) sprintf(sender, "%s%s%s@%s", pname, (pinst[0]?".":""),
-		       pinst, prealm);
+        sender = malloc(ANAME_SZ+INST_SZ+REALM_SZ+3);
+	if (sender)
+	  (void) sprintf(sender, "%s%s%s@%s", pname, (pinst[0]?".":""),
+			 pinst, prealm);
 	return (sender);
     }
 #endif
+#endif
 
     /* XXX a uid_t is a u_short (now),  but getpwuid
      * wants an int. AARGH! */
     pw = getpwuid((int) getuid());
     if (!pw)
 	return ("unknown");
-    (void) sprintf(sender, "%s@%s", pw->pw_name, __Zephyr_realm);
+    sender = malloc(strlen(pw->pw_name) + strlen(__Zephyr_realm) + 2);
+    if (sender)
+      (void) sprintf(sender, "%s@%s", pw->pw_name, __Zephyr_realm);
     return (sender);
 }

Modified: trunk/athena/lib/zephyr/lib/ZInit.c
===================================================================
--- trunk/athena/lib/zephyr/lib/ZInit.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/ZInit.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -21,6 +21,12 @@
 #ifdef HAVE_KRB4
 #include <krb_err.h>
 #endif
+#ifdef HAVE_KRB5
+#include <krb5.h>
+#endif
+#ifdef HAVE_KRB5_ERR_H
+#include <krb5_err.h>
+#endif
 
 #ifndef INADDR_NONE
 #define INADDR_NONE 0xffffffff
@@ -36,13 +42,22 @@
     int s, sinsize = sizeof(sin);
     Code_t code;
     ZNotice_t notice;
+#ifdef HAVE_KRB5
+    char **krealms = NULL;
+#else
 #ifdef HAVE_KRB4
     char *krealm = NULL;
     int krbval;
     char d1[ANAME_SZ], d2[INST_SZ];
+#endif
+#endif
 
+#ifdef HAVE_KRB4
     initialize_krb_error_table();
 #endif
+#ifdef HAVE_KRB5
+    initialize_krb5_error_table();
+#endif
 
     initialize_zeph_error_table();
     
@@ -67,6 +82,11 @@
     __Q_Tail = NULL;
     __Q_Head = NULL;
     
+#ifdef HAVE_KRB5
+    if ((code = krb5_init_context(&Z_krb5_ctx)))
+        return(code);
+#endif
+
     /* if the application is a server, there might not be a zhm.  The
        code will fall back to something which might not be "right",
        but this is is ok, since none of the servers call krb_rd_req. */
@@ -85,9 +105,15 @@
 	  If this code ever support a multiplexing zhm, this will have to
 	  be made smarter, and probably per-message */
 
+#ifdef HAVE_KRB5
+       code = krb5_get_host_realm(Z_krb5_ctx, notice.z_message, &krealms);
+       if (code)
+	 return(code);
+#else
 #ifdef HAVE_KRB4
        krealm = krb_realmofhost(notice.z_message);
 #endif
+#endif
        hostent = gethostbyname(notice.z_message);
        if (hostent && hostent->h_addrtype == AF_INET)
 	   memcpy(&servaddr, hostent->h_addr, sizeof(servaddr));
@@ -95,6 +121,24 @@
        ZFreeNotice(&notice);
     }
 
+#ifdef HAVE_KRB5
+    if (krealms) {
+      strcpy(__Zephyr_realm, krealms[0]);
+      krb5_free_host_realm(Z_krb5_ctx, krealms);
+    } else {
+      char *p; /* XXX define this somewhere portable */
+      /* XXX check ticket file here */
+      code = krb5_get_default_realm(Z_krb5_ctx, &p);
+      strcpy(__Zephyr_realm, p);
+#ifdef HAVE_KRB5_FREE_DEFAULT_REALM
+      krb5_free_default_realm(Z_krb5_ctx, p);
+#else
+      free(p);
+#endif
+      if (code)
+	return code;
+    }
+#else
 #ifdef HAVE_KRB4
     if (krealm) {
 	strcpy(__Zephyr_realm, krealm);
@@ -106,6 +150,7 @@
 #else
     strcpy(__Zephyr_realm, "local-realm");
 #endif
+#endif
 
     __My_addr.s_addr = INADDR_NONE;
     if (servaddr.s_addr != INADDR_NONE) {

Added: trunk/athena/lib/zephyr/lib/ZMakeZcode.c

Modified: trunk/athena/lib/zephyr/lib/ZMkAuth.c
===================================================================
--- trunk/athena/lib/zephyr/lib/ZMkAuth.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/ZMkAuth.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -20,6 +20,10 @@
 #include <krb_err.h>
 #endif
 
+#if defined(HAVE_KRB5) && !HAVE_KRB5_FREE_DATA
+#define krb5_free_data(ctx, dat) free((dat)->data)
+#endif
+
 Code_t ZResetAuthentication () {
     return ZERR_NONE;
 }
@@ -30,15 +34,39 @@
     int buffer_len;
     int *len;
 {
-#ifdef HAVE_KRB4
+#if 1
+    return ZMakeZcodeAuthentication(notice, buffer, buffer_len, len/*?XXX*/);
+#else
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
     int result;
     time_t now;
     KTEXT_ST authent;
     char *cstart, *cend;
     ZChecksum_t checksum;
     CREDENTIALS cred;
-    extern unsigned long des_quad_cksum();
+    C_Block *session;
+#ifdef HAVE_KRB5
+    krb5_creds *creds_out;
 
+    result = ZGetCreds(&creds_out);
+    if (result)
+      return result;
+
+    result = krb5_524_convert_creds(Z_krb5_ctx, creds_out, &cred);
+    /* krb5_free_creds(Z_krb5_ctx, creds_out);*/
+    if (result)
+      return result;
+    /* HOLDING: creds_out */
+
+    if (creds_out->keyblock.enctype != ENCTYPE_DES_CBC_CRC)
+      return (KRB5_BAD_ENCTYPE);
+    session = (C_Block *)creds_out->keyblock.contents;
+
+    result = krb_mk_req_creds(&authent, &cred, 0);
+    if (result != MK_AP_OK)
+      return result + krb_err_base;
+#endif
+#ifndef HAVE_KRB5
     result = krb_mk_req(&authent, SERVER_SERVICE, 
 			SERVER_INSTANCE, __Zephyr_realm, 0);
     if (result != MK_AP_OK)
@@ -48,6 +76,9 @@
     if (result != KSUCCESS)
 	return (result+krb_err_base);
 
+    session = (C_Block *)cred.session;
+#endif
+
     notice->z_auth = 1;
     notice->z_authent_len = authent.length;
     notice->z_ascii_authent = (char *)malloc((unsigned)authent.length*3);
@@ -69,11 +100,11 @@
 	return(result);
 
     /* Compute a checksum over the header and message. */
-    checksum = des_quad_cksum(buffer, NULL, cstart - buffer, 0, cred.session);
+    checksum = des_quad_cksum(buffer, NULL, cstart - buffer, 0, session);
     checksum ^= des_quad_cksum(cend, NULL, buffer + *len - cend, 0,
-			       cred.session);
+			       session);
     checksum ^= des_quad_cksum(notice->z_message, NULL, notice->z_message_len,
-			       0, cred.session);
+			       0, session);
     notice->z_checksum = checksum;
     ZMakeAscii32(cstart, buffer + buffer_len - cstart, checksum);
 
@@ -85,4 +116,151 @@
     notice->z_ascii_authent = "";
     return (Z_FormatRawHeader(notice, buffer, buffer_len, len, NULL, NULL));
 #endif
+#endif
 }
+
+Code_t ZMakeZcodeAuthentication(notice, buffer, buffer_len, phdr_len)
+    register ZNotice_t *notice;
+    char *buffer;
+    int buffer_len;
+    int *phdr_len;
+{
+    return ZMakeZcodeRealmAuthentication(notice, buffer, buffer_len, phdr_len,
+					 __Zephyr_realm);
+}
+
+Code_t ZMakeZcodeRealmAuthentication(notice, buffer, buffer_len, phdr_len, 
+				     realm)
+    register ZNotice_t *notice;
+    char *buffer;
+    int buffer_len;
+    int *phdr_len;
+    char *realm;
+{
+#ifdef HAVE_KRB5
+    krb5_error_code result;
+    krb5_creds *creds;
+    krb5_keyblock *keyblock;
+    krb5_enctype enctype;
+    krb5_cksumtype cksumtype;
+    krb5_auth_context authctx;
+    krb5_data *authent;
+    char *svcinst, *x, *y;
+    char *cksum_start, *cstart, *cend, *asn1_data;
+    int i, cksum_len, zcode_len, asn1_len, phdr_adj;
+    
+    result = ZGetCredsRealm(&creds, realm);
+    if (result)
+	return result;
+    /* HOLDING: creds */
+    
+    /* Figure out what checksum type to use */
+    keyblock = Z_credskey(creds);
+    /* HOLDING: creds */
+    
+    /* Create the authenticator */
+    result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
+    if (result) {
+	krb5_free_creds(Z_krb5_ctx, creds);
+	return (result);
+    }
+	
+    authent = (krb5_data *)malloc(sizeof(krb5_data));
+
+    /* HOLDING: creds, authctx */
+    result = krb5_mk_req_extended(Z_krb5_ctx, &authctx, 0 /* options */,
+				  0 /* in_data */, creds, authent);
+    krb5_auth_con_free(Z_krb5_ctx, authctx);
+    if (result) {
+	krb5_free_creds(Z_krb5_ctx, creds);
+	return (result);
+    }
+    /* HOLDING: creds, authent */
+    
+    /* Encode the authenticator */
+    notice->z_auth = 1;
+    notice->z_authent_len = authent->length;
+    zcode_len = authent->length * 2 + 2; /* 2x growth plus Z and null */
+    notice->z_ascii_authent = (char *)malloc(zcode_len);
+    if (!notice->z_ascii_authent) {
+	krb5_free_data(Z_krb5_ctx, authent);
+	krb5_free_creds(Z_krb5_ctx, creds);
+	return (ENOMEM);
+    }
+    /* HOLDING: creds, authent, notice->z_ascii_authent */
+    result = ZMakeZcode(notice->z_ascii_authent, zcode_len, 
+			authent->data, authent->length);
+    krb5_free_data(Z_krb5_ctx, authent);
+    if (result) {
+	free(notice->z_ascii_authent);
+	krb5_free_creds(Z_krb5_ctx, creds);
+	return (result);
+    }
+    /* HOLDING: creds, notice->z_ascii_authent */
+    
+    /* format the notice header, with a zero checksum */
+    result = Z_NewFormatRawHeader(notice, buffer, buffer_len, phdr_len,
+				  &cksum_start, &cksum_len, &cstart, &cend);
+    free(notice->z_ascii_authent);
+    notice->z_authent_len = 0;
+    if (result) {
+	krb5_free_creds(Z_krb5_ctx, creds);
+	return (result);
+    }
+    result = Z_InsertZcodeChecksum(keyblock, notice, buffer, cksum_start,
+                                   cksum_len, cstart, cend, buffer_len,
+                                   &phdr_adj);
+    krb5_free_creds(Z_krb5_ctx, creds);
+    if (result) {
+         return result;
+    }
+    *phdr_len += phdr_adj;
+
+    return (result);
+#endif /* HAVE_KRB5 */
+}
+
+#ifdef HAVE_KRB5
+int ZGetCreds(krb5_creds **creds_out) {
+  return ZGetCredsRealm(creds_out, __Zephyr_realm);
+}
+
+int ZGetCredsRealm(krb5_creds **creds_out, char *realm) {
+  krb5_creds creds_in;
+  krb5_ccache ccache; /* XXX make this a global or static?*/
+  int result;
+  
+  result = krb5_cc_default(Z_krb5_ctx, &ccache);
+  if (result)
+    return result;
+
+  memset((char *)&creds_in, 0, sizeof(creds_in));
+  result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
+				strlen(realm),
+				realm,
+				SERVER_SERVICE, SERVER_INSTANCE, 0);
+  if (result) {
+    krb5_cc_close(Z_krb5_ctx, ccache);
+    return result;
+  }
+  
+  result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
+  if (result) {
+    krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
+    krb5_cc_close(Z_krb5_ctx, ccache);
+    return result;
+  }
+ 
+#ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE 
+  creds_in.keyblock.enctype = ENCTYPE_DES_CBC_CRC; /* XXX? */
+#else
+  creds_in.session.keytype = KEYTYPE_DES; /* XXX? */
+#endif
+  
+  result = krb5_get_credentials(Z_krb5_ctx, 0, ccache, &creds_in, creds_out);
+  krb5_cc_close(Z_krb5_ctx, ccache);
+  krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
+
+  return result;
+}
+#endif

Modified: trunk/athena/lib/zephyr/lib/ZParseNot.c
===================================================================
--- trunk/athena/lib/zephyr/lib/ZParseNot.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/ZParseNot.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -209,12 +209,23 @@
     else
 	notice->z_default_format = "";
 	
-    if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
-	BAD_PACKET;
-    notice->z_checksum = temp;
-    numfields--;
-    ptr = next_field(ptr, end);
+    if (numfields && ptr < end) {
+      notice->z_ascii_checksum = ptr;
 
+      if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
+	notice->z_checksum = 0;
+      else
+	notice->z_checksum = temp;
+
+      numfields--;
+      ptr = next_field (ptr, end);
+    }
+    else 
+      {
+	notice->z_ascii_checksum = "";
+	notice->z_checksum = 0;
+      }
+
     if (numfields && ptr < end) {
 	notice->z_multinotice = ptr;
 	numfields--;

Added: trunk/athena/lib/zephyr/lib/ZReadZcode.c

Modified: trunk/athena/lib/zephyr/lib/ZVariables.c
===================================================================
--- trunk/athena/lib/zephyr/lib/ZVariables.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/ZVariables.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -36,7 +36,7 @@
     if ((ret = get_varval(varfile, var)) != ZERR_NONE)
 	return (ret);
 
-    sprintf(varfile, "%s/zephyr.vars", SYSCONFDIR);
+    sprintf(varfile, "%s/zephyr/zephyr.vars", SYSCONFDIR);
     return (get_varval(varfile, var));
 }
 

Modified: trunk/athena/lib/zephyr/lib/Zinternal.c
===================================================================
--- trunk/athena/lib/zephyr/lib/Zinternal.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/lib/Zinternal.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -44,9 +44,60 @@
 int __subscriptions_next;
 int Z_discarded_packets = 0;
 
-#ifdef HAVE_KRB4
-C_Block __Zephyr_session;
-#endif
+#ifdef HAVE_KRB5
+/* This context is used throughout */
+krb5_context Z_krb5_ctx;
+
+static struct cksum_map_s {
+  krb5_enctype e;
+  krb5_cksumtype c;
+} cksum_map[] = {
+  /* per RFC1510 and draft-ietf-krb-wg-crypto-02.txt */
+  { ENCTYPE_NULL,                     CKSUMTYPE_RSA_MD5 },
+  { ENCTYPE_DES_CBC_CRC,              CKSUMTYPE_RSA_MD5_DES },
+  { ENCTYPE_DES_CBC_MD4,              CKSUMTYPE_RSA_MD4_DES },
+  { ENCTYPE_DES_CBC_MD5,              CKSUMTYPE_RSA_MD5_DES },
+
+  /* 
+   * The implementors hate us, and are inconsistent with names for
+   * most things defined after RFC1510.  Note that des3-cbc-sha1
+   * and des3-cbc-sha1-kd are listed by number to avoid confusion 
+   * caused by inconsistency between the names used in the specs
+   * and those used by implementations.
+   * -- jhutz, 30-Nov-2002
+   */
+
+  /* source lost in history (an expired internet-draft) */
+  { 5 /* des3-cbc-md5 */,             9  /* rsa-md5-des3 */ },
+  { 7 /* des3-cbc-sha1 */,            13 /* hmac-sha1-des3 */ },
+
+  /* per draft-ietf-krb-wg-crypto-02.txt */
+  { 16 /* des3-cbc-sha1-kd */,        12 /* hmac-sha1-des3-kd */ },
+
+  /* per draft-raeburn-krb-rijndael-krb-02.txt */
+  { 17 /* aes128-cts-hmac-sha1-96 */, 15 /* hmac-sha1-96-aes128 */ },
+  { 18 /* aes256-cts-hmac-sha1-96 */, 16 /* hmac-sha1-96-aes256 */ },
+
+  /* per draft-brezak-win2k-krb-rc4-hmac-04.txt */
+  { 23 /* rc4-hmac */,                -138 /* hmac-md5 */ },
+  { 24 /* rc4-hmac-exp */,            -138 /* hmac-md5 */ },
+};
+#define N_CKSUM_MAP (sizeof(cksum_map) / sizeof(struct cksum_map_s))
+
+Code_t Z_krb5_lookup_cksumtype(krb5_enctype e, krb5_cksumtype *c)
+{
+  int i;
+
+  for (i = 0; i < N_CKSUM_MAP; i++) {
+    if (cksum_map[i].e == e) {
+      *c = cksum_map[i].c;
+      return ZERR_NONE;
+    }
+  }
+  return KRB5_PROG_ETYPE_NOSUPP;
+}
+#endif /* HAVE_KRB5 */
+
 char __Zephyr_realm[REALM_SZ];
 
 #ifdef Z_DEBUG
@@ -58,6 +109,8 @@
 
 static int Z_AddField __P((char **ptr, char *field, char *end));
 static int find_or_insert_uid __P((ZUnique_Id_t *uid, ZNotice_Kind_t kind));
+static Code_t Z_ZcodeFormatRawHeader __P((ZNotice_t *, char *, int, int *, char **, 
+                                 int *, char **, char **, int cksumtype));
 
 /* Find or insert uid in the old uids buffer.  The buffer is a sorted
  * circular queue.  We make the assumption that most packets arrive in
@@ -580,6 +633,14 @@
     return (ZERR_NONE);
 }
 
+void Z_gettimeofday(struct _ZTimeval *ztv, struct timezone *tz)
+{
+        struct timeval tv;
+        (void) gettimeofday(&tv, tz); /* yeah, yeah, I know */
+        ztv->tv_sec=tv.tv_sec;
+        ztv->tv_usec=tv.tv_usec;
+}
+
 Code_t Z_FormatHeader(notice, buffer, buffer_len, len, cert_routine)
     ZNotice_t *notice;
     char *buffer;
@@ -609,7 +670,7 @@
 
     notice->z_multinotice = "";
     
-    (void) gettimeofday(&notice->z_uid.tv, (struct timezone *)0);
+    (void) Z_gettimeofday(&notice->z_uid.tv, (struct timezone *)0);
     notice->z_uid.tv.tv_sec = htonl((u_long) notice->z_uid.tv.tv_sec);
     notice->z_uid.tv.tv_usec = htonl((u_long) notice->z_uid.tv.tv_usec);
     
@@ -625,6 +686,52 @@
     return Z_FormatAuthHeader(notice, buffer, buffer_len, len, cert_routine);
 }
 
+Code_t Z_NewFormatHeader(notice, buffer, buffer_len, len, cert_routine)
+    ZNotice_t *notice;
+    char *buffer;
+    int buffer_len;
+    int *len;
+    Z_AuthProc cert_routine;
+{
+    Code_t retval;
+    static char version[BUFSIZ]; /* default init should be all \0 */
+    struct sockaddr_in name;
+    struct timeval tv;
+    int namelen = sizeof(name);
+
+    if (!notice->z_sender)
+	notice->z_sender = ZGetSender();
+
+    if (notice->z_port == 0) {
+	if (ZGetFD() < 0) {
+	    retval = ZOpenPort((u_short *)0);
+	    if (retval != ZERR_NONE)
+		return (retval);
+	}
+	retval = getsockname(ZGetFD(), (struct sockaddr *) &name, &namelen);
+	if (retval != 0)
+	    return (retval);
+	notice->z_port = name.sin_port;
+    }
+
+    notice->z_multinotice = "";
+    
+    (void) gettimeofday(&tv, (struct timezone *)0);
+    notice->z_uid.tv.tv_sec = htonl((u_long) tv.tv_sec);
+    notice->z_uid.tv.tv_usec = htonl((u_long) tv.tv_usec);
+    
+    (void) memcpy(&notice->z_uid.zuid_addr, &__My_addr, sizeof(__My_addr));
+
+    notice->z_multiuid = notice->z_uid;
+
+    if (!version[0])
+	    (void) sprintf(version, "%s%d.%d", ZVERSIONHDR, ZVERSIONMAJOR,
+			   ZVERSIONMINOR);
+    notice->z_version = version;
+
+    return Z_NewFormatAuthHeader(notice, buffer, buffer_len, len, cert_routine);
+}
+
 Code_t Z_FormatAuthHeader(notice, buffer, buffer_len, len, cert_routine)
     ZNotice_t *notice;
     char *buffer;
@@ -644,6 +751,210 @@
     return ((*cert_routine)(notice, buffer, buffer_len, len));
 } 
 	
+Code_t Z_NewFormatAuthHeader(notice, buffer, buffer_len, len, cert_routine)
+    ZNotice_t *notice;
+    char *buffer;
+    int buffer_len;
+    int *len;
+    Z_AuthProc cert_routine;
+{
+    if (!cert_routine) {
+	notice->z_auth = 0;
+	notice->z_authent_len = 0;
+	notice->z_ascii_authent = "";
+	notice->z_checksum = 0;
+	return (Z_FormatRawHeader(notice, buffer, buffer_len,
+				     len, NULL, NULL));
+    }
+    
+    return ((*cert_routine)(notice, buffer, buffer_len, len));
+} 
+	
+Code_t Z_NewFormatRawHeader(notice, buffer, buffer_len, hdr_len,
+                         cksum_start, cksum_len, cstart, cend)
+    ZNotice_t *notice;
+    char *buffer;
+    int buffer_len;
+    int *hdr_len;
+    char **cksum_start;
+    int *cksum_len;
+    char **cstart, **cend;
+{
+   return(Z_ZcodeFormatRawHeader(notice, buffer, buffer_len, hdr_len,
+				 cksum_start, cksum_len, cstart, cend, 0));
+}
+
+Code_t Z_AsciiFormatRawHeader(notice, buffer, buffer_len, hdr_len,
+			      cksum_start, cksum_len, cstart, cend)
+    ZNotice_t *notice;
+    char *buffer;
+    int buffer_len;
+    int *hdr_len;
+    char **cksum_start;
+    int *cksum_len;
+    char **cstart, **cend;
+{
+   return(Z_ZcodeFormatRawHeader(notice, buffer, buffer_len, hdr_len,
+				 cksum_start, cksum_len, cstart, cend, 1));
+}
+
+static Code_t Z_ZcodeFormatRawHeader(notice, buffer, buffer_len, hdr_len, cksum_start,
+			      cksum_len, cstart, cend, cksumstyle)
+    ZNotice_t *notice;
+    char *buffer;
+    int buffer_len;
+    int *hdr_len;
+    char **cksum_start;
+    int *cksum_len;
+    char **cstart, **cend;
+    int cksumstyle;
+{
+    static char version_nogalaxy[BUFSIZ]; /* default init should be all \0 */
+    char newrecip[BUFSIZ];
+    char *ptr, *end;
+    int i;
+
+    if (!notice->z_class)
+            notice->z_class = "";
+
+    if (!notice->z_class_inst)
+            notice->z_class_inst = "";
+
+    if (!notice->z_opcode)
+            notice->z_opcode = "";
+
+    if (!notice->z_recipient)
+            notice->z_recipient = "";
+
+    if (!notice->z_default_format)
+            notice->z_default_format = "";
+
+    ptr = buffer;
+    end = buffer+buffer_len;
+
+    if (cksum_start)
+        *cksum_start = ptr;
+
+    (void) sprintf(version_nogalaxy, "%s%d.%d", ZVERSIONHDR,
+		   ZVERSIONMAJOR, ZVERSIONMINOR);
+
+    notice->z_version = version_nogalaxy;
+
+    if (Z_AddField(&ptr, version_nogalaxy, end))
+        return (ZERR_HEADERLEN);
+
+    if (ZMakeAscii32(ptr, end-ptr,
+                     Z_NUMFIELDS + notice->z_num_other_fields)
+        == ZERR_FIELDLEN)
+        return (ZERR_HEADERLEN);
+    ptr += strlen(ptr)+1;
+
+    if (ZMakeAscii32(ptr, end-ptr, notice->z_kind) == ZERR_FIELDLEN)
+        return (ZERR_HEADERLEN);
+    ptr += strlen(ptr)+1;
+
+    if (ZMakeAscii(ptr, end-ptr, (unsigned char *)&notice->z_uid, 
+                   sizeof(ZUnique_Id_t)) == ZERR_FIELDLEN)
+        return (ZERR_HEADERLEN);
+    ptr += strlen(ptr)+1;
+
+    if (ZMakeAscii16(ptr, end-ptr, ntohs(notice->z_port)) == ZERR_FIELDLEN)
+        return (ZERR_HEADERLEN);
+    ptr += strlen(ptr)+1;
+
+    if (ZMakeAscii32(ptr, end-ptr, notice->z_auth) == ZERR_FIELDLEN)
+        return (ZERR_HEADERLEN);
+    ptr += strlen(ptr)+1;
+
+    if (ZMakeAscii32(ptr, end-ptr, notice->z_authent_len) == ZERR_FIELDLEN)
+        return (ZERR_HEADERLEN);
+    ptr += strlen(ptr)+1;
+
+    if (Z_AddField(&ptr, notice->z_ascii_authent, end))
+        return (ZERR_HEADERLEN);
+    if (Z_AddField(&ptr, notice->z_class, end))
+        return (ZERR_HEADERLEN);
+    if (Z_AddField(&ptr, notice->z_class_inst, end))
+        return (ZERR_HEADERLEN);
+    if (Z_AddField(&ptr, notice->z_opcode, end))
+        return (ZERR_HEADERLEN);
+    if (Z_AddField(&ptr, notice->z_sender, end))
+        return (ZERR_HEADERLEN);
+    if (strchr(notice->z_recipient, '@') || !*notice->z_recipient) {
+        if (Z_AddField(&ptr, notice->z_recipient, end))
+            return (ZERR_HEADERLEN);
+    }
+    else {
+	if (strlen(notice->z_recipient) + strlen(__Zephyr_realm) + 2 >
+            sizeof(newrecip))
+            return (ZERR_HEADERLEN);
+        (void) sprintf(newrecip, "%s@%s", notice->z_recipient, __Zephyr_realm);
+        if (Z_AddField(&ptr, newrecip, end))
+            return (ZERR_HEADERLEN);
+    }           
+    if (Z_AddField(&ptr, notice->z_default_format, end))
+        return (ZERR_HEADERLEN);
+
+    /* copy back the end pointer location for crypto checksum */
+    if (cstart)
+        *cstart = ptr;
+    if (cksumstyle == 1) {
+      if (Z_AddField(&ptr, notice->z_ascii_checksum, end))
+	 return (ZERR_HEADERLEN);
+    } else {
+#ifdef xZCODE_K4SUM
+    if (ZMakeZcode32(ptr, end-ptr, notice->z_checksum) == ZERR_FIELDLEN)
+        return ZERR_HEADERLEN;
+#else
+    if (ZMakeAscii32(ptr, end-ptr, notice->z_checksum) == ZERR_FIELDLEN)
+        return (ZERR_HEADERLEN);
+#endif
+    ptr += strlen(ptr)+1;
+    }
+    if (cend)
+        *cend = ptr;
+
+    if (Z_AddField(&ptr, notice->z_multinotice, end))
+        return (ZERR_HEADERLEN);
+
+    if (ZMakeAscii(ptr, end-ptr, (unsigned char *)&notice->z_multiuid, 
+                   sizeof(ZUnique_Id_t)) == ZERR_FIELDLEN)
+        return (ZERR_HEADERLEN);
+    ptr += strlen(ptr)+1;
+        
+    for (i=0;i<notice->z_num_other_fields;i++)
+        if (Z_AddField(&ptr, notice->z_other_fields[i], end))
+            return (ZERR_HEADERLEN);
+    
+    if (cksum_len)
+        *cksum_len = ptr-*cksum_start;
+
+    *hdr_len = ptr-buffer;
+
+#if 0
+    {
+        printf("Z_FormatRawHeader output:\n");
+        for (i = 0; i < *hdr_len; i += 16) {
+            int i2;
+            printf("%03d:", i);
+            for (i2 = i; i2 < i+16 && i2 < *hdr_len; i2++)
+                printf(" %02x", buffer[i2] & 0xff);
+            for (; i2 < i+16; i2++)
+                printf("   ");
+            printf("  ");
+            for (i2 = i; i2 < i+16 && i2 < *hdr_len; i2++)
+                printf("%c",
+                       ((buffer[i2] > 0 && buffer[i2] < 127 && isprint(buffer[i2]))
+                        ? buffer[i2]
+                        : '.'));
+            printf("\n");
+        }
+    }
+#endif
+
+    return (ZERR_NONE);
+}
+
 Code_t Z_FormatRawHeader(notice, buffer, buffer_len, len, cstart, cend)
     ZNotice_t *notice;
     char *buffer;
@@ -734,7 +1045,7 @@
     if (cstart)
 	*cstart = ptr;
     if (ZMakeAscii32(ptr, end-ptr, notice->z_checksum) == ZERR_FIELDLEN)
-	return (ZERR_HEADERLEN);
+        return (ZERR_HEADERLEN);
     ptr += strlen(ptr)+1;
     if (cend)
 	*cend = ptr;
@@ -878,8 +1189,8 @@
 	(void) sprintf(multi, "%d/%d", offset, notice->z_message_len);
 	partnotice.z_multinotice = multi;
 	if (offset > 0) {
-	    (void) gettimeofday(&partnotice.z_uid.tv,
-				(struct timezone *)0);
+	    (void) Z_gettimeofday(&partnotice.z_uid.tv,
+				  (struct timezone *)0);
 	    partnotice.z_uid.tv.tv_sec =
 		htonl((u_long) partnotice.z_uid.tv.tv_sec);
 	    partnotice.z_uid.tv.tv_usec =
@@ -987,3 +1298,186 @@
 }
 #endif /* Z_DEBUG */
 
+#ifdef HAVE_KRB5
+Code_t Z_Checksum(krb5_data *cksumbuf, krb5_keyblock *keyblock, 
+                  krb5_cksumtype cksumtype, 
+                  char **asn1_data, int *asn1_len) {
+    krb5_error_code result;
+    char *data;
+    int len;
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+    krb5_checksum checksum;
+#else
+    Checksum checksum;
+    krb5_crypto cryptctx;
+#endif
+    
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+    /* Create the checksum -- MIT crypto API */
+    result = krb5_c_make_checksum(Z_krb5_ctx, cksumtype,
+				  keyblock, Z_KEYUSAGE_CLT_CKSUM,
+				  cksumbuf, &checksum);
+    if (result)
+	return result;
+    /* HOLDING: checksum */
+
+    data = checksum.contents;
+    len = checksum.length;
+#else
+    /* Create the checksum -- heimdal crypto API */
+    result = krb5_crypto_init(Z_krb5_ctx, keyblock, keyblock->keytype, 
+                              &cryptctx);
+    if (result)
+	return result;
+
+    /* HOLDING: cryptctx */
+    result = krb5_create_checksum(Z_krb5_ctx, cryptctx,
+				  Z_KEYUSAGE_CLT_CKSUM, cksumtype,
+				  cksumbuf->data, cksumbuf->length,
+				  &checksum);
+    krb5_crypto_destroy(Z_krb5_ctx, cryptctx);
+    if (result)
+	return result;
+
+    len = checksum.checksum.length;
+    data = checksum.checksum.data;
+    /* HOLDING: checksum */
+#endif
+
+    *asn1_data = malloc(len);
+    if (*asn1_data == NULL)
+	return errno;
+    memcpy(*asn1_data, data, len);
+    *asn1_len = len;
+
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+    krb5_free_checksum_contents(Z_krb5_ctx, &checksum);
+#else
+    free_Checksum(&checksum);
+#endif
+
+    return 0;
+}
+
+Code_t
+Z_InsertZcodeChecksum(krb5_keyblock *keyblock, ZNotice_t *notice, 
+                      char *buffer, char *cksum_start, int cksum_len, 
+                      char *cstart, char *cend, int buffer_len, 
+                      int *length_adjust)
+{
+     int plain_len;   /* length of part not to be checksummed */
+     int cksum0_len;  /* length of part before checksum */
+     int cksum1_len;  /* length of part after checksum */
+     krb5_data cksumbuf;
+     krb5_data cksum;
+     char *key_data;
+     int key_len;
+     krb5_enctype enctype;
+     krb5_cksumtype cksumtype;
+     Code_t result;
+     
+     key_data = Z_keydata(keyblock);
+     key_len = Z_keylen(keyblock);
+     result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+     if (result)
+          return (ZAUTH_FAILED);
+     
+     /* Assemble the things to be checksummed */
+     plain_len  = cksum_start - buffer;
+     cksum0_len = cstart - cksum_start;
+     cksum1_len = (cksum_start + cksum_len) - cend;
+     memset(&cksumbuf, 0, sizeof(cksumbuf));
+     cksumbuf.length = cksum0_len + cksum1_len + notice->z_message_len;
+     cksumbuf.data = malloc(cksumbuf.length);
+     if (!cksumbuf.data)
+          return ENOMEM;
+     memcpy(cksumbuf.data, cksum_start, cksum0_len);
+     memcpy(cksumbuf.data + cksum0_len, cend, cksum1_len);
+     memcpy(cksumbuf.data + cksum0_len + cksum1_len,
+            notice->z_message, notice->z_message_len);
+     /* compute the checksum */
+     result = Z_Checksum(&cksumbuf, keyblock, cksumtype, 
+                        (char **)&cksum.data, &cksum.length);
+     if (result) {
+          free(cksumbuf.data);
+          return result;
+     }
+     
+     /*
+      * OK....  we can zcode to a space starting at 'cstart',
+      * with a length of buffer_len - (plain_len + cksum_len).
+      * Then we tack on the end part, which is located at
+      * cksumbuf.data + cksum0_len and has length cksum1_len
+      */
+     
+     result = ZMakeZcode(cstart, buffer_len - (plain_len + cksum_len),
+                         cksum.data, cksum.length);
+     free(cksum.data);
+     if (!result) {
+          int zcode_len = strlen(cstart) + 1;
+          memcpy(cstart + zcode_len, cksumbuf.data + cksum0_len, cksum1_len);
+          *length_adjust = zcode_len - cksum_len + (cksum0_len + cksum1_len);
+     }
+     free(cksumbuf.data);
+     return result;
+}
+
+Code_t
+Z_ExtractEncCksum(krb5_keyblock *keyblock, krb5_enctype *enctype, 
+                  krb5_cksumtype *cksumtype) {
+    *enctype  = Z_enctype(keyblock); 
+    return Z_krb5_lookup_cksumtype(*enctype, cksumtype); 
+}
+#endif
+
+#ifdef HAVE_KRB5
+/* returns 0 if invalid or losing, 1 if valid, *sigh* */
+int
+Z_krb5_verify_cksum(krb5_keyblock *keyblock, krb5_data *cksumbuf, 
+                    krb5_cksumtype cksumtype, char *asn1_data, 
+                    int asn1_len) {
+    krb5_error_code result;
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+    krb5_checksum checksum;
+    krb5_boolean valid;
+#else
+    krb5_crypto cryptctx;
+    Checksum checksum;
+    size_t xlen;
+#endif
+
+    memset(&checksum, 0, sizeof(checksum));
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+    /* Verify the checksum -- MIT crypto API */
+    checksum.length = asn1_len;
+    checksum.contents = asn1_data;
+    checksum.checksum_type = cksumtype;
+    result = krb5_c_verify_checksum(Z_krb5_ctx,
+				    keyblock, Z_KEYUSAGE_SRV_CKSUM,
+				    cksumbuf, &checksum, &valid);
+    if (!result && valid)
+	return 1;
+    else
+	return 0;
+#else
+    checksum.checksum.length = asn1_len;
+    checksum.checksum.data = asn1_data;
+    checksum.cksumtype = cksumtype;
+
+    result = krb5_crypto_init(Z_krb5_ctx, keyblock, keyblock->keytype, &cryptctx);
+    if (result)
+	return result;
+    
+    /* HOLDING: cryptctx */
+    result = krb5_verify_checksum(Z_krb5_ctx, cryptctx,
+				  Z_KEYUSAGE_SRV_CKSUM,
+				  cksumbuf->data, cksumbuf->length,
+				  &checksum);
+    krb5_crypto_destroy(Z_krb5_ctx, cryptctx);
+    if (result)
+	return 0;
+    else
+	return 1;
+#endif
+}
+#endif

Modified: trunk/athena/lib/zephyr/server/bdump.c
===================================================================
--- trunk/athena/lib/zephyr/server/bdump.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/bdump.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -66,6 +66,12 @@
 static void shutdown_file_pointers __P((void));
 static void cleanup __P((Server *server));
 
+#ifdef HAVE_KRB5
+static long ticket5_time;
+#define TKT5LIFETIME 8*60*60
+#define tkt5_lifetime(val) (val)
+#endif
+
 #ifdef HAVE_KRB4
 static long ticket_time;
 
@@ -82,6 +88,9 @@
 static int live_socket = -1;
 static FILE *input, *output;
 static struct sockaddr_in bdump_sin;
+#ifdef HAVE_KRB5
+static krb5_auth_context bdump_ac;
+#endif
 #ifdef notdef
 static int cancel_outgoing_dump;
 #endif
@@ -89,6 +98,7 @@
 int bdumping;
 int bdump_concurrent;
 extern char *bdump_version;
+extern int bdump_auth_proto;
 
 /*
  * Functions for performing a brain dump between servers.
@@ -110,9 +120,9 @@
 #if 1
     zdbug((LOG_DEBUG, "bdump_offer"));
 #endif
-#ifdef HAVE_KRB4
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
     /* 
-     * when using HAVE_KRB4 server-server authentication, we can
+     * when using kerberos server-server authentication, we can
      * use any random local address 
      */
     bdump_socket = socket(AF_INET, SOCK_STREAM, 0);
@@ -211,11 +221,25 @@
 #ifdef _POSIX_VERSION
     struct sigaction action;
 #endif
-
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
+    char *data = NULL;
+    int len = 0;
+    int proto = 0;
+#endif
 #ifdef HAVE_KRB4
     KTEXT_ST ticket;
     AUTH_DAT kdata;
-#else
+    /* may be moved into kstuff.c */
+    char instance [INST_SZ];
+#endif
+#ifdef HAVE_KRB5
+    /* may be moved into kstuff.c */
+    krb5_principal principal;
+    krb5_data k5data;
+    krb5_ap_rep_enc_part *rep;
+    krb5_keytab kt;
+#endif
+#if !defined(HAVE_KRB4) && !defined(HAVE_KRB5)
     unsigned short fromport;
 #endif /* HAVE_KRB4 */
  
@@ -270,48 +294,164 @@
 	bdump_socket = -1;
 	timer_reset(bdump_timer);
     }
- 
+
     /* Now begin the brain dump. */
- 
-#ifdef HAVE_KRB4
-    /* receive the authenticator */
-    retval = GetKerberosData(live_socket, from.sin_addr, &kdata,
-			     SERVER_SERVICE, srvtab_file);
-    if (retval != KSUCCESS) {
-	syslog(LOG_ERR, "bdump_send: getkdata: %s",
+#if defined(HAVE_KRB5) || defined(HAVE_KRB4)
+    retval = ReadKerberosData(live_socket, &len, &data, &proto);
+
+    if (retval != 0) {
+	syslog(LOG_ERR, "bdump_send: ReadKerberosData: %s",
 	       krb_get_err_text(retval));
 	cleanup(server);
 	return;
     }
+
+    syslog(LOG_INFO, "bdump_send: got %d bytes of authenticator for protocol %d", len, proto);
+
     if (get_tgt()) {
+	syslog(LOG_ERR, "bdump_send: get_tgt failed");
 	cleanup(server);
 	return;
     }
-    if (strcmp(kdata.pname, SERVER_SERVICE) ||
-	strcmp(kdata.pinst, SERVER_INSTANCE) ||
-	strcmp(kdata.prealm, ZGetRealm())) {
-	syslog(LOG_ERR, "bdump_send: peer not zephyr: %s.%s@%s",
-	       kdata.pname, kdata.pinst, kdata.prealm);
-	cleanup(server);
-	return;
+ 
+    switch(proto) {
+#ifdef HAVE_KRB5
+    case 5:
+	/* "server" side */
+	retval = krb5_build_principal(Z_krb5_ctx, &principal, 
+				      strlen(ZGetRealm()),
+				      ZGetRealm(),
+				      SERVER_KRB5_SERVICE, SERVER_INSTANCE,
+				      0); 
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_send: krb5_build_principal: %s", error_message(retval));
+	    cleanup(server);
+	    return;
+	}
+	
+
+	retval = krb5_auth_con_init(Z_krb5_ctx, &bdump_ac);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_send: krb5_auth_con_init: %s", error_message(retval));
+	    cleanup(server);
+	    return;
+	}
+
+	retval = krb5_auth_con_setflags(Z_krb5_ctx, bdump_ac, KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_send: krb5_auth_con_setflags: %s", error_message(retval));
+	    cleanup(server);
+	    return;
+	}
+
+	retval = krb5_auth_con_genaddrs(Z_krb5_ctx, bdump_ac, live_socket,
+                                       KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR|KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_send: krb5_auth_con_genaddrs: %s", error_message(retval));
+	    cleanup(server);
+	    return;
+	}
+
+	/* Get the "client" krb_ap_req */
+
+	memset((char *)&k5data, 0, sizeof(krb5_data));
+	k5data.length = len;
+	k5data.data = data;
+	if (retval) {
+	     syslog(LOG_ERR, "bdump_send: cannot get auth response: %s",
+	            error_message(retval)); 
+	     cleanup(server);
+	     return;
+	}
+
+	/* resolve keytab */
+	retval = krb5_kt_resolve(Z_krb5_ctx, keytab_file, &kt);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_send: cannot resolve keytab: %s", 
+		   error_message(retval));
+	    krb5_kt_close(Z_krb5_ctx, kt);
+	    cleanup(server);
+	    return;
+	}
+
+	retval = krb5_rd_req(Z_krb5_ctx, &bdump_ac, &k5data, principal, kt, NULL, NULL);
+	krb5_free_principal(Z_krb5_ctx, principal);
+	krb5_kt_close(Z_krb5_ctx, kt);
+	free(k5data.data);
+	memset((char *)&k5data, 0, sizeof(krb5_data));
+	if (retval) {
+	     syslog(LOG_ERR, "bdump_send: mutual authentication failed: %s",
+	            error_message(retval));
+	     cleanup(server);
+	     return;
+	}
+
+	/* Now send back our auth packet */
+
+	retval = krb5_mk_rep(Z_krb5_ctx, bdump_ac, &k5data);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_send: krb5_mk_rep: %s", error_message(retval));
+	    cleanup(server);
+	    return;
+	}
+	retval = SendKrb5Data(live_socket, &k5data);
+	if (retval) {
+	     syslog(LOG_ERR, "bdump_send: cannot send authenticator: %s",
+	            error_message(retval));
+	     krb5_free_data_contents(Z_krb5_ctx, &k5data);
+	     cleanup(server);
+	     return;
+	}    
+	krb5_free_data_contents(Z_krb5_ctx, &k5data);
+	break;
+#endif  /* HAVE_KRB5 */  
+#ifdef HAVE_KRB4
+    case 4:
+	/* here to krb_rd_req from GetKerberosData candidate for refactoring
+	   back into kstuff.c */
+	(void) strcpy(instance, "*"); 		/* let Kerberos fill it in */
+
+	ticket.length = len;
+	memcpy(&ticket.dat, data, MIN(len, sizeof(ticket.dat)));
+	retval = krb_rd_req(&ticket, SERVER_SERVICE, instance,
+			    from.sin_addr.s_addr, &kdata, srvtab_file);
+	/*
+	retval = GetKerberosData(live_socket, from.sin_addr, &kdata,
+				 SERVER_SERVICE, srvtab_file);
+	*/
+	if (retval != KSUCCESS) {
+	    syslog(LOG_ERR, "bdump_send: getkdata: %s",
+		   krb_get_err_text(retval));
+	    cleanup(server);
+	    return;
+	}
+	if (strcmp(kdata.pname, SERVER_SERVICE) ||
+	    strcmp(kdata.pinst, SERVER_INSTANCE) ||
+	    strcmp(kdata.prealm, ZGetRealm())) {
+	    syslog(LOG_ERR, "bdump_send: peer not zephyr: %s.%s@%s",
+		   kdata.pname, kdata.pinst, kdata.prealm);
+	    cleanup(server);
+	    return;
+	}
+	/* authenticate back */
+	retval = SendKerberosData(live_socket, &ticket, SERVER_SERVICE,
+				  SERVER_INSTANCE);
+	if (retval != 0) {
+	    syslog(LOG_ERR,"bdump_send: SendKerberosData: %s",
+		   error_message (retval));
+	    cleanup(server);
+	    return;
+	}
+	break;
+#endif /* HAVE_KRB4 */
     }
-    /* authenticate back */
-    retval = SendKerberosData(live_socket, &ticket, SERVER_SERVICE,
-			      SERVER_INSTANCE);
-    if (retval != 0) {
-	syslog(LOG_ERR,"bdump_send: SendKerberosData: %s",
-	       error_message (retval));
-	cleanup(server);
-	return;
-    }
-#else  /* !HAVE_KRB4 */
+#else /* HAVE_KRB4 || HAVE_KRB5 */
     if (fromport > IPPORT_RESERVED || fromport < IPPORT_RESERVED / 2) {
 	syslog(LOG_ERR, "bdump_send: bad port from peer: %d", fromport);
 	cleanup(server);
 	return;
     }
-#endif /* HAVE_KRB4 */
-
+#endif /* HAVE_KRB4 || HAVE_KRB5 */
     retval = setup_file_pointers();
     if (retval != 0) {
 	syslog (LOG_WARNING, "bdump_send: can't set up file pointers: %s",
@@ -374,12 +514,21 @@
 #ifdef _POSIX_VERSION
     struct sigaction action;
 #endif
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
+#ifdef HAVE_KRB5
+    krb5_creds creds;
+    krb5_creds *credsp;
+    krb5_principal principal;
+    krb5_data data;
+    krb5_ap_rep_enc_part *rep;
+#endif
 #ifdef HAVE_KRB4
     KTEXT_ST ticket;
     AUTH_DAT kdata;
-#else  /* !HAVE_KRB4 */
+#endif
+#else  /* !HAVE_KRB4 && !HAVE_KRB5 */
     int reserved_port = IPPORT_RESERVED - 1;
-#endif /* HAVE_KRB4 */
+#endif /* !HAVE_KRB4 && !HAVE_KRB5 */
     
     bdumping = 1;
     server->dumping = 1;
@@ -419,7 +568,7 @@
 	server->dumping = 0;
 	return;
     }
-#ifndef HAVE_KRB4
+#if !defined(HAVE_KRB4) && !defined(HAVE_KRB5)
     if (ntohs(from.sin_port) > IPPORT_RESERVED ||
 	ntohs(from.sin_port) < IPPORT_RESERVED / 2) {
 	syslog(LOG_ERR, "bdump_get: port not reserved: %d",
@@ -428,9 +577,9 @@
 	return;
     }
     live_socket = rresvport(&reserved_port);
-#else  /* !HAVE_KRB4 */
+#else  /* !HAVE_KRB4 && !HAVE_KRB5 */
     live_socket = socket(AF_INET, SOCK_STREAM, 0);
-#endif /* HAVE_KRB4 */
+#endif /* !HAVE_KRB4 && !HAVE_KRB5 */
     if (live_socket < 0) {
 	syslog(LOG_ERR, "bdump_get: socket: %m");
 	cleanup(server);
@@ -449,42 +598,150 @@
 #endif
  
     /* Now begin the brain dump. */
-
-#ifdef HAVE_KRB4
-    /* send an authenticator */
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
     if (get_tgt()) {
+	syslog(LOG_ERR, "bdump_get: get_tgt failed"); 
 	cleanup(server);
 	return;
     }
-    retval = SendKerberosData(live_socket, &ticket, SERVER_SERVICE,
-			      SERVER_INSTANCE);
-    if (retval != 0) {
-	syslog(LOG_ERR,"bdump_get: %s", error_message(retval));
-	cleanup(server);
-	return;
-    }
-#if 1
-    zdbug((LOG_DEBUG, "bdump_get: SendKerberosData ok"));
+    switch(bdump_auth_proto) {
+#ifdef HAVE_KRB5
+    case 5: /* "client" side */
+ 	memset((char *)&creds, 0, sizeof(creds));
+
+	retval = krb5_build_principal(Z_krb5_ctx, &principal, 
+				      strlen(ZGetRealm()),
+				      ZGetRealm(),
+				      SERVER_KRB5_SERVICE, SERVER_INSTANCE,
+				      0); 
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_get: krb5_build_principal: %s", error_message(retval));
+	    cleanup(server);
+	    return;
+	}
+
+	retval = krb5_copy_principal(Z_krb5_ctx, principal, &creds.server);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_get: krb5_copy_principal (server): %s", error_message(retval));
+	    krb5_free_principal(Z_krb5_ctx, principal);
+	    cleanup(server);
+	    return;
+	}
+	
+	retval = krb5_copy_principal(Z_krb5_ctx, principal, &creds.client);
+	krb5_free_principal(Z_krb5_ctx, principal);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_get: krb5_copy_principal (client): %s", error_message(retval));
+	    krb5_free_cred_contents(Z_krb5_ctx, &creds);
+	    cleanup(server);
+	    return;
+	}
+
+	retval = krb5_get_credentials(Z_krb5_ctx, 0, Z_krb5_ccache,
+				      &creds, &credsp);
+	krb5_free_cred_contents(Z_krb5_ctx, &creds);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_get: krb5_get_credentials: %s", error_message(retval));
+	    cleanup(server);
+	    return;
+	}
+
+	retval = krb5_auth_con_init(Z_krb5_ctx, &bdump_ac);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_get: krb5_auth_con_init: %s", error_message(retval));
+	    krb5_free_creds(Z_krb5_ctx, credsp);
+	    cleanup(server);
+	    return;
+	}
+
+	retval = krb5_auth_con_setflags(Z_krb5_ctx, bdump_ac, KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_get: krb5_auth_con_setflags: %s", error_message(retval));
+	    krb5_free_creds(Z_krb5_ctx, credsp);
+	    cleanup(server);
+	    return;
+	}
+
+	retval = krb5_auth_con_genaddrs(Z_krb5_ctx, bdump_ac, live_socket,
+		KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR|KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_get: krb5_auth_con_genaddrs: %s", error_message(retval));
+	    krb5_free_creds(Z_krb5_ctx, credsp);
+	    cleanup(server);
+	    return;
+	}
+
+	memset((char *)&data, 0, sizeof(krb5_data));
+	retval = krb5_mk_req_extended(Z_krb5_ctx, &bdump_ac, AP_OPTS_MUTUAL_REQUIRED|AP_OPTS_USE_SUBKEY,
+				 NULL, credsp, &data);
+	if (retval) {
+	    syslog(LOG_ERR, "bdump_get: krb5_mk_req_ext: %s", error_message(retval));
+	    krb5_free_creds(Z_krb5_ctx, credsp);
+	    cleanup(server);
+	    return;
+	}
+        retval = SendKrb5Data(live_socket, &data);
+        krb5_free_creds(Z_krb5_ctx, credsp);
+        if (retval) {
+             syslog(LOG_ERR, "bdump_get: cannot send authenticator: %s",
+                    error_message(retval));
+             krb5_free_data_contents(Z_krb5_ctx, &data);
+             cleanup(server);
+             return;
+        }    
+        krb5_free_data_contents(Z_krb5_ctx, &data);
+	memset((char *)&data, 0, sizeof(krb5_data));
+        retval = GetKrb5Data(live_socket, &data);
+        if (retval) {
+             syslog(LOG_ERR, "bdump_get: cannot get auth response: %s",
+                    error_message(retval));
+             cleanup(server);
+             return;
+        }    
+        retval = krb5_rd_rep(Z_krb5_ctx, bdump_ac, &data, &rep);
+        free(data.data);
+        memset((char *)&data, 0, sizeof(krb5_data));
+        if (retval) {
+             syslog(LOG_ERR, "bdump_get: mutual authentication failed: %s",
+                    error_message(retval));
+             cleanup(server);
+             return;
+        }    
+	break;
 #endif
- 
-    /* get his authenticator */
-    retval = GetKerberosData(live_socket, from.sin_addr, &kdata,
-			     SERVER_SERVICE, srvtab_file);
-    if (retval != KSUCCESS) {
-	syslog(LOG_ERR, "bdump_get getkdata: %s",krb_get_err_text(retval));
-	cleanup(server);
-	return;
-    }
+#ifdef HAVE_KRB4
+    case 4:
+	/* send an authenticator */
+	retval = SendKerberosData(live_socket, &ticket, SERVER_SERVICE,
+				  SERVER_INSTANCE);
+	if (retval != 0) {
+	    syslog(LOG_ERR,"bdump_get: %s", error_message(retval));
+	    cleanup(server);
+	    return;
+	}
+	zdbug((LOG_DEBUG, "bdump_get: SendKerberosData ok"));
+	
+	/* get his authenticator */
+	retval = GetKerberosData(live_socket, from.sin_addr, &kdata,
+				 SERVER_SERVICE, srvtab_file);
+	if (retval != KSUCCESS) {
+	    syslog(LOG_ERR, "bdump_get getkdata: %s",krb_get_err_text(retval));
+	    cleanup(server);
+	    return;
+	}
 
-    if (strcmp(kdata.pname, SERVER_SERVICE) ||
-	strcmp(kdata.pinst, SERVER_INSTANCE) ||
-	strcmp(kdata.prealm, ZGetRealm())) {
-	syslog(LOG_ERR, "bdump_get: peer not zephyr in lrealm: %s.%s@%s",
-	       kdata.pname, kdata.pinst,kdata.prealm);
-	cleanup(server);
-	return;
+	if (strcmp(kdata.pname, SERVER_SERVICE) ||
+	    strcmp(kdata.pinst, SERVER_INSTANCE) ||
+	    strcmp(kdata.prealm, ZGetRealm())) {
+	    syslog(LOG_ERR, "bdump_get: peer not zephyr in lrealm: %s.%s@%s",
+		   kdata.pname, kdata.pinst,kdata.prealm);
+	    cleanup(server);
+	    return;
+	}
+	break;
+#endif /* HAVE_KRB4 */
     }
-#endif /* HAVE_KRB4 */
+#endif /* defined(HAVE_KRB4) || defined(HAVE_KRB5) */   
     retval = setup_file_pointers();
     if (retval != 0) {
 	syslog(LOG_WARNING, "bdump_get: can't set up file pointers: %s",
@@ -499,9 +756,7 @@
 	cleanup(server);
 	return;
     }
-#if 1
     zdbug((LOG_DEBUG,"bdump_get: gbdl ok"));
-#endif
     retval = bdump_send_loop(server);
     if (retval != ZERR_NONE) {
 	syslog(LOG_WARNING, "bdump_send_loop failed: %s",
@@ -605,7 +860,30 @@
     retval = ZFormatNoticeList(&notice, lyst, num, &pack, &packlen, ZNOAUTH);
     if (retval != ZERR_NONE)
 	return retval;
-	
+
+#ifdef HAVE_KRB5
+    if (bdump_ac) {
+        krb5_data indata, outmsg;
+        indata.length=packlen;
+        indata.data=pack;
+        memset(&outmsg, 0, sizeof(krb5_data));
+        retval = krb5_mk_priv(Z_krb5_ctx, bdump_ac, &indata, &outmsg, NULL);
+        if (retval != ZERR_NONE)
+	    return retval;
+        if (outmsg.length > Z_MAXPKTLEN) {
+	    syslog(LOG_ERR, "bsl: encrypted packet is too large");
+            return ZERR_PKTLEN;
+        }
+        packlen = outmsg.length;
+        free(pack);
+        pack=malloc(packlen);
+        if (!pack)
+	    return ENOMEM;
+        memcpy(pack, outmsg.data, packlen);
+        krb5_free_data_contents(Z_krb5_ctx, &outmsg);
+    }
+#endif
+
     length = htons((u_short) packlen);
  
     count = net_write(output, (char *) &length, sizeof(length));
@@ -650,6 +928,11 @@
     if (live_socket >= 0) {
 	close(live_socket);
 	live_socket = -1;
+#ifdef HAVE_KRB5
+	if (bdump_ac)
+		krb5_auth_con_free(Z_krb5_ctx, bdump_ac);
+	bdump_ac = NULL;
+#endif
     }
 }
 
@@ -694,7 +977,7 @@
 #ifndef NOENCRYPTION
     Sched *s;
 #endif
-	
+    
     /* have they expired ? */
     if (ticket_time < NOW - tkt_lifetime(TKTLIFETIME) + (15L * 60L)) {
 	/* +15 for leeway */
@@ -728,6 +1011,54 @@
 	des_key_sched(serv_key, serv_ksched.s);
 #endif /* !NOENCRYPTION */
     }
+#ifdef HAVE_KRB5	
+    /* XXX */
+    if (ticket5_time < NOW - tkt5_lifetime(TKT5LIFETIME) + (15L * 60L)) {
+	krb5_keytab kt;
+	krb5_get_init_creds_opt opt;
+	krb5_creds cred;
+	krb5_principal principal;
+
+	memset(&cred, 0, sizeof(cred));
+
+	retval = krb5_build_principal(Z_krb5_ctx, &principal, 
+				      strlen(ZGetRealm()),
+				      ZGetRealm(),
+				      SERVER_KRB5_SERVICE, SERVER_INSTANCE,
+				      0); 
+	if (retval) {
+	  krb5_free_principal(Z_krb5_ctx, principal);
+	  return(1);
+	}
+
+	krb5_get_init_creds_opt_init (&opt);
+	krb5_get_init_creds_opt_set_tkt_life (&opt, TKT5LIFETIME);
+
+	retval = krb5_kt_resolve(Z_krb5_ctx, keytab_file, &kt);
+	if (retval) return(1);
+	
+	retval = krb5_get_init_creds_keytab (Z_krb5_ctx,
+					     &cred,
+					     principal,
+					     kt,
+					     0,
+					     NULL,
+					     &opt);
+	krb5_free_principal(Z_krb5_ctx, principal);
+	krb5_kt_close(Z_krb5_ctx, kt);
+	if (retval) return(1);
+
+	retval = krb5_cc_initialize (Z_krb5_ctx, Z_krb5_ccache, cred.client);
+	if (retval) return(1);
+    
+	retval = krb5_cc_store_cred (Z_krb5_ctx, Z_krb5_ccache, &cred);
+	if (retval) return(1);
+
+	ticket5_time = NOW;
+
+	krb5_free_cred_contents (Z_krb5_ctx, &cred);
+    }
+#endif
     return(0);
 }
 #endif /* HAVE_KRB4 */
@@ -771,8 +1102,14 @@
     Code_t retval;
     Client *client = NULL;
     struct sockaddr_in who;
+#ifdef HAVE_KRB5
+    char buf[512];
+    int blen;
+#endif
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)    
+    char *cp;
+#endif
 #ifdef HAVE_KRB4
-    char *cp;
     C_Block cblock;
 #endif /* HAVE_KRB4 */
     ZRealm *realm = NULL;
@@ -798,6 +1135,23 @@
 	    return retval;
 	}
 
+#if HAVE_KRB5
+	if (bdump_ac) {
+	    krb5_data in, out;
+	    in.length = len;
+	    in.data = packet;
+	    memset(&out, 0, sizeof(krb5_data));
+	    retval = krb5_rd_priv(Z_krb5_ctx, bdump_ac, &in, &out, NULL);
+	    if (retval != ZERR_NONE) {
+	        syslog(LOG_ERR, "brl krb5 rd priv: %s", error_message(retval));
+	        return retval;
+	    }
+	    memcpy(packet, out.data, out.length);
+	    len = out.length;
+	    krb5_free_data_contents(Z_krb5_ctx, &out);
+	}
+#endif
+
 	retval = ZParseNotice(packet, len, &notice);
 	if (retval != ZERR_NONE) {
 	    syslog(LOG_ERR, "brl notice parse: %s", error_message(retval));
@@ -853,6 +1207,52 @@
 		syslog(LOG_ERR,"brl failed: %s", error_message(retval));
 		return retval;
 	    }
+#ifdef HAVE_KRB5
+	    client->session_keyblock = NULL;
+	    if (*notice.z_class_inst) {
+		/* check out this session key I found */
+		cp = notice.z_message + strlen(notice.z_message) + 1;
+		if (*cp == '0') {
+		    /* ****ing netascii; this is an encrypted DES keyblock
+		       XXX this code should be conditionalized for server
+		       transitions   */
+		    retval = Z_krb5_init_keyblock(Z_krb5_ctx, ENCTYPE_DES_CBC_CRC,
+						sizeof(C_Block),
+						&client->session_keyblock);
+		    if (retval) {
+			syslog(LOG_ERR, "brl failed to allocate DES keyblock: %s",
+			       error_message(retval));
+			return retval;
+		    }
+		    retval = ZReadAscii(cp, strlen(cp), cblock, sizeof(C_Block));
+		    if (retval != ZERR_NONE) {
+			syslog(LOG_ERR,"brl bad cblk read: %s (%s)",
+			       error_message(retval), cp);
+		    } else {
+			des_ecb_encrypt(cblock, Z_keydata(client->session_keyblock),
+					serv_ksched.s, DES_DECRYPT);
+		    }
+		} else if (*cp == 'Z') { /* Zcode! Long live the new flesh! */
+		    retval = ZReadZcode(cp, buf, sizeof(buf), &blen);
+		    if (retval != ZERR_NONE) {
+			syslog(LOG_ERR,"brl bad cblk read: %s (%s)",
+			       error_message(retval), cp);
+		    } else {
+			retval = Z_krb5_init_keyblock(Z_krb5_ctx,
+						    ntohl(*(krb5_enctype *)&buf[0]),
+						    ntohl(*(u_int32_t *)&buf[4]),
+						    &client->session_keyblock);
+			if (retval) {
+			    syslog(LOG_ERR, "brl failed to allocate keyblock: %s",
+				   error_message(retval));
+			    return retval;
+			}
+			memcpy(Z_keydata(client->session_keyblock), &buf[8],
+			       Z_keylen(client->session_keyblock));
+		    }
+		}
+	    }
+#else
 #ifdef HAVE_KRB4
 	    memset(client->session_key, 0, sizeof(C_Block));
 	    if (*notice.z_class_inst) {
@@ -872,6 +1272,7 @@
 		}
 	    }
 #endif /* HAVE_KRB4 */
+#endif
 	} else if (strcmp(notice.z_opcode, CLIENT_SUBSCRIBE) == 0) { 
 	    /* a subscription packet */
 	    if (!client) {
@@ -1025,6 +1426,29 @@
 	return retval;
     }
  
+#ifdef HAVE_KRB5
+    if (bdump_ac) {
+        krb5_data indata, outmsg;
+        indata.length=packlen;
+        indata.data=pack;
+        memset(&outmsg, 0, sizeof(krb5_data));
+        retval = krb5_mk_priv(Z_krb5_ctx, bdump_ac, &indata, &outmsg, NULL);
+        if (retval != ZERR_NONE)
+	    return retval;
+        if (outmsg.length > Z_MAXPKTLEN) {
+	    syslog(LOG_ERR, "sn: encrypted packet is too large");
+            return ZERR_PKTLEN;
+        }
+        packlen = outmsg.length;
+        free(pack);
+        pack=malloc(packlen);
+        if (!pack)
+	    return ENOMEM;
+        memcpy(pack, outmsg.data, packlen);
+        krb5_free_data_contents(Z_krb5_ctx, &outmsg);
+    }
+#endif
+
     length = htons((u_short) packlen);
  
     count = net_write(output, (char *) &length, sizeof(length));
@@ -1138,7 +1562,13 @@
 	errno = 0;
 	cc = fread(buf, 1, len, f);
 	if (cc == 0)
+	  {
+	    if (feof(f))
+	      return len2;
+	    if (errno == 0)
+	      errno = EIO;
 	    return -1;
+	  }
 	buf += cc;
 	len2 += cc;
 	len -= cc;

Modified: trunk/athena/lib/zephyr/server/client.c
===================================================================
--- trunk/athena/lib/zephyr/server/client.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/client.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -84,9 +84,13 @@
 	if (!client)
 	    return ENOMEM;
 	memset(&client->addr, 0, sizeof(struct sockaddr_in));
-#ifdef KERBEROS
+#ifdef HAVE_KRB5
+        client->session_keyblock = NULL;
+#else
+#ifdef HAVE_KRB4
 	memset(&client->session_key, 0, sizeof(client->session_key));
 #endif
+#endif
 	client->last_send = 0;
 	client->last_ack = NOW;
 	client->addr.sin_family = AF_INET;
@@ -122,6 +126,10 @@
     nack_release(client);
     subscr_cancel_client(client);
     free_string(client->principal);
+#ifdef HAVE_KRB5
+    if (client->session_keyblock)
+         krb5_free_keyblock(Z_krb5_ctx, client->session_keyblock);
+#endif
     if (flush)
 	uloc_flush_client(&client->addr);
     free(client);

Modified: trunk/athena/lib/zephyr/server/dispatch.c
===================================================================
--- trunk/athena/lib/zephyr/server/dispatch.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/dispatch.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -14,6 +14,7 @@
 #include <zephyr/mit-copyright.h>
 #include "zserver.h"
 #include <sys/socket.h>
+#include <com_err.h>
 
 #ifndef lint
 #ifndef SABER
@@ -582,14 +583,23 @@
 				   we are distributing authentic and
 				   we have a pointer to auth info
 				   */
-#ifdef HAVE_KRB4
-	retval = ZFormatAuthenticNotice(notice, noticepack, packlen, &packlen,
-					client->session_key);
-	if (retval != ZERR_NONE) {
-	    syslog(LOG_ERR, "xmit auth format: %s", error_message(retval));
-	    free(noticepack);
-	    return;
-	}
+#ifdef HAVE_KRB5
+         retval = ZFormatAuthenticNoticeV5(notice, noticepack, packlen,
+                                           &packlen, client->session_keyblock);
+         if (retval != ZERR_NONE) {
+              syslog(LOG_ERR, "xmit auth format: %s", error_message(retval));
+              free(noticepack);
+              return;
+         }
+#else
+#if defined(HAVE_KRB4)
+         retval = ZFormatAuthenticNotice(notice, noticepack, packlen,
+                                           &packlen, client->session_key);
+         if (retval != ZERR_NONE) {
+              syslog(LOG_ERR, "xmit auth format: %s", error_message(retval));
+              free(noticepack);
+              return;
+         }
 #else /* !HAVE_KRB4 */
 	notice->z_auth = 1;
 	retval = ZFormatSmallRawNotice(notice, noticepack, &packlen);
@@ -599,6 +609,7 @@
 	    return;
 	}
 #endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB5 */
     } else {
 	notice->z_auth = 0;
 	notice->z_authent_len = 0;
@@ -1126,10 +1137,28 @@
 		clt_ack(notice, who, AUTH_FAILED);
 	    return ZERR_NONE;
 	}
+#ifdef HAVE_KRB5
+        if (client->session_keyblock) {
+             krb5_free_keyblock_contents(Z_krb5_ctx, client->session_keyblock);
+             retval = krb5_copy_keyblock_contents(Z_krb5_ctx, ZGetSession(),
+                                         client->session_keyblock);
+        } else {
+             retval = krb5_copy_keyblock(Z_krb5_ctx, ZGetSession(), 
+                                &client->session_keyblock);
+        }
+        if (retval) {
+             syslog(LOG_WARNING, "keyblock copy failed in subscr: %s",
+                    error_message(retval));
+             if (server == me_server)
+                  nack(notice, who);
+             return ZERR_NONE;
+        }
+#else
 #ifdef HAVE_KRB4
 	/* in case it's changed */
 	memcpy(client->session_key, ZGetSession(), sizeof(C_Block));
 #endif
+#endif
 	retval = subscr_subscribe(client, notice, server);
 	if (retval != ZERR_NONE) {
 	    syslog(LOG_WARNING, "subscr failed: %s", error_message(retval));

Modified: trunk/athena/lib/zephyr/server/kstuff.c
===================================================================
--- trunk/athena/lib/zephyr/server/kstuff.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/kstuff.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -22,30 +22,6 @@
 
 #ifdef HAVE_KRB4
 
-/* Keep a hash table mapping tickets to session keys, so we can do a fast
- * check of the cryptographic checksum without doing and DES decryptions.
- * Also remember the expiry time of the ticket, so that we can sweep the
- * table periodically. */
-
-#define HASHTAB_SIZE 4091
-
-typedef struct hash_entry Hash_entry;
-
-/* The ticket comes at the end, in a variable-length array. */
-struct hash_entry {
-    C_Block session_key;
-    time_t expires;
-    char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4];
-    Hash_entry *next;
-    int ticket_len;
-    unsigned char ticket[1];
-};
-
-Hash_entry *hashtab[HASHTAB_SIZE];
-
-static int hash_ticket __P((unsigned char *, int));
-static void add_session_key __P((KTEXT, C_Block, char *, time_t));
-static int find_session_key __P((KTEXT, C_Block, char *));
 static ZChecksum_t compute_checksum __P((ZNotice_t *, C_Block));
 static ZChecksum_t compute_rlm_checksum __P((ZNotice_t *, C_Block));
 
@@ -113,6 +89,10 @@
  * get the ticket and write it to the file descriptor
  */
 
+#if !defined(krb_err_base) && defined(ERROR_TABLE_BASE_krb)
+#define krb_err_base ERROR_TABLE_BASE_krb
+#endif
+
 Code_t
 SendKerberosData(fd, ticket, service, host)
      int fd;		/* file descriptor to write onto */
@@ -142,21 +122,157 @@
 
 #endif /* HAVE_KRB4 */
 
+#if defined(HAVE_KRB5) || defined(HAVE_KRB4)
 Code_t
+ReadKerberosData(int fd, int *size, char **data, int *proto) {
+    char p[20];
+    int i;
+    unsigned char *dst;
+    Code_t retval;
+    int len = 0;
+
+    for (i=0; i<20; i++) {
+	if (read(fd, &p[i], 1) != 1) {
+	    p[i] = 0;
+	    syslog(LOG_WARNING,"ReadKerberosData: bad read reply len @%d (got \"%s\"", i, p);
+	    return(KFAILURE);
+	}
+	if (p[i] == ' ') {
+	    p[i] = '\0';
+	    break;
+	}
+    }
+
+    if (i == 20) {
+	syslog(LOG_WARNING, "ReadKerberosData: read reply len exceeds buffer");
+	    return KFAILURE;
+    }
+
+    if (!strncmp(p, "V5-", 3) && (len = atoi(p+3)) > 0)
+	*proto = 5;
+    else if ((len = atoi(p)) > 0)
+	*proto = 4;
+
+    if (*proto < 4 | *proto > 5) {
+	syslog(LOG_WARNING, "ReadKerberosData: error parsing authenticator length (\"%s\")", p);
+	return KFAILURE;
+    }
+
+    if (len <= 0) {
+	syslog(LOG_WARNING, "ReadKerberosData: read reply len = %d", len);
+	return KFAILURE;
+    }
+
+    *data = malloc(len);
+    if (! *data) {
+	syslog(LOG_WARNING, "ReadKerberosData: failure allocating %d bytes: %m", len);
+	return errno;
+    }
+    
+    dst=*data;
+    for (i=0; i < len; i++) {
+	if (read(fd, dst++, 1) != 1) {
+            free(*data);
+	    *data = NULL;
+	    *size = 0;
+            syslog(LOG_WARNING,"ReadKerberosData: bad read reply string");
+            return ZSRV_PKSHORT;
+        }
+    }
+    *size = len;
+    return 0;
+}
+#endif
+
+#ifdef HAVE_KRB5
+Code_t
+GetKrb5Data(int fd, krb5_data *data) {
+    char p[20];
+    int i;
+    unsigned char *dst;
+    Code_t retval;
+
+    for (i=0; i<20; i++) {
+	if (read(fd, &p[i], 1) != 1) {
+	    p[i] = 0;
+	    syslog(LOG_WARNING,"bad read reply len @%d (got \"%s\")", i, p);
+	    return(KFAILURE);
+	}
+	if (p[i] == ' ') {
+	    p[i] = '\0';
+	    break;
+	}
+    }
+    if (i == 20 || strncmp(p, "V5-", 3) || !atoi(p+3)) {
+        syslog(LOG_WARNING,"bad reply len");
+        return ZSRV_PKSHORT;
+    }
+    data->length = atoi(p+3);
+    data->data = malloc(data->length);
+    if (! data->data) {
+       data->length = 0;
+       return errno;
+    }
+    dst=data->data;
+    for (i=0; i < data->length; i++) {
+	if (read(fd, dst++, 1) != 1) {
+            free(data->data);
+            memset((char *)data, 0, sizeof(krb5_data));
+            syslog(LOG_WARNING,"bad read reply string");
+            return ZSRV_PKSHORT;
+        }
+    }
+    return 0;
+}
+
+Code_t
+SendKrb5Data(int fd, krb5_data *data) {
+    char p[32];
+    int written, size_to_write;
+    sprintf(p, "V5-%d ", data->length);
+    size_to_write = strlen (p);
+    if (size_to_write != (written = write(fd, p, size_to_write)) ||
+        data->length != (written = write(fd, data->data, data->length))) {
+        return (written < 0) ? errno : ZSRV_PKSHORT; 
+    }    
+    return 0;
+}
+#endif
+
+Code_t
 ZCheckRealmAuthentication(notice, from, realm)
     ZNotice_t *notice;
     struct sockaddr_in *from;
     char *realm;
 {       
-#ifdef HAVE_KRB4
-    int result;
-    char rlmprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4];
-    char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4];
-    KTEXT_ST authent, ticket;
-    AUTH_DAT dat;
-    ZChecksum_t checksum;
-    CREDENTIALS cred;
-    C_Block session_key;
+#ifdef HAVE_KRB5
+    char *authbuf;
+    char rlmprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4+1024];
+    krb5_principal princ;
+    krb5_data packet;
+    krb5_ticket *tkt;
+    char *name;
+    krb5_error_code result;
+    krb5_principal server;
+    krb5_keytab keytabid = 0;
+    krb5_auth_context authctx;
+    krb5_keyblock *keyblock; 
+    krb5_enctype enctype; 
+    krb5_cksumtype cksumtype; 
+    krb5_data cksumbuf;
+    int valid;
+    char *cksum0_base, *cksum1_base, *cksum2_base; 
+    char *svcinst, *x, *y; 
+    char *asn1_data, *key_data; 
+    int asn1_len, key_len, cksum0_len, cksum1_len, cksum2_len; 
+#ifdef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER
+    krb5_authenticator *authenticator;
+#define KRB5AUTHENT authenticator
+#else
+    krb5_authenticator authenticator;
+#define KRB5AUTHENT &authenticator
+#endif
+    int len;
 
     if (!notice->z_auth)
         return ZAUTH_NO;
@@ -165,52 +281,537 @@
     if (notice->z_authent_len <= 0)
         return ZAUTH_FAILED;
 
+    len = strlen(notice->z_ascii_authent)+1;
+    authbuf=malloc(len);
+
     /* Read in the authentication data. */
-    if (ZReadAscii(notice->z_ascii_authent, 
-                   strlen(notice->z_ascii_authent)+1, 
-                   (unsigned char *)authent.dat, 
-                   notice->z_authent_len) == ZERR_BADFIELD) {
+    if (ZReadZcode(notice->z_ascii_authent, 
+                   authbuf,
+                   len, &len) == ZERR_BADFIELD) {
         return ZAUTH_FAILED;
     }
-    authent.length = notice->z_authent_len;
 
-    (void) sprintf(rlmprincipal, "%s.%s@%s", SERVER_SERVICE,
+    (void) sprintf(rlmprincipal, "%s/%s@%s", SERVER_SERVICE,
                    SERVER_INSTANCE, realm);
 
-    result = krb_rd_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
-                        from->sin_addr.s_addr, &dat, srvtab_file);
-    if (result == RD_AP_OK) {
-        sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "",
-		dat.pinst, dat.prealm);
-        if (strcmp(rlmprincipal, srcprincipal))
-            return ZAUTH_FAILED;
-    } else {
-        return ZAUTH_FAILED;    /* didn't decode correctly */
+    packet.length = len;
+    packet.data = authbuf;
+
+    result = krb5_kt_resolve(Z_krb5_ctx, 
+                        keytab_file, &keytabid);
+    if (result) {
+      free(authbuf);
+      return (result);
     }
 
-    /* Check the cryptographic checksum. */
-#ifdef NOENCRYPTION
-    checksum = 0;
+    /* HOLDING: authbuf, keytabid */
+    /* Create the auth context */
+    result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
+    if (result) {
+        krb5_kt_close(Z_krb5_ctx, keytabid);
+        free(authbuf);
+        return (result);
+    }
+
+    /* HOLDING: authbuf, authctx */
+    result = krb5_build_principal(Z_krb5_ctx, &server, strlen(__Zephyr_realm), 
+				  __Zephyr_realm, SERVER_SERVICE, 
+				  SERVER_INSTANCE, NULL);
+    if (!result) {
+        result = krb5_rd_req(Z_krb5_ctx, &authctx, &packet, server, 
+                             keytabid, 0, &tkt);
+	krb5_free_principal(Z_krb5_ctx, server);
+    }
+    krb5_kt_close(Z_krb5_ctx, keytabid);
+
+    if (result) {
+      if (result == KRB5KRB_AP_ERR_REPEAT)
+	syslog(LOG_DEBUG, "ZCheckRealmAuthentication: k5 auth failed: %s", error_message(result));
+      else
+        syslog(LOG_WARNING,"ZCheckRealmAuthentication: k5 auth failed: %s", error_message(result));
+        free(authbuf);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        return ZAUTH_FAILED;
+    }
+
+    /* HOLDING: authbuf, authctx, tkt */
+    
+    if (tkt == 0 || !Z_tktprincp(tkt)) {
+	if (tkt)
+	    krb5_free_ticket(Z_krb5_ctx, tkt);
+	free(authbuf);
+	krb5_auth_con_free(Z_krb5_ctx, authctx);
+	return ZAUTH_FAILED;
+    }
+
+    princ = Z_tktprinc(tkt);
+
+    if (princ == 0) {
+        krb5_free_ticket(Z_krb5_ctx, tkt);
+        free(authbuf);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        return ZAUTH_FAILED;
+    }
+
+    /* HOLDING: authbuf, authctx, tkt */
+    result = krb5_unparse_name(Z_krb5_ctx, princ, &name);
+    if (result) {
+        syslog(LOG_WARNING, "k5 unparse_name failed: %s",
+               error_message(result));
+        free(authbuf);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        krb5_free_ticket(Z_krb5_ctx, tkt);
+        return ZAUTH_FAILED;
+    }
+
+    krb5_free_ticket(Z_krb5_ctx, tkt);
+
+    /* HOLDING: authbuf, authctx, name */
+    if (strcmp(name, rlmprincipal)) {
+        syslog(LOG_WARNING, "k5 name mismatch: '%s' vs '%s'",
+               name, rlmprincipal);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        free(name);
+        free(authbuf);
+        return ZAUTH_FAILED;
+    }
+    free(name);
+    free(authbuf);
+
+    /* HOLDING: authctx */
+    /* Get an authenticator so we can get the keyblock */
+    result = krb5_auth_con_getauthenticator (Z_krb5_ctx, authctx,
+    					     &authenticator);
+    if(result) {
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        return result;
+    }
+
+    /* HOLDING: authctx, authenticator */
+    result = krb5_auth_con_getkey(Z_krb5_ctx, authctx, &keyblock);
+    if (result) {
+      krb5_auth_con_free(Z_krb5_ctx, authctx);
+      krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+      return (ZAUTH_FAILED);
+    }
+    
+    /* HOLDING: authctx, authenticator, keyblock */
+    /* Figure out what checksum type to use */
+    key_data = Z_keydata(keyblock);
+    key_len = Z_keylen(keyblock);
+    result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+    if (result) {
+	krb5_free_keyblock(Z_krb5_ctx, keyblock);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+        return (ZAUTH_FAILED);
+    }
+    /* HOLDING: authctx, authenticator, keyblock */
+ 
+    /* Assemble the things to be checksummed */ 
+    /* first part is from start of packet through z_default_format: 
+     * - z_version 
+     * - z_num_other_fields 
+     * - z_kind 
+     * - z_uid 
+     * - z_port 
+     * - z_auth 
+     * - z_authent_len 
+     * - z_ascii_authent 
+     * - z_class 
+     * - z_class_inst 
+     * - z_opcode 
+     * - z_sender 
+     * - z_recipient 
+     * - z_default_format 
+     */ 
+    cksum0_base = notice->z_packet; 
+    x           = notice->z_default_format; 
+    cksum0_len  = x + strlen(x) + 1 - cksum0_base; 
+    /* second part is from z_multinotice through other fields: 
+     * - z_multinotice 
+     * - z_multiuid 
+     * - z_other_fields[] 
+     */ 
+    cksum1_base = notice->z_multinotice; 
+    if (notice->z_num_other_fields) 
+        x = notice->z_other_fields[notice->z_num_other_fields]; 
+    else 
+        x = cksum1_base + strlen(cksum1_base) + 1; /* multiuid */ 
+    cksum1_len  = x + strlen(x) + 1 - cksum1_base; 
+ 
+    /* last part is the message body */ 
+    cksum2_base = notice->z_message; 
+    cksum2_len  = notice->z_message_len; 
+ 
+    if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') && 
+        key_len == 8 && 
+        (enctype == ENCTYPE_DES_CBC_CRC || 
+         enctype == ENCTYPE_DES_CBC_MD4 || 
+         enctype == ENCTYPE_DES_CBC_MD5)) { 
+      /* try old-format checksum (covers cksum0 only) */ 
+ 
+      ZChecksum_t our_checksum; 
+
+      our_checksum = compute_rlm_checksum(notice, key_data);
+
+      krb5_free_keyblock(Z_krb5_ctx, keyblock);
+      krb5_auth_con_free(Z_krb5_ctx, authctx);
+      krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+      
+      if (our_checksum == notice->z_checksum) { 
+          return ZAUTH_YES; 
+      } else
+	  return ZAUTH_FAILED;
+    } 
+
+    /* HOLDING: authctx, authenticator */
+ 
+    cksumbuf.length = cksum0_len + cksum1_len + cksum2_len; 
+    cksumbuf.data = malloc(cksumbuf.length); 
+    if (!cksumbuf.data) { 
+        krb5_free_keyblock(Z_krb5_ctx, keyblock);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+        return ZAUTH_FAILED; 
+    } 
+    /* HOLDING: authctx, authenticator, cksumbuf.data */ 
+ 
+    memcpy(cksumbuf.data, cksum0_base, cksum0_len); 
+    memcpy(cksumbuf.data + cksum0_len, cksum1_base, cksum1_len); 
+    memcpy(cksumbuf.data + cksum0_len + cksum1_len, 
+           cksum2_base, cksum2_len); 
+ 
+    /* decode zcoded checksum */ 
+    /* The encoded form is always longer than the original */ 
+    asn1_len = strlen(notice->z_ascii_checksum) + 1; 
+    asn1_data = malloc(asn1_len); 
+    if (!asn1_data) { 
+        krb5_free_keyblock(Z_krb5_ctx, keyblock);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+        free(cksumbuf.data); 
+        return ZAUTH_FAILED; 
+    } 
+    /* HOLDING: authctx, authenticator, cksumbuf.data, asn1_data */ 
+    result = ZReadZcode(notice->z_ascii_checksum, 
+                        asn1_data, asn1_len, &asn1_len); 
+    if (result != ZERR_NONE) { 
+        krb5_free_keyblock(Z_krb5_ctx, keyblock);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+        free(asn1_data); 
+        free(cksumbuf.data); 
+        return ZAUTH_FAILED; 
+    } 
+    /* HOLDING: asn1_data, cksumbuf.data */ 
+
+    valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype, asn1_data, asn1_len);
+
+    free(asn1_data); 
+    krb5_auth_con_free(Z_krb5_ctx, authctx);
+    krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+    krb5_free_keyblock(Z_krb5_ctx, keyblock);
+    free(cksumbuf.data); 
+    
+    if (valid) 
+        return (ZAUTH_YES); 
+    else 
+        return (ZAUTH_FAILED); 
 #else
-    checksum = compute_rlm_checksum(notice, dat.session);
+    return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO;
 #endif
-    if (checksum != notice->z_checksum) {
-#ifndef NOENCRYPTION
-      checksum = compute_checksum(notice, dat.session);
-      if (checksum != notice->z_checksum)
+}
+
+Code_t
+ZCheckAuthentication(notice, from)
+    ZNotice_t *notice;
+    struct sockaddr_in *from;
+{       
+#ifdef HAVE_KRB5
+    char *authbuf;
+    krb5_principal princ;
+    krb5_data packet;
+    krb5_ticket *tkt;
+    char *name;
+    krb5_error_code result;
+    krb5_principal server;
+    krb5_keytab keytabid = 0;
+    krb5_auth_context authctx;
+    krb5_keyblock *keyblock; 
+    krb5_enctype enctype; 
+    krb5_cksumtype cksumtype; 
+    krb5_data cksumbuf;
+    int valid;
+    char *cksum0_base, *cksum1_base, *cksum2_base; 
+    char *svcinst, *x, *y; 
+    char *asn1_data, *key_data; 
+    int asn1_len, key_len, cksum0_len, cksum1_len, cksum2_len; 
+#ifdef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER
+    krb5_authenticator *authenticator;
+#define KRB5AUTHENT authenticator
+#else
+    krb5_authenticator authenticator;
+#define KRB5AUTHENT &authenticator
 #endif
+    int len;
+
+    if (!notice->z_auth)
+        return ZAUTH_NO;
+
+    /* Check for bogus authentication data length. */
+    if (notice->z_authent_len <= 1)
         return ZAUTH_FAILED;
+
+#ifdef HAVE_KRB4
+    if (notice->z_ascii_authent[0] != 'Z')
+      return ZCheckAuthentication4(notice, from);
+#endif
+    
+    len = strlen(notice->z_ascii_authent)+1;
+    authbuf=malloc(len);
+
+    /* Read in the authentication data. */
+    if (ZReadZcode(notice->z_ascii_authent, 
+                   authbuf,
+                   len, &len) == ZERR_BADFIELD) {
+        return ZAUTH_FAILED;
     }
 
-    return ZAUTH_YES;
+    packet.length = len;
+    packet.data = authbuf;
 
-#else /* !HAVE_KRB4 */
+    result = krb5_kt_resolve(Z_krb5_ctx, 
+                        keytab_file, &keytabid);
+    if (result) {
+      free(authbuf);
+      return (result);
+    }
+
+    /* HOLDING: authbuf, keytabid */
+    /* Create the auth context */
+    result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
+    if (result) {
+        krb5_kt_close(Z_krb5_ctx, keytabid);
+        free(authbuf);
+        return (result);
+    }
+
+    /* HOLDING: authbuf, authctx */
+    result = krb5_build_principal(Z_krb5_ctx, &server, strlen(__Zephyr_realm), 
+				  __Zephyr_realm, SERVER_SERVICE, 
+				  SERVER_INSTANCE, NULL);
+    if (!result) {
+        result = krb5_rd_req(Z_krb5_ctx, &authctx, &packet, server, 
+                             keytabid, 0, &tkt);
+	krb5_free_principal(Z_krb5_ctx, server);
+    }
+    krb5_kt_close(Z_krb5_ctx, keytabid);
+
+    if (result) {
+      if (result == KRB5KRB_AP_ERR_REPEAT)
+	syslog(LOG_DEBUG, "ZCheckAuthentication: k5 auth failed: %s", error_message(result));
+      else
+        syslog(LOG_WARNING,"ZCheckAuthentication: k5 auth failed: %s", error_message(result));
+        free(authbuf);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        return ZAUTH_FAILED;
+    }
+
+    /* HOLDING: authbuf, authctx, tkt */
+
+    if (tkt == 0 || !Z_tktprincp(tkt)) {
+       if (tkt)
+	   krb5_free_ticket(Z_krb5_ctx, tkt);
+       free(authbuf);
+       krb5_auth_con_free(Z_krb5_ctx, authctx);
+       return ZAUTH_FAILED;
+    }
+    princ = Z_tktprinc(tkt);
+
+    if (princ == 0) {
+        krb5_free_ticket(Z_krb5_ctx, tkt);
+        free(authbuf);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        return ZAUTH_FAILED;
+    }
+
+    /* HOLDING: authbuf, authctx, tkt */
+    result = krb5_unparse_name(Z_krb5_ctx, princ, &name);
+    if (result) {
+        syslog(LOG_WARNING, "k5 unparse_name failed: %s",
+               error_message(result));
+        free(authbuf);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        krb5_free_ticket(Z_krb5_ctx, tkt);
+        return ZAUTH_FAILED;
+    }
+
+    krb5_free_ticket(Z_krb5_ctx, tkt);
+
+    /* HOLDING: authbuf, authctx, name */
+    if (strcmp(name, notice->z_sender)) {
+        syslog(LOG_WARNING, "k5 name mismatch: '%s' vs '%s'",
+               name, notice->z_sender);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        free(name);
+        free(authbuf);
+        return ZAUTH_FAILED;
+    }
+    free(name);
+    free(authbuf);
+
+    /* HOLDING: authctx */
+    /* Get an authenticator so we can get the keyblock */
+    result = krb5_auth_con_getauthenticator (Z_krb5_ctx, authctx,
+    					     &authenticator);
+    if(result) {
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        return result;
+    }
+
+    /* HOLDING: authctx, authenticator */
+    result = krb5_auth_con_getkey(Z_krb5_ctx, authctx, &keyblock);
+    if (result) {
+      krb5_auth_con_free(Z_krb5_ctx, authctx);
+      krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+      return (ZAUTH_FAILED);
+    }
+    
+    /* HOLDING: authctx, authenticator, keyblock */
+    /* Figure out what checksum type to use */
+    key_data = Z_keydata(keyblock);
+    key_len = Z_keylen(keyblock);
+    result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+    if (result) { 
+        krb5_free_keyblock(Z_krb5_ctx, keyblock);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+        return (ZAUTH_FAILED); 
+    } 
+    /* HOLDING: authctx, authenticator, keyblock */
+
+    ZSetSession(keyblock);
+ 
+    /* Assemble the things to be checksummed */ 
+    /* first part is from start of packet through z_default_format: 
+     * - z_version 
+     * - z_num_other_fields 
+     * - z_kind 
+     * - z_uid 
+     * - z_port 
+     * - z_auth 
+     * - z_authent_len 
+     * - z_ascii_authent 
+     * - z_class 
+     * - z_class_inst 
+     * - z_opcode 
+     * - z_sender 
+     * - z_recipient 
+     * - z_default_format 
+     */ 
+    cksum0_base = notice->z_packet; 
+    x           = notice->z_default_format; 
+    cksum0_len  = x + strlen(x) + 1 - cksum0_base; 
+    /* second part is from z_multinotice through other fields: 
+     * - z_multinotice 
+     * - z_multiuid 
+     * - z_other_fields[] 
+     */ 
+    cksum1_base = notice->z_multinotice; 
+    if (notice->z_num_other_fields) 
+        x = notice->z_other_fields[notice->z_num_other_fields]; 
+    else 
+        x = cksum1_base + strlen(cksum1_base) + 1; /* multiuid */ 
+    cksum1_len  = x + strlen(x) + 1 - cksum1_base; 
+ 
+    /* last part is the message body */ 
+    cksum2_base = notice->z_message; 
+    cksum2_len  = notice->z_message_len; 
+ 
+    if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') && 
+        key_len == 8 && 
+        (enctype == ENCTYPE_DES_CBC_CRC || 
+         enctype == ENCTYPE_DES_CBC_MD4 || 
+         enctype == ENCTYPE_DES_CBC_MD5)) { 
+      /* try old-format checksum (covers cksum0 only) */ 
+ 
+      ZChecksum_t our_checksum; 
+ 
+      our_checksum = compute_checksum(notice, key_data);
+      
+      krb5_free_keyblock(Z_krb5_ctx, keyblock);
+      krb5_auth_con_free(Z_krb5_ctx, authctx);
+      krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+
+      if (our_checksum == notice->z_checksum)
+	return ZAUTH_YES; 
+      else
+	return ZAUTH_FAILED;
+    } 
+
+    /* HOLDING: authctx, authenticator */
+ 
+    cksumbuf.length = cksum0_len + cksum1_len + cksum2_len; 
+    cksumbuf.data = malloc(cksumbuf.length); 
+    if (!cksumbuf.data) { 
+        krb5_free_keyblock(Z_krb5_ctx, keyblock);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+        return ZAUTH_FAILED; 
+    } 
+    /* HOLDING: authctx, authenticator, cksumbuf.data */ 
+ 
+    memcpy(cksumbuf.data, cksum0_base, cksum0_len); 
+    memcpy(cksumbuf.data + cksum0_len, cksum1_base, cksum1_len); 
+    memcpy(cksumbuf.data + cksum0_len + cksum1_len, 
+           cksum2_base, cksum2_len); 
+ 
+    /* decode zcoded checksum */ 
+    /* The encoded form is always longer than the original */ 
+    asn1_len = strlen(notice->z_ascii_checksum) + 1; 
+    asn1_data = malloc(asn1_len); 
+    if (!asn1_data) { 
+        krb5_free_keyblock(Z_krb5_ctx, keyblock);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+        free(cksumbuf.data); 
+        return ZAUTH_FAILED; 
+    } 
+    /* HOLDING: authctx, authenticator, cksumbuf.data, asn1_data */ 
+    result = ZReadZcode(notice->z_ascii_checksum, 
+                        asn1_data, asn1_len, &asn1_len); 
+    if (result != ZERR_NONE) { 
+        krb5_free_keyblock(Z_krb5_ctx, keyblock);
+        krb5_auth_con_free(Z_krb5_ctx, authctx);
+        krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+        free(asn1_data); 
+        free(cksumbuf.data); 
+        return ZAUTH_FAILED; 
+    } 
+    /* HOLDING: asn1_data, cksumbuf.data, authctx, authenticator */ 
+
+    valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype, asn1_data, asn1_len);
+
+    free(asn1_data); 
+    krb5_auth_con_free(Z_krb5_ctx, authctx);
+    krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+    krb5_free_keyblock(Z_krb5_ctx, keyblock);
+    free(cksumbuf.data); 
+    
+    if (valid) 
+        return (ZAUTH_YES); 
+    else 
+        return (ZAUTH_FAILED); 
+#else
     return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO;
 #endif
 }
 
+#undef KRB5AUTHENT
+
 Code_t
-ZCheckAuthentication(notice, from)
+ZCheckAuthentication4(notice, from)
     ZNotice_t *notice;
     struct sockaddr_in *from;
 {	
@@ -221,6 +822,7 @@
     AUTH_DAT dat;
     ZChecksum_t checksum;
     C_Block session_key;
+    char instance[INST_SZ+1];
 
     if (!notice->z_auth)
 	return ZAUTH_NO;
@@ -238,10 +840,12 @@
     }
     authent.length = notice->z_authent_len;
 
-    result = krb_rd_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
+    strcpy(instance, SERVER_INSTANCE);
+
+    result = krb_rd_req(&authent, SERVER_SERVICE, instance,
 			from->sin_addr.s_addr, &dat, srvtab_file);
     if (result == RD_AP_OK) {
-	memcpy(__Zephyr_session, dat.session, sizeof(C_Block));
+	ZSetSessionDES(&dat.session);
 	sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "",
 		dat.pinst, dat.prealm);
 	if (strcmp(srcprincipal, notice->z_sender))
@@ -266,76 +870,8 @@
 #endif
 }
 
+
 #ifdef HAVE_KRB4
-
-static int hash_ticket(p, len)
-    unsigned char *p;
-    int len;
-{
-    unsigned long hashval = 0, g;
-
-    for (; len > 0; p++, len--) {
-	hashval = (hashval << 4) + *p;
-	g = hashval & 0xf0000000;
-	if (g) {
-	    hashval ^= g >> 24;
-	    hashval ^= g;
-	}
-    }
-    return hashval % HASHTAB_SIZE;
-}
-
-static void add_session_key(ticket, session_key, srcprincipal, expires)
-    KTEXT ticket;
-    C_Block session_key;
-    char *srcprincipal;
-    time_t expires;
-{
-    Hash_entry *entry;
-    int hashval;
-
-    /* If we can't allocate memory for the hash table entry, just forget
-     * about it. */
-    entry = (Hash_entry *) malloc(sizeof(Hash_entry) - 1 + ticket->length);
-    if (!entry)
-	return;
-
-    /* Initialize the new entry. */
-    memcpy(entry->session_key, session_key, sizeof(entry->session_key));
-    strcpy(entry->srcprincipal, srcprincipal);
-    entry->expires = expires;
-    entry->ticket_len = ticket->length;
-    memcpy(entry->ticket, ticket->dat, ticket->length * sizeof(unsigned char));
-
-    /* Insert the new entry in the hash table. */
-    hashval = hash_ticket(ticket->dat, ticket->length);
-    entry->next = hashtab[hashval];
-    hashtab[hashval] = entry;
-}
-
-static int find_session_key(ticket, key, srcprincipal)
-    KTEXT ticket;
-    C_Block key;
-    char *srcprincipal;
-{
-    unsigned char *dat;
-    int hashval, len;
-    Hash_entry *entry;
-
-    dat = ticket->dat;
-    len = ticket->length;
-    hashval = hash_ticket(dat, len);
-
-    for (entry = hashtab[hashval]; entry; entry = entry->next) {
-	if (entry->ticket_len == len && memcmp(entry->ticket, dat, len) == 0) {
-	    memcpy(key, entry->session_key, sizeof(entry->session_key));
-	    strcpy(srcprincipal, entry->srcprincipal);
-	    return 0;
-	}
-    }
-    return -1;
-}
-
 static ZChecksum_t compute_checksum(notice, session_key)
     ZNotice_t *notice;
     C_Block session_key;
@@ -373,26 +909,87 @@
 #endif
 }
 
-void sweep_ticket_hash_table(arg)
-    void *arg;
+#ifdef HAVE_KRB5
+krb5_error_code 
+Z_krb5_init_keyblock(krb5_context context,
+	krb5_enctype type,
+	size_t size,
+	krb5_keyblock **key)
 {
-    int i;
-    Hash_entry **ptr, *entry;
+#ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
+	return krb5_init_keyblock(context, type, size, key);
+#else
+	krb5_error_code ret;
+	krb5_keyblock *tmp, tmp_ss;
+	tmp = &tmp_ss;
 
-    for (i = 0; i < HASHTAB_SIZE; i++) {
-	ptr = &hashtab[i];
-	while (*ptr) {
-	    entry = *ptr;
-	    if (entry->expires < NOW) {
-		*ptr = entry->next;
-		free(entry);
-	    } else {
-		ptr = &(*ptr)->next;
-	    }
-	}
+	*key = NULL;
+	Z_enctype(tmp) = type;
+	Z_keylen(tmp) = size;
+	Z_keydata(tmp) = malloc(size);
+	if (!Z_keydata(tmp))
+		return ENOMEM;
+	ret =  krb5_copy_keyblock(context, tmp, key);
+	free(Z_keydata(tmp));
+	return ret;
+#endif
+}
+
+#if 0
+void ZLogKey(char *label, krb5_keyblock *keyblock) {
+   char *p, *buf;
+   unsigned char *k;
+   int i;
+   buf = malloc(5 *Z_keylen(keyblock)+1);
+
+   k=Z_keydata(keyblock);
+   for (i=0,p=buf; i < Z_keylen(keyblock); i++,p+=strlen(p))
+       sprintf(p, " 0x%02x", k[i]);
+   syslog(LOG_ERR, "key %s is type %d, %d bytes, %s", label, Z_enctype(keyblock), Z_keylen(keyblock), buf);
+   free(buf);
+}
+#endif
+
+void
+ZSetSession(krb5_keyblock *keyblock) {
+#if 1
+    krb5_error_code result;
+
+    if (__Zephyr_keyblock) {
+         krb5_free_keyblock_contents(Z_krb5_ctx, __Zephyr_keyblock);
+         result = krb5_copy_keyblock_contents(Z_krb5_ctx, keyblock, __Zephyr_keyblock);
+    } else {
+         result = krb5_copy_keyblock(Z_krb5_ctx, keyblock, &__Zephyr_keyblock);
     }
-    timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL);
+    
+    if (result) /*XXX we're out of memory? */
+	;
+#else
+    memcpy(__Zephyr_session, Z_keydata(keyblock), sizeof(C_Block));
+#endif
 }
+#endif
+#ifdef HAVE_KRB4
+void
+ZSetSessionDES(C_Block *key) {
+#ifdef HAVE_KRB5
+     Code_t result;
+     if (__Zephyr_keyblock) {
+          krb5_free_keyblock(Z_krb5_ctx, __Zephyr_keyblock);
+          __Zephyr_keyblock=NULL;
+     }
+     result = Z_krb5_init_keyblock(Z_krb5_ctx, ENCTYPE_DES_CBC_CRC, 
+                                 sizeof(C_Block),
+                                 &__Zephyr_keyblock);
+     if (result) /*XXX we're out of memory? */
+	return;
 
+     memcpy(Z_keydata(__Zephyr_keyblock), key, sizeof(C_Block));
+#else
+    memcpy(__Zephyr_session, key, sizeof(C_Block));
+#endif
+}
+#endif
+
 #endif /* HAVE_KRB4 */
 

Modified: trunk/athena/lib/zephyr/server/main.c
===================================================================
--- trunk/athena/lib/zephyr/server/main.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/main.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -92,6 +92,10 @@
 char myname[MAXHOSTNAMELEN];		/* my host name */
 
 char list_file[128];
+#ifdef HAVE_KRB5
+char keytab_file[128];
+static char tkt5_file[256];
+#endif
 #ifdef HAVE_KRB4
 char srvtab_file[128];
 char my_realm[REALM_SZ];
@@ -120,6 +124,25 @@
 struct in_addr my_addr;
 char *bdump_version = "1.2";
 
+#ifdef HAVE_KRB5
+int bdump_auth_proto = 5;
+#else /* HAVE_KRB5 */
+#ifdef HAVE_KRB4
+int bdump_auth_proto = 4;
+#else /* HAVE_KRB4 */
+int bdump_auth_proto = 0;
+#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB5 */
+
+#ifdef HAVE_KRB5
+krb5_ccache Z_krb5_ccache;
+krb5_keyblock *__Zephyr_keyblock;
+#else
+#ifdef HAVE_KRB4
+C_Block __Zephyr_session;
+#endif
+#endif
+
 int
 main(argc, argv)
     int argc;
@@ -142,6 +165,10 @@
     sprintf(srvtab_file, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_SRVTAB);
     sprintf(tkt_file, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_TKFILE);
 #endif
+#ifdef HAVE_KRB5
+    sprintf(keytab_file, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_KEYTAB);
+    sprintf(tkt5_file, "FILE:%s/zephyr/%s", SYSCONFDIR, ZEPHYR_TK5FILE);
+#endif
     sprintf(acl_dir, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_ACL_DIR);
     sprintf(subs_file, "%s/zephyr/%s", SYSCONFDIR, DEFAULT_SUBS_FILE);
 
@@ -150,7 +177,7 @@
     programname = (programname) ? programname + 1 : argv[0];
 
     /* process arguments */
-    while ((optchar = getopt(argc, argv, "dsnv:f:k:")) != EOF) {
+    while ((optchar = getopt(argc, argv, "dsnv4f:k:")) != EOF) {
 	switch(optchar) {
 	  case 'd':
 	    zdebug = 1;
@@ -175,6 +202,9 @@
 	    init_from_dump = 0;
 	    dumpfile = optarg;
 	    break;
+	case '4':
+	    bdump_auth_proto = 4;
+	    break;
 	  case '?':
 	  default:
 	    usage();
@@ -293,9 +323,6 @@
     /* Reinitialize t_local now that initialization is done. */
     gettimeofday(&t_local, NULL);
     uptime = NOW;
-#ifdef HAVE_KRB4
-    timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL);
-#endif
 
     realm_wakeup();
 #ifdef DEBUG_MALLOC
@@ -381,6 +408,20 @@
     
     ZSetServerState(1);
     ZInitialize();		/* set up the library */
+#ifdef HAVE_KRB5
+    krb5_cc_resolve(Z_krb5_ctx, tkt5_file, &Z_krb5_ccache);
+#ifdef HAVE_KRB5_CC_SET_DEFAULT_NAME
+    krb5_cc_set_default_name(Z_krb5_ctx, tkt5_file);
+#else
+    {
+	/* Hack to make krb5_cc_default do something reasonable */
+	char *env=(char *)malloc(strlen(tkt5_file)+12);
+	if (!env) return(1);
+	sprintf(env, "KRB5CCNAME=%s", tkt5_file);
+	putenv(env);
+    }
+#endif
+#endif
 #ifdef HAVE_KRB4
     /* Override what Zinitialize set for ZGetRealm() */
     if (*my_realm) 

Modified: trunk/athena/lib/zephyr/server/realm.c
===================================================================
--- trunk/athena/lib/zephyr/server/realm.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/realm.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -61,7 +61,7 @@
  *
  */
 static void realm_sendit __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, ZRealm *realm, int ack_to_sender));
-static void realm_sendit_auth __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, ZRealm *realm, int ack_to_sender));
+static Code_t realm_sendit_auth __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, ZRealm *realm, int ack_to_sender));
 static void rlm_ack __P((ZNotice_t *notice, Unacked *nacked));
 static void rlm_nack_cancel __P((ZNotice_t *notice, struct sockaddr_in *who));
 static void rlm_new_ticket __P(());
@@ -72,7 +72,6 @@
 #ifdef HAVE_KRB4
 static Code_t ticket_retrieve __P((ZRealm *realm));
 static int ticket_lookup __P((char *realm));
-static int ticket_expired __P((CREDENTIALS *cred));
 #endif
 
 static int
@@ -229,6 +228,7 @@
     }
     *rlm_list[nused].name = '\0';
   
+    fclose(fp);
     return(rlm_list);
 }
 
@@ -240,6 +240,7 @@
 	if (retval = (subscr_send_realm_subs(&otherrealms[cnt])) != ZERR_NONE)
 	    return(retval);
     }
+    return ZERR_NONE;
 }
 
 int
@@ -282,7 +283,7 @@
     return 0;
 }
 
-sender_in_realm(notice)
+int sender_in_realm(notice)
     ZNotice_t *notice;
 {
   char *realm;
@@ -557,9 +558,13 @@
 	    abort();
 	}
 	memset(&client->addr, 0, sizeof(struct sockaddr_in));
+#ifdef HAVE_KRB5
+        client->session_keyblock = NULL;
+#else
 #ifdef HAVE_KRB4
 	memset(&client->session_key, 0, sizeof(client->session_key));
 #endif
+#endif
 	sprintf(rlmprinc, "%s.%s@%s", SERVER_SERVICE, SERVER_INSTANCE, 
 		rlm->name);
 	client->principal = make_string(rlmprinc, 0);
@@ -619,14 +624,16 @@
 	zdbug((LOG_DEBUG, "rlm_deathgram: suggesting %s to %s", 
 	       (server) ? server->addr_str : "nothing", realm->name));
 
+#ifdef HAVE_KRB5
 	if (!ticket_lookup(realm->name))
 	    if ((retval = ticket_retrieve(realm)) != ZERR_NONE) {
 		syslog(LOG_WARNING, "rlm_deathgram failed: %s", 
 		       error_message(retval));
 		return;
 	    }
+#endif
 
-	if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZAUTH)) 
+	if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZCAUTH)) 
 	    != ZERR_NONE) 
 	{
 	    syslog(LOG_WARNING, "rlm_deathgram format: %s",
@@ -683,12 +690,14 @@
 	    snotice.z_message = NULL;
 	    snotice.z_message_len = 0;
 
+#ifdef HAVE_KRB5
 	    if (!ticket_lookup(realm->name))
 		if ((retval = ticket_retrieve(realm)) != ZERR_NONE) {
 		    syslog(LOG_WARNING, "rlm_wakeup failed: %s", 
 			   error_message(retval));
 		    continue;
 		}
+#endif
 
 	    if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZAUTH)) 
 		!= ZERR_NONE) 
@@ -893,7 +902,7 @@
     ZRealm *realm;
     int ack_to_sender;
 {
-#ifdef HAVE_KRB4
+#ifdef HAVE_KRB5
     Code_t retval;
 
     if (!auth) {
@@ -913,7 +922,7 @@
     
     zdbug((LOG_DEBUG, "realm_sendit to realm %s auth %d", realm->name, auth)); 
     /* valid ticket available now, send the message */
-    realm_sendit_auth(notice, who, auth, realm, ack_to_sender);
+    retval = realm_sendit_auth(notice, who, auth, realm, ack_to_sender);
 #else /* HAVE_KRB4 */
     realm_sendit(notice, who, auth, realm, ack_to_sender);
 #endif /* HAVE_KRB4 */
@@ -1095,8 +1104,8 @@
     }
 }
 
-#ifdef HAVE_KRB4
-static void
+#ifdef HAVE_KRB5
+static Code_t
 realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
     ZNotice_t *notice;
     int auth;
@@ -1111,33 +1120,27 @@
     Code_t retval;
     Unacked *nacked;
     char buf[1024], multi[64];
-    CREDENTIALS cred;
-    KTEXT_ST authent;
     ZNotice_t partnotice, newnotice;
 
     offset = 0;
 
-    /* build an authent. first, make sure we have the ticket available */
-    retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm->name, &cred);
-    if (retval != GC_OK) {
-	syslog(LOG_WARNING, "rlm_sendit_auth get_cred: %s",
-	       error_message(retval+krb_err_base));
-	return;
+    buffer = (char *) malloc(sizeof(ZPacket_t));
+    if (!buffer) {
+        syslog(LOG_ERR, "realm_sendit_auth malloc");
+        return ENOMEM;                 /* DON'T put on nack list */
     }
 
-    retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE, 
-			realm->name, 1);
-    if (retval != MK_AP_OK) {
-	syslog(LOG_WARNING, "rlm_sendit_auth mk_req: %s",
-	       error_message(retval+krb_err_base));
-	return;
-    }
+    buffer_len = sizeof(ZPacket_t);
 
-    retval = ZMakeAscii(buf, sizeof(buf), authent.dat, authent.length);
+    newnotice = *notice;
+
+    hdrlen = 0;
+    retval = ZMakeZcodeRealmAuthentication(&newnotice, buffer, buffer_len,
+					   &hdrlen, realm->name);
     if (retval != ZERR_NONE) {
-	syslog(LOG_WARNING, "rlm_sendit_auth mk_ascii: %s",
+	syslog(LOG_WARNING, "rlm_sendit_auth make zcksum: %s", 
 	       error_message(retval));
-	return;
+	return (retval);
     }
 
     /* set the dest addr */
@@ -1145,46 +1148,8 @@
     if (retval != ZERR_NONE) {
 	syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s", 
 	       error_message(retval));
-	return;
+	return (retval);
     }
-
-    /* now format the notice, refragmenting if needed */
-    newnotice = *notice;
-    newnotice.z_auth = 1;
-    newnotice.z_ascii_authent = buf;
-    newnotice.z_authent_len = authent.length;
-    
-    buffer = (char *) malloc(sizeof(ZPacket_t));
-    if (!buffer) {
-	syslog(LOG_ERR, "realm_sendit_auth malloc");
-	return;                 /* DON'T put on nack list */
-    }
-    
-    buffer_len = sizeof(ZPacket_t);
-    
-    retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, &ptr, 
-			       NULL);
-    if (retval != ZERR_NONE) {
-	syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
-	free(buffer);
-	return;
-    }
-
-#ifdef NOENCRYPTION
-    newnotice.z_checksum = 0;
-#else
-    newnotice.z_checksum =
-	(ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, 
-				    cred.session);
-#endif
-
-    retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, 
-			       NULL, NULL);
-    if (retval != ZERR_NONE) {
-	syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
-	free(buffer);
-	return;
-    }
   
     /* This is not terribly pretty, but it does do its job. 
      * If a packet we get that needs to get sent off to another realm is
@@ -1195,17 +1160,14 @@
      * but only the server uses it.
      */ 
 
-    if ((newnotice.z_message_len+hdrlen > buffer_len) || 
-	(newnotice.z_message_len+hdrlen > Z_MAXPKTLEN)) {
-	/* Deallocate buffer, use a local one */
+    if ((notice->z_message_len+hdrlen > buffer_len) || 
+	(notice->z_message_len+hdrlen > Z_MAXPKTLEN)) {
+
+	/* Reallocate buffers inside the refragmenter */
 	free(buffer);
-    
+
 	partnotice = *notice;
 
-	partnotice.z_auth = 1;
-	partnotice.z_ascii_authent = buf;
-	partnotice.z_authent_len = authent.length;
-
 	origoffset = 0;
 	origlen = notice->z_message_len;
 
@@ -1213,7 +1175,7 @@
 	    if (sscanf(notice->z_multinotice, "%d/%d", &origoffset, 
 		       &origlen) != 2) {
 		syslog(LOG_WARNING, "rlm_sendit_auth frag: parse failed");
-		return;
+		return ZERR_BADFIELD;
 	    }
 
 #if 0
@@ -1227,8 +1189,8 @@
 	    (void) sprintf(multi, "%d/%d", offset+origoffset, origlen);
 	    partnotice.z_multinotice = multi;
 	    if (offset > 0) {
-		(void) gettimeofday(&partnotice.z_uid.tv, 
-				    (struct timezone *)0);
+		(void) Z_gettimeofday(&partnotice.z_uid.tv, 
+				      (struct timezone *)0);
 		partnotice.z_uid.tv.tv_sec = htonl((u_long) 
 						   partnotice.z_uid.tv.tv_sec);
 		partnotice.z_uid.tv.tv_usec = 
@@ -1248,35 +1210,21 @@
 	    buffer = (char *) malloc(sizeof(ZPacket_t));
 	    if (!buffer) {
 		syslog(LOG_ERR, "realm_sendit_auth malloc");
-		return;                 /* DON'T put on nack list */
+		return ENOMEM;                 /* DON'T put on nack list */
 	    }
+
+	    buffer_len = sizeof(ZPacket_t);
 	    
-	    retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, 
-				       &hdrlen, &ptr, NULL);
+	    retval = ZMakeZcodeRealmAuthentication(&partnotice, buffer, 
+						   buffer_len, &hdrlen, 
+						   realm->name);
 	    if (retval != ZERR_NONE) {
-		syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", 
+		syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s", 
 		       error_message(retval));
 		free(buffer);
-		return;
+		return (retval);
 	    }
 
-#ifdef NOENCRYPTION
-	    partnotice.z_checksum = 0;
-#else
-	    partnotice.z_checksum =
-		(ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0, 
-					    cred.session);
-#endif
-
-	    retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len, 
-				       &hdrlen, NULL, NULL);
-	    if (retval != ZERR_NONE) {
-		syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", 
-		       error_message(retval));
-		free(buffer);
-		return;
-	    }
-
 	    ptr = buffer+hdrlen;
 
 	    (void) memcpy(ptr, partnotice.z_message, partnotice.z_message_len);
@@ -1288,14 +1236,14 @@
 		syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", 
 		       error_message(retval));
 		free(buffer);
-		return;
+		return(retval);
 	    }
 
 	    if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
 		/* no space: just punt */
 		syslog(LOG_ERR, "rlm_sendit_auth nack malloc");
 		free(buffer);
-		return;
+		return ENOMEM;
 	    }
 
 	    nacked->rexmits = 0;
@@ -1322,35 +1270,30 @@
 	    if (!notice->z_message_len)
 		break;
 	}
-#if 0
-	zdbug((LOG_DEBUG, "rlm_sendit_auth frag message sent"));
-#endif
-    } else {
+    }
+    else {
 	/* This is easy, no further fragmentation needed */
 	ptr = buffer+hdrlen;
 
 	(void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
 
-	buffer_len = hdrlen+newnotice.z_message_len;
+        buffer_len = hdrlen+newnotice.z_message_len;
     
 	/* now send */
 	if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) {
 	    syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s", 
 		   error_message(retval));
 	    free(buffer);
-	    return;
+	    return(retval);
 	}
 
-#if 0
-	zdbug((LOG_DEBUG, "rlm_sendit_auth message sent"));
-#endif
 	/* now we've sent it, mark it as not ack'ed */
     
 	if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
 	    /* no space: just punt */
 	    syslog(LOG_ERR, "rlm_sendit_auth nack malloc");
 	    free(buffer);
-	    return;
+	    return 0;
 	}
 
 	nacked->rexmits = 0;
@@ -1371,33 +1314,52 @@
 	/* chain in */
 	LIST_INSERT(&rlm_nacklist, nacked);
     }
-    return;
+    return 0;
 }
 
 static int
-ticket_expired(cred)
-CREDENTIALS *cred;
-{
-#ifdef HAVE_KRB_LIFE_TO_TIME
-    return (krb_life_to_time(cred->issue_date, cred->lifetime) < NOW);
-#else /* HAVE_KRB_LIFE_TO_TIME */
-    return (cred->issue_date + cred->lifetime*5*60 < NOW);
-#endif /* HAVE_KRB_LIFE_TO_TIME */
-}
-
-static int
 ticket_lookup(realm)
 char *realm;
 {
-    CREDENTIALS cred;
-    KTEXT_ST authent;
-    int retval;
+    krb5_error_code result;
+    krb5_timestamp sec;
+    krb5_ccache ccache; 
+    krb5_creds creds_in, *creds; 
 
-    retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm, &cred);
-    if (retval == GC_OK && !ticket_expired(&cred))
-	/* good ticket */
-	return(1);
+    result = krb5_cc_default(Z_krb5_ctx, &ccache); 
+    if (result) 
+      return 0;
 
+    memset(&creds_in, 0, sizeof(creds_in)); 
+ 
+    result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client); 
+    if (result) {
+      krb5_cc_close(Z_krb5_ctx, ccache);
+      return 0;
+    }
+
+    result = krb5_build_principal(Z_krb5_ctx, &creds_in.server, 
+                                  strlen(realm), 
+                                  realm, 
+                                  SERVER_KRB5_SERVICE, SERVER_INSTANCE, 0); 
+    if (result) {
+      krb5_cc_close(Z_krb5_ctx, ccache);
+      return 0;
+    }
+
+    result = krb5_get_credentials(Z_krb5_ctx, 0 /* flags */, ccache, 
+                                  &creds_in, &creds); 
+    krb5_cc_close(Z_krb5_ctx, ccache);
+    /* good ticket? */
+
+    krb5_timeofday (Z_krb5_ctx, &sec);
+    krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */ 
+    if ((result == 0) && (sec < creds->times.endtime)) {
+      krb5_free_creds(Z_krb5_ctx, creds);
+      return (1);
+    }
+    if (!result) krb5_free_creds(Z_krb5_ctx, creds);
+
     return (0);
 }
 
@@ -1405,27 +1367,50 @@
 ticket_retrieve(realm)
     ZRealm *realm;
 {
-    int pid, retval = 0;
-    KTEXT_ST authent;
+    int pid;
+    krb5_ccache ccache;
+    krb5_error_code result; 
+    krb5_auth_context authctx; 
+    krb5_creds creds_in, *creds; 
     
     get_tgt();
 
     if (realm->child_pid) 
 	/* Right idea. Basically, we haven't gotten it yet */
-	return KRBET_KDC_AUTH_EXP;
+	return KRB5KRB_AP_ERR_TKT_EXPIRED;
 
-    /* For Putrify */
-    memset(&authent.dat,0,MAX_KTXT_LEN);
-    authent.mbz=0;
+    if (realm->have_tkt) {
+	/* Get a pointer to the default ccache. We don't need to free this. */ 
+	result = krb5_cc_default(Z_krb5_ctx, &ccache); 
 
-    if (realm->have_tkt) {
-	retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
-			    realm->name, 0);
-	if (retval == KSUCCESS) {
-	    return retval;
+	/* GRRR.  There's no allocator or constructor for krb5_creds */ 
+	/* GRRR.  It would be nice if this API were documented at all */ 
+	memset(&creds_in, 0, sizeof(creds_in)); 
+ 
+	if (!result) 
+	    result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client); 
+	/* construct the service principal */ 
+	if (!result)  
+	    result = krb5_build_principal(Z_krb5_ctx, &creds_in.server, 
+					  strlen(realm->name), realm->name, 
+					  SERVER_KRB5_SERVICE, SERVER_INSTANCE, 
+					  0); 
+
+	/* HOLDING: creds_in.server */ 
+     
+	/* look up or get the credentials we need */ 
+	if (!result) 
+	    result = krb5_get_credentials(Z_krb5_ctx, 0 /* flags */, ccache, 
+					  &creds_in, &creds); 
+	krb5_cc_close(Z_krb5_ctx, ccache);
+	krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */ 
+	if (!result) {
+	    krb5_free_creds(Z_krb5_ctx, creds); 
+	    return 0; 
 	}
     } else {
 	syslog(LOG_ERR, "tkt_rtrv: don't have ticket, but have no child");
+        result = KRB5KRB_AP_ERR_TKT_EXPIRED;
     }
  
     pid = fork();
@@ -1463,11 +1448,37 @@
 #endif
 #endif
 
+	syslog(LOG_INFO, "tkt_rtrv running for %s", realm->name);
 	while (1) {
-	    retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
-				realm->name, 0);
-	    if (retval == KSUCCESS)
+	    /* Get a pointer to the default ccache. We don't need to free this. */ 
+	    result = krb5_cc_default(Z_krb5_ctx, &ccache); 
+
+	    /* GRRR.  There's no allocator or constructor for krb5_creds */ 
+	    /* GRRR.  It would be nice if this API were documented at all */ 
+	    memset(&creds_in, 0, sizeof(creds_in)); 
+ 
+	    if (!result) 
+		result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client); 
+	    /* construct the service principal */ 
+	    if (!result)  
+		result = krb5_build_principal(Z_krb5_ctx, &creds_in.server, 
+					      strlen(realm->name), realm->name, 
+					      SERVER_KRB5_SERVICE, SERVER_INSTANCE, 
+					      0); 
+
+	    /* HOLDING: creds_in.server */ 
+	    
+	    /* look up or get the credentials we need */ 
+	    if (!result) 
+		result = krb5_get_credentials(Z_krb5_ctx, 0 /* flags */, ccache, 
+					      &creds_in, &creds); 
+	    krb5_cc_close(Z_krb5_ctx, ccache);
+	    krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */ 
+	    if (!result) {
+		krb5_free_creds(Z_krb5_ctx, creds); 
+		syslog(LOG_INFO, "tkt_rtrv succeeded for %s", realm->name);
 		exit(0);
+	    }
       
 	    /* Sleep a little while before retrying */
 	    sleep(30);
@@ -1475,11 +1486,11 @@
     } else {
 	realm->child_pid = pid;
 	realm->have_tkt = 0;
-	
-	syslog(LOG_WARNING, "tkt_rtrv: %s: %s", realm->name,
-	       krb_err_txt[retval]);
-	return (retval+krb_err_base);
+
+	syslog(LOG_WARNING, "tkt_rtrv: %s: %d", realm->name,
+	       result);
+	return (result);
     }
 }
-#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB5 */
 

Modified: trunk/athena/lib/zephyr/server/server.c
===================================================================
--- trunk/athena/lib/zephyr/server/server.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/server.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -1405,7 +1405,7 @@
 	    syslog(LOG_CRIT, "srv_fwd malloc");
 	    abort();
 	}
-	retval = ZFormatSmallRawNotice(notice, pack, &packlen);
+	retval = ZNewFormatSmallRawNotice(notice, pack, &packlen);
 	if (retval != ZERR_NONE) {
 	    syslog(LOG_WARNING, "srv_fwd format: %s", error_message(retval));
 	    continue;

Modified: trunk/athena/lib/zephyr/server/subscr.c
===================================================================
--- trunk/athena/lib/zephyr/server/subscr.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/subscr.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -187,18 +187,13 @@
 	    }
 	}
 	if (realm && !bdumping) {
-	    if (server && server == me_server) {
-	        retval = subscr_realm_sendit(who, subs, notice, realm);
-	        if (retval != ZERR_NONE) {
-		    free_subscriptions(subs);
-		    free_string(sender);
-		    return(retval);
-		} else {
-		    /* free this one, will get from ADD */
-		    free_subscription(subs);
-		}
+	    retval = subscr_realm_sendit(who, subs, notice, realm);
+	    if (retval != ZERR_NONE) {
+		free_subscription(subs);
+		continue; /* the for loop */
 	    } else {
-	            /* Indicates we leaked traffic back to our realm */
+		/* Indicates we leaked traffic back to our realm */
+		free_subscription(subs); /* free this one, wil get from ADD */
 	    }
 	} else {
 	  retval = triplet_register(who, &subs->dest, NULL);
@@ -842,10 +837,15 @@
 {
     int i = 0;
     Destlist *subs;
+#ifdef HAVE_KRB5
+    char buf[512];
+    char *bufp;
+#else
 #ifdef HAVE_KRB4
     char buf[512];
     C_Block cblock;
 #endif /* HAVE_KRB4 */
+#endif
     char buf2[512];
     char *list[7 * NUM_FIELDS];
     int num = 0;
@@ -858,14 +858,45 @@
 
     list[num++] = buf2;
 
+#ifdef HAVE_KRB5
+#ifdef HAVE_KRB4 /* XXX make this optional for server transition time */
+    if (Z_enctype(client->session_keyblock) == ENCTYPE_DES_CBC_CRC) {
+	bufp = malloc(Z_keylen(client->session_keyblock));
+	if (bufp == NULL) {
+	    syslog(LOG_WARNING, "subscr_send_subs: cannot allocate memory for DES keyblock: %m");
+	    return errno;
+	}
+	des_ecb_encrypt(Z_keydata(client->session_keyblock), bufp, serv_ksched.s, DES_ENCRYPT);
+	retval = ZMakeAscii(buf, sizeof(buf), bufp, Z_keylen(client->session_keyblock));
+    } else {
+#endif
+	bufp = malloc(Z_keylen(client->session_keyblock) + 8); /* + enctype
+								+ length */
+	if (bufp == NULL) {
+	    syslog(LOG_WARNING, "subscr_send_subs: cannot allocate memory for keyblock: %m");
+	    return errno;
+	}
+	*(krb5_enctype *)&bufp[0] = htonl(Z_enctype(client->session_keyblock));
+	*(u_int32_t *)&bufp[4] = htonl(Z_keylen(client->session_keyblock));
+	memcpy(&bufp[8], Z_keydata(client->session_keyblock), Z_keylen(client->session_keyblock));
+
+	retval = ZMakeZcode(buf, sizeof(buf), bufp, Z_keylen(client->session_keyblock) + 8);
 #ifdef HAVE_KRB4
+    }
+#endif /* HAVE_KRB4 */
+#else /* HAVE_KRB5 */
+#ifdef HAVE_KRB4
 #ifdef NOENCRYPTION
     memcpy(cblock, client->session_key, sizeof(C_Block));
-#else
+#else /* NOENCRYPTION */
     des_ecb_encrypt(client->session_key, cblock, serv_ksched.s, DES_ENCRYPT);
-#endif
+#endif /* NOENCRYPTION */
 
     retval = ZMakeAscii(buf, sizeof(buf), cblock, sizeof(C_Block));
+#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB5 */    
+
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
     if (retval != ZERR_NONE) {
 #if 0
 	zdbug((LOG_DEBUG,"zmakeascii failed: %s", error_message(retval)));
@@ -876,7 +907,7 @@
 	zdbug((LOG_DEBUG, "cblock %s", buf));
 #endif
     }		
-#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB4 || HAVE_KRB5*/
     retval = bdump_send_list_tcp(SERVACK, &client->addr, ZEPHYR_ADMIN_CLASS,
 				 num > 1 ? "CBLOCK" : "", ADMIN_NEWCLT,
 				 client->principal->string, "", list, num);

Modified: trunk/athena/lib/zephyr/server/uloc.c
===================================================================
--- trunk/athena/lib/zephyr/server/uloc.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/uloc.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -241,7 +241,12 @@
 		login_sendit(notice, auth, who, 1);
 	}
     } else {
-	syslog(LOG_ERR, "unknown ulog opcode %s", notice->z_opcode);
+	if (!strcmp(notice->z_opcode, LOGIN_USER_LOGIN)) {
+	    zdbug((LOG_DEBUG, "ulog opcode from unknown foreign realm %s", 
+		   notice->z_opcode));
+	} else {
+	    syslog(LOG_ERR, "unknown ulog opcode %s", notice->z_opcode);
+	}
 	if (server == me_server)
 	    nack(notice, who);
 	return ZERR_NONE;
@@ -441,6 +446,7 @@
 	  default:
 	    syslog(LOG_ERR,"broken location state %s/%d",
 		   loc->user->string, (int) loc->exposure);
+	    exposure_level = EXPOSE_OPSTAFF;
 	    break;
 	}
 	retval = bdump_send_list_tcp(ACKED, &loc->addr, LOGIN_CLASS,
@@ -1085,6 +1091,11 @@
   lnotice = *notice;
   lnotice.z_opcode = LOCATE_LOCATE;
   lnotice.z_kind = ACKED;
+  lnotice.z_auth = 0;
+  lnotice.z_authent_len = 0;
+  lnotice.z_ascii_authent = "";
+  lnotice.z_checksum = 0;
+  lnotice.z_ascii_checksum = "";
   
   if ((retval = ZFormatRawNotice(&lnotice, &pack, &packlen)) != ZERR_NONE) {
     syslog(LOG_WARNING, "ulog_relay_loc format: %s",

Modified: trunk/athena/lib/zephyr/server/zserver.h
===================================================================
--- trunk/athena/lib/zephyr/server/zserver.h	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/zserver.h	2008-04-03 17:51:46 UTC (rev 22814)
@@ -17,6 +17,9 @@
 #include <zephyr/mit-copyright.h>
 
 #include <internal.h>
+
+#include <com_err.h>
+
 #include <arpa/inet.h>
 
 #include "zsrv_err.h"
@@ -28,10 +31,21 @@
 #include "access.h"
 #include "acl.h"
 
-#ifdef HAVE_KRB4
+#if defined(HAVE_KRB5) || defined(HAVE_KRB4)
 /* Kerberos-specific library interfaces used only by the server. */
+#ifdef HAVE_KRB5
+extern krb5_keyblock *__Zephyr_keyblock;
+#define ZGetSession() (__Zephyr_keyblock)
+void ZSetSession(krb5_keyblock *keyblock);
+Code_t ZFormatAuthenticNoticeV5 __P((ZNotice_t*, char*, int, int*, krb5_keyblock *));
+krb5_error_code Z_krb5_init_keyblock(krb5_context, krb5_enctype, size_t,
+        krb5_keyblock **);
+#else
 extern C_Block __Zephyr_session;
 #define ZGetSession() (__Zephyr_session)
+#endif
+void ZSetSessionDES(C_Block *key);
+
 Code_t ZFormatAuthenticNotice __P((ZNotice_t*, char*, int, int*, C_Block));
 #endif
 
@@ -120,9 +134,13 @@
 struct _Client {
     struct sockaddr_in	addr;		/* ipaddr/port of client */
     Destlist		*subs	;	/* subscriptions */
+#ifdef HAVE_KRB5
+    krb5_keyblock       *session_keyblock;
+#else
 #ifdef HAVE_KRB4
     C_Block		session_key;	/* session key for this client */
 #endif /* HAVE_KRB4 */
+#endif
     String		*principal;	/* krb principal of user */
     int			last_send;	/* Counter for last sent packet. */
     time_t		last_ack;	/* Time of last received ack */
@@ -268,9 +286,6 @@
 #ifndef NOENCRYPTION
 Sched *check_key_sched_cache __P((des_cblock key));
 void add_to_key_sched_cache __P((des_cblock key, Sched *sched));
-int krb_set_key __P((char *key, int cvt));
-int krb_rd_req __P((KTEXT authent, char *service, char *instance,
-		    unsigned KRB_INT32 from_addr, AUTH_DAT *ad, char *fn));
 int krb_find_ticket __P((KTEXT authent, KTEXT ticket));
 int krb_get_lrealm __P((char *r, int n));
 #endif
@@ -355,6 +370,10 @@
 extern int zdebug;
 extern char myname[];			/* domain name of this host */
 extern char list_file[];
+#ifdef HAVE_KRB5
+extern char keytab_file[];
+extern krb5_ccache Z_krb5_ccache;
+#endif
 #ifdef HAVE_KRB4
 extern char srvtab_file[];
 extern char my_realm[];

Modified: trunk/athena/lib/zephyr/server/zsrv_conf.h
===================================================================
--- trunk/athena/lib/zephyr/server/zsrv_conf.h	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/server/zsrv_conf.h	2008-04-03 17:51:46 UTC (rev 22814)
@@ -18,6 +18,10 @@
 
 #define SERVER_LIST_FILE	"server.list"
 #define REALM_LIST_FILE		"realm.list"
+#ifdef HAVE_KRB5
+#define ZEPHYR_KEYTAB		"krb5.keytab"
+#define ZEPHYR_TK5FILE		"z5tkts"
+#endif
 #ifdef HAVE_KRB4
 #define ZEPHYR_SRVTAB		"srvtab"
 #define ZEPHYR_TKFILE		"ztkts"

Modified: trunk/athena/lib/zephyr/zhm/zhm_client.c
===================================================================
--- trunk/athena/lib/zephyr/zhm/zhm_client.c	2008-04-03 17:32:17 UTC (rev 22813)
+++ trunk/athena/lib/zephyr/zhm/zhm_client.c	2008-04-03 17:51:46 UTC (rev 22814)
@@ -74,7 +74,7 @@
 	    Zperr(ret);
 	    com_err("hm", ret, "setting destination");
 	}
-	if ((ret = send_outgoing(notice)) != ZERR_NONE) {
+	if ((ret = ZSendPacket(packet, pak_len, 0)) != ZERR_NONE) {
 	    Zperr(ret);
 	    com_err("hm", ret, "while sending raw notice");
 	}


home help back first fref pref prev next nref lref last post