Files
heimdal/lib/kafs/afssys.c
Björn Groenvall b789954d34 Include unistd.h
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@125 ec53bebd-3082-4978-b11e-865c3cabbd6b
1995-09-28 16:12:41 +00:00

331 lines
6.9 KiB
C

#include "config.h"
#include "protos.h"
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h>
#endif
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include <krb.h>
#include <kafs.h>
#include "afssysdefs.h"
#define AUTH_SUPERUSER "afs"
/*
* Here only ASCII characters are relevant.
*/
#define IsAsciiLower(c) ('a' <= (c) && (c) <= 'z')
#define ToAsciiUpper(c) ((c) - 'a' + 'A')
static void
foldup(a, b)
char *a, *b;
{
for (; *b; a++, b++)
if (IsAsciiLower(*b))
*a = ToAsciiUpper(*b);
else
*a = *b;
*a = '\0';
}
#define _PATH_THISCELL "/usr/vice/etc/ThisCell"
static char *
k_cell()
{
static char cell[64];
FILE *f = fopen(_PATH_THISCELL, "r");
if (f == 0)
return 0;
fscanf(f, "%s\n", cell);
if (cell[0] != 0)
return cell;
else
return 0;
}
static int
get_cred(char *princ, char *inst, char *krealm, CREDENTIALS *c, KTEXT_ST *tkt)
{
int k_errno = krb_get_cred(princ, inst, krealm, c);
if (k_errno != KSUCCESS)
{
k_errno = krb_mk_req(tkt, princ, inst, krealm, 0);
if (k_errno == KSUCCESS)
k_errno = krb_get_cred(princ, inst, krealm, c);
}
return k_errno;
}
int
k_afsklog(char *cell, char *krealm)
{
int k_errno;
CREDENTIALS c;
KTEXT_ST ticket;
char realm[REALM_SZ];
char CELL[64];
if (!k_hasafs())
return KSUCCESS;
if (cell == 0 || cell[0] == 0)
cell = k_cell();
if (cell == 0)
return KSUCCESS; /* Not running AFS */
foldup(CELL, cell);
if (krealm == 0 || krealm[0] == 0)
{
k_errno = krb_get_lrealm(realm, 0);
if (k_errno != KSUCCESS)
return k_errno;
krealm = realm;
}
/* First we try afs.cell@REALM, if there is no such thing try
* afs@CELL instead. */
k_errno = get_cred(AUTH_SUPERUSER, cell, krealm, &c, &ticket);
if (k_errno != KSUCCESS)
k_errno = get_cred(AUTH_SUPERUSER, "", CELL, &c, &ticket);
if (k_errno == KSUCCESS)
{
struct ViceIoctl parms;
struct ClearToken ct;
int32_t sizeof_x;
char buf[2048], *t;
/*
* Build a struct ClearToken
*/
ct.AuthHandle = c.kvno;
bcopy((char *)c.session, ct.HandShakeKey, sizeof(c.session));
ct.ViceId = getuid(); /* is this always valid? */
ct.BeginTimestamp = 1 + c.issue_date;
ct.EndTimestamp = krb_life_to_time(c.issue_date, c.lifetime);
t = buf;
/*
* length of secret token followed by secret token
*/
sizeof_x = c.ticket_st.length;
bcopy((char *)&sizeof_x, t, sizeof(sizeof_x));
t += sizeof(sizeof_x);
bcopy((char *)c.ticket_st.dat, t, sizeof_x);
t += sizeof_x;
/*
* length of clear token followed by clear token
*/
sizeof_x = sizeof(ct);
bcopy((char *)&sizeof_x, t, sizeof(sizeof_x));
t += sizeof(sizeof_x);
bcopy((char *)&ct, t, sizeof_x);
t += sizeof_x;
/*
* do *not* mark as primary cell
*/
sizeof_x = 0;
bcopy((char *)&sizeof_x, t, sizeof(sizeof_x));
t += sizeof(sizeof_x);
/*
* follow with cell name
*/
sizeof_x = strlen(cell) + 1;
bcopy(cell, t, sizeof_x);
t += sizeof_x;
/*
* Build argument block
*/
parms.in = buf;
parms.in_size = t - buf;
parms.out = 0;
parms.out_size = 0;
(void) k_pioctl(0, VIOCSETTOK, &parms, 0);
}
return k_errno;
}
#define NO_ENTRY_POINT 0
#define SINGLE_ENTRY_POINT 1
#define MULTIPLE_ENTRY_POINT 2
#define SINGLE_ENTRY_POINT2 3
#define AIX_ENTRY_POINTS 4
#define UNKNOWN_ENTRY_POINT 5
static int afs_entry_point = UNKNOWN_ENTRY_POINT;
int
k_pioctl(char *a_path,
int o_opcode,
struct ViceIoctl *a_paramsP,
int a_followSymlinks)
{
#ifdef AFS_SYSCALL
if (afs_entry_point == SINGLE_ENTRY_POINT)
return syscall(AFS_SYSCALL, AFSCALL_PIOCTL,
a_path, o_opcode, a_paramsP, a_followSymlinks);
#endif
#ifdef AFS_PIOCTL
if (afs_entry_point == MULTIPLE_ENTRY_POINT)
return syscall(AFS_PIOCTL,
a_path, o_opcode, a_paramsP, a_followSymlinks);
#endif
#ifdef AFS_SYSCALL2
if (afs_entry_point == SINGLE_ENTRY_POINT2)
return syscall(AFS_SYSCALL2, AFSCALL_PIOCTL,
a_path, o_opcode, a_paramsP, a_followSymlinks);
#endif
#ifdef _AIX
if (afs_entry_point == AIX_ENTRY_POINTS)
return lpioctl(a_path, o_opcode, a_paramsP, a_followSymlinks);
#endif
errno = ENOSYS;
kill(getpid(), SIGSYS); /* You loose! */
return -1;
}
int
k_unlog(void)
{
struct ViceIoctl parms;
bzero((char *)&parms, sizeof(parms));
return k_pioctl(0, VIOCUNLOG, &parms, 0);
}
int
k_setpag(void)
{
#ifdef AFS_SYSCALL
if (afs_entry_point == SINGLE_ENTRY_POINT)
return syscall(AFS_SYSCALL, AFSCALL_SETPAG);
#endif
#ifdef AFS_SETPAG
if (afs_entry_point == MULTIPLE_ENTRY_POINT)
return syscall(AFS_SETPAG);
#endif
#ifdef AFS_SYSCALL2
if (afs_entry_point == SINGLE_ENTRY_POINT2)
return syscall(AFS_SYSCALL2, AFSCALL_SETPAG);
#endif
#ifdef _AIX
if (afs_entry_point == AIX_ENTRY_POINTS)
return lsetpag();
#endif
errno = ENOSYS;
kill(getpid(), SIGSYS); /* You loose! */
return -1;
}
static jmp_buf catch_SIGSYS;
static void
SIGSYS_handler()
{
errno = 0;
signal(SIGSYS, SIGSYS_handler); /* Need to reinstall handler on SYSV */
longjmp(catch_SIGSYS, 1);
}
int
k_hasafs(void)
{
int saved_errno;
RETSIGTYPE (*saved_func)();
struct ViceIoctl parms;
/*
* Already checked presence of AFS syscalls?
*/
if (afs_entry_point != UNKNOWN_ENTRY_POINT)
return afs_entry_point != NO_ENTRY_POINT;
/*
* Probe kernel for AFS specific syscalls,
* they (currently) come in two flavors.
* If the syscall is absent we recive a SIGSYS.
*/
afs_entry_point = NO_ENTRY_POINT;
bzero(&parms, sizeof(parms));
saved_errno = errno;
saved_func = signal(SIGSYS, SIGSYS_handler);
#ifdef AFS_SYSCALL
if (setjmp(catch_SIGSYS) == 0)
{
syscall(AFS_SYSCALL, AFSCALL_PIOCTL,
0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (errno == EINVAL)
{
afs_entry_point = SINGLE_ENTRY_POINT;
goto done;
}
}
#endif /* AFS_SYSCALL */
#ifdef AFS_PIOCTL
if (setjmp(catch_SIGSYS) == 0)
{
syscall(AFS_PIOCTL,
0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (errno == EINVAL)
{
afs_entry_point = MULTIPLE_ENTRY_POINT;
goto done;
}
}
#endif /* AFS_PIOCTL */
#ifdef AFS_SYSCALL2
if (setjmp(catch_SIGSYS) == 0)
{
syscall(AFS_SYSCALL2, AFSCALL_PIOCTL,
0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (errno == EINVAL)
{
afs_entry_point = SINGLE_ENTRY_POINT2;
goto done;
}
}
#endif /* AFS_SYSCALL */
#ifdef _AIX
if (setjmp(catch_SIGSYS) == 0)
{
lpioctl(0, 0, 0, 0);
if (errno == EINVAL)
{
afs_entry_point = AIX_ENTRY_POINTS;
goto done;
}
}
#endif
done:
(void) signal(SIGSYS, saved_func);
errno = saved_errno;
return afs_entry_point != NO_ENTRY_POINT;
}