#include "k5-int.h"
#include "rc-int.h"
#ifdef _WIN32
#include "../os/os-proto.h"
#else
#include <sys/types.h>
#include <sys/stat.h>
#endif
#ifdef _WIN32
static krb5_error_code
open_file(krb5_context context, int *fd_out)
{
krb5_error_code ret;
char *fname;
const char *dir;
*fd_out = -1;
dir = getenv("KRB5RCACHEDIR");
if (dir != NULL) {
if (asprintf(&fname, "%s\\krb5.rcache2") < 0)
return ENOMEM;
} else {
ret = k5_expand_path_tokens(context, "%{LOCAL_APPDATA}\\krb5.rcache2",
&fname);
if (ret)
return ret;
}
*fd_out = open(fname, O_CREAT | O_RDWR | O_BINARY, 0600);
ret = (*fd_out < 0) ? errno : 0;
if (ret) {
k5_setmsg(context, ret, "%s (filename: %s)",
error_message(ret), fname);
}
free(fname);
return ret;
}
#else
static krb5_error_code
open_file(krb5_context context, int *fd_out)
{
krb5_error_code ret;
int fd = -1;
char *fname = NULL;
const char *dir;
struct stat statbuf;
uid_t euid = geteuid();
*fd_out = -1;
dir = secure_getenv("KRB5RCACHEDIR");
if (dir == NULL) {
dir = secure_getenv("TMPDIR");
if (dir == NULL)
dir = RCTMPDIR;
}
if (asprintf(&fname, "%s/krb5_%lu.rcache2", dir, (unsigned long)euid) < 0)
return ENOMEM;
fd = open(fname, O_CREAT | O_RDWR | O_NOFOLLOW, 0600);
if (fd < 0) {
ret = errno;
k5_setmsg(context, ret, "%s (filename: %s)",
error_message(ret), fname);
goto cleanup;
}
if (fstat(fd, &statbuf) < 0 || statbuf.st_uid != euid) {
ret = EIO;
k5_setmsg(context, ret, "Replay cache file %s is not owned by uid %lu",
fname, (unsigned long)euid);
goto cleanup;
}
*fd_out = fd;
fd = -1;
ret = 0;
cleanup:
if (fd != -1)
close(fd);
free(fname);
return ret;
}
#endif
static krb5_error_code
dfl_resolve(krb5_context context, const char *residual, void **rcdata_out)
{
*rcdata_out = NULL;
return 0;
}
static void
dfl_close(krb5_context context, void *rcdata)
{
}
static krb5_error_code
dfl_store(krb5_context context, void *rcdata, const krb5_data *tag)
{
krb5_error_code ret;
int fd;
ret = open_file(context, &fd);
if (ret)
return ret;
ret = k5_rcfile2_store(context, fd, tag);
close(fd);
return ret;
}
const krb5_rc_ops k5_rc_dfl_ops =
{
"dfl",
dfl_resolve,
dfl_close,
dfl_store
};