45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This file of the Kerberos V5 software is derived from public-domain code
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * I/O functions for the replay cache default implementation.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#if defined(_WIN32)
ebb7ba5d39a1fc27566910c47e9749493f961e3fTony Nguyen /* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#if !defined(_WINSOCKAPI_)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#error find some way to use net-byte-order file version numbers.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#define GETDIR (dir = getdir(), dirlen = strlen(dir) + sizeof(PATH_SEPARATOR) - 1)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic char *
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk/* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk#if defined(_WIN32)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Called from krb5_rc_io_creat(); calls mkstemp() and does some
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * sanity checking on the file modes in case some broken mkstemp()
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * implementation creates the file with overly permissive modes. To
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * avoid race conditions, do not fchmod() a file for which mkstemp set
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * incorrect modes.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkkrb5_rc_io_mkstemp(krb5_context context, krb5_rc_iostuff *d, char *dir)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * This return value is deliberate because d->fd == -1 causes
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * caller to go into errno interpretation code.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Be paranoid and check that mkstemp made the file accessible
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * only to the user.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "Cannot fstat replay cache file %s: %s"),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "Insecure mkstemp() file mode "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "for replay cache file %s; "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "try running this program "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkstatic krb5_error_code rc_map_errno (int) __attribute__((cold));
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkrc_map_errno (krb5_context context, int e, const char *fn,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk const char *operation)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk switch (e) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "Cannot %s replay cache file %s: %s"),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "Cannot %s replay cache: %s"),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkkrb5_rc_io_creat(krb5_context context, krb5_rc_iostuff *d, char **fn)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (asprintf(&d->fn, "%s%s%s", dir, PATH_SEPARATOR, *fn) < 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk d->fd = THREEPARAMOPEN(d->fn, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL |
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retval = krb5_rc_io_write(context, d, (krb5_pointer)&rc_vno,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkkrb5_rc_io_open_internal(krb5_context context, krb5_rc_iostuff *d, char *fn,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (asprintf(&d->fn, "%s%s%s", dir, PATH_SEPARATOR, fn) < 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (retval != 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (d->fd < 0) {
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* check if someone was playing with symlinks */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if ((sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* check that non other can read/write/execute the file */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk krb5_set_error_message(context, retval, dgettext(TEXT_DOMAIN,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "Insecure file mode "
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* owned by me */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk /* Solaris Kerberos */
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk krb5_set_error_message(context, retval, dgettext(TEXT_DOMAIN,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk "rcache not owned by %d"),
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk retval = krb5_rc_io_read(context, d, (krb5_pointer) &rc_vno,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk if (d->fd >= 0)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkkrb5_rc_io_open(krb5_context context, krb5_rc_iostuff *d, char *fn)
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpkkrb5_rc_io_move(krb5_context context, krb5_rc_iostuff *new1,
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Initial work around provided by Tom Sanfilippo to work around
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * poor Windows emulation of POSIX functions. Rename and dup has
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * different semantics!
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Additional fixes and explanation provided by dalmeida@mit.edu:
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * First, we save the offset of "old". Then, we close and remove
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * the "new" file so we can do the rename. We also close "old" to
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * make sure the rename succeeds (though that might not be
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * necessary on some systems).
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Next, we do the rename. If all goes well, we seek the "new"
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * file to the position "old" was at.
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * --- WARNING!!! ---
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * Since "old" is now gone, we mourn its disappearance, but we
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * cannot emulate that Unix behavior... THIS BEHAVIOR IS
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * DIFFERENT FROM UNIX. However, it is ok because this function
45916cd2fec6e79bca5dee0421bd39e3c2910d1ejpk * gets called such that "old" gets closed right afterwards.
goto cleanup;
if (retval)
goto cleanup;
goto cleanup;
return retval;
return KRB5_RC_IO_UNKNOWN;
unsigned int num)
switch(errno)
#ifdef EDQUOT
case EDQUOT:
case EFBIG:
case ENOSPC:
return KRB5_RC_IO_SPACE;
case EIO:
return KRB5_RC_IO_IO;
case EBADF:
return KRB5_RC_IO_UNKNOWN;
#if defined(_WIN32)
#ifndef fsync
switch(errno)
return KRB5_RC_IO_UNKNOWN;
unsigned int num)
switch(errno)
case EBADF:
return KRB5_RC_IO_UNKNOWN;
return KRB5_RC_IO_EOF;
return KRB5_RC_IO_UNKNOWN;
switch(errno)
case EIO:
return KRB5_RC_IO_IO;
case EPERM:
case EBUSY:
case EROFS:
return KRB5_RC_IO_PERM;
case EBADF:
return KRB5_RC_IO_UNKNOWN;