Tidy up UKERNEL includes
[openafs.git] / src / auth / ktc.c
index 531ee60..bb885be 100644 (file)
 /* ticket caching code */
 
 #include <afsconfig.h>
-#if defined(UKERNEL)
-#include "afs/param.h"
-#else
 #include <afs/param.h>
-#endif
-
-RCSID
-    ("$Header$");
 
 #if defined(UKERNEL)
-#include "afs/sysincludes.h"
 #include "afsincludes.h"
-#include "afs/stds.h"
-#include "afs/pthread_glock.h"
-#include "afs/vice.h"
-#include "afs/auth.h"
-#include "afs/venus.h"
-#include "afs/pthread_glock.h"
-#include "afs/dirpath.h"
-
-#if !defined(min)
-#define min(a,b) ((a)<(b)?(a):(b))
-#endif /* !defined(min) */
-
-#else /* defined(UKERNEL) */
+#endif
 
 #ifdef AFS_SUN5_ENV
 #include <unistd.h>
 #endif
 #include <stdio.h>
+#include <stdlib.h>
 #include <afs/stds.h>
 #include <afs/pthread_glock.h>
 #include <sys/types.h>
@@ -49,29 +30,39 @@ RCSID
 #include <errno.h>
 #include <sys/ioctl.h>
 #include <netinet/in.h>
-#ifdef HAVE_STRING_H
 #include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
 #include <afs/vice.h>
 #ifdef AFS_AIX_ENV
 #include <sys/lockf.h>
+#ifdef AFS_AIX51_ENV
+#include <sys/cred.h>
+#ifdef HAVE_SYS_PAG_H
+#include <sys/pag.h>
+#endif
+#endif
+#endif
+#ifdef AFS_DARWIN100_ENV
+#include <crt_externs.h>
 #endif
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
-#include "auth.h"
+#include <afs/auth.h>
 #include <afs/venus.h>
 #include <afs/afsutil.h>
 
-#endif /* defined(UKERNEL) */
+#if !defined(UKERNEL)
+#include <afs/sys_prototypes.h>
+#endif
+
+#if defined(LINUX_KEYRING_SUPPORT) && defined(HAVE_SESSION_TO_PARENT)
+#include <sys/syscall.h>
+#define KEYCTL_SESSION_TO_PARENT        18
+#endif
 
 /* For malloc() */
 #include <stdlib.h>
-
+#include "ktc.h"
 
 #ifdef notdef
 /* AFS_KERBEROS_ENV is now conditionally defined in the Makefile */
@@ -81,7 +72,7 @@ RCSID
 #ifdef AFS_KERBEROS_ENV
 #include <fcntl.h>
 #include <sys/file.h>
-#include "cellconfig.h"
+#include <afs/cellconfig.h>
 static char lcell[MAXCELLCHARS];
 
 #define TKT_ROOT "/tmp/tkt"
@@ -128,11 +119,16 @@ static struct flock fileUlock = { F_UNLCK, 0, 0, 0, 0 };
 /* the following routines aren't static anymore on behalf of the kerberos IV
  * compatibility library built in subtree krb.
  */
-int afs_tf_init(), afs_tf_get_pname(), afs_tf_get_pinst(), afs_tf_get_cred();
-int afs_tf_save_cred(), afs_tf_close(), afs_tf_create();
-int afs_tf_dest_tkt();
-static void ktc_LocalCell();
-char *ktc_tkt_string();
+int afs_tf_init(char *, int);
+int afs_tf_get_pname(char *);
+int afs_tf_get_pinst(char *);
+int afs_tf_get_cred(struct ktc_principal *, struct ktc_token *);
+int afs_tf_save_cred(struct ktc_principal *, struct ktc_token *, 
+                    struct ktc_principal *);
+int afs_tf_close(void);
+int afs_tf_create(char *, char *);
+int afs_tf_dest_tkt(void);
+static void ktc_LocalCell(void);
 #endif /* AFS_KERBEROS_ENV */
 
 #ifdef AFS_DUX40_ENV
@@ -143,86 +139,6 @@ char *ktc_tkt_string();
 #define PIOCTL pioctl
 #endif
 
