#include "includes.h"
#ifdef WITH_FAKE_KASERVER
#include <afs/stds.h>
#include <afs/afs.h>
#include <afs/auth.h>
#include <afs/venus.h>
#include <asm/unistd.h>
#include <openssl/des.h>
_syscall5(int, afs_syscall, int, subcall,
char *, path,
int, cmd,
char *, cmarg,
int, follow);
struct ClearToken {
uint32 AuthHandle;
char HandShakeKey[8];
uint32 ViceId;
uint32 BeginTimestamp;
uint32 EndTimestamp;
};
static BOOL afs_settoken(const char *username, const char *cell,
const struct ClearToken *ctok,
char *v4tkt_data, int v4tkt_length)
{
int ret;
struct {
char *in, *out;
uint16 in_size, out_size;
} iob;
char buf[1024];
char *p = buf;
int tmp;
memcpy(p, &v4tkt_length, sizeof(uint32));
p += sizeof(uint32);
memcpy(p, v4tkt_data, v4tkt_length);
p += v4tkt_length;
tmp = sizeof(struct ClearToken);
memcpy(p, &tmp, sizeof(uint32));
p += sizeof(uint32);
memcpy(p, ctok, tmp);
p += tmp;
tmp = 0;
memcpy(p, &tmp, sizeof(uint32));
p += sizeof(uint32);
tmp = strlen(cell);
if (tmp >= MAXKTCREALMLEN) {
DEBUG(1, ("Realm too long\n"));
return False;
}
strncpy(p, cell, tmp);
p += tmp;
*p = 0;
p +=1;
iob.in = buf;
iob.in_size = PTR_DIFF(p,buf);
iob.out = buf;
iob.out_size = sizeof(buf);
#if 0
file_save("/tmp/ioctlbuf", iob.in, iob.in_size);
#endif
ret = afs_syscall(AFSCALL_PIOCTL, 0, VIOCSETTOK, (char *)&iob, 0);
DEBUG(10, ("afs VIOCSETTOK returned %d\n", ret));
return (ret == 0);
}
BOOL afs_login(connection_struct *conn)
{
fstring ticket;
char *p = ticket;
uint32 len;
struct afs_key key;
pstring afs_username;
char *cell;
struct ClearToken ct;
uint32 now;
des_key_schedule key_schedule;
pstrcpy(afs_username, lp_afs_username_map());
standard_sub_conn(conn, afs_username, sizeof(afs_username));
strlower_m(afs_username);
cell = strchr(afs_username, '@');
if (cell == NULL) {
DEBUG(1, ("AFS username doesn't contain a @, "
"could not find cell\n"));
return False;
}
*cell = '\0';
cell += 1;
DEBUG(10, ("Trying to log into AFS for user %s@%s\n",
afs_username, cell));
if (!secrets_init())
return False;
if (!secrets_fetch_afs_key(cell, &key)) {
DEBUG(5, ("Could not fetch AFS service key\n"));
return False;
}
ct.AuthHandle = key.kvno;
p = ticket;
*p = 1;
p += 1;
strncpy(p, afs_username, sizeof(ticket)-PTR_DIFF(p,ticket)-1);
p += strlen(p)+1;
strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1);
p += strlen(p)+1;
strncpy(p, cell, sizeof(ticket)-PTR_DIFF(p,ticket)-1);
p += strlen(p)+1;
ct.ViceId = getuid();
DEBUG(10, ("Creating Token for uid %d\n", ct.ViceId));
SIVAL(p, 0, 0);
p += 4;
generate_random_buffer(p, 8, False);
memcpy(ct.HandShakeKey, p, 8);
p += 8;
*p = 255;
p += 1;
now = time(NULL);
SIVAL(p, 0, now);
ct.BeginTimestamp = now;
ct.EndTimestamp = now + (255*60*5);
if (((ct.EndTimestamp - ct.BeginTimestamp) & 1) == 1) {
ct.BeginTimestamp += 1;
}
p += 4;
strncpy(p, "afs", sizeof(ticket)-PTR_DIFF(p,ticket)-1);
p += strlen(p)+1;
strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1);
p += strlen(p)+1;
len = PTR_DIFF(p, ticket);
if (len & 7) {
uint32 extra_space = 8-(len & 7);
memset(p, 0, extra_space);
p+=extra_space;
}
len = PTR_DIFF(p, ticket);
des_key_sched((const_des_cblock *)key.key, key_schedule);
des_pcbc_encrypt(ticket, ticket,
len, key_schedule, (C_Block *)key.key, 1);
ZERO_STRUCT(key);
return afs_settoken(afs_username, cell, &ct, ticket, len);
}
#else
BOOL afs_login(connection_struct *conn)
{
return True;
}
#endif