diff --git a/lib/kafs/Makefile.in b/lib/kafs/Makefile.in new file mode 100644 index 000000000..8fcc69ff3 --- /dev/null +++ b/lib/kafs/Makefile.in @@ -0,0 +1,68 @@ + +SHELL = /bin/sh + +srcdir = @srcdir@ +VPATH = @srcdir@ + +CC = @CC@ +AR = ar +RANLIB = @RANLIB@ +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +prefix = @prefix@ +exec_prefix = $(prefix) +libdir = $(exec_prefix)/lib + +LIB = libkafs.a + +SOURCES = afssys.c + +OBJECTS = afssys.o + +all: $(LIB) + +Wall: + make CFLAGS="-g -Wall -Wmissing-prototypes -Wmissing-declarations -D__USE_FIXED_PROTOTYPES__" + +.c.o: + $(CC) -c $(CPPFLAGS) $(DEFS) -I../.. -I../../include -I$(srcdir) -I$(srcdir)/../../include $(CFLAGS) $< + +install: all + $(INSTALL) -d $(libdir) + $(INSTALL_DATA) $(LIB) $(libdir) + -$(RANLIB) $(libdir)/$(LIB) + +uninstall: + +TAGS: $(SOURCES) + etags $(SOURCES) + +check: + +clean: + rm -f *.a *.o + +mostlyclean: clean + +distclean: clean + rm -f Makefile *.tab.c + +realclean: distclean + rm -f TAGS + +dist: $(DISTFILES) + for file in $(DISTFILES); do \ + ln $$file ../`cat ../.fname`/lib \ + || cp -p $$file ../`cat ../.fname`/lib; \ + done + +$(LIB): $(OBJECTS) + rm -f $@ + $(AR) cr $@ $(OBJECTS) + -$(RANLIB) $@ + +$(OBJECTS): ../../config.h diff --git a/lib/kafs/afssys.c b/lib/kafs/afssys.c new file mode 100644 index 000000000..f15ac91af --- /dev/null +++ b/lib/kafs/afssys.c @@ -0,0 +1,261 @@ +#include "config.h" +#include "protos.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include "afssysdefs.h" + +#define AUTH_SUPERUSER "afs" + +/* + * Here only ASCII characters are relevant. + */ + +#define IsAsciiUpper(c) ('A' <= (c) && (c) <= 'Z') + +#define ToAsciiLower(c) ((c) - 'A' + 'a') + +static void +folddown(a, b) + char *a, *b; +{ + for (; *b; a++, b++) + if (IsAsciiUpper(*b)) + *a = ToAsciiLower(*b); + else + *a = *b; + *a = '\0'; +} + +int +k_afsklog(char *realm) +{ + int k_errno; + CREDENTIALS c; + KTEXT_ST ticket; + char username[256]; + + if (!k_hasafs()) + return KSUCCESS; + + k_errno = krb_get_cred(AUTH_SUPERUSER, "", realm, &c); + if (k_errno != KSUCCESS) + { + k_errno = krb_mk_req(&ticket, AUTH_SUPERUSER, "", realm, 0); + if (k_errno == KSUCCESS) + k_errno = krb_get_cred(AUTH_SUPERUSER, "", realm, &c); + } + + if (k_errno == KSUCCESS) + { + char cell[256]; + struct ViceIoctl parms; + struct ClearToken ct; + int32_t sizeof_x; + char buf[2048], *t; + + folddown(cell, realm); + + /* + * 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 UNKNOWN_ENTRY_POINT 4 +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 + + 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 + + errno = ENOSYS; + kill(getpid(), SIGSYS); /* You loose! */ + return -1; +} + +static jmp_buf catch_SIGSYS; + +static void +SIGSYS_handler() +{ + errno = 0; + 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 */ + + done: + (void) signal(SIGSYS, saved_func); + errno = saved_errno; + return afs_entry_point != NO_ENTRY_POINT; +} diff --git a/lib/kafs/afssysdefs.h b/lib/kafs/afssysdefs.h new file mode 100644 index 000000000..682ce0846 --- /dev/null +++ b/lib/kafs/afssysdefs.h @@ -0,0 +1,31 @@ +/* + * This section is for machines using single entry point AFS syscalls! + * or + * This section is for machines using multiple entry point AFS syscalls! + */ + +#if defined(sun) && !defined(__svr4__) +#define AFS_SYSCALL 31 +#endif + +#if defined(sun) && defined(__svr4__) +#define AFS_SYSCALL 105 +#endif + +#if defined(hpux) +#define AFS_SYSCALL 49 +#endif + +#if defined(_AIX) +#define AFS_SYSCALL 38 +#endif + +#if defined(sgi) +#define AFS_PIOCTL (64+1000) +#define AFS_SETPAG (65+1000) +#endif + +#if defined(__osf__) +#define AFS_SYSCALL 232 +#define AFS_SYSCALL2 258 +#endif diff --git a/lib/kafs/kafs.h b/lib/kafs/kafs.h new file mode 100644 index 000000000..a19dbf098 --- /dev/null +++ b/lib/kafs/kafs.h @@ -0,0 +1,47 @@ +#ifndef __KAFS_H +#define __KAFS_H + +/* + */ +#define AFSCALL_PIOCTL 20 +#define AFSCALL_SETPAG 21 + +#ifndef _VICEIOCTL +#if defined(__STDC__) +#define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl)) +#else +#define _VICEIOCTL(id) ((unsigned int ) _IOW(V, id, struct ViceIoctl)) +#endif +#endif /* _VICEIOCTL */ + +#define VIOCSETTOK _VICEIOCTL(3) +#define VIOCUNLOG _VICEIOCTL(9) + +struct ViceIoctl { + caddr_t in, out; + short in_size; + short out_size; +}; + +struct ClearToken { + int32_t AuthHandle; + char HandShakeKey[8]; + int32_t ViceId; + int32_t BeginTimestamp; + int32_t EndTimestamp; +}; + +/* Use k_hasafs() to probe if the machine supports AFS syscalls. + The other functions will generate a SIGSYS if AFS is not supported */ + +int k_hasafs __P((void)); + +int k_afsklog __P((char *realm)); +int k_pioctl __P((char *a_path, + int o_opcode, + struct ViceIoctl *a_paramsP, + int a_followSymlinks)); +int k_unlog __P((void)); +int k_setpag __P((void)); + +#endif /* __KAFS_H */