-
-#ifdef KERNEL_KTC_COMPAT
-
-#ifndef KTC_SYSCALL
-#define KTC_SYSCALL    32
-#endif
-
-/* Kernel call opcode definitions */
-#define KTC_OPCODE_BASE                4300
-#define KTC_NO_OP              (0+KTC_OPCODE_BASE)
-#define KTC_SETTOKEN_OP        (1+KTC_OPCODE_BASE)
-#define KTC_GETTOKEN_OP        (2+KTC_OPCODE_BASE)
-#define KTC_LISTTOKENS_OP      (3+KTC_OPCODE_BASE)
-#define KTC_FORGETTOKEN_OP     (4+KTC_OPCODE_BASE)
-#define KTC_FORGETALLTOKENS_OP  (5+KTC_OPCODE_BASE)
-#define KTC_STATUS_OP          (6+KTC_OPCODE_BASE)
-#define KTC_GC_OP              (7+KTC_OPCODE_BASE)
-
-#define KTC_INTERFACE_VERSION 3
-
-/* We have to determine if the kernel supports the ktc system call.  To do so
- * we attempt to execute its noop function.  If this is successful we use the
- * kernel calls in the future otherwise we let the old code run. */
-
-/* To safely check to see whether a system call exists we have to intercept the
- * SIGSYS signal which is caused by executing a non-existant system call.  If
- * it is ignored the syscall routine returns EINVAL.  The SIGSYS is reset to
- * its old value after the return from syscall.  */
-
-static int kernelKTC = 0;
-
-#ifdef AFS_DECOSF_ENV
-/*
- * SIGSYS semantics are broken on Dec AXP OSF/1 v1.2 systems.  You need
- * to ignore SIGTRAP too.  It is claimed to be fixed under v1.3, but...
- */
-
-#define CHECK_KERNEL                                                           \
-    if (kernelKTC == 0) {                                              \
-       int code, ecode;                                                \
-       int (*old)();                                                   \
-       int (*old_t)();                                                 \
-       old = (int (*)())signal(SIGSYS, SIG_IGN);                       \
-       old_t = (int (*)())signal(SIGTRAP, SIG_IGN);                    \
-       code = syscall (KTC_SYSCALL, KTC_NO_OP, 0,0,0,0,0);             \
-       ecode = errno;                                                  \
-       signal(SIGSYS, old);                                            \
-       signal(SIGTRAP, old_t);                                         \
-       if (code == 0) kernelKTC = 1;                                   \
-       else kernelKTC = 2;                                             \
-/* printf ("returned from KTC_NO_OP kernelKTC <= %d; code=%d, errno=%d\n", kernelKTC, code, errno); */\
-    }
-
-#else /* AFS_DECOSF_ENV */
-
-#define CHECK_KERNEL                                                           \
-    if (kernelKTC == 0) {                                              \
-       int code, ecode;                                                \
-       int (*old)();                                                   \
-       old = (int (*)())signal(SIGSYS, SIG_IGN);                       \
-       code = syscall (KTC_SYSCALL, KTC_NO_OP, 0,0,0,0,0);             \
-       ecode = errno;                                                  \
-       signal(SIGSYS, old);                                            \
-       if (code == 0) kernelKTC = 1;                                   \
-       else kernelKTC = 2;                                             \
-/* printf ("returned from KTC_NO_OP kernelKTC <= %d; code=%d, errno=%d\n", kernelKTC, code, errno); */\
-    }
-#endif /* AFS_DECOSF_ENV */
-
-#define TRY_KERNEL(cmd,a1,a2,a3,a4)                                    \
-{   CHECK_KERNEL;                                                      \
-    if (kernelKTC == 1)                                                        \
-       return syscall (KTC_SYSCALL, cmd,                               \
-                       KTC_INTERFACE_VERSION, a1,a2,a3,a4);            \
-}
-
-#else
-#define TRY_KERNEL(cmd,a1,a2,a3,a4)
-#endif /* KERNEL_KTC_COMPAT */
-
 #if !defined(UKERNEL)
 /* this is a structure used to communicate with the afs cache mgr, but is
  * otherwise irrelevant */
@@ -248,30 +164,13 @@ static struct {
 0}, {
 0}};
 
