#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "krb.h"
#include <fcntl.h>
#include <sys/stat.h>
#include "autoconf.h"
#ifdef TKT_SHMEM
#include <sys/param.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
extern int krb_debug;
#include "k5-util.h"
#define do_seteuid krb5_seteuid
#ifndef O_SYNC
#define O_SYNC 0
#endif
int KRB5_CALLCONV
in_tkt(pname,pinst)
char *pname;
char *pinst;
{
int tktfile;
uid_t me, metoo, getuid(), geteuid();
struct stat statpre, statpost;
int count;
const char *file = TKT_FILE;
int fd;
register int i;
char charbuf[BUFSIZ];
mode_t mask;
#ifdef TKT_SHMEM
char shmidname[MAXPATHLEN];
#endif
if (file == 0)
file = tkt_string();
me = getuid ();
metoo = geteuid();
if (lstat(file, &statpre) == 0) {
if (statpre.st_uid != me || !(statpre.st_mode & S_IFREG)
|| statpre.st_nlink != 1 || statpre.st_mode & 077) {
if (krb_debug)
fprintf(stderr,"Error initializing %s",file);
return(KFAILURE);
}
if (me != metoo && do_seteuid(me) < 0)
return KFAILURE;
fd = open(file, O_RDWR|O_SYNC, 0);
(void)unlink(file);
if (me != metoo && do_seteuid(metoo) < 0)
return KFAILURE;
if (fd < 0) {
goto out;
}
if (fstat(fd, &statpost) < 0) {
(void)close(fd);
goto out;
}
if (statpre.st_dev != statpost.st_dev
|| statpre.st_ino != statpost.st_ino) {
(void)close(fd);
errno = 0;
goto out;
}
memset(charbuf, 0, sizeof(charbuf));
for (i = 0; i < statpost.st_size; i += sizeof(charbuf))
if (write(fd, charbuf, sizeof(charbuf)) != sizeof(charbuf)) {
#ifndef NO_FSYNC
(void) fsync(fd);
#endif
(void) close(fd);
goto out;
}
#ifndef NO_FSYNC
(void) fsync(fd);
#endif
(void) close(fd);
}
out:
if (me != metoo) {
if (do_seteuid(me) < 0) {
if (krb_debug)
perror("in_tkt: seteuid");
return(KFAILURE);
} else
if (krb_debug)
printf("swapped UID's %d and %d\n",(int) metoo, (int) me);
}
mask = umask(077);
tktfile = open(file, O_RDWR|O_SYNC|O_CREAT|O_EXCL, 0600);
umask(mask);
if (me != metoo) {
if (do_seteuid(metoo) < 0) {
if (krb_debug)
perror("in_tkt: seteuid2");
return(KFAILURE);
} else
if (krb_debug)
printf("swapped UID's %d and %d\n", (int) me, (int) metoo);
}
if (tktfile < 0) {
if (krb_debug)
fprintf(stderr,"Error initializing %s",TKT_FILE);
return(KFAILURE);
}
count = strlen(pname)+1;
if (write(tktfile,pname,count) != count) {
(void) close(tktfile);
return(KFAILURE);
}
count = strlen(pinst)+1;
if (write(tktfile,pinst,count) != count) {
(void) close(tktfile);
return(KFAILURE);
}
(void) close(tktfile);
#ifdef TKT_SHMEM
(void) strncpy(shmidname, file, sizeof(shmidname) - 1);
shmidname[sizeof(shmidname) - 1] = '\0';
(void) strncat(shmidname, ".shm", sizeof(shmidname) - 1 - strlen(shmidname));
return(krb_shm_create(shmidname));
#else
return(KSUCCESS);
#endif
}
int KRB5_CALLCONV
krb_in_tkt(pname, pinst, prealm)
char *pname;
char *pinst;
char *prealm;
{
return in_tkt(pname, pinst);
}