1b528cefcSMark Murray /* 2c19800e8SDoug Rabson * Copyright (c) 1997 - 2008 Kungliga Tekniska H�gskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "krb5_locl.h" 35b528cefcSMark Murray 36c19800e8SDoug Rabson RCSID("$Id: fcache.c 22522 2008-01-24 11:56:25Z lha $"); 37b528cefcSMark Murray 38b528cefcSMark Murray typedef struct krb5_fcache{ 39b528cefcSMark Murray char *filename; 40b528cefcSMark Murray int version; 41b528cefcSMark Murray }krb5_fcache; 42b528cefcSMark Murray 43b528cefcSMark Murray struct fcc_cursor { 44b528cefcSMark Murray int fd; 45b528cefcSMark Murray krb5_storage *sp; 46b528cefcSMark Murray }; 47b528cefcSMark Murray 48b528cefcSMark Murray #define KRB5_FCC_FVNO_1 1 49b528cefcSMark Murray #define KRB5_FCC_FVNO_2 2 50b528cefcSMark Murray #define KRB5_FCC_FVNO_3 3 51b528cefcSMark Murray #define KRB5_FCC_FVNO_4 4 52b528cefcSMark Murray 53b528cefcSMark Murray #define FCC_TAG_DELTATIME 1 54b528cefcSMark Murray 55b528cefcSMark Murray #define FCACHE(X) ((krb5_fcache*)(X)->data.data) 56b528cefcSMark Murray 57b528cefcSMark Murray #define FILENAME(X) (FCACHE(X)->filename) 58b528cefcSMark Murray 59b528cefcSMark Murray #define FCC_CURSOR(C) ((struct fcc_cursor*)(C)) 60b528cefcSMark Murray 618373020dSJacques Vidrine static const char* 62b528cefcSMark Murray fcc_get_name(krb5_context context, 63b528cefcSMark Murray krb5_ccache id) 64b528cefcSMark Murray { 65b528cefcSMark Murray return FILENAME(id); 66b528cefcSMark Murray } 67b528cefcSMark Murray 681c43270aSJacques Vidrine int 691c43270aSJacques Vidrine _krb5_xlock(krb5_context context, int fd, krb5_boolean exclusive, 701c43270aSJacques Vidrine const char *filename) 711c43270aSJacques Vidrine { 721c43270aSJacques Vidrine int ret; 731c43270aSJacques Vidrine #ifdef HAVE_FCNTL 741c43270aSJacques Vidrine struct flock l; 751c43270aSJacques Vidrine 761c43270aSJacques Vidrine l.l_start = 0; 771c43270aSJacques Vidrine l.l_len = 0; 781c43270aSJacques Vidrine l.l_type = exclusive ? F_WRLCK : F_RDLCK; 791c43270aSJacques Vidrine l.l_whence = SEEK_SET; 801c43270aSJacques Vidrine ret = fcntl(fd, F_SETLKW, &l); 811c43270aSJacques Vidrine #else 821c43270aSJacques Vidrine ret = flock(fd, exclusive ? LOCK_EX : LOCK_SH); 831c43270aSJacques Vidrine #endif 841c43270aSJacques Vidrine if(ret < 0) 851c43270aSJacques Vidrine ret = errno; 861c43270aSJacques Vidrine if(ret == EACCES) /* fcntl can return EACCES instead of EAGAIN */ 871c43270aSJacques Vidrine ret = EAGAIN; 881c43270aSJacques Vidrine 891c43270aSJacques Vidrine switch (ret) { 901c43270aSJacques Vidrine case 0: 911c43270aSJacques Vidrine break; 921c43270aSJacques Vidrine case EINVAL: /* filesystem doesn't support locking, let the user have it */ 931c43270aSJacques Vidrine ret = 0; 941c43270aSJacques Vidrine break; 951c43270aSJacques Vidrine case EAGAIN: 961c43270aSJacques Vidrine krb5_set_error_string(context, "timed out locking cache file %s", 971c43270aSJacques Vidrine filename); 981c43270aSJacques Vidrine break; 991c43270aSJacques Vidrine default: 1001c43270aSJacques Vidrine krb5_set_error_string(context, "error locking cache file %s: %s", 1011c43270aSJacques Vidrine filename, strerror(ret)); 1021c43270aSJacques Vidrine break; 1031c43270aSJacques Vidrine } 1041c43270aSJacques Vidrine return ret; 1051c43270aSJacques Vidrine } 1061c43270aSJacques Vidrine 1071c43270aSJacques Vidrine int 108c19800e8SDoug Rabson _krb5_xunlock(krb5_context context, int fd) 1091c43270aSJacques Vidrine { 110c19800e8SDoug Rabson int ret; 111c19800e8SDoug Rabson #ifdef HAVE_FCNTL 1121c43270aSJacques Vidrine struct flock l; 1131c43270aSJacques Vidrine l.l_start = 0; 1141c43270aSJacques Vidrine l.l_len = 0; 1151c43270aSJacques Vidrine l.l_type = F_UNLCK; 1161c43270aSJacques Vidrine l.l_whence = SEEK_SET; 117c19800e8SDoug Rabson ret = fcntl(fd, F_SETLKW, &l); 1181c43270aSJacques Vidrine #else 119c19800e8SDoug Rabson ret = flock(fd, LOCK_UN); 1201c43270aSJacques Vidrine #endif 121c19800e8SDoug Rabson if (ret < 0) 122c19800e8SDoug Rabson ret = errno; 123c19800e8SDoug Rabson switch (ret) { 124c19800e8SDoug Rabson case 0: 125c19800e8SDoug Rabson break; 126c19800e8SDoug Rabson case EINVAL: /* filesystem doesn't support locking, let the user have it */ 127c19800e8SDoug Rabson ret = 0; 128c19800e8SDoug Rabson break; 129c19800e8SDoug Rabson default: 130c19800e8SDoug Rabson krb5_set_error_string(context, 131c19800e8SDoug Rabson "Failed to unlock file: %s", strerror(ret)); 132c19800e8SDoug Rabson break; 133c19800e8SDoug Rabson } 134c19800e8SDoug Rabson return ret; 1351c43270aSJacques Vidrine } 1361c43270aSJacques Vidrine 1371c43270aSJacques Vidrine static krb5_error_code 1381c43270aSJacques Vidrine fcc_lock(krb5_context context, krb5_ccache id, 1391c43270aSJacques Vidrine int fd, krb5_boolean exclusive) 1401c43270aSJacques Vidrine { 1411c43270aSJacques Vidrine return _krb5_xlock(context, fd, exclusive, fcc_get_name(context, id)); 1421c43270aSJacques Vidrine } 1431c43270aSJacques Vidrine 1441c43270aSJacques Vidrine static krb5_error_code 1451c43270aSJacques Vidrine fcc_unlock(krb5_context context, int fd) 1461c43270aSJacques Vidrine { 147c19800e8SDoug Rabson return _krb5_xunlock(context, fd); 1481c43270aSJacques Vidrine } 1491c43270aSJacques Vidrine 150b528cefcSMark Murray static krb5_error_code 151b528cefcSMark Murray fcc_resolve(krb5_context context, krb5_ccache *id, const char *res) 152b528cefcSMark Murray { 153b528cefcSMark Murray krb5_fcache *f; 154b528cefcSMark Murray f = malloc(sizeof(*f)); 155adb0ddaeSAssar Westerlund if(f == NULL) { 156adb0ddaeSAssar Westerlund krb5_set_error_string(context, "malloc: out of memory"); 157b528cefcSMark Murray return KRB5_CC_NOMEM; 158adb0ddaeSAssar Westerlund } 159b528cefcSMark Murray f->filename = strdup(res); 160b528cefcSMark Murray if(f->filename == NULL){ 161b528cefcSMark Murray free(f); 162adb0ddaeSAssar Westerlund krb5_set_error_string(context, "malloc: out of memory"); 163b528cefcSMark Murray return KRB5_CC_NOMEM; 164b528cefcSMark Murray } 165b528cefcSMark Murray f->version = 0; 166b528cefcSMark Murray (*id)->data.data = f; 167b528cefcSMark Murray (*id)->data.length = sizeof(*f); 168b528cefcSMark Murray return 0; 169b528cefcSMark Murray } 170b528cefcSMark Murray 1715e9cd1aeSAssar Westerlund /* 1725e9cd1aeSAssar Westerlund * Try to scrub the contents of `filename' safely. 1735e9cd1aeSAssar Westerlund */ 1745e9cd1aeSAssar Westerlund 1755e9cd1aeSAssar Westerlund static int 1765e9cd1aeSAssar Westerlund scrub_file (int fd) 1775e9cd1aeSAssar Westerlund { 1785e9cd1aeSAssar Westerlund off_t pos; 1795e9cd1aeSAssar Westerlund char buf[128]; 1805e9cd1aeSAssar Westerlund 1815e9cd1aeSAssar Westerlund pos = lseek(fd, 0, SEEK_END); 1825e9cd1aeSAssar Westerlund if (pos < 0) 1835e9cd1aeSAssar Westerlund return errno; 1845e9cd1aeSAssar Westerlund if (lseek(fd, 0, SEEK_SET) < 0) 1855e9cd1aeSAssar Westerlund return errno; 1865e9cd1aeSAssar Westerlund memset(buf, 0, sizeof(buf)); 1875e9cd1aeSAssar Westerlund while(pos > 0) { 1885e9cd1aeSAssar Westerlund ssize_t tmp = write(fd, buf, min(sizeof(buf), pos)); 1895e9cd1aeSAssar Westerlund 1905e9cd1aeSAssar Westerlund if (tmp < 0) 1915e9cd1aeSAssar Westerlund return errno; 1925e9cd1aeSAssar Westerlund pos -= tmp; 1935e9cd1aeSAssar Westerlund } 1945e9cd1aeSAssar Westerlund fsync (fd); 1955e9cd1aeSAssar Westerlund return 0; 1965e9cd1aeSAssar Westerlund } 1975e9cd1aeSAssar Westerlund 1985e9cd1aeSAssar Westerlund /* 1995e9cd1aeSAssar Westerlund * Erase `filename' if it exists, trying to remove the contents if 2005e9cd1aeSAssar Westerlund * it's `safe'. We always try to remove the file, it it exists. It's 2015e9cd1aeSAssar Westerlund * only overwritten if it's a regular file (not a symlink and not a 2025e9cd1aeSAssar Westerlund * hardlink) 2035e9cd1aeSAssar Westerlund */ 2045e9cd1aeSAssar Westerlund 205b528cefcSMark Murray static krb5_error_code 206b528cefcSMark Murray erase_file(const char *filename) 207b528cefcSMark Murray { 208b528cefcSMark Murray int fd; 2095e9cd1aeSAssar Westerlund struct stat sb1, sb2; 2105e9cd1aeSAssar Westerlund int ret; 2115e9cd1aeSAssar Westerlund 2125e9cd1aeSAssar Westerlund ret = lstat (filename, &sb1); 2135e9cd1aeSAssar Westerlund if (ret < 0) 2145e9cd1aeSAssar Westerlund return errno; 215b528cefcSMark Murray 216b528cefcSMark Murray fd = open(filename, O_RDWR | O_BINARY); 217b528cefcSMark Murray if(fd < 0) { 218b528cefcSMark Murray if(errno == ENOENT) 219b528cefcSMark Murray return 0; 220b528cefcSMark Murray else 221b528cefcSMark Murray return errno; 222b528cefcSMark Murray } 2235e9cd1aeSAssar Westerlund if (unlink(filename) < 0) { 224b528cefcSMark Murray close (fd); 2255e9cd1aeSAssar Westerlund return errno; 2265e9cd1aeSAssar Westerlund } 2275e9cd1aeSAssar Westerlund ret = fstat (fd, &sb2); 2285e9cd1aeSAssar Westerlund if (ret < 0) { 2295e9cd1aeSAssar Westerlund close (fd); 2305e9cd1aeSAssar Westerlund return errno; 2315e9cd1aeSAssar Westerlund } 2325e9cd1aeSAssar Westerlund 2335e9cd1aeSAssar Westerlund /* check if someone was playing with symlinks */ 2345e9cd1aeSAssar Westerlund 2355e9cd1aeSAssar Westerlund if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) { 2365e9cd1aeSAssar Westerlund close (fd); 2375e9cd1aeSAssar Westerlund return EPERM; 2385e9cd1aeSAssar Westerlund } 2395e9cd1aeSAssar Westerlund 2405e9cd1aeSAssar Westerlund /* there are still hard links to this file */ 2415e9cd1aeSAssar Westerlund 2425e9cd1aeSAssar Westerlund if (sb2.st_nlink != 0) { 2435e9cd1aeSAssar Westerlund close (fd); 244b528cefcSMark Murray return 0; 245b528cefcSMark Murray } 246b528cefcSMark Murray 2475e9cd1aeSAssar Westerlund ret = scrub_file (fd); 2485e9cd1aeSAssar Westerlund close (fd); 2495e9cd1aeSAssar Westerlund return ret; 2505e9cd1aeSAssar Westerlund } 2515e9cd1aeSAssar Westerlund 252b528cefcSMark Murray static krb5_error_code 253b528cefcSMark Murray fcc_gen_new(krb5_context context, krb5_ccache *id) 254b528cefcSMark Murray { 255b528cefcSMark Murray krb5_fcache *f; 256b528cefcSMark Murray int fd; 257b528cefcSMark Murray char *file; 258adb0ddaeSAssar Westerlund 259b528cefcSMark Murray f = malloc(sizeof(*f)); 260adb0ddaeSAssar Westerlund if(f == NULL) { 261adb0ddaeSAssar Westerlund krb5_set_error_string(context, "malloc: out of memory"); 262b528cefcSMark Murray return KRB5_CC_NOMEM; 263adb0ddaeSAssar Westerlund } 2645e9cd1aeSAssar Westerlund asprintf (&file, "%sXXXXXX", KRB5_DEFAULT_CCFILE_ROOT); 265b528cefcSMark Murray if(file == NULL) { 266b528cefcSMark Murray free(f); 267adb0ddaeSAssar Westerlund krb5_set_error_string(context, "malloc: out of memory"); 268b528cefcSMark Murray return KRB5_CC_NOMEM; 269b528cefcSMark Murray } 270b528cefcSMark Murray fd = mkstemp(file); 271b528cefcSMark Murray if(fd < 0) { 272c19800e8SDoug Rabson int ret = errno; 273c19800e8SDoug Rabson krb5_set_error_string(context, "mkstemp %s", file); 274b528cefcSMark Murray free(f); 275b528cefcSMark Murray free(file); 276c19800e8SDoug Rabson return ret; 277b528cefcSMark Murray } 278b528cefcSMark Murray close(fd); 279b528cefcSMark Murray f->filename = file; 280b528cefcSMark Murray f->version = 0; 281b528cefcSMark Murray (*id)->data.data = f; 282b528cefcSMark Murray (*id)->data.length = sizeof(*f); 283b528cefcSMark Murray return 0; 284b528cefcSMark Murray } 285b528cefcSMark Murray 286b528cefcSMark Murray static void 287b528cefcSMark Murray storage_set_flags(krb5_context context, krb5_storage *sp, int vno) 288b528cefcSMark Murray { 289b528cefcSMark Murray int flags = 0; 290b528cefcSMark Murray switch(vno) { 291b528cefcSMark Murray case KRB5_FCC_FVNO_1: 292b528cefcSMark Murray flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS; 293b528cefcSMark Murray flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE; 294b528cefcSMark Murray flags |= KRB5_STORAGE_HOST_BYTEORDER; 295b528cefcSMark Murray break; 296b528cefcSMark Murray case KRB5_FCC_FVNO_2: 297b528cefcSMark Murray flags |= KRB5_STORAGE_HOST_BYTEORDER; 298b528cefcSMark Murray break; 299b528cefcSMark Murray case KRB5_FCC_FVNO_3: 300b528cefcSMark Murray flags |= KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE; 301b528cefcSMark Murray break; 302b528cefcSMark Murray case KRB5_FCC_FVNO_4: 303b528cefcSMark Murray break; 304b528cefcSMark Murray default: 305b528cefcSMark Murray krb5_abortx(context, 306b528cefcSMark Murray "storage_set_flags called with bad vno (%x)", vno); 307b528cefcSMark Murray } 308b528cefcSMark Murray krb5_storage_set_flags(sp, flags); 309b528cefcSMark Murray } 310b528cefcSMark Murray 311b528cefcSMark Murray static krb5_error_code 3121c43270aSJacques Vidrine fcc_open(krb5_context context, 3131c43270aSJacques Vidrine krb5_ccache id, 3141c43270aSJacques Vidrine int *fd_ret, 3151c43270aSJacques Vidrine int flags, 3161c43270aSJacques Vidrine mode_t mode) 3171c43270aSJacques Vidrine { 3181c43270aSJacques Vidrine krb5_boolean exclusive = ((flags | O_WRONLY) == flags || 3191c43270aSJacques Vidrine (flags | O_RDWR) == flags); 3201c43270aSJacques Vidrine krb5_error_code ret; 3211c43270aSJacques Vidrine const char *filename = FILENAME(id); 3221c43270aSJacques Vidrine int fd; 3231c43270aSJacques Vidrine fd = open(filename, flags, mode); 3241c43270aSJacques Vidrine if(fd < 0) { 3251c43270aSJacques Vidrine ret = errno; 3261c43270aSJacques Vidrine krb5_set_error_string(context, "open(%s): %s", filename, 3271c43270aSJacques Vidrine strerror(ret)); 3281c43270aSJacques Vidrine return ret; 3291c43270aSJacques Vidrine } 3301c43270aSJacques Vidrine 3311c43270aSJacques Vidrine if((ret = fcc_lock(context, id, fd, exclusive)) != 0) { 3321c43270aSJacques Vidrine close(fd); 3331c43270aSJacques Vidrine return ret; 3341c43270aSJacques Vidrine } 3351c43270aSJacques Vidrine *fd_ret = fd; 3361c43270aSJacques Vidrine return 0; 3371c43270aSJacques Vidrine } 3381c43270aSJacques Vidrine 3391c43270aSJacques Vidrine static krb5_error_code 340b528cefcSMark Murray fcc_initialize(krb5_context context, 341b528cefcSMark Murray krb5_ccache id, 342b528cefcSMark Murray krb5_principal primary_principal) 343b528cefcSMark Murray { 344b528cefcSMark Murray krb5_fcache *f = FCACHE(id); 3455e9cd1aeSAssar Westerlund int ret = 0; 346b528cefcSMark Murray int fd; 347b528cefcSMark Murray char *filename = f->filename; 348b528cefcSMark Murray 3495e9cd1aeSAssar Westerlund unlink (filename); 350b528cefcSMark Murray 3511c43270aSJacques Vidrine ret = fcc_open(context, id, &fd, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); 3521c43270aSJacques Vidrine if(ret) 353adb0ddaeSAssar Westerlund return ret; 354b528cefcSMark Murray { 355b528cefcSMark Murray krb5_storage *sp; 356b528cefcSMark Murray sp = krb5_storage_from_fd(fd); 3578373020dSJacques Vidrine krb5_storage_set_eof_code(sp, KRB5_CC_END); 358b528cefcSMark Murray if(context->fcache_vno != 0) 359b528cefcSMark Murray f->version = context->fcache_vno; 360b528cefcSMark Murray else 361b528cefcSMark Murray f->version = KRB5_FCC_FVNO_4; 3625e9cd1aeSAssar Westerlund ret |= krb5_store_int8(sp, 5); 3635e9cd1aeSAssar Westerlund ret |= krb5_store_int8(sp, f->version); 364b528cefcSMark Murray storage_set_flags(context, sp, f->version); 3655e9cd1aeSAssar Westerlund if(f->version == KRB5_FCC_FVNO_4 && ret == 0) { 366b528cefcSMark Murray /* V4 stuff */ 367b528cefcSMark Murray if (context->kdc_sec_offset) { 3685e9cd1aeSAssar Westerlund ret |= krb5_store_int16 (sp, 12); /* length */ 3695e9cd1aeSAssar Westerlund ret |= krb5_store_int16 (sp, FCC_TAG_DELTATIME); /* Tag */ 3705e9cd1aeSAssar Westerlund ret |= krb5_store_int16 (sp, 8); /* length of data */ 3715e9cd1aeSAssar Westerlund ret |= krb5_store_int32 (sp, context->kdc_sec_offset); 3725e9cd1aeSAssar Westerlund ret |= krb5_store_int32 (sp, context->kdc_usec_offset); 373b528cefcSMark Murray } else { 3745e9cd1aeSAssar Westerlund ret |= krb5_store_int16 (sp, 0); 375b528cefcSMark Murray } 376b528cefcSMark Murray } 3775e9cd1aeSAssar Westerlund ret |= krb5_store_principal(sp, primary_principal); 3781c43270aSJacques Vidrine 379b528cefcSMark Murray krb5_storage_free(sp); 380b528cefcSMark Murray } 3811c43270aSJacques Vidrine fcc_unlock(context, fd); 3825e9cd1aeSAssar Westerlund if (close(fd) < 0) 383adb0ddaeSAssar Westerlund if (ret == 0) { 3845e9cd1aeSAssar Westerlund ret = errno; 3851c43270aSJacques Vidrine krb5_set_error_string (context, "close %s: %s", 3861c43270aSJacques Vidrine FILENAME(id), strerror(ret)); 387adb0ddaeSAssar Westerlund } 3885e9cd1aeSAssar Westerlund return ret; 389b528cefcSMark Murray } 390b528cefcSMark Murray 391b528cefcSMark Murray static krb5_error_code 392b528cefcSMark Murray fcc_close(krb5_context context, 393b528cefcSMark Murray krb5_ccache id) 394b528cefcSMark Murray { 395b528cefcSMark Murray free (FILENAME(id)); 396b528cefcSMark Murray krb5_data_free(&id->data); 397b528cefcSMark Murray return 0; 398b528cefcSMark Murray } 399b528cefcSMark Murray 400b528cefcSMark Murray static krb5_error_code 401b528cefcSMark Murray fcc_destroy(krb5_context context, 402b528cefcSMark Murray krb5_ccache id) 403b528cefcSMark Murray { 4041c43270aSJacques Vidrine erase_file(FILENAME(id)); 405b528cefcSMark Murray return 0; 406b528cefcSMark Murray } 407b528cefcSMark Murray 408b528cefcSMark Murray static krb5_error_code 409b528cefcSMark Murray fcc_store_cred(krb5_context context, 410b528cefcSMark Murray krb5_ccache id, 411b528cefcSMark Murray krb5_creds *creds) 412b528cefcSMark Murray { 4135e9cd1aeSAssar Westerlund int ret; 414b528cefcSMark Murray int fd; 415b528cefcSMark Murray 4161c43270aSJacques Vidrine ret = fcc_open(context, id, &fd, O_WRONLY | O_APPEND | O_BINARY, 0); 4171c43270aSJacques Vidrine if(ret) 418adb0ddaeSAssar Westerlund return ret; 419b528cefcSMark Murray { 420b528cefcSMark Murray krb5_storage *sp; 421b528cefcSMark Murray sp = krb5_storage_from_fd(fd); 4228373020dSJacques Vidrine krb5_storage_set_eof_code(sp, KRB5_CC_END); 423b528cefcSMark Murray storage_set_flags(context, sp, FCACHE(id)->version); 424c19800e8SDoug Rabson if (!krb5_config_get_bool_default(context, NULL, TRUE, 4251c43270aSJacques Vidrine "libdefaults", 4261c43270aSJacques Vidrine "fcc-mit-ticketflags", 4271c43270aSJacques Vidrine NULL)) 428c19800e8SDoug Rabson krb5_storage_set_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER); 429c19800e8SDoug Rabson ret = krb5_store_creds(sp, creds); 430b528cefcSMark Murray krb5_storage_free(sp); 431b528cefcSMark Murray } 4321c43270aSJacques Vidrine fcc_unlock(context, fd); 4335e9cd1aeSAssar Westerlund if (close(fd) < 0) 434adb0ddaeSAssar Westerlund if (ret == 0) { 4355e9cd1aeSAssar Westerlund ret = errno; 4361c43270aSJacques Vidrine krb5_set_error_string (context, "close %s: %s", 4371c43270aSJacques Vidrine FILENAME(id), strerror(ret)); 438adb0ddaeSAssar Westerlund } 4395e9cd1aeSAssar Westerlund return ret; 440b528cefcSMark Murray } 441b528cefcSMark Murray 442b528cefcSMark Murray static krb5_error_code 443b528cefcSMark Murray init_fcc (krb5_context context, 4441c43270aSJacques Vidrine krb5_ccache id, 445b528cefcSMark Murray krb5_storage **ret_sp, 446b528cefcSMark Murray int *ret_fd) 447b528cefcSMark Murray { 448b528cefcSMark Murray int fd; 449b528cefcSMark Murray int8_t pvno, tag; 450b528cefcSMark Murray krb5_storage *sp; 4515e9cd1aeSAssar Westerlund krb5_error_code ret; 452b528cefcSMark Murray 4531c43270aSJacques Vidrine ret = fcc_open(context, id, &fd, O_RDONLY | O_BINARY, 0); 4545e9cd1aeSAssar Westerlund if(ret) 4555e9cd1aeSAssar Westerlund return ret; 4561c43270aSJacques Vidrine 4571c43270aSJacques Vidrine sp = krb5_storage_from_fd(fd); 4581c43270aSJacques Vidrine if(sp == NULL) { 459c19800e8SDoug Rabson krb5_clear_error_string(context); 4601c43270aSJacques Vidrine ret = ENOMEM; 4611c43270aSJacques Vidrine goto out; 462b528cefcSMark Murray } 4631c43270aSJacques Vidrine krb5_storage_set_eof_code(sp, KRB5_CC_END); 4641c43270aSJacques Vidrine ret = krb5_ret_int8(sp, &pvno); 4651c43270aSJacques Vidrine if(ret != 0) { 466c19800e8SDoug Rabson if(ret == KRB5_CC_END) { 467c19800e8SDoug Rabson krb5_set_error_string(context, "Empty credential cache file: %s", 468c19800e8SDoug Rabson FILENAME(id)); 469c19800e8SDoug Rabson ret = ENOENT; 470c19800e8SDoug Rabson } else 471c19800e8SDoug Rabson krb5_set_error_string(context, "Error reading pvno in " 472c19800e8SDoug Rabson "cache file: %s", FILENAME(id)); 4731c43270aSJacques Vidrine goto out; 4741c43270aSJacques Vidrine } 4751c43270aSJacques Vidrine if(pvno != 5) { 476c19800e8SDoug Rabson krb5_set_error_string(context, "Bad version number in credential " 477c19800e8SDoug Rabson "cache file: %s", FILENAME(id)); 4781c43270aSJacques Vidrine ret = KRB5_CCACHE_BADVNO; 4791c43270aSJacques Vidrine goto out; 4801c43270aSJacques Vidrine } 4811c43270aSJacques Vidrine ret = krb5_ret_int8(sp, &tag); /* should not be host byte order */ 4821c43270aSJacques Vidrine if(ret != 0) { 483c19800e8SDoug Rabson krb5_set_error_string(context, "Error reading tag in " 484c19800e8SDoug Rabson "cache file: %s", FILENAME(id)); 4851c43270aSJacques Vidrine ret = KRB5_CC_FORMAT; 4861c43270aSJacques Vidrine goto out; 4871c43270aSJacques Vidrine } 4881c43270aSJacques Vidrine FCACHE(id)->version = tag; 4891c43270aSJacques Vidrine storage_set_flags(context, sp, FCACHE(id)->version); 490b528cefcSMark Murray switch (tag) { 491b528cefcSMark Murray case KRB5_FCC_FVNO_4: { 492b528cefcSMark Murray int16_t length; 493b528cefcSMark Murray 4941c43270aSJacques Vidrine ret = krb5_ret_int16 (sp, &length); 4951c43270aSJacques Vidrine if(ret) { 4961c43270aSJacques Vidrine ret = KRB5_CC_FORMAT; 497c19800e8SDoug Rabson krb5_set_error_string(context, "Error reading tag length in " 498c19800e8SDoug Rabson "cache file: %s", FILENAME(id)); 4991c43270aSJacques Vidrine goto out; 5001c43270aSJacques Vidrine } 501b528cefcSMark Murray while(length > 0) { 502c19800e8SDoug Rabson int16_t dtag, data_len; 503b528cefcSMark Murray int i; 504b528cefcSMark Murray int8_t dummy; 505b528cefcSMark Murray 506c19800e8SDoug Rabson ret = krb5_ret_int16 (sp, &dtag); 5071c43270aSJacques Vidrine if(ret) { 508c19800e8SDoug Rabson krb5_set_error_string(context, "Error reading dtag in " 509c19800e8SDoug Rabson "cache file: %s", FILENAME(id)); 5101c43270aSJacques Vidrine ret = KRB5_CC_FORMAT; 5111c43270aSJacques Vidrine goto out; 5121c43270aSJacques Vidrine } 5131c43270aSJacques Vidrine ret = krb5_ret_int16 (sp, &data_len); 5141c43270aSJacques Vidrine if(ret) { 515c19800e8SDoug Rabson krb5_set_error_string(context, "Error reading dlength in " 516c19800e8SDoug Rabson "cache file: %s", FILENAME(id)); 5171c43270aSJacques Vidrine ret = KRB5_CC_FORMAT; 5181c43270aSJacques Vidrine goto out; 5191c43270aSJacques Vidrine } 520c19800e8SDoug Rabson switch (dtag) { 521b528cefcSMark Murray case FCC_TAG_DELTATIME : 5221c43270aSJacques Vidrine ret = krb5_ret_int32 (sp, &context->kdc_sec_offset); 5231c43270aSJacques Vidrine if(ret) { 524c19800e8SDoug Rabson krb5_set_error_string(context, "Error reading kdc_sec in " 525c19800e8SDoug Rabson "cache file: %s", FILENAME(id)); 5261c43270aSJacques Vidrine ret = KRB5_CC_FORMAT; 5271c43270aSJacques Vidrine goto out; 5281c43270aSJacques Vidrine } 5291c43270aSJacques Vidrine ret = krb5_ret_int32 (sp, &context->kdc_usec_offset); 5301c43270aSJacques Vidrine if(ret) { 531c19800e8SDoug Rabson krb5_set_error_string(context, "Error reading kdc_usec in " 532c19800e8SDoug Rabson "cache file: %s", FILENAME(id)); 5331c43270aSJacques Vidrine ret = KRB5_CC_FORMAT; 5341c43270aSJacques Vidrine goto out; 5351c43270aSJacques Vidrine } 536b528cefcSMark Murray break; 537b528cefcSMark Murray default : 5381c43270aSJacques Vidrine for (i = 0; i < data_len; ++i) { 5391c43270aSJacques Vidrine ret = krb5_ret_int8 (sp, &dummy); 5401c43270aSJacques Vidrine if(ret) { 541c19800e8SDoug Rabson krb5_set_error_string(context, "Error reading unknown " 542c19800e8SDoug Rabson "tag in cache file: %s", 543c19800e8SDoug Rabson FILENAME(id)); 5441c43270aSJacques Vidrine ret = KRB5_CC_FORMAT; 5451c43270aSJacques Vidrine goto out; 5461c43270aSJacques Vidrine } 5471c43270aSJacques Vidrine } 548b528cefcSMark Murray break; 549b528cefcSMark Murray } 550b528cefcSMark Murray length -= 4 + data_len; 551b528cefcSMark Murray } 552b528cefcSMark Murray break; 553b528cefcSMark Murray } 554b528cefcSMark Murray case KRB5_FCC_FVNO_3: 555b528cefcSMark Murray case KRB5_FCC_FVNO_2: 556b528cefcSMark Murray case KRB5_FCC_FVNO_1: 557b528cefcSMark Murray break; 558b528cefcSMark Murray default : 5591c43270aSJacques Vidrine ret = KRB5_CCACHE_BADVNO; 560c19800e8SDoug Rabson krb5_set_error_string(context, "Unknown version number (%d) in " 561c19800e8SDoug Rabson "credential cache file: %s", 562c19800e8SDoug Rabson (int)tag, FILENAME(id)); 5631c43270aSJacques Vidrine goto out; 564b528cefcSMark Murray } 565b528cefcSMark Murray *ret_sp = sp; 566b528cefcSMark Murray *ret_fd = fd; 5671c43270aSJacques Vidrine 568b528cefcSMark Murray return 0; 5691c43270aSJacques Vidrine out: 5701c43270aSJacques Vidrine if(sp != NULL) 5711c43270aSJacques Vidrine krb5_storage_free(sp); 5721c43270aSJacques Vidrine fcc_unlock(context, fd); 5731c43270aSJacques Vidrine close(fd); 5741c43270aSJacques Vidrine return ret; 575b528cefcSMark Murray } 576b528cefcSMark Murray 577b528cefcSMark Murray static krb5_error_code 578b528cefcSMark Murray fcc_get_principal(krb5_context context, 579b528cefcSMark Murray krb5_ccache id, 580b528cefcSMark Murray krb5_principal *principal) 581b528cefcSMark Murray { 582b528cefcSMark Murray krb5_error_code ret; 583b528cefcSMark Murray int fd; 584b528cefcSMark Murray krb5_storage *sp; 585b528cefcSMark Murray 5861c43270aSJacques Vidrine ret = init_fcc (context, id, &sp, &fd); 587b528cefcSMark Murray if (ret) 588b528cefcSMark Murray return ret; 5895e9cd1aeSAssar Westerlund ret = krb5_ret_principal(sp, principal); 590c19800e8SDoug Rabson if (ret) 591c19800e8SDoug Rabson krb5_clear_error_string(context); 592b528cefcSMark Murray krb5_storage_free(sp); 5931c43270aSJacques Vidrine fcc_unlock(context, fd); 594b528cefcSMark Murray close(fd); 5955e9cd1aeSAssar Westerlund return ret; 596b528cefcSMark Murray } 597b528cefcSMark Murray 598b528cefcSMark Murray static krb5_error_code 5991c43270aSJacques Vidrine fcc_end_get (krb5_context context, 6001c43270aSJacques Vidrine krb5_ccache id, 6011c43270aSJacques Vidrine krb5_cc_cursor *cursor); 6021c43270aSJacques Vidrine 6031c43270aSJacques Vidrine static krb5_error_code 604b528cefcSMark Murray fcc_get_first (krb5_context context, 605b528cefcSMark Murray krb5_ccache id, 606b528cefcSMark Murray krb5_cc_cursor *cursor) 607b528cefcSMark Murray { 608b528cefcSMark Murray krb5_error_code ret; 609b528cefcSMark Murray krb5_principal principal; 610b528cefcSMark Murray 611b528cefcSMark Murray *cursor = malloc(sizeof(struct fcc_cursor)); 612c19800e8SDoug Rabson if (*cursor == NULL) { 613c19800e8SDoug Rabson krb5_set_error_string (context, "malloc: out of memory"); 614c19800e8SDoug Rabson return ENOMEM; 615c19800e8SDoug Rabson } 616c19800e8SDoug Rabson memset(*cursor, 0, sizeof(struct fcc_cursor)); 617b528cefcSMark Murray 6181c43270aSJacques Vidrine ret = init_fcc (context, id, &FCC_CURSOR(*cursor)->sp, 619b528cefcSMark Murray &FCC_CURSOR(*cursor)->fd); 6201c43270aSJacques Vidrine if (ret) { 6211c43270aSJacques Vidrine free(*cursor); 622c19800e8SDoug Rabson *cursor = NULL; 623b528cefcSMark Murray return ret; 6241c43270aSJacques Vidrine } 6251c43270aSJacques Vidrine ret = krb5_ret_principal (FCC_CURSOR(*cursor)->sp, &principal); 6261c43270aSJacques Vidrine if(ret) { 627c19800e8SDoug Rabson krb5_clear_error_string(context); 6281c43270aSJacques Vidrine fcc_end_get(context, id, cursor); 6291c43270aSJacques Vidrine return ret; 6301c43270aSJacques Vidrine } 631b528cefcSMark Murray krb5_free_principal (context, principal); 6321c43270aSJacques Vidrine fcc_unlock(context, FCC_CURSOR(*cursor)->fd); 633b528cefcSMark Murray return 0; 634b528cefcSMark Murray } 635b528cefcSMark Murray 636b528cefcSMark Murray static krb5_error_code 637b528cefcSMark Murray fcc_get_next (krb5_context context, 638b528cefcSMark Murray krb5_ccache id, 639b528cefcSMark Murray krb5_cc_cursor *cursor, 640b528cefcSMark Murray krb5_creds *creds) 641b528cefcSMark Murray { 6421c43270aSJacques Vidrine krb5_error_code ret; 6431c43270aSJacques Vidrine if((ret = fcc_lock(context, id, FCC_CURSOR(*cursor)->fd, FALSE)) != 0) 6441c43270aSJacques Vidrine return ret; 6451c43270aSJacques Vidrine 6461c43270aSJacques Vidrine ret = krb5_ret_creds(FCC_CURSOR(*cursor)->sp, creds); 647c19800e8SDoug Rabson if (ret) 648c19800e8SDoug Rabson krb5_clear_error_string(context); 6491c43270aSJacques Vidrine 6501c43270aSJacques Vidrine fcc_unlock(context, FCC_CURSOR(*cursor)->fd); 6511c43270aSJacques Vidrine return ret; 652b528cefcSMark Murray } 653b528cefcSMark Murray 654b528cefcSMark Murray static krb5_error_code 655b528cefcSMark Murray fcc_end_get (krb5_context context, 656b528cefcSMark Murray krb5_ccache id, 657b528cefcSMark Murray krb5_cc_cursor *cursor) 658b528cefcSMark Murray { 659b528cefcSMark Murray krb5_storage_free(FCC_CURSOR(*cursor)->sp); 660b528cefcSMark Murray close (FCC_CURSOR(*cursor)->fd); 661b528cefcSMark Murray free(*cursor); 6621c43270aSJacques Vidrine *cursor = NULL; 663b528cefcSMark Murray return 0; 664b528cefcSMark Murray } 665b528cefcSMark Murray 666b528cefcSMark Murray static krb5_error_code 667b528cefcSMark Murray fcc_remove_cred(krb5_context context, 668b528cefcSMark Murray krb5_ccache id, 669b528cefcSMark Murray krb5_flags which, 670b528cefcSMark Murray krb5_creds *cred) 671b528cefcSMark Murray { 672c19800e8SDoug Rabson krb5_error_code ret; 673c19800e8SDoug Rabson krb5_ccache copy; 674c19800e8SDoug Rabson 675c19800e8SDoug Rabson ret = krb5_cc_gen_new(context, &krb5_mcc_ops, ©); 676c19800e8SDoug Rabson if (ret) 677c19800e8SDoug Rabson return ret; 678c19800e8SDoug Rabson 679c19800e8SDoug Rabson ret = krb5_cc_copy_cache(context, id, copy); 680c19800e8SDoug Rabson if (ret) { 681c19800e8SDoug Rabson krb5_cc_destroy(context, copy); 682c19800e8SDoug Rabson return ret; 683c19800e8SDoug Rabson } 684c19800e8SDoug Rabson 685c19800e8SDoug Rabson ret = krb5_cc_remove_cred(context, copy, which, cred); 686c19800e8SDoug Rabson if (ret) { 687c19800e8SDoug Rabson krb5_cc_destroy(context, copy); 688c19800e8SDoug Rabson return ret; 689c19800e8SDoug Rabson } 690c19800e8SDoug Rabson 691c19800e8SDoug Rabson fcc_destroy(context, id); 692c19800e8SDoug Rabson 693c19800e8SDoug Rabson ret = krb5_cc_copy_cache(context, copy, id); 694c19800e8SDoug Rabson krb5_cc_destroy(context, copy); 695c19800e8SDoug Rabson 696c19800e8SDoug Rabson return ret; 697b528cefcSMark Murray } 698b528cefcSMark Murray 699b528cefcSMark Murray static krb5_error_code 700b528cefcSMark Murray fcc_set_flags(krb5_context context, 701b528cefcSMark Murray krb5_ccache id, 702b528cefcSMark Murray krb5_flags flags) 703b528cefcSMark Murray { 704b528cefcSMark Murray return 0; /* XXX */ 705b528cefcSMark Murray } 706b528cefcSMark Murray 707b528cefcSMark Murray static krb5_error_code 708b528cefcSMark Murray fcc_get_version(krb5_context context, 709b528cefcSMark Murray krb5_ccache id) 710b528cefcSMark Murray { 711b528cefcSMark Murray return FCACHE(id)->version; 712b528cefcSMark Murray } 713b528cefcSMark Murray 714c19800e8SDoug Rabson struct fcache_iter { 715c19800e8SDoug Rabson int first; 716c19800e8SDoug Rabson }; 717c19800e8SDoug Rabson 718c19800e8SDoug Rabson static krb5_error_code 719c19800e8SDoug Rabson fcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) 720c19800e8SDoug Rabson { 721c19800e8SDoug Rabson struct fcache_iter *iter; 722c19800e8SDoug Rabson 723c19800e8SDoug Rabson iter = calloc(1, sizeof(*iter)); 724c19800e8SDoug Rabson if (iter == NULL) { 725c19800e8SDoug Rabson krb5_set_error_string(context, "malloc - out of memory"); 726c19800e8SDoug Rabson return ENOMEM; 727c19800e8SDoug Rabson } 728c19800e8SDoug Rabson iter->first = 1; 729c19800e8SDoug Rabson *cursor = iter; 730c19800e8SDoug Rabson return 0; 731c19800e8SDoug Rabson } 732c19800e8SDoug Rabson 733c19800e8SDoug Rabson static krb5_error_code 734c19800e8SDoug Rabson fcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) 735c19800e8SDoug Rabson { 736c19800e8SDoug Rabson struct fcache_iter *iter = cursor; 737c19800e8SDoug Rabson krb5_error_code ret; 738c19800e8SDoug Rabson const char *fn; 739c19800e8SDoug Rabson char *expandedfn = NULL; 740c19800e8SDoug Rabson 741c19800e8SDoug Rabson if (!iter->first) { 742c19800e8SDoug Rabson krb5_clear_error_string(context); 743c19800e8SDoug Rabson return KRB5_CC_END; 744c19800e8SDoug Rabson } 745c19800e8SDoug Rabson iter->first = 0; 746c19800e8SDoug Rabson 747c19800e8SDoug Rabson fn = krb5_cc_default_name(context); 748c19800e8SDoug Rabson if (strncasecmp(fn, "FILE:", 5) != 0) { 749c19800e8SDoug Rabson ret = _krb5_expand_default_cc_name(context, 750c19800e8SDoug Rabson KRB5_DEFAULT_CCNAME_FILE, 751c19800e8SDoug Rabson &expandedfn); 752c19800e8SDoug Rabson if (ret) 753c19800e8SDoug Rabson return ret; 754c19800e8SDoug Rabson } 755c19800e8SDoug Rabson ret = krb5_cc_resolve(context, fn, id); 756c19800e8SDoug Rabson if (expandedfn) 757c19800e8SDoug Rabson free(expandedfn); 758c19800e8SDoug Rabson 759c19800e8SDoug Rabson return ret; 760c19800e8SDoug Rabson } 761c19800e8SDoug Rabson 762c19800e8SDoug Rabson static krb5_error_code 763c19800e8SDoug Rabson fcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) 764c19800e8SDoug Rabson { 765c19800e8SDoug Rabson struct fcache_iter *iter = cursor; 766c19800e8SDoug Rabson free(iter); 767c19800e8SDoug Rabson return 0; 768c19800e8SDoug Rabson } 769c19800e8SDoug Rabson 770c19800e8SDoug Rabson static krb5_error_code 771c19800e8SDoug Rabson fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) 772c19800e8SDoug Rabson { 773c19800e8SDoug Rabson krb5_error_code ret = 0; 774c19800e8SDoug Rabson 775c19800e8SDoug Rabson ret = rename(FILENAME(from), FILENAME(to)); 776c19800e8SDoug Rabson if (ret && errno != EXDEV) { 777c19800e8SDoug Rabson ret = errno; 778c19800e8SDoug Rabson krb5_set_error_string(context, 779c19800e8SDoug Rabson "Rename of file from %s to %s failed: %s", 780c19800e8SDoug Rabson FILENAME(from), FILENAME(to), 781c19800e8SDoug Rabson strerror(ret)); 782c19800e8SDoug Rabson return ret; 783c19800e8SDoug Rabson } else if (ret && errno == EXDEV) { 784c19800e8SDoug Rabson /* make a copy and delete the orignal */ 785c19800e8SDoug Rabson krb5_ssize_t sz1, sz2; 786c19800e8SDoug Rabson int fd1, fd2; 787c19800e8SDoug Rabson char buf[BUFSIZ]; 788c19800e8SDoug Rabson 789c19800e8SDoug Rabson ret = fcc_open(context, from, &fd1, O_RDONLY | O_BINARY, 0); 790c19800e8SDoug Rabson if(ret) 791c19800e8SDoug Rabson return ret; 792c19800e8SDoug Rabson 793c19800e8SDoug Rabson unlink(FILENAME(to)); 794c19800e8SDoug Rabson 795c19800e8SDoug Rabson ret = fcc_open(context, to, &fd2, 796c19800e8SDoug Rabson O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600); 797c19800e8SDoug Rabson if(ret) 798c19800e8SDoug Rabson goto out1; 799c19800e8SDoug Rabson 800c19800e8SDoug Rabson while((sz1 = read(fd1, buf, sizeof(buf))) > 0) { 801c19800e8SDoug Rabson sz2 = write(fd2, buf, sz1); 802c19800e8SDoug Rabson if (sz1 != sz2) { 803c19800e8SDoug Rabson ret = EIO; 804c19800e8SDoug Rabson krb5_set_error_string(context, 805c19800e8SDoug Rabson "Failed to write data from one file " 806c19800e8SDoug Rabson "credential cache to the other"); 807c19800e8SDoug Rabson goto out2; 808c19800e8SDoug Rabson } 809c19800e8SDoug Rabson } 810c19800e8SDoug Rabson if (sz1 < 0) { 811c19800e8SDoug Rabson ret = EIO; 812c19800e8SDoug Rabson krb5_set_error_string(context, 813c19800e8SDoug Rabson "Failed to read data from one file " 814c19800e8SDoug Rabson "credential cache to the other"); 815c19800e8SDoug Rabson goto out2; 816c19800e8SDoug Rabson } 817c19800e8SDoug Rabson erase_file(FILENAME(from)); 818c19800e8SDoug Rabson 819c19800e8SDoug Rabson out2: 820c19800e8SDoug Rabson fcc_unlock(context, fd2); 821c19800e8SDoug Rabson close(fd2); 822c19800e8SDoug Rabson 823c19800e8SDoug Rabson out1: 824c19800e8SDoug Rabson fcc_unlock(context, fd1); 825c19800e8SDoug Rabson close(fd1); 826c19800e8SDoug Rabson 827c19800e8SDoug Rabson if (ret) { 828c19800e8SDoug Rabson erase_file(FILENAME(to)); 829c19800e8SDoug Rabson return ret; 830c19800e8SDoug Rabson } 831c19800e8SDoug Rabson } 832c19800e8SDoug Rabson 833c19800e8SDoug Rabson /* make sure ->version is uptodate */ 834c19800e8SDoug Rabson { 835c19800e8SDoug Rabson krb5_storage *sp; 836c19800e8SDoug Rabson int fd; 837c19800e8SDoug Rabson ret = init_fcc (context, to, &sp, &fd); 838c19800e8SDoug Rabson krb5_storage_free(sp); 839c19800e8SDoug Rabson fcc_unlock(context, fd); 840c19800e8SDoug Rabson close(fd); 841c19800e8SDoug Rabson } 842c19800e8SDoug Rabson return ret; 843c19800e8SDoug Rabson } 844c19800e8SDoug Rabson 845c19800e8SDoug Rabson static krb5_error_code 846c19800e8SDoug Rabson fcc_default_name(krb5_context context, char **str) 847c19800e8SDoug Rabson { 848c19800e8SDoug Rabson return _krb5_expand_default_cc_name(context, 849c19800e8SDoug Rabson KRB5_DEFAULT_CCNAME_FILE, 850c19800e8SDoug Rabson str); 851c19800e8SDoug Rabson } 852c19800e8SDoug Rabson 853c19800e8SDoug Rabson /** 854c19800e8SDoug Rabson * Variable containing the FILE based credential cache implemention. 855c19800e8SDoug Rabson * 856c19800e8SDoug Rabson * @ingroup krb5_ccache 857c19800e8SDoug Rabson */ 858c19800e8SDoug Rabson 859b528cefcSMark Murray const krb5_cc_ops krb5_fcc_ops = { 860b528cefcSMark Murray "FILE", 861b528cefcSMark Murray fcc_get_name, 862b528cefcSMark Murray fcc_resolve, 863b528cefcSMark Murray fcc_gen_new, 864b528cefcSMark Murray fcc_initialize, 865b528cefcSMark Murray fcc_destroy, 866b528cefcSMark Murray fcc_close, 867b528cefcSMark Murray fcc_store_cred, 868b528cefcSMark Murray NULL, /* fcc_retrieve */ 869b528cefcSMark Murray fcc_get_principal, 870b528cefcSMark Murray fcc_get_first, 871b528cefcSMark Murray fcc_get_next, 872b528cefcSMark Murray fcc_end_get, 873b528cefcSMark Murray fcc_remove_cred, 874b528cefcSMark Murray fcc_set_flags, 875c19800e8SDoug Rabson fcc_get_version, 876c19800e8SDoug Rabson fcc_get_cache_first, 877c19800e8SDoug Rabson fcc_get_cache_next, 878c19800e8SDoug Rabson fcc_end_cache_get, 879c19800e8SDoug Rabson fcc_move, 880c19800e8SDoug Rabson fcc_default_name 881b528cefcSMark Murray }; 882