-/* new interface routines to the ticket cache.  Only handle afs service right
- * now. */
-
-static int
-NewSetToken(aserver, atoken, aclient, flags)
-     struct ktc_principal *aserver;
-     struct ktc_principal *aclient;
-     struct ktc_token *atoken;
-     afs_int32 flags;
-{
-    TRY_KERNEL(KTC_SETTOKEN_OP, aserver, aclient, atoken,
-              sizeof(struct ktc_token));
-    /* no kernel ticket cache */
-    return EINVAL;
-}
 
 #define MAXPIOCTLTOKENLEN \
 (3*sizeof(afs_int32)+MAXKTCTICKETLEN+sizeof(struct ClearToken)+MAXKTCREALMLEN)
 
 static int
-OldSetToken(aserver, atoken, aclient, flags)
-     struct ktc_principal *aserver, *aclient;
-     struct ktc_token *atoken;
-     afs_int32 flags;
+SetToken(struct ktc_principal *aserver, struct ktc_token *atoken,
+           struct ktc_principal *aclient, afs_int32 flags)
 {
     struct ViceIoctl iob;
     char tbuffer[MAXPIOCTLTOKENLEN];
@@ -353,8 +252,8 @@ OldSetToken(aserver, atoken, aclient, flags)
     /*
      * Information needed by the user space cache manager
      */
-    u.u_expiration = ct.EndTimestamp;
-    u.u_viceid = ct.ViceId;
+    get_user_struct()->u_expiration = ct.EndTimestamp;
+    get_user_struct()->u_viceid = ct.ViceId;
 #endif
 
     temp = sizeof(struct ClearToken);
@@ -409,20 +308,27 @@ OldSetToken(aserver, atoken, aclient, flags)
     }
 #else /* NO_AFS_CLIENT */
     code = PIOCTL(0, VIOCSETTOK, &iob, 0);
+#if defined(LINUX_KEYRING_SUPPORT) && defined(HAVE_SESSION_TO_PARENT)
+    /*
+     * If we're using keyring based PAGs and the SESSION_TO_PARENT keyctl
+     * is available, use it to copy the session keyring to the parent process
+     */
+    if (flags & AFS_SETTOK_SETPAG)
+       syscall(SYS_keyctl, KEYCTL_SESSION_TO_PARENT);
+#endif
 #endif /* NO_AFS_CLIENT */
     if (code)
        return KTC_PIOCTLFAIL;
     return 0;
 }
 
-
-ktc_SetToken(aserver, atoken, aclient, flags)
-     struct ktc_principal *aserver;
-     struct ktc_principal *aclient;
-     struct ktc_token *atoken;
-     afs_int32 flags;
+int
+ktc_SetToken(struct ktc_principal *aserver,
+    struct ktc_token *atoken,
+    struct ktc_principal *aclient,
+    afs_int32 flags)
 {
-    int ncode, ocode;
+    int code;
 
     LOCK_GLOBAL_MUTEX;
 #ifdef AFS_KERBEROS_ENV
@@ -442,41 +348,36 @@ ktc_SetToken(aserver, atoken, aclient, flags)
            }
        }
 
