 7c10c53f6a
			
		
	
	7c10c53f6a
	
	
	
		
			
			git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@73 ec53bebd-3082-4978-b11e-865c3cabbd6b
		
			
				
	
	
		
			295 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			295 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "config.h"
 | |
| #include "protos.h"
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <sys/ioctl.h>
 | |
| #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 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];
 | |
|   char krealm[REALM_SZ];
 | |
| 
 | |
|   if (!k_hasafs())
 | |
|     return KSUCCESS;
 | |
| 
 | |
|   if (realm == 0 || realm[0] == 0)
 | |
|     {
 | |
|       k_errno = krb_get_lrealm(krealm, 0);
 | |
|       if (k_errno != KSUCCESS)
 | |
| 	return k_errno;
 | |
|       realm = krealm;
 | |
|     }
 | |
| 
 | |
|   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 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;
 | |
| }
 |