Make ktc_curpag also detect ONEGROUP PAG gids
[openafs.git] / src / auth / ktc.c
index 6770b14..eabc95c 100644 (file)
@@ -16,8 +16,6 @@
 #include <afs/param.h>
 #endif
 
-RCSID
-    ("$Header$");
 
 #if defined(UKERNEL)
 #include "afs/sysincludes.h"
@@ -29,6 +27,7 @@ RCSID
 #include "afs/venus.h"
 #include "afs/pthread_glock.h"
 #include "afs/dirpath.h"
+#include <ctype.h>
 
 #if !defined(min)
 #define min(a,b) ((a)<(b)?(a):(b))
@@ -40,6 +39,7 @@ RCSID
 #include <unistd.h>
 #endif
 #include <stdio.h>
+#include <stdlib.h>
 #include <afs/stds.h>
 #include <afs/pthread_glock.h>
 #include <sys/types.h>
@@ -55,17 +55,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 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>
+#include <afs/sys_prototypes.h>
 
 #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>
 #include "ktc.h"
@@ -78,7 +90,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"
@@ -125,10 +137,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();
+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
@@ -248,11 +266,10 @@ static struct {
  * now. */
 
 static int
-NewSetToken(aserver, atoken, aclient, flags)
-     struct ktc_principal *aserver;
-     struct ktc_principal *aclient;
-     struct ktc_token *atoken;
-     afs_int32 flags;
+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));
@@ -264,10 +281,8 @@ NewSetToken(aserver, atoken, aclient, flags)
 (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;
+OldSetToken(struct ktc_principal *aserver, struct ktc_token *atoken, 
+           struct ktc_principal *aclient, afs_int32 flags)
 {
     struct ViceIoctl iob;
     char tbuffer[MAXPIOCTLTOKENLEN];
@@ -405,6 +420,14 @@ 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;
@@ -483,14 +506,13 @@ ktc_SetToken(struct ktc_principal *aserver,
 /* 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;
@@ -498,7 +520,9 @@ 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
@@ -536,8 +560,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;
            }
        }
@@ -667,8 +691,8 @@ 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;
 
@@ -692,7 +716,7 @@ ktc_ListTokens(int aprevIndex,
 {
     struct ViceIoctl iob;
     char tbuffer[MAXPIOCTLTOKENLEN];
-    register afs_int32 code;
+    register afs_int32 code = 0 ;
     register char *tp;
     afs_int32 temp, index;
 
@@ -897,7 +921,8 @@ ktc_ForgetAllTokens(void)
 /* 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;
@@ -911,6 +936,70 @@ ktc_OldPioctl()
     return rc;
 }
 
+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
+       gid_t groups[NGROUPS_MAX];
+       afs_uint32 g0, g1;
+       afs_uint32 h, l, ret;
+       int ngroups;
+       int i;
+
+       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;
+}
+
 
 #ifdef AFS_KERBEROS_ENV
  /*
@@ -947,12 +1036,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.
@@ -1017,8 +1107,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;
@@ -1111,8 +1201,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;
@@ -1132,8 +1222,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;
@@ -1154,9 +1244,8 @@ 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;
@@ -1214,7 +1303,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)
@@ -1226,6 +1316,7 @@ afs_tf_close()
        fd = -1;                /* see declaration of fd above */
     }
     memset(tfbfr, 0, sizeof(tfbfr));
+    return 0;
 }
 
 /*
@@ -1246,11 +1337,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;
@@ -1282,12 +1372,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)) {
@@ -1302,8 +1390,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().
@@ -1315,10 +1401,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];
@@ -1417,8 +1503,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.
@@ -1448,7 +1532,7 @@ ktc_tkt_string_uid(afs_uint32 uid)
 
     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';
@@ -1491,9 +1575,8 @@ ktc_set_tkt_string(char * 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;
@@ -1570,7 +1653,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;
@@ -1609,63 +1693,35 @@ afs_tf_dest_tkt()
     return 0;
 }
 
-static afs_uint32
-curpag()
+int
+ktc_newpag(void)
 {
-#if defined(AFS_AIX51_ENV)
-    afs_int32 pag;
-
-    if (get_pag(PAG_AFS, &pag) < 0 || pag == 0)
-        pag = NOPAG;
-    return pag;
+#ifdef AFS_DARWIN100_ENV
+#define environ (*_NSGetEnviron())
 #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;
+extern char **environ;
 #endif
-}
-
-
-ktc_newpag()
-{
-    extern char **environ;
 
     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);
 
@@ -1673,17 +1729,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;
 }
 
 /*
@@ -1691,7 +1753,7 @@ ktc_newpag()
  * find out what the local cell is.
  */
 static void
-ktc_LocalCell()
+ktc_LocalCell(void)
 {
     int code;
     struct afsconf_dir *conf;