--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ * $Id$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains constant and function declarations used in the
+ * file-based credential cache routines.
+ */
+
+#include <krb5/copyright.h>
+
+#ifndef __KRB5_FILE_CCACHE__
+#define __KRB5_FILE_CCACHE__
+
+#include <krb5/krb5.h>
+
+/* XXX Until I find out the right #define for this.. XXX */
+#define KRB5_OK 0
+#define KRB5_NOMEM 1
+
+#ifndef TKT_ROOT
+#define TKT_ROOT "/tmp/tkt"
+#endif
+
+typedef struct _krb5_fcc_data {
+ char *filename;
+ int fd;
+} krb5_fcc_data;
+
+/* An off_t can be arbitrarily complex */
+typedef struct _krb5_fcc_cursor {
+ off_t pos;
+} krb5_fcc_cursor;
+
+/* DO NOT ADD ANYTHING AFTER THIS #endif */
+#endif /* __KRB5_FILE_CCACHE__ */
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_close.
+ */
+
+#ifndef lint
+static char fcc_resolve_c[] = "$Id$";
+#endif /* lint */
+
+#include <krb5/copyright.h>
+
+/*
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Closes the file cache, invalidates the id, and frees any resources
+ * associated with the cache.
+ *
+ * Errors:
+ * system errors
+ * permission errors
+ */
+krb5_error
+krb5_fcc_close(krb5_ccache id)
+{
+ int ret;
+
+#ifdef OPENCLOSE
+#else
+ close(id->data->fd);
+#endif
+
+ ret = unlink(id->data->filename);
+ if (ret < 0)
+ return errno;
+
+ free(id->data->filename);
+ free(id->data);
+ free(id);
+
+ return KRB5_OK;
+}
--- /dev/null
+/*
+ * Ooops. This file is completely unncessesary, I think. <sigh>
+ *
+ * Barr3y
+ */
+
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_default_name.
+ */
+
+#ifndef lint
+static char fcc_defnam_c[] = "$Id$";
+#endif lint
+
+#include "fcc.h"
+
+#include <krb5/copyright.h>
+
+static char krb5_default_name_string[KRB5_FCC_MAXLEN] = "";
+
+/*
+ * Effects:
+ *
+ * Forms the default credential cache name for the current user, which
+ * is defined in the following way. If it is set, the environment
+ * variable "KRB5CCACHE" will be used (up to the maximum number of
+ * characters of a legal operating system defined path). Otherwise
+ * TKT_ROOT (from fcc.h) and the user's uid are concatenated to
+ * produce the ticket file name (e.g., "/tmp/tkt123"). The pointer
+ * returned is to static storage; the name must be copied elsewhere.
+ */
+
+char *
+krb5_fcc_default_name (void)
+{
+ char *krb5ccache;
+ int len;
+
+ /* Is the environment variable defined? */
+ krb5ccache = getenv("KRB5CCACHE");
+ if (krb5ccache != NULL) {
+ len = strlen(krb5ccache);
+ len = (len < sizeof(krb5_default_name_string) ? len :
+ sizeof(krb5_default_name_string));
+
+ strncpy(krb5_default_name_string, krb5ccache, len);
+ krb5_default_name_string[len] = '\0';
+ }
+
+ /* No. Use TKT_ROOT and uid */
+ else {
+ /* XXX It'd be nice if we didn't have to pull in printf */
+ sprintf(krb5_default_name_string, "%s%d", TKT_ROOT, getuid());
+ }
+
+ return krb5_default_name_string;
+}
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_destroy.
+ */
+
+#ifndef lint
+static char fcc_destry_c[] = "$Id$";
+#endif lint
+
+#include <krb5/copyright.h>
+
+/*
+ * Effects:
+ * Destroys the contents of id.
+ *
+ * Errors:
+ * system errors
+ */
+krb5_error
+krb5_fcc_destroy(krb5_ccache id)
+{
+ struct stat buf;
+ unsigned long size;
+ char zeros[BUFSIZ];
+ int ret;
+
+#ifdef OPENCLOSE
+ id->data->fd = open(id->data->filename, O_RDWR, 0);
+ if (id->data->fd < 0)
+ return errno;
+#else
+ lseek(id->data->fd, 0, L_SET);
+#endif
+
+ ret = fstat(id->data->fd, &buf);
+ if (ret < 0)
+ return errno;
+
+ /* XXX This may not be legal XXX */
+ size = (unsigned long) buf.st_size;
+
+ bzero(zeros, BUFSIZ);
+ for (i=0; i < size / BUFSIZ; i++)
+ if (write(id->data->fd, zeros, BUFSIZ) < 0)
+ return errno;
+
+ if (write(id->data->fd, zeros, size % BUFSIZ) < 0)
+ return errno;
+
+#ifdef OPENCLOSE
+ close(id->data->fd);
+#endif
+}
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_end_seq_get.
+ */
+
+#ifndef lint
+static char fcc_eseq_c[] = "$Id$";
+#endif lint
+
+#include <krb5/copyright.h>
+#include "fcc.h"
+
+/*
+ * Requires:
+ * cursor is a krb5_cc_cursor originally obtained from
+ * krb5_fcc_start_seq_get.
+ *
+ * Modifies:
+ * id, cursor
+ *
+ * Effects:
+ * Finishes sequential processing of the file credentials ccache id,
+ * and invalidates the cursor (it must never be used after this call).
+ */
+krb5_error
+krb5_fcc_end_seq_get(krb5_ccache id, krb5_cc_cursor *cursor)
+{
+#ifdef OPENCLOSE
+#else
+ close(id->data->fd);
+#endif
+
+ free((krb5_fcc_cursor) cursor);
+
+ return KRB5_OK;
+}
+
+
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_generate_new.
+ */
+
+#ifndef lint
+static char fcc_resolve_c[] = "$Id$";
+#endif lint
+
+#include "fcc.h"
+
+#include <krb5/copyright.h>
+
+/*
+ * Effects:
+ * Creates a new file cred cache whose name is guaranteed to be
+ * unique. The name begins with the string TKT_ROOT (from fcc.h).
+ * The cache is not opened, but the new filename is reserved.
+ *
+ * Returns:
+ * The filled in krb5_ccache id.
+ *
+ * Errors:
+ * KRB5_NOMEM - there was insufficient memory to allocate the
+ * krb5_ccache. id is undefined.
+ */
+krb5_err
+krb5_fcc_generate_new (krb5_ccache id)
+{
+ char scratch[100]; /* XXX Is this large enough */
+
+ /* Allocate memory */
+ id = (krb_ccache) malloc(sizeof(struct _krb5_ccache));
+ if (id == NULL)
+ return KRB5_NOMEM;
+
+ sprintf(scratch, "%sXXXXXX", TKT_ROOT);
+ mktemp(scratch);
+
+ id->data = malloc(sizeof(krb5_fcc_data));
+ if (id->data == NULL) {
+ free(id);
+ return KRB5_NOMEM;
+ }
+
+ id->data->filename = malloc(strlen(scratch) + 1);
+ if (id->data->filename == NULL) {
+ free(id->data);
+ free(id);
+ return KRB5_NOMEM;
+ }
+
+ /* Set up the filename */
+ strcpy(id->data->filename, scratch);
+
+ /* Copy the virtual operation pointers into id */
+ bcopy((char *) &krb5_fcc_ops, id->ops, sizeof(struct _krb5_ccache));
+
+ /* Make sure the file name is reserved */
+ ret = open(id->data->filename, O_CREAT | O_EXCL, 0);
+ if (ret == -1 && errno != EEXIST)
+ return ret;
+ else {
+ close(ret);
+ return KRB5_OK;
+ }
+}
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_get_name.
+ */
+
+#ifndef lint
+static char fcc_resolve_c[] = "$Id$";
+#endif lint
+
+#include <krb5/copyright.h>
+
+#include "fcc.h"
+
+/*
+ * Requires:
+ * id is a file credential cache
+ *
+ * Returns:
+ * The name of the file cred cache id.
+ */
+char *
+krb5_fcc_get_name (krb5_ccache id)
+{
+ return (char *) id->data->filename;
+}
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_get_principal.
+ */
+
+#ifndef lint
+static char fcc_gprinc_c[] = "$Id$";
+#endif lint
+
+#include <krb5/copyright.h>
+
+/*
+ * Modifies:
+ * id, princ
+ *
+ * Effects:
+ * Retrieves the primary principal from id, as set with
+ * krb5_fcc_initialize. The principal is returned is allocated
+ * storage that must be freed by the caller via krb5_free_principal.
+ *
+ * Errors:
+ * system errors
+ * KRB5_NOMEM
+ */
+krb5_error
+krb5_fcc_get_principal(krb5_ccache id, krb5_principal *princ)
+{
+#ifdef OPENCLOSE
+ id->data->fd = open(id->data->filename, O_RDONLY, 0);
+ if (id->data->fd < 0)
+ return errno;
+#else
+ lseek(id->data->fd, 0, L_SET);
+#endif
+
+ return (krb5_fcc_read_principal(princ));
+}
+
+
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_initialize.
+ */
+
+#ifndef lint
+static char fcc_resolve_c[] = "$Id$";
+#endif /* lint */
+
+#include <krb5/copyright.h>
+
+#include "fcc.h"
+
+/*
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * Creates/refreshes the file cred cache id. If the cache exists, its
+ * contents ae destroyed.
+ *
+ * Errors:
+ * system errors
+ * permission errors
+ */
+krb5_error
+krb5_fcc_initialize(krb5_ccache id, krb5_principal princ)
+{
+ int ret;
+
+ ret = open(id->data->filename, O_CREAT | O_TRUNC | O_RDWR, 0);
+ if (ret < 0)
+ return errno;
+ id->data->fd = ret;
+
+ ret = fchmod(id->data->fd, S_IREAD | S_IWRITE);
+ if (ret == -1)
+ return ret;
+
+ krb5_fcc_write_principal(id, princ);
+
+#ifdef OPENCLOSE
+ close(id->data->fd);
+#endif
+
+ return KRB5_OK;
+}
+
+
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_next_cred.
+ */
+
+#ifndef lint
+static char fcc_nseq_c[] = "$Id$";
+#endif lint
+
+#include <krb5/copyright.h>
+
+#include "fcc.h"
+
+/*
+ * Requires:
+ * cursor is a krb5_cc_cursor originally obtained from
+ * krb5_fcc_start_seq_get.
+ *
+ * Modifes:
+ * cursor, creds
+ *
+ * Effects:
+ * Fills in creds with the "next" credentals structure from the cache
+ * id. The actual order the creds are returned in is arbitrary.
+ * creds is set to allocated storage which must be freed by the caller
+ * via a call to krb5_free_credentials.
+ *
+ * The cursor is updated for the next call to krb5_fcc_next_cred.
+ *
+ * Errors:
+ * system errors
+ */
+krb5_error
+krb5_fcc_next_cred(krb5_ccache id, krb5_creds *creds, krb5_cc_cursor *cursor)
+{
+ int ret;
+ krb5_error kret;
+ krb5_fcc_cursor *fcursor;
+
+#ifdef OPENCLOSE
+ ret = open(id->data->filename, O_RDONLY, 0);
+ if (ret < 0)
+ return errno;
+ id->data->fd = ret;
+#endif
+
+ fcursor = (krb5_fcc_cursor *) cursor;
+
+ ret = lseek(id->data->fd, fcursor->pos, L_SET);
+ if (ret < 0)
+ return errno;
+
+ creds = (krb5_creds *) malloc(sizeof(krb5_creds));
+ if (creds == NULL)
+ return KRB5_NOMEM;
+
+ kret = krb5_fcc_read_principal(&creds->client);
+ kret = krb5_fcc_read_principal(&creds->server);
+ kret = krb5_fcc_read_keyblock(&creds->keyblock);
+ kret = krb5_fcc_read_times(&creds->times);
+ kret = krb5_fcc_read_bool(&creds->is_skey);
+ kret = krb5_fcc_read_flags(&creds->ticket_flags);
+ kret = krb5_fcc_read_data(&creds->ticket);
+ kret = krb5_fcc_read_data(&creds->second_ticket);
+
+ fcursor->pos = tell(id->data->fd);
+ cursor = (krb5_cc_cursor) fcursor;
+
+#ifdef OPENCLOSE
+ close(id->data->fd);
+#endif
+
+ return KRB5_OK;
+}
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for reading variables from a
+ * credentials cache. These are not library-exported functions.
+ */
+
+#ifndef lint
+static char fcc_read_c[] = "$Id$";
+#endif lint
+
+#include <krb5/copyright.h>
+
+/* XXX Doesn't deal if < sizeof(o) bytes are written XXX */
+#define krb5_fcc_read(i,b,l) (read(i->data->fd,b,l)==-1 ? errno : KRB5_OK)
+
+/*
+ * FOR ALL OF THE FOLLOWING FUNCTIONS:
+ *
+ * Requires:
+ * id->data->fd is open and at the right position in the file.
+ *
+ * Effects:
+ * Allocates memory for and decodes the appropriate type from the
+ * cache id. The memory must be freed by the caller.
+ *
+ * Errors:
+ * system errors
+ * KRB5_NOMEM
+ */
+
+krb5_error
+krb5_fcc_read_principal(krb5_ccache id, krb5_principal princ)
+{
+ krb5_error kret;
+ krb5_int32 length;
+
+ /* Read the number of components */
+ krb5_fcc_read_int32(id, &length);
+
+ /* Get memory for length components */
+ princ = (krb5_principal) malloc(sizeof(krb5_data *)*length);
+ if (princ == NULL)
+ return KRB5_NOMEM;
+
+ /* Read length components */
+ for (i=0; i < length; i++) {
+ kret = krb5_fcc_read_data(id, princ[i]);
+ }
+
+ return KRB5_OK;
+}
+
+krb5_error
+krb5_fcc_read_keyblock(krb5_ccache id, krb5_keyblock *keyblock)
+{
+ krb5_error kret;
+ int ret;
+
+ keyblock = (krb5_keyblock *) malloc(sizeof(krb5_keyblock));
+ if (keyblock == NULL)
+ return KRB5_NOMEM;
+
+ kret = krb5_fcc_read_keytype(id, &keyblock->keytype);
+ kret = krb5_fcc_read_int(id, &keyblock->length);
+ ret = read(id->data->fd, keyblock->contents,
+ (keyblock->length)*sizeof(krb5_octet));
+
+ return KRB5_OK;
+}
+
+krb5_error
+krb5_fcc_read_data(krb5_ccache id, krb5_data *data)
+{
+ krb5_error kret;
+ int ret;
+
+ data = (krb5_data *) malloc(sizeof(krb5_data));
+ if (data == NULL)
+ return KRB5_NOMEM;
+
+ kret = krb5_fcc_read_int32(id, data->length);
+
+ data->data = (char *) malloc(data->length);
+ if (data->data == NULL) {
+ free(data);
+ return KRB5_NOMEM;
+ }
+
+ ret = read(id->data->fd, data->data, data->length);
+ if (ret == -1)
+ return errno;
+
+ return KRB5_OK;
+}
+
+krb5_error
+krb5_fcc_read_int32(krb5_ccache id, krb5_int32 *i)
+{
+ return krb5_fcc_read(id, i, sizeof(krb5_int32));
+}
+
+krb5_error
+krb5_fcc_read_keytype(krb5_ccache id, krb5_keytype *k)
+{
+ return krb5_fcc_read(id, k, sizeof(krb5_keytype));
+}
+
+krb5_error
+krb5_fcc_read_int(krb5_ccache id, int *i)
+{
+ return krb5_fcc_read(id, i, sizeof(int));
+}
+
+krb5_error
+krb5_fcc_read_bool(krb5_ccache id, krb5_boolean *b)
+{
+ return krb5_fcc_read(id, b, sizeof(krb5_boolean));
+}
+
+krb5_error
+krb5_fcc_read_times(krb5_ccache id, krb5_ticket_times *t)
+{
+ return krb5_fcc_read(id, t, sizeof(krb5_ticket_times));
+}
+
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_resolve.
+ */
+
+#ifndef lint
+static char fcc_resolve_c[] = "$Id$";
+#endif lint
+
+#include <krb5/copyright.h>
+
+#include "fcc.h"
+
+extern struct krb5_cc_ops krb5_fcc_ops;
+
+/*
+ * Requires:
+ * residual is a legal path name, and a null-terminated string
+ *
+ * Modifies:
+ * id
+ *
+ * Effects:
+ * creates a file-based cred cache that will reside in the file
+ * residual. The cache is not opened, but the filename is reserved.
+ *
+ * Returns:
+ * A filled in krb5_ccache structure "id".
+ *
+ * Errors:
+ * KRB5_NOMEM - there was insufficient memory to allocate the
+ * krb5_ccache. id is undefined.
+ * permission errors
+ */
+krb5_error
+krb5_fcc_resolve (krb5_ccache id, char *residual)
+{
+ int ret;
+
+ id = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
+ if (id == NULL)
+ return KRB5_NOMEM;
+
+ id->data = (char *) malloc(sizeof(krb5_fcc_data));
+ if (id->data == NULL) {
+ free(id);
+ return KRB5_NOMEM;
+ }
+
+ id->data->filename = (char *) malloc(strlen(residual) + 1);
+ if (id->data->filename == NULL) {
+ free(id->data);
+ free(id);
+ return KRB5_NOMEM;
+ }
+
+ /* Copy the virtual operation pointers into id */
+ bcopy((char *) &krb5_fcc_ops, id->ops, sizeof(struct _krb5_ccache));
+
+ /* Set up the filename */
+ strcpy(id->data->filename, residual);
+
+ /* Make sure the file name is reserved */
+ ret = open(id->data->filename, O_CREAT | O_EXCL, 0);
+ if (ret == -1 && errno != EEXIST)
+ return ret;
+ else {
+ close(ret);
+ return KRB5_OK;
+ }
+}
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_retrieve.
+ */
+
+#ifndef lint
+static char fcc_retrieve_c[] = "$Id$";
+#endif /* lint */
+
+#include <krb5/copyright.h>
+
+#include "fcc.h"
+
+/*
+ * Effects:
+ * Searches the file cred cache is for a credential matching mcreds.
+ * If one if found, it is returned in creds, which should be freed by
+ * the caller with krb5_free_credentials().
+ *
+ * Errors:
+ * system errors
+ * permission errors
+ * KRB5_NOMEM
+ */
+krb5_error
+krb5_fcc_retrieve(krb5_ccache id, krb5_flags whichfields,
+ krb5_creds *mcreds, krb5_creds *creds)
+{
+ /* Just a wrapper for the sequential search routines */
+}
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_start_seq_get.
+ */
+
+#ifndef lint
+static char fcc_sseq_c[] = "$Id$";
+#endif lint
+
+#include <krb5/copyright.h>
+
+#include "fcc.h"
+
+/*
+ * Effects:
+ * Prepares for a sequential search of the credentials cache.
+ * Returns and krb5_cc_cursor to be used with krb5_fcc_next_cred and
+ * krb5_fcc_end_seq_get.
+ *
+ * If the cache is modified between the time of this call and the time
+ * of the final krb5_fcc_end_seq_get, the results are undefined.
+ *
+ * Errors:
+ * KRB5_NOMEM
+ * system errors
+ */
+krb5_error
+krb5_fcc_start_seq_get(krb5_ccache id, krb5_cc_cursor *cursor)
+{
+ krb5_fcc_cursor *fcursor;
+
+ fcursor = (krb5_cc_cursor) malloc(sizeof(krb5_fcc_cursor));
+ if (fcursor == NULL)
+ return KRB5_NOMEM;
+
+ /* Make sure we start reading right after the primary principal */
+#ifdef OPENCLOSE
+ ret = open(id->data->filename, O_RDONLY, 0);
+ if (ret < 0)
+ return errno;
+ id->data->fd = ret;
+#else
+ lseek(id->data->fd, 0, L_SET);
+#endif
+
+ krb5_fcc_skip_pprincipal(id);
+ fcursor->pos = tell(id->data->fd);
+ cursor = (krb5_cc_cursor) fcursor;
+
+#ifdef OPENCLOSE
+ close(id->data->fd);
+#endif
+}
--- /dev/null
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1990 by the Massachusetts Institute of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <krb5/mit-copyright.h>.
+ *
+ * This file contains the source code for krb5_fcc_store.
+ */
+
+#ifndef lint
+static char fcc_store_c[] = "$Id$";
+#endif /* lint */
+
+#include <krb5/copyright.h>
+
+#include "fcc.h"
+
+/* XXX Doesn't deal if < sizeof(o) bytes are written XXX */
+#define krb5_fcc_write(i,b,l) (write(i->data->fd,b,l)==-1 ? errno : KRB5_OK)
+#define krb5_fcc_store_int32(id,i) krb5_fcc_write(id, i, sizeof(krb5_int32))
+#define krb5_fcc_store_keytype(id,k) krb5_fcc_write(id,k,sizeof(krb5_keytype))
+#define krb5_fcc_store_int(id,i) krb5_fcc_write(id,i,sizeof(int))
+#define krb5_fcc_store_bool(id,b) krb5_fcc_write(id,b,sizeof(krb5_boolean))
+#define krb5_fcc_store_times(id,t) krb5_fcc_write(id,t,sizeof(krb5_ticket_times))
+
+#define CHECK(ret) if (ret != KRB5_OK) return ret;
+
+/*
+ * Modifies:
+ * the file cache
+ *
+ * Effects:
+ * stores creds in the file cred cache
+ *
+ * Errors:
+ * system errors
+ * storage failure errors
+ */
+krb5_error
+krb5_fcc_store(krb5_ccache id, krb5_creds *creds)
+{
+#define TCHECK(ret) if (ret != KRB5_OK) goto lose;
+ krb5_error ret;
+
+ /* Make sure we are writing to the end of the file */
+#ifdef OPENCLOSE
+ id->data->fd = open(id->data->filename, O_APPEND, 0);
+ if (id->data->fd < 0)
+ return errno;
+#else
+ ret = lseek(id->data->fd, L_XTND, 0);
+ if (ret < 0)
+ return errno;
+#endif
+
+ ret = krb5_fcc_store_principal(id, creds->client);
+ TCHECK(ret);
+ ret = krb5_fcc_store_principal(id, creds->server);
+ TCHECK(ret);
+ ret = krb5_fcc_store_keyblock(id, &creds->keyblock);
+ TCHECK(ret);
+ ret = krb5_fcc_store_times(id, &creds->times);
+ TCHECK(ret);
+ ret = krb5_fcc_store_bool(id, &creds->is_skey);
+ TCHECK(ret);
+ ret = krb5_fcc_store_data(id, &creds->ticket);
+ TCHECK(ret);
+ ret = krb5_fcc_store_data(id, &creds->second_ticket);
+ TCHECK(ret);
+
+lose:
+
+#ifdef OPENCLOSE
+ close(id->data->fd);
+#endif
+
+ return ret;
+#undef TCHECK
+}
+
+/*
+ * FOR ALL OF THE FOLLOWING FUNCTIONS:
+ *
+ * Requires:
+ * id->data->fd is open and at the right position.
+ *
+ * Effects:
+ * Stores an encoded version of the second argument in the
+ * cache file.
+ *
+ * Errors:
+ * system errors
+ */
+
+static krb5_error
+krb5_fcc_store_principal(krb5_ccache id, krb5_principal princ)
+{
+ krb5_error ret;
+ krb5_principal temp;
+ krb5_int32 i, length = 0;
+
+ /* Count the number of components */
+ temp = princ;
+ while (temp++)
+ length += 1;
+
+ ret = krb5_fcc_store_int32(id, &length);
+ CHECK(ret);
+ for (i=0; i < length; i++) {
+ ret = krb5_store_data(id, princ[i]);
+ CHECK(ret);
+ }
+
+ return KRB5_OK;
+}
+
+static krb5_error
+krb5_store_keyblock(krb5_ccache id, krb5_keyblock *keyblock)
+{
+ krb5_error ret;
+
+ ret = krb5_fcc_store_keytype(id, &keyblock->keytype);
+ CHECK(ret);
+ ret = krb5_fcc_store_int(id, &keyblock->length);
+ CHECK(ret);
+ ret = write(id->data->fd, keyblock->contents,
+ (keyblock->length)*sizeof(krb5_octet));
+ CHECK(ret);
+
+ return KRB5_OK;
+}
+
+
+static krb5_error
+krb5_fcc_store_data(krb5_ccache id, krb5_data *data)
+{
+ krb5_error ret;
+
+ ret = krb5_fcc_store_int32(id, data->length);
+ CHECK(ret);
+ ret = write(id->data->fd, data->data, data->length);
+ if (ret == -1)
+ return errno;
+
+ return KRB5_OK;
+}
+
+