/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
/* ticket caching code */
#include <afsconfig.h>
-#if defined(UKERNEL)
-#include "afs/param.h"
-#else
#include <afs/param.h>
-#endif
-RCSID
- ("$Header$");
+#include <roken.h>
-#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) */
-
-#ifdef AFS_SUN5_ENV
-#include <unistd.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
#include <afs/stds.h>
+#include <afs/opr.h>
#include <afs/pthread_glock.h>
-#include <sys/types.h>
#include <ctype.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <afs/vice.h>
+
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+#if defined(UKERNEL)
+#include "afsincludes.h"
+#endif
+
#ifdef AFS_AIX_ENV
#include <sys/lockf.h>
#ifdef AFS_AIX51_ENV
#endif
#endif
#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+
+#ifdef HAVE_CRT_EXTERNS_H
+#include <crt_externs.h>
#endif
+
+#include <afs/vice.h>
#include "auth.h"
#include <afs/venus.h>
#include <afs/afsutil.h>
+
+#if !defined(UKERNEL)
#include <afs/sys_prototypes.h>
+#endif
-#endif /* defined(UKERNEL) */
+#if defined(AFS_LINUX26_ENV)
+#include <sys/syscall.h>
+#if defined(SYS_keyctl)
+/* Open code this value to avoid a dependency on keyutils */
+#define KEYCTL_SESSION_TO_PARENT 18
+#endif
+#endif
-/* For malloc() */
-#include <stdlib.h>
+#include "token.h"
#include "ktc.h"
-#ifdef notdef
-/* AFS_KERBEROS_ENV is now conditionally defined in the Makefile */
-#define AFS_KERBEROS_ENV
-#endif
-
#ifdef AFS_KERBEROS_ENV
-#include <fcntl.h>
-#include <sys/file.h>
#include "cellconfig.h"
static char lcell[MAXCELLCHARS];
#define BUFSIZ 4096
#endif
-#ifdef AFS_HPUX_ENV
-#include <unistd.h>
-#endif
#if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
static struct flock fileWlock = { F_WRLCK, 0, 0, 0, 0, 0 };
static struct flock fileRlock = { F_RDLCK, 0, 0, 0, 0, 0 };
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 *,
+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 *);
static void ktc_LocalCell(void);
#endif /* AFS_KERBEROS_ENV */
-#ifdef AFS_DUX40_ENV
-#define PIOCTL afs_pioctl
-#elif defined(UKERNEL)
-#define PIOCTL(A,B,C,D) call_syscall(AFSCALL_PIOCTL,A,B,C,D)
+#if defined(UKERNEL)
+#define PIOCTL(A,B,C,D) (errno = (call_syscall(AFSCALL_PIOCTL,A,B,C,D)), errno?-1:0)
#else
#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 */
struct ktc_principal server;
struct ktc_principal client;
struct ktc_token token;
-} local_tokens[MAXLOCALTOKENS] = { {
-0}, {
-0}, {
-0}, {
-0}};
-
-/* new interface routines to the ticket cache. Only handle afs service right
- * now. */
+} local_tokens[MAXLOCALTOKENS];
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;
-}
+GetToken(struct ktc_principal *aserver, struct ktc_token *atoken,
+ int atokenLen, struct ktc_principal *alicnet, afs_int32 *aviceid);
+
#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;
char tbuffer[MAXPIOCTLTOKENLEN];
- register char *tp;
+ char *tp;
struct ClearToken ct;
- register afs_int32 code;
+ afs_int32 code;
afs_int32 temp;
if (strcmp(aserver->name, "afs") != 0) {
0)) {
found = i; /* replace existing entry */
break;
- } else /* valid, but no match */
- ;
+ } else {
+ /* valid, but no match */
+ }
} else
found = i; /* remember this empty slot */
if (found == -1)
/*
* 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);
}
int
+ktc_SetTokenEx(struct ktc_setTokenData *token) {
+ struct ViceIoctl iob;
+ afs_int32 code;
+ XDR xdrs;
+
+ xdrlen_create(&xdrs);
+ if (!xdr_ktc_setTokenData(&xdrs, token))
+ return EINVAL;
+ iob.in_size = xdr_getpos(&xdrs);
+ xdr_destroy(&xdrs);
+
+ iob.in = malloc(iob.in_size);
+ if (iob.in == NULL)
+ return ENOMEM;
+
+ xdrmem_create(&xdrs, iob.in, iob.in_size, XDR_ENCODE);
+ if (!xdr_ktc_setTokenData(&xdrs, token))
+ return KTC_INVAL;
+ xdr_destroy(&xdrs);
+
+ iob.out = NULL;
+ iob.out_size = 0;
+
+ code = PIOCTL(0, VIOC_SETTOK2, &iob, 0);
+
+ free(iob.in);
+
+ /* If we can't use the new pioctl, then fallback to using the old
+ * one, with just the rxkad portion of the token we're being asked to
+ * set
+ */
+ if (code == -1 && errno == EINVAL) {
+ struct ktc_principal server, client;
+ struct ktc_token *rxkadToken;
+ afs_int32 flags;
+
+ /* With the growth of ticket sizes, a ktc_token is now 12k. Don't
+ * allocate it on the stack! */
+ rxkadToken = malloc(sizeof(*rxkadToken));
+ if (rxkadToken == NULL)
+ return ENOMEM;
+
+ code = token_extractRxkad(token, rxkadToken, &flags, &client);
+ if (code) {
+ free(rxkadToken);
+ return KTC_INVAL;
+ }
+
+ memset(&server, 0, sizeof(server));
+ strcpy(server.name, "afs");
+ if (strlcpy(server.cell, token->cell, sizeof(server.cell))
+ >= sizeof(server.cell)) {
+ free(rxkadToken);
+ return KTC_INVAL;
+ }
+ code = ktc_SetToken(&server, rxkadToken, &client, flags);
+ free(rxkadToken);
+ return code;
+ }
+
+ if (code)
+ return KTC_PIOCTLFAIL;
+#if defined(AFS_LINUX26_ENV) && defined(SYS_keyctl)
+ else
+ /*
+ * 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 (token->flags & AFS_SETTOK_SETPAG)
+ syscall(SYS_keyctl, KEYCTL_SESSION_TO_PARENT);
+#endif
+
+ return 0;
+}
+
+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
}
}
- 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;
}
return 0;
}
+/*!
+ * Get a token, given the cell that we need to get information for
+ *
+ * @param cellName
+ * The name of the cell we're getting the token for - if NULL, we'll
+ * get information for the primary cell
+ */
+int
+ktc_GetTokenEx(char *cellName, struct ktc_setTokenData **tokenSet) {
+ struct ViceIoctl iob;
+ char tbuffer[MAXPIOCTLTOKENLEN];
+ char *tp;
+ afs_int32 code;
+ XDR xdrs;
+
+ tp = tbuffer;
+
+ /* If we have a cellName, write it out here */
+ if (cellName) {
+ memcpy(tp, cellName, strlen(cellName) +1);
+ tp += strlen(cellName)+1;
+ }
+
+ iob.in = tbuffer;
+ iob.in_size = tp - tbuffer;
+ iob.out = tbuffer;
+ iob.out_size = sizeof(tbuffer);
+
+ code = PIOCTL(0, VIOC_GETTOK2, &iob, 0);
+
+ /* If we can't use the new pioctl, the fall back to the old one. We then
+ * need to convert the rxkad token we get back into the new format
+ */
+ if (code == -1 && errno == EINVAL) {
+ struct ktc_principal server;
+ struct ktc_tokenUnion token;
+ struct ktc_token *ktcToken; /* too huge for the stack */
+ afs_int32 viceid;
+
+ memset(&server, 0, sizeof(server));
+ ktcToken = malloc(sizeof(struct ktc_token));
+ if (ktcToken == NULL)
+ return ENOMEM;
+ memset(ktcToken, 0, sizeof(struct ktc_token));
+
+ strcpy(server.name, "afs");
+
+ if (cellName != NULL)
+ strcpy(server.cell, cellName);
+
+ code = GetToken(&server, ktcToken, sizeof(struct ktc_token),
+ NULL /*client*/, &viceid);
+ if (code == 0) {
+ *tokenSet = token_buildTokenJar(cellName);
+ token.at_type = AFSTOKEN_UNION_KAD;
+ token.ktc_tokenUnion_u.at_kad.rk_kvno = ktcToken->kvno;
+ memcpy(token.ktc_tokenUnion_u.at_kad.rk_key,
+ ktcToken->sessionKey.data, 8);
+
+ token.ktc_tokenUnion_u.at_kad.rk_begintime = ktcToken->startTime;
+ token.ktc_tokenUnion_u.at_kad.rk_endtime = ktcToken->endTime;
+ token.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_len
+ = ktcToken->ticketLen;
+ token.ktc_tokenUnion_u.at_kad.rk_ticket.rk_ticket_val
+ = ktcToken->ticket;
+ token.ktc_tokenUnion_u.at_kad.rk_viceid = viceid;
+
+ token_addToken(*tokenSet, &token);
+
+ memset(ktcToken, 0, sizeof(struct ktc_token));
+ }
+ free(ktcToken);
+ return code;
+ }
+ if (code)
+ return KTC_PIOCTLFAIL;
+
+ *tokenSet = malloc(sizeof(struct ktc_setTokenData));
+ if (*tokenSet == NULL)
+ return ENOMEM;
+ memset(*tokenSet, 0, sizeof(struct ktc_setTokenData));
+
+ xdrmem_create(&xdrs, iob.out, iob.out_size, XDR_DECODE);
+ if (!xdr_ktc_setTokenData(&xdrs, *tokenSet)) {
+ free(*tokenSet);
+ *tokenSet = NULL;
+ xdr_destroy(&xdrs);
+ return EINVAL;
+ }
+ xdr_destroy(&xdrs);
+ return 0;
+}
+
/* get token, given server we need and token buffer. aclient will eventually
* be set to our identity to the server.
*/
int
-ktc_GetToken(struct ktc_principal *aserver, struct ktc_token *atoken,
+ktc_GetToken(struct ktc_principal *aserver, struct ktc_token *atoken,
int atokenLen, struct ktc_principal *aclient)
{
+ return GetToken(aserver, atoken, atokenLen, aclient, NULL);
+}
+
+static int
+GetToken(struct ktc_principal *aserver, struct ktc_token *atoken,
+ int atokenLen, struct ktc_principal *aclient, afs_int32 *aviceid)
+{
struct ViceIoctl iob;
char tbuffer[MAXPIOCTLTOKENLEN];
- register afs_int32 code = 0;
+ afs_int32 code = 0;
int index;
char *stp, *cellp; /* secret token ptr */
struct ClearToken ct;
- register char *tp;
+ char *tp;
afs_int32 temp;
int maxLen; /* biggest ticket we can copy */
int tktLen; /* server ticket length */
#ifdef AFS_KERBEROS_ENV
char found = 0;
#endif
+ if (aviceid) {
+ *aviceid = 0;
+ }
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])
/* got token for cell; check that it will fit */
maxLen =
atokenLen - sizeof(struct ktc_token) + MAXKTCTICKETLEN;
- if (maxLen < tktLen) {
+ if (tktLen < 0 || tktLen > maxLen) {
UNLOCK_GLOBAL_MUTEX;
return KTC_TOOBIG;
}
sizeof(struct ktc_encryptionKey));
atoken->ticketLen = tktLen;
- if (aclient) {
- strcpy(aclient->cell, cellp);
- aclient->instance[0] = 0;
+ if (aclient || aviceid) {
+ if (aclient) {
+ strlcpy(aclient->cell, cellp, sizeof(aclient->cell));
+ aclient->instance[0] = 0;
+ }
if ((atoken->kvno == 999) || /* old style bcrypt ticket */
(ct.BeginTimestamp && /* new w/ prserver lookup */
(((ct.EndTimestamp - ct.BeginTimestamp) & 1) == 1))) {
- sprintf(aclient->name, "AFS ID %d", ct.ViceId);
- } else {
+ if (aclient) {
+ sprintf(aclient->name, "AFS ID %d", ct.ViceId);
+ }
+ if (aviceid) {
+ *aviceid = ct.ViceId;
+ }
+ } else if (aclient) {
sprintf(aclient->name, "Unix UID %d", ct.ViceId);
}
}
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;
}
#endif /* NO_AFS_CLIENT */
+/*!
+ * An iterator which can list all cells with tokens in the cache
+ *
+ * This function may be used to list the names of all cells for which
+ * tokens exist in the current cache. The first time that it is called,
+ * prevIndex should be set to 0. On all subsequent calls, prevIndex
+ * should be set to the value returned in newIndex by the last call
+ * to the function. Note that there is no guarantee that the index value
+ * is monotonically increasing.
+ *
+ * @param prevIndex
+ * The index returned by the last call, or 0 if this is the first
+ * call in an iteration
+ * @param newIndex
+ * A pointer to an int which, upon return, will hold the next value
+ * to be used.
+ * @param cellName
+ * A pointer to a char * which, upon return, will hold a cellname.
+ * This must be freed by the caller using free()
+ */
+
+int
+ktc_ListTokensEx(int prevIndex, int *newIndex, char **cellName) {
+ struct ViceIoctl iob;
+ char tbuffer[MAXPIOCTLTOKENLEN];
+ afs_int32 code;
+ afs_int32 index;
+ struct ktc_setTokenData tokenSet;
+ XDR xdrs;
+
+ memset(&tokenSet, 0, sizeof(tokenSet));
+
+ *cellName = NULL;
+ *newIndex = prevIndex;
+
+ index = prevIndex;
+
+ while (index<100) { /* Safety, incase of pioctl failure */
+ memset(tbuffer, 0, sizeof(tbuffer));
+ iob.in = tbuffer;
+ memcpy(tbuffer, &index, sizeof(afs_int32));
+ iob.in_size = sizeof(afs_int32);
+ iob.out = tbuffer;
+ iob.out_size = sizeof(tbuffer);
+
+ code = PIOCTL(0, VIOC_GETTOK2, &iob, 0);
+
+ /* Can't use new pioctl, so must use old one */
+ if (code == -1 && errno == EINVAL) {
+ struct ktc_principal server;
+
+ code = ktc_ListTokens(index, newIndex, &server);
+ if (code == 0)
+ *cellName = strdup(server.cell);
+ return code;
+ }
+
+ if (code == 0) {
+ /* Got a token from the pioctl. Now we throw it away,
+ * so we can return just a cellname. This is rather wasteful,
+ * but it's what the old API does. Ho hum. */
+
+ xdrmem_create(&xdrs, iob.out, iob.out_size, XDR_DECODE);
+ if (!xdr_ktc_setTokenData(&xdrs, &tokenSet)) {
+ xdr_destroy(&xdrs);
+ return EINVAL;
+ }
+ xdr_destroy(&xdrs);
+ *cellName = strdup(tokenSet.cell);
+ xdr_free((xdrproc_t)xdr_ktc_setTokenData, &tokenSet);
+ *newIndex = index + 1;
+ return 0;
+ }
+ index++;
+ }
+ return KTC_PIOCTLFAIL;
+}
+
/* ktc_ListTokens - list all tokens. start aprevIndex at 0, it returns the
* next rock in (*aindex). (*aserver) is set to the relevant ticket on
* success. */
{
struct ViceIoctl iob;
char tbuffer[MAXPIOCTLTOKENLEN];
- register afs_int32 code = 0 ;
- register char *tp;
+ afs_int32 code = 0 ;
+ 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
tp += temp; /* skip clear token itself */
tp += sizeof(afs_int32); /* skip primary flag */
/* tp now points to the cell name */
- strcpy(aserver->cell, tp);
+ strlcpy(aserver->cell, tp, sizeof(aserver->cell));
aserver->instance[0] = 0;
strcpy(aserver->name, "afs");
#endif /* NO_AFS_CLIENT */
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;
+ afs_int32 code;
int i;
for (i = 0; i < MAXLOCALTOKENS; i++)
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)
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_PAG_ONEGROUP_ENV
+ int i;
#endif
- UNLOCK_GLOBAL_MUTEX;
- return rc;
+
+ ngroups = getgroups(sizeof groups / sizeof groups[0], groups);
+
+#ifdef AFS_PAG_ONEGROUP_ENV
+ /* Check for one-group 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;
}
*/
#if 0
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <sys/file.h>
#include <krb.h>
#endif
* are invalid (ie. when deciding whether afs_tf_init has been
* called.)
* c. In tf_close, be sure it gets reinitialized to a negative
- * number.
+ * number.
*/
static int fd = -1;
static int curpos; /* Position in tfbfr */
* afs_tf_close() closes the ticket file and releases the lock.
*
* tf_gets() returns the next null-terminated string. It's an internal
- * routine used by afs_tf_get_pname(), afs_tf_get_pinst(), and
+ * routine used by afs_tf_get_pname(), afs_tf_get_pinst(), and
* afs_tf_get_cred().
*
* tf_read() reads a given number of bytes. It's an internal routine
/*
* afs_tf_init() should be called before the other ticket file routines.
* It takes the name of the ticket file to use, "tf_name", and a
- * read/write flag "rw" as arguments.
+ * read/write flag "rw" as arguments.
*
* It tries to open the ticket file, checks the mode, and if everything
* is okay, locks the file. If it's opened for reading, the lock is
- * shared. If it's opened for writing, the lock is exclusive.
+ * shared. If it's opened for writing, the lock is exclusive.
*
- * Returns 0 if all went well, otherwise one of the following:
+ * Returns 0 if all went well, otherwise one of the following:
*
* NO_TKT_FIL - file wasn't there
* TKT_FIL_ACC - file was in wrong mode, etc.
* If "wflag" is set, open the ticket file in append-writeonly mode
* and lock the ticket file in exclusive mode. If unable to lock
* the file, sleep and try again. If we fail again, return with the
- * proper error message.
+ * proper error message.
*/
curpos = sizeof(tfbfr);
}
/*
* Otherwise "wflag" is not set and the ticket file should be opened
- * for read-only operations and locked for shared access.
+ * for read-only operations and locked for shared access.
*/
fd = open(tf_name, O_RDONLY, 0600);
* principal's name is filled into the "p" parameter. If all goes well,
* 0 is returned. If afs_tf_init() wasn't called, TKT_FIL_INI is
* returned. If the name was null, or EOF was encountered, or the name
- * was longer than MAXKTCNAMELEN, TKT_FIL_FMT is returned.
+ * was longer than MAXKTCNAMELEN, TKT_FIL_FMT is returned.
*/
int
* goes well, 0 is returned. If afs_tf_init() wasn't called,
* TKT_FIL_INI is returned. If EOF was encountered, or the instance
* was longer than MAXKTCNAMELEN, TKT_FIL_FMT is returned. Note that the
- * instance may be null.
+ * instance may be null.
*/
int
/*
* afs_tf_get_cred() reads a CREDENTIALS record from a ticket file and fills
* in the given structure "c". It should only be called after afs_tf_init(),
- * afs_tf_get_pname(), and afs_tf_get_pinst() have been called. If all goes
- * well, 0 is returned. Possible error codes are:
+ * afs_tf_get_pname(), and afs_tf_get_pinst() have been called. If all goes
+ * well, 0 is returned. Possible error codes are:
*
* TKT_FIL_INI - afs_tf_init wasn't called first
* TKT_FIL_FMT - bad format
*/
static int
-tf_gets(register char *s, int n)
+tf_gets(char *s, int n)
{
- register int count;
+ int count;
if (fd < 0) {
return TKT_FIL_INI;
*/
static int
-tf_read(register char *s, register int n)
+tf_read(char *s, int n)
{
- register int count;
+ int count;
for (count = n; count > 0; --count) {
if (curpos >= sizeof(tfbfr)) {
*/
int
-afs_tf_save_cred(struct ktc_principal *aserver,
- struct ktc_token *atoken,
+afs_tf_save_cred(struct ktc_principal *aserver,
+ struct ktc_token *atoken,
struct ktc_principal *aclient)
{
char realm[MAXKTCREALMLEN + 1];
int count;
char *file = ktc_tkt_string();
int fd;
- register int i;
+ int i;
char zerobuf[1024];
struct stat sbuf;
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%lu", prefix, afs_cast_uint32(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);
for (senv = environ, numenv = 0; *senv; senv++)
numenv++;
- newenv = (char **)malloc((numenv + 2) * sizeof(char *));
+ newenv = 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;
}
static void
ktc_LocalCell(void)
{
- int code;
+ int code = 0;
struct afsconf_dir *conf;
if ((conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))