-       ncode = afs_tf_init(ktc_tkt_string(), W_TKT_FIL);
-       if (ncode == NO_TKT_FIL) {
+       code = afs_tf_init(ktc_tkt_string(), W_TKT_FIL);
+       if (code == NO_TKT_FIL) {
            (void)afs_tf_create(aclient->name, aclient->instance);
-           ncode = afs_tf_init(ktc_tkt_string(), W_TKT_FIL);
+           code = afs_tf_init(ktc_tkt_string(), W_TKT_FIL);
        }
 
-       if (!ncode) {
+       if (!code) {
            afs_tf_save_cred(aserver, atoken, aclient);
        }
        afs_tf_close();
 #ifdef NO_AFS_CLIENT
        UNLOCK_GLOBAL_MUTEX;
-       return ncode;
+       return code;
 #endif /* NO_AFS_CLIENT */
     }
 #endif
 
 #ifndef NO_AFS_CLIENT
-    ncode = NewSetToken(aserver, atoken, aclient, flags);
-    if (ncode ||               /* new style failed */
-       (strcmp(aserver->name, "afs") == 0)) {  /* for afs tokens do both */
-       ocode = OldSetToken(aserver, atoken, aclient, flags);
-    } else
-       ocode = 0;
-    if (ncode && ocode) {
+    code = SetToken(aserver, atoken, aclient, flags);
+    if (code) {
        UNLOCK_GLOBAL_MUTEX;
-       if (ocode == -1)
-           ocode = errno;
-       else if (ocode == KTC_PIOCTLFAIL)
-           ocode = errno;
-       if (ocode == ESRCH)
+       if (code == -1)
+           code = errno;
+       else if (code == KTC_PIOCTLFAIL)
+           code = errno;
+       if (code == ESRCH)
            return KTC_NOCELL;
-       if (ocode == EINVAL)
+       if (code == EINVAL)
            return KTC_NOPIOCTL;
-       if (ocode == EIO)
+       if (code == EIO)
            return KTC_NOCM;
        return KTC_PIOCTLFAIL;
     }
@@ -488,14 +389,13 @@ ktc_SetToken(aserver, atoken, aclient, flags)
 /* get token, given server we need and token buffer.  aclient will eventually
  * be set to our identity to the server.
  */
-ktc_GetToken(aserver, atoken, atokenLen, aclient)
-     struct ktc_principal *aserver, *aclient;
-     int atokenLen;
-     struct ktc_token *atoken;
+int
+ktc_GetToken(struct ktc_principal *aserver, struct ktc_token *atoken, 
+            int atokenLen, struct ktc_principal *aclient)
 {
     struct ViceIoctl iob;
     char tbuffer[MAXPIOCTLTOKENLEN];
-    register afs_int32 code;
+    register afs_int32 code = 0;
     int index;
     char *stp, *cellp;         /* secret token ptr */
     struct ClearToken ct;
@@ -503,12 +403,11 @@ ktc_GetToken(aserver, atoken, atokenLen, aclient)
     afs_int32 temp;
     int maxLen;                        /* biggest ticket we can copy */
     int tktLen;                        /* server ticket length */
+#ifdef AFS_KERBEROS_ENV
     char found = 0;
+#endif
 
     LOCK_GLOBAL_MUTEX;
-#ifndef NO_AFS_CLIENT
-    TRY_KERNEL(KTC_GETTOKEN_OP, aserver, aclient, atoken, atokenLen);
-#endif /* NO_AFS_CLIENT */
 
 #ifdef AFS_KERBEROS_ENV
     if (!lcell[0])
@@ -541,8 +440,8 @@ ktc_GetToken(aserver, atoken, atokenLen, aclient)
                    found = 1;
            } else {
                char tmpstring[MAXHOSTCHARS];
-               afs_tf_get_pname(&tmpstring);
-               afs_tf_get_pinst(&tmpstring);
+               afs_tf_get_pname(tmpstring);
+               afs_tf_get_pinst(tmpstring);
                found = 1;
            }
        }
@@ -672,14 +571,12 @@ ktc_GetToken(aserver, atoken, atokenLen, aclient)
  * NOT IMPLEMENTED YET!
  */
 #ifndef NO_AFS_CLIENT
-ktc_ForgetToken(aserver)
-     struct ktc_principal *aserver;
+int
+ktc_ForgetToken(struct ktc_principal *aserver)
 {
     int rc;
 
     LOCK_GLOBAL_MUTEX;
-    TRY_KERNEL(KTC_FORGETTOKEN_OP, aserver, 0, 0, 0);
-
     rc = ktc_ForgetAllTokens();        /* bogus, but better */
     UNLOCK_GLOBAL_MUTEX;
     return rc;
@@ -690,22 +587,20 @@ ktc_ForgetToken(aserver)
  * next rock in (*aindex).  (*aserver) is set to the relevant ticket on
  * success.  */
 
-ktc_ListTokens(aprevIndex, aindex, aserver)
-     int aprevIndex, *aindex;
-     struct ktc_principal *aserver;
+int
+ktc_ListTokens(int aprevIndex,
+    int *aindex,
+    struct ktc_principal *aserver)
 {
     struct ViceIoctl iob;
     char tbuffer[MAXPIOCTLTOKENLEN];
-    register afs_int32 code;
+    register afs_int32 code = 0 ;
     register char *tp;
     afs_int32 temp, index;
 
     memset(tbuffer, 0, sizeof(tbuffer));
 
     LOCK_GLOBAL_MUTEX;
-#ifndef NO_AFS_CLIENT
-    TRY_KERNEL(KTC_LISTTOKENS_OP, aserver, aprevIndex, aindex, 0);
-#endif /* NO_AFS_CLIENT */
 
     index = aprevIndex;
 #ifdef NO_AFS_CLIENT
@@ -839,19 +734,8 @@ ktc_ListTokens(aprevIndex, aindex, aserver)
     return 0;
 }
 
-/* discard all tokens from this user's cache */
-
 static int
-NewForgetAll()
-{
-#ifndef NO_AFS_CLIENT
-    TRY_KERNEL(KTC_FORGETALLTOKENS_OP, 0, 0, 0, 0);
-#endif /* NO_AFS_CLIENT */
-    return EINVAL;
-}
-
-static int
-OldForgetAll()
+ForgetAll(void)
 {
     struct ViceIoctl iob;
     register afs_int32 code;
@@ -873,18 +757,17 @@ OldForgetAll()
 }
 
 int
-ktc_ForgetAllTokens()
+ktc_ForgetAllTokens(void)
 {
-    int ncode, ocode;
+    int ocode;
 
     LOCK_GLOBAL_MUTEX;
 #ifdef AFS_KERBEROS_ENV
     (void)afs_tf_dest_tkt();
 #endif
 
-    ncode = NewForgetAll();
-    ocode = OldForgetAll();
-    if (ncode && ocode) {
+    ocode = ForgetAll();
+    if (ocode) {
        if (ocode == -1)
            ocode = errno;
        else if (ocode == KTC_PIOCTLFAIL)
@@ -901,18 +784,76 @@ ktc_ForgetAllTokens()
 /* ktc_OldPioctl - returns a boolean true if the kernel supports only the old
  * pioctl interface for delivering AFS tickets to the cache manager. */
 
-ktc_OldPioctl()
+int
+ktc_OldPioctl(void)
 {
-    int rc;
-    LOCK_GLOBAL_MUTEX;
-#ifdef KERNEL_KTC_COMPAT
-    CHECK_KERNEL;
-    rc = (kernelKTC != 1);     /* old style interface */
+    return 1;
+}
+
+afs_uint32
+ktc_curpag(void)
+{
+    int code;
+    struct ViceIoctl iob;
+    afs_uint32 pag;
+
+    /* now setup for the pioctl */
+    iob.in = NULL;
+    iob.in_size = 0;
+    iob.out = (caddr_t) &pag;
+    iob.out_size = sizeof(afs_uint32);
+
+    code = PIOCTL(0, VIOC_GETPAG, &iob, 0);
+    if (code < 0) {
+#if defined(AFS_AIX52_ENV)
+       code = getpagvalue("afs");
+       if (code < 0 && errno == EINVAL)
+           code = 0;
+       return code;
+#elif defined(AFS_AIX51_ENV)
+       return -1;
 #else
-    rc = 1;
+       gid_t groups[NGROUPS_MAX];
+       afs_uint32 g0, g1;
+       afs_uint32 h, l, ret;
+       int ngroups;
+#ifdef AFS_LINUX26_ENV
+       int i;
 #endif
-    UNLOCK_GLOBAL_MUTEX;
-    return rc;
+
+       ngroups = getgroups(sizeof groups / sizeof groups[0], groups);
+
+#ifdef AFS_LINUX26_ENV
+       /* check for AFS_LINUX26_ONEGROUP_ENV PAGs */
+       for (i = 0; i < ngroups; i++) {
+           if (((groups[i] >> 24) & 0xff) == 'A') {
+               return groups[i];
+           }
+       }
+#endif
+
+       if (ngroups < 2)
+           return 0;
+
+       g0 = groups[0] & 0xffff;
+       g1 = groups[1] & 0xffff;
+       g0 -= 0x3f00;
+       g1 -= 0x3f00;
+       if (g0 < 0xc000 && g1 < 0xc000) {
+           l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
+           h = (g0 >> 14);
+           h = (g1 >> 14) + h + h + h;
+           ret = ((h << 28) | l);
+           /* Additional testing */
+           if (((ret >> 24) & 0xff) == 'A')
+               return ret;
+           else
+               return -1;
+       }
+       return -1;
+#endif
+    }
+    return pag;
 }
 
 
@@ -951,12 +892,13 @@ ktc_OldPioctl()
  *     c. In tf_close, be sure it gets reinitialized to a negative
  *        number. 
  */
-static fd = -1;
-static curpos;                 /* Position in tfbfr */
-static lastpos;                        /* End of tfbfr */
+static int fd = -1;
+static int curpos;                     /* Position in tfbfr */
+static int lastpos;                    /* End of tfbfr */
 static char tfbfr[BUFSIZ];     /* Buffer for ticket data */
 
-static tf_gets(), tf_read();
+static int tf_gets(char *, int);
+static int tf_read(char *, int);
 
 /*
  * This file contains routines for manipulating the ticket cache file.
@@ -1021,8 +963,8 @@ static tf_gets(), tf_read();
  * TKT_FIL_LCK  - couldn't lock the file, even after a retry
  */
 
-afs_tf_init(tf_name, rw)
-     char *tf_name;
+int
+afs_tf_init(char *tf_name, int rw)
 {
     int wflag;
     int me;
@@ -1115,8 +1057,8 @@ afs_tf_init(tf_name, rw)
  * was longer than MAXKTCNAMELEN, TKT_FIL_FMT is returned. 
  */
 
-afs_tf_get_pname(p)
-     char *p;
+int
+afs_tf_get_pname(char *p)
 {
     if (fd < 0) {
        return TKT_FIL_INI;
@@ -1136,8 +1078,8 @@ afs_tf_get_pname(p)
  * instance may be null. 
  */
 
-afs_tf_get_pinst(inst)
-     char *inst;
+int
+afs_tf_get_pinst(char *inst)
 {
     if (fd < 0) {
        return TKT_FIL_INI;
@@ -1158,12 +1100,12 @@ afs_tf_get_pinst(inst)
  * EOF          - end of file encountered
  */
 
-afs_tf_get_cred(principal, token)
-     struct ktc_principal *principal;
-     struct ktc_token *token;
+int
+afs_tf_get_cred(struct ktc_principal *principal, struct ktc_token *token)
 {
     int k_errno;
     int kvno, lifetime;
+    long mit_compat;           /* MIT Kerberos 5 with Krb4 uses a "long" for issue_date */
 
     if (fd < 0) {
        return TKT_FIL_INI;
@@ -1200,10 +1142,10 @@ afs_tf_get_cred(principal, token)
        /* don't try to read a silly amount into ticket->dat */
        token->ticketLen > MAXKTCTICKETLEN
        || tf_read((char *)(token->ticket), token->ticketLen) < 1
-       || tf_read((char *)&(token->startTime),
-                  sizeof(token->startTime)) < 1) {
+       || tf_read((char *)&mit_compat, sizeof(mit_compat)) < 1) {
        return TKT_FIL_FMT;
     }
+    token->startTime = mit_compat;
     token->endTime = life_to_time(token->startTime, lifetime);
     token->kvno = kvno;
     return 0;
@@ -1217,7 +1159,8 @@ afs_tf_get_cred(principal, token)
  * The return value is not defined.
  */
 
-afs_tf_close()
+int
+afs_tf_close(void)
 {
     if (!(fd < 0)) {
 #if defined(AFS_AIX_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV)
@@ -1229,6 +1172,7 @@ afs_tf_close()
        fd = -1;                /* see declaration of fd above */
     }
     memset(tfbfr, 0, sizeof(tfbfr));
+    return 0;
 }
 
 /*
@@ -1249,11 +1193,10 @@ afs_tf_close()
  *             file is seriously ill.
  */
 
-static
-tf_gets(s, n)
-     register char *s;
+static int
+tf_gets(register char *s, int n)
 {
-    register count;
+    register int count;
 
     if (fd < 0) {
        return TKT_FIL_INI;
@@ -1285,12 +1228,10 @@ tf_gets(s, n)
  * 0           on end of file or read error
  */
 
-static
-tf_read(s, n)
-     register char *s;
-     register n;
+static int
+tf_read(register char *s, register int n)
 {
-    register count;
+    register int count;
 
     for (count = n; count > 0; --count) {
        if (curpos >= sizeof(tfbfr)) {
@@ -1305,8 +1246,6 @@ tf_read(s, n)
     return n;
 }
 
-char *tkt_string();
-
 /*
  * afs_tf_save_cred() appends an incoming ticket to the end of the ticket
  * file.  You must call afs_tf_init() before calling afs_tf_save_cred().
@@ -1318,10 +1257,10 @@ char *tkt_string();
  * called previously, and KFAILURE for anything else that went wrong.
  */
 
-afs_tf_save_cred(aserver, atoken, aclient)
-     struct ktc_principal *aserver;
-     struct ktc_principal *aclient;
-     struct ktc_token *atoken; /* Token */
+int
+afs_tf_save_cred(struct ktc_principal *aserver, 
+                struct ktc_token *atoken, 
+                struct ktc_principal *aclient)
 {
     char realm[MAXKTCREALMLEN + 1];
     char junk[MAXKTCNAMELEN];
@@ -1331,6 +1270,7 @@ afs_tf_save_cred(aserver, atoken, aclient)
     off_t start;
     int lifetime, kvno;
     int count;                 /* count for write */
+    long mit_compat;           /* MIT Kerberos 5 with Krb4 uses a "long" for issue_date */
 
     if (fd < 0) {              /* fd is ticket file as set by afs_tf_init */
        return TKT_FIL_INI;
@@ -1400,8 +1340,9 @@ afs_tf_save_cred(aserver, atoken, aclient)
     if (write(fd, atoken->ticket, count) != count)
        goto bad;
     /* Issue date */
-    if (write(fd, (char *)&atoken->startTime, sizeof(afs_int32))
-       != sizeof(afs_int32))
+    mit_compat = atoken->startTime;
+    if (write(fd, (char *)&mit_compat, sizeof(mit_compat))
+       != sizeof(mit_compat))
        goto bad;
 
     /* Actually, we should check each write for success */
@@ -1418,8 +1359,6 @@ afs_tf_save_cred(aserver, atoken, aclient)
  * <mit-copyright.h>.
  */
 
-char *getenv();
-
 /*
  * This routine is used to generate the name of the file that holds
  * the user's cache of server tickets and associated session keys.
@@ -1437,20 +1376,26 @@ char *getenv();
 static char krb_ticket_string[4096] = "";
 
 char *
-ktc_tkt_string()
+ktc_tkt_string(void)
+{
+    return ktc_tkt_string_uid(getuid());
+}
+
+char *
+ktc_tkt_string_uid(afs_uint32 uid)
 {
     char *env;
 
     LOCK_GLOBAL_MUTEX;
     if (!*krb_ticket_string) {
-       if (env = getenv("KRBTKFILE")) {
+       if ((env = getenv("KRBTKFILE"))) {
            (void)strncpy(krb_ticket_string, env,
                          sizeof(krb_ticket_string) - 1);
            krb_ticket_string[sizeof(krb_ticket_string) - 1] = '\0';
        } else {
            /* 32 bits of signed integer will always fit in 11 characters
             * (including the sign), so no need to worry about overflow */
-           (void)sprintf(krb_ticket_string, "%s%d", TKT_ROOT, getuid());
+           (void)sprintf(krb_ticket_string, "%s%d", TKT_ROOT, uid);
        }
     }
     UNLOCK_GLOBAL_MUTEX;
@@ -1469,8 +1414,7 @@ ktc_tkt_string()
  */
 
 void
-ktc_set_tkt_string(val)
-     char *val;
+ktc_set_tkt_string(char * val)
 {
 
     LOCK_GLOBAL_MUTEX;
@@ -1487,9 +1431,8 @@ ktc_set_tkt_string(val)
  * success, or KFAILURE if something goes wrong.
  */
 
-afs_tf_create(pname, pinst)
-     char *pname;
-     char *pinst;
+int
+afs_tf_create(char *pname, char *pinst)
 {
     int tktfile;
     int me, metoo;
@@ -1566,7 +1509,8 @@ afs_tf_create(pname, pinst)
  * failure.
  */
 
-afs_tf_dest_tkt()
+int
+afs_tf_dest_tkt(void)
 {
     char *file = ktc_tkt_string();
     int i, fd;
@@ -1605,55 +1549,35 @@ afs_tf_dest_tkt()
     return 0;
 }
 
-static afs_uint32
-curpag()
-{
-    gid_t groups[NGROUPS_MAX];
-    afs_uint32 g0, g1;
-    afs_uint32 h, l, ret;
-
-    if (getgroups(sizeof groups / sizeof groups[0], groups) < 2)
-       return 0;
-
-    g0 = groups[0] & 0xffff;
-    g1 = groups[1] & 0xffff;
-    g0 -= 0x3f00;
-    g1 -= 0x3f00;
-    if (g0 < 0xc000 && g1 < 0xc000) {
-       l = ((g0 & 0x3fff) << 14) | (g1 & 0x3fff);
-       h = (g0 >> 14);
-       h = (g1 >> 14) + h + h + h;
-       ret = ((h << 28) | l);
-       /* Additional testing */
-       if (((ret >> 24) & 0xff) == 'A')
-           return ret;
-       else
-           return -1;
-    }
-    return -1;
-}
-
-
-ktc_newpag()
+int
+ktc_newpag(void)
 {
-    extern char **environ;
+#ifdef AFS_DARWIN100_ENV
+#define environ (*_NSGetEnviron())
+#else
+extern char **environ;
+#endif
 
     afs_uint32 pag;
     struct stat sbuf;
     char fname[256], *prefix = "/ticket/";
+    char fname5[256], *prefix5 = "FILE:/ticket/krb5cc_";
     int numenv;
     char **newenv, **senv, **denv;
 
     LOCK_GLOBAL_MUTEX;
     if (stat("/ticket", &sbuf) == -1) {
        prefix = "/tmp/tkt";
+       prefix5 = "FILE:/tmp/krb5cc_";
     }
 
-    pag = curpag() & 0xffffffff;
+    pag = ktc_curpag() & 0xffffffff;
     if (pag == -1) {
        sprintf(fname, "%s%d", prefix, getuid());
+       sprintf(fname5, "%s%d", prefix5, getuid());
     } else {
-       sprintf(fname, "%sp%ld", prefix, pag);
+       sprintf(fname, "%sp%lu", prefix, afs_printable_uint32_lu(pag));
+       sprintf(fname5, "%sp%lud", prefix5, afs_printable_uint32_lu(pag));
     }
     ktc_set_tkt_string(fname);
 
@@ -1661,17 +1585,23 @@ ktc_newpag()
        numenv++;
     newenv = (char **)malloc((numenv + 2) * sizeof(char *));
 
-    for (senv = environ, denv = newenv; *senv; *senv++) {
-       if (strncmp(*senv, "KRBTKFILE=", 10) != 0)
+    for (senv = environ, denv = newenv; *senv; senv++) {
+       if (strncmp(*senv, "KRBTKFILE=", 10) != 0 &&
+           strncmp(*senv, "KRB5CCNAME=", 11) != 0)
            *denv++ = *senv;
     }
 
-    *denv = (char *)malloc(10 + strlen(fname) + 1);
+    *denv = malloc(10+11 + strlen(fname) + strlen(fname5) + 2);
     strcpy(*denv, "KRBTKFILE=");
     strcat(*denv, fname);
+    *(denv+1) = *denv + strlen(*denv) + 1;
+    denv++;
+    strcpy(*denv, "KRB5CCNAME=");
+    strcat(*denv, fname5);
     *++denv = 0;
     environ = newenv;
     UNLOCK_GLOBAL_MUTEX;
+    return 0;
 }
 
 /*
@@ -1679,9 +1609,9 @@ ktc_newpag()
  * find out what the local cell is.
  */
 static void
-ktc_LocalCell()
+ktc_LocalCell(void)
 {
-    int code;
+    int code = 0;
     struct afsconf_dir *conf;
 
     if ((conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))