ktc newpag stub when environ is not supported
[openafs.git] / src / auth / ktc.c
index f83af5b..3dc4e2d 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>
@@ -56,18 +36,29 @@ RCSID
 #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 HAVE_CRT_EXTERNS_H
+#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>
+
+#if !defined(UKERNEL)
 #include <afs/sys_prototypes.h>
+#endif
 
-#endif /* defined(UKERNEL) */
+#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>
@@ -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"
@@ -148,86 +139,6 @@ static void ktc_LocalCell(void);
 #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 */
@@ -253,26 +164,12 @@ static struct {
 0}, {
 0}};
 
-/* new interface routines to the ticket cache.  Only handle afs service right
- * now. */
-
-static int
-NewSetToken(struct ktc_principal *aserver, 
-           struct ktc_token *atoken, 
-           struct ktc_principal *aclient, 
-            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(struct ktc_principal *aserver, struct ktc_token *atoken, 
+SetToken(struct ktc_principal *aserver, struct ktc_token *atoken,
            struct ktc_principal *aclient, afs_int32 flags)
 {
     struct ViceIoctl iob;
@@ -355,8 +252,8 @@ OldSetToken(struct ktc_principal *aserver, struct ktc_token *atoken,
     /*
      * 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);
@@ -411,6 +308,14 @@ OldSetToken(struct ktc_principal *aserver, struct ktc_token *atoken,
     }
 #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;
@@ -423,7 +328,7 @@ ktc_SetToken(struct ktc_principal *aserver,
     struct ktc_principal *aclient,
     afs_int32 flags)
 {
-    int ncode, ocode;
+    int code;
 
     LOCK_GLOBAL_MUTEX;
 #ifdef AFS_KERBEROS_ENV
@@ -443,41 +348,36 @@ ktc_SetToken(struct ktc_principal *aserver,
            }
        }
 
-       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;
     }
@@ -508,9 +408,6 @@ ktc_GetToken(struct ktc_principal *aserver, struct ktc_token *atoken,
 #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])
@@ -680,8 +577,6 @@ 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;
@@ -706,9 +601,6 @@ ktc_ListTokens(int aprevIndex,
     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
@@ -842,19 +734,8 @@ ktc_ListTokens(int aprevIndex,
     return 0;
 }
 
-/* discard all tokens from this user's cache */
-
 static int
-NewForgetAll(void)
-{
-#ifndef NO_AFS_CLIENT
-    TRY_KERNEL(KTC_FORGETALLTOKENS_OP, 0, 0, 0, 0);
-#endif /* NO_AFS_CLIENT */
-    return EINVAL;
-}
-
-static int
-OldForgetAll(void)
+ForgetAll(void)
 {
     struct ViceIoctl iob;
     register afs_int32 code;
@@ -878,16 +759,15 @@ OldForgetAll(void)
 int
 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)
@@ -907,16 +787,73 @@ ktc_ForgetAllTokens(void)
 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;
 }
 
 
@@ -1612,62 +1549,36 @@ afs_tf_dest_tkt(void)
     return 0;
 }
 
-static afs_uint32
-curpag(void)
-{
-#if defined(AFS_AIX51_ENV)
-    int code = getpagvalue("afs");
-    if (code < 0 && errno == EINVAL)
-       code = 0;
-    return code;
-#else
-    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;
-#endif
-}
-
 int
 ktc_newpag(void)
 {
-    extern char **environ;
+#if !defined(AFS_DARWIN100_ENV) || defined(HAVE_CRT_EXTERNS_H)
+# if defined(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, (long int) 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);
 
@@ -1676,16 +1587,22 @@ ktc_newpag(void)
     newenv = (char **)malloc((numenv + 2) * sizeof(char *));
 
     for (senv = environ, denv = newenv; *senv; senv++) {
-       if (strncmp(*senv, "KRBTKFILE=", 10) != 0)
+       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;
+#endif
     return 0;
 }
 
@@ -1696,7 +1613,7 @@ ktc_newpag(void)
 static void
 ktc_LocalCell(void)
 {
-    int code;
+    int code = 0;
     struct afsconf_dir *conf;
 
     if ((conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))