summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2014-05-05 00:06:56 -0400
committerGreg Hudson <ghudson@mit.edu>2014-05-17 19:13:59 -0400
commitb99c7c79dee33de966c8bed02ac79439989f6f99 (patch)
tree9121754c0f807b54c83f0b5b107856d59ab7371f
parentd3dd3d147aa403135d07bfca685aced769e361c2 (diff)
downloadkrb5-b99c7c79dee33de966c8bed02ac79439989f6f99.tar.gz
krb5-b99c7c79dee33de966c8bed02ac79439989f6f99.tar.xz
krb5-b99c7c79dee33de966c8bed02ac79439989f6f99.zip
Use cred marshalling functions in cc_file.c
Replace the cc_file.c credential and principal marshalling and unmarshalling functions with calls to the ccmarshal.c functions. For unmarshalling, we still need code to read the appropriate amount of data into a memory buffer. Because there is no outer length header for principals and credentials, this code needs to understand the credential and principal representations, but is much simpler than the old code as it only needs to store the data it reads, not assemble a data structure.
-rw-r--r--src/lib/krb5/ccache/cc_file.c823
1 files changed, 170 insertions, 653 deletions
diff --git a/src/lib/krb5/ccache/cc_file.c b/src/lib/krb5/ccache/cc_file.c
index b2124f8f4..7b6279d87 100644
--- a/src/lib/krb5/ccache/cc_file.c
+++ b/src/lib/krb5/ccache/cc_file.c
@@ -75,21 +75,6 @@ extern const krb5_cc_ops krb5_cc_file_ops;
krb5_error_code krb5_change_cache(void);
-static krb5_error_code read_data(krb5_context, krb5_ccache id,
- krb5_data *data);
-static krb5_error_code read32(krb5_context, krb5_ccache id, int32_t *i);
-static krb5_error_code read16(krb5_context, krb5_ccache id, uint16_t *i);
-static krb5_error_code read_addr(krb5_context context, krb5_ccache id,
- krb5_address *addr);
-static krb5_error_code read_authdatum(krb5_context, krb5_ccache,
- krb5_authdata *);
-static krb5_error_code store_data(krb5_context, krb5_ccache id,
- krb5_data *data);
-static krb5_error_code store32(krb5_context, krb5_ccache id, uint32_t i);
-static krb5_error_code store16(krb5_context, krb5_ccache id, uint16_t i);
-static krb5_error_code store_addr(krb5_context, krb5_ccache, krb5_address *);
-static krb5_error_code store_authdatum(krb5_context, krb5_ccache,
- krb5_authdata *);
static krb5_error_code interpret_errno(krb5_context, int);
#define FVNO_1 0x0501 /* krb v5, fcc v1 */
@@ -143,6 +128,24 @@ version(krb5_ccache id)
return ((fcc_data *)id->data)->version - FVNO_1 + 1;
}
+/* Get the size of the cache file as a size_t, or SIZE_MAX if it is too
+ * large to be represented as a size_t. */
+static krb5_error_code
+get_size(krb5_context context, krb5_ccache id, size_t *size_out)
+{
+ fcc_data *data = id->data;
+ struct stat sb;
+
+ k5_cc_mutex_assert_locked(context, &data->lock);
+ if (fstat(data->fd, &sb) == -1)
+ return interpret_errno(context, errno);
+ if (sizeof(off_t) > sizeof(size_t) && sb.st_size > (off_t)SIZE_MAX)
+ *size_out = SIZE_MAX;
+ else
+ *size_out = sb.st_size;
+ return 0;
+}
+
/* Discard cached read information within data. */
static inline void
invalidate_cache(fcc_data *data)
@@ -207,8 +210,6 @@ typedef struct _krb5_fcc_cursor {
} \
}
-#define CHECK(ret) if (ret) goto errout;
-
#define NO_FILE -1
/* Read len bytes from the cache id, storing them in buf. Return KRB5_CC_END
@@ -252,297 +253,10 @@ read_bytes(krb5_context context, krb5_ccache id, void *buf, unsigned int len)
return 0;
}
-/*
- * FOR ALL OF THE FOLLOWING FUNCTIONS:
- *
- * Requires:
- * id is open and set to read at the appropriate place in the file
- *
- * mutex is locked
- *
- * Effects:
- * Fills in the second argument with data of the appropriate type from
- * the file. In some cases, the functions have to allocate space for
- * variable length fields; therefore, krb5_destroy_<type> must be
- * called for each filled in structure.
- *
- * Errors:
- * system errors (read errors)
- * KRB5_CC_NOMEM
- */
-
-#define ALLOC(NUM, TYPE) \
- (((NUM) <= (((size_t)0 - 1) / sizeof(TYPE))) ? \
- (TYPE *)calloc((NUM), sizeof(TYPE)) : \
- (errno = ENOMEM, (TYPE *)0))
-
-static krb5_error_code
-read_principal(krb5_context context, krb5_ccache id, krb5_principal *princ)
-{
- fcc_data *data = id->data;
- krb5_error_code kret;
- register krb5_principal tmpprinc;
- int32_t length, type;
- int i;
-
- k5_cc_mutex_assert_locked(context, &data->lock);
-
- *princ = NULL;
-
- if (version(id) == 1) {
- type = KRB5_NT_UNKNOWN;
- } else {
- /* Read principal type. */
- kret = read32(context, id, &type);
- if (kret)
- return kret;
- }
-
- /* Read the number of components. */
- kret = read32(context, id, &length);
- if (kret)
- return kret;
-
- /*
- * DCE includes the principal's realm in the count; the new format
- * does not.
- */
- if (version(id) == 1)
- length--;
- if (length < 0)
- return KRB5_CC_NOMEM;
-
- tmpprinc = malloc(sizeof(*tmpprinc));
- if (tmpprinc == NULL)
- return KRB5_CC_NOMEM;
- if (length) {
- size_t msize = length;
- if (msize != (uint32_t)length) {
- free(tmpprinc);
- return KRB5_CC_NOMEM;
- }
- tmpprinc->data = ALLOC(msize, krb5_data);
- if (tmpprinc->data == 0) {
- free(tmpprinc);
- return KRB5_CC_NOMEM;
- }
- } else {
- tmpprinc->data = 0;
- }
- tmpprinc->magic = KV5M_PRINCIPAL;
- tmpprinc->length = length;
- tmpprinc->type = type;
-
- kret = read_data(context, id, &tmpprinc->realm);
-
- i = 0;
- CHECK(kret);
-
- for (i = 0; i < length; i++) {
- kret = read_data(context, id, &tmpprinc->data[i]);
- CHECK(kret);
- }
- *princ = tmpprinc;
- return 0;
-
-errout:
- while (--i >= 0)
- free(tmpprinc->data[i].data);
- free(tmpprinc->realm.data);
- free(tmpprinc->data);
- free(tmpprinc);
- return kret;
-}
-
-static krb5_error_code
-read_addrs(krb5_context context, krb5_ccache id, krb5_address ***addrs)
-{
- krb5_error_code kret;
- int32_t length;
- size_t msize;
- int i;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- *addrs = NULL;
-
- /* Read the number of components */
- kret = read32(context, id, &length);
- CHECK(kret);
-
- /* Make *addrs able to hold length pointers to krb5_address structs
- * Add one extra for a null-terminated list */
- msize = length;
- msize += 1;
- if (msize == 0 || msize - 1 != (uint32_t)length || length < 0)
- return KRB5_CC_NOMEM;
- *addrs = ALLOC(msize, krb5_address *);
- if (*addrs == NULL)
- return KRB5_CC_NOMEM;
-
- for (i = 0; i < length; i++) {
- (*addrs)[i] = malloc(sizeof(krb5_address));
- if ((*addrs)[i] == NULL) {
- krb5_free_addresses(context, *addrs);
- *addrs = 0;
- return KRB5_CC_NOMEM;
- }
- (*addrs)[i]->contents = NULL;
- kret = read_addr(context, id, (*addrs)[i]);
- CHECK(kret);
- }
-
- return 0;
-errout:
- if (*addrs) {
- krb5_free_addresses(context, *addrs);
- *addrs = NULL;
- }
- return kret;
-}
-
-static krb5_error_code
-read_keyblock(krb5_context context, krb5_ccache id, krb5_keyblock *keyblock)
-{
- krb5_error_code kret;
- uint16_t ui2;
- int32_t int32;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- keyblock->magic = KV5M_KEYBLOCK;
- keyblock->contents = 0;
-
- /* Enctype is signed, so sign-extend the 16-bit value we read. */
- kret = read16(context, id, &ui2);
- keyblock->enctype = (int16_t)ui2;
- CHECK(kret);
- if (version(id) == 3) {
- /* This works because the old etype is the same as the new enctype. */
- kret = read16(context, id, &ui2);
- /* keyblock->enctype = ui2; */
- CHECK(kret);
- }
-
- kret = read32(context, id, &int32);
- CHECK(kret);
- if (int32 < 0)
- return KRB5_CC_NOMEM;
- keyblock->length = int32;
- /* Overflow check. */
- if (keyblock->length != (uint32_t)int32)
- return KRB5_CC_NOMEM;
- if (keyblock->length == 0)
- return 0;
- keyblock->contents = malloc(keyblock->length);
- if (keyblock->contents == NULL)
- return KRB5_CC_NOMEM;
-
- kret = read_bytes(context, id, keyblock->contents, keyblock->length);
- if (kret)
- goto errout;
-
- return 0;
-
-errout:
- if (keyblock->contents) {
- free(keyblock->contents);
- keyblock->contents = NULL;
- }
- return kret;
-}
-
-static krb5_error_code
-read_data(krb5_context context, krb5_ccache id, krb5_data *data)
-{
- krb5_error_code kret;
- int32_t len;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- data->magic = KV5M_DATA;
- data->data = 0;
-
- kret = read32(context, id, &len);
- CHECK(kret);
- if (len < 0)
- return KRB5_CC_NOMEM;
- data->length = len;
- if (data->length != (uint32_t)len || data->length + 1 == 0)
- return KRB5_CC_NOMEM;
-
- if (data->length == 0) {
- data->data = NULL;
- return 0;
- }
-
- data->data = malloc(data->length + 1);
- if (data->data == NULL)
- return KRB5_CC_NOMEM;
-
- kret = read_bytes(context, id, data->data, data->length);
- CHECK(kret);
-
- data->data[data->length] = 0; /* Null terminate, just in case.... */
- return 0;
-
-errout:
- if (data->data) {
- free(data->data);
- data->data = NULL;
- }
- return kret;
-}
-
-static krb5_error_code
-read_addr(krb5_context context, krb5_ccache id, krb5_address *addr)
-{
- krb5_error_code kret;
- uint16_t ui2;
- int32_t int32;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- addr->magic = KV5M_ADDRESS;
- addr->contents = 0;
-
- kret = read16(context, id, &ui2);
- CHECK(kret);
- addr->addrtype = ui2;
-
- kret = read32(context, id, &int32);
- CHECK(kret);
- if ((int32 & VALID_INT_BITS) != int32) /* Overflow int??? */
- return KRB5_CC_NOMEM;
- addr->length = int32;
- /* Length field is "unsigned int", which may be smaller than 32 bits. */
- if (addr->length != (uint32_t)int32)
- return KRB5_CC_NOMEM; /* XXX */
-
- if (addr->length == 0)
- return 0;
-
- addr->contents = malloc(addr->length);
- if (addr->contents == NULL)
- return KRB5_CC_NOMEM;
-
- kret = read_bytes(context, id, addr->contents, addr->length);
- CHECK(kret);
-
- return 0;
-
-errout:
- if (addr->contents) {
- free(addr->contents);
- addr->contents = NULL;
- }
- return kret;
-}
-
/* Load four bytes from the cache file and return their value as a 32-bit
- * signed integer according to the file format. */
+ * unsigned integer according to the file format. Also append them to buf. */
static krb5_error_code
-read32(krb5_context context, krb5_ccache id, int32_t *out)
+read32(krb5_context context, krb5_ccache id, struct k5buf *buf, uint32_t *out)
{
krb5_error_code ret;
char bytes[4];
@@ -552,6 +266,8 @@ read32(krb5_context context, krb5_ccache id, int32_t *out)
ret = read_bytes(context, id, bytes, 4);
if (ret)
return ret;
+ if (buf != NULL)
+ k5_buf_add_len(buf, bytes, 4);
*out = (version(id) < 3) ? load_32_n(bytes) : load_32_be(bytes);
return 0;
}
@@ -573,142 +289,145 @@ read16(krb5_context context, krb5_ccache id, uint16_t *out)
return 0;
}
+/* Read len bytes from the cache file and add them to buf. */
static krb5_error_code
-read_octet(krb5_context context, krb5_ccache id, unsigned char *i)
+load_bytes(krb5_context context, krb5_ccache id, size_t len, struct k5buf *buf)
{
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
- return read_bytes(context, id, i, 1);
+ void *ptr;
+
+ ptr = k5_buf_get_space(buf, len);
+ return (ptr == NULL) ? ENOMEM : read_bytes(context, id, ptr, len);
}
+/* Load a 32-bit length and data from the cache file into buf, but not more
+ * than maxsize bytes. */
static krb5_error_code
-read_times(krb5_context context, krb5_ccache id, krb5_ticket_times *t)
+load_data(krb5_context context, krb5_ccache id, size_t maxsize,
+ struct k5buf *buf)
{
- fcc_data *data = id->data;
- krb5_error_code retval;
- int32_t i;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- if (data->version == FVNO_1 || data->version == FVNO_2) {
- return read_bytes(context, id, t, sizeof(krb5_ticket_times));
- } else {
- retval = read32(context, id, &i);
- CHECK(retval);
- t->authtime = i;
+ krb5_error_code ret;
+ uint32_t count;
- retval = read32(context, id, &i);
- CHECK(retval);
- t->starttime = i;
+ ret = read32(context, id, buf, &count);
+ if (ret)
+ return ret;
+ if (count > maxsize)
+ return KRB5_CC_FORMAT;
+ return load_bytes(context, id, count, buf);
+}
- retval = read32(context, id, &i);
- CHECK(retval);
- t->endtime = i;
+/* Load a marshalled principal from the cache file into buf, without
+ * unmarshalling it. */
+static krb5_error_code
+load_principal(krb5_context context, krb5_ccache id, size_t maxsize,
+ struct k5buf *buf)
+{
+ krb5_error_code ret;
+ uint32_t count;
- retval = read32(context, id, &i);
- CHECK(retval);
- t->renew_till = i;
+ if (version(id) > 1) {
+ ret = load_bytes(context, id, 4, buf);
+ if (ret)
+ return ret;
+ }
+ ret = read32(context, id, buf, &count);
+ if (ret)
+ return ret;
+ /* Add one for the realm (except in version 1 which already counts it). */
+ if (version(id) != 1)
+ count++;
+ while (count-- > 0) {
+ ret = load_data(context, id, maxsize, buf);
+ if (ret)
+ return ret;
}
return 0;
-errout:
- return retval;
}
+/* Load a marshalled credential from the cache file into buf, without
+ * unmarshalling it. */
static krb5_error_code
-read_authdata(krb5_context context, krb5_ccache id, krb5_authdata ***a)
+load_cred(krb5_context context, krb5_ccache id, size_t maxsize,
+ struct k5buf *buf)
{
- krb5_error_code kret;
- int32_t length;
- size_t msize;
- int i;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- *a = 0;
+ krb5_error_code ret;
+ uint32_t count, i;
- /* Read the number of components */
- kret = read32(context, id, &length);
- CHECK(kret);
+ /* client and server */
+ ret = load_principal(context, id, maxsize, buf);
+ if (ret)
+ return ret;
+ ret = load_principal(context, id, maxsize, buf);
+ if (ret)
+ return ret;
- if (length == 0)
- return 0;
+ /* keyblock (enctype, enctype again for version 3, length, value) */
+ ret = load_bytes(context, id, (version(id) == 3) ? 4 : 2, buf);
+ if (ret)
+ return ret;
+ ret = load_data(context, id, maxsize, buf);
+ if (ret)
+ return ret;
- /* Make *a able to hold length pointers to krb5_authdata structs
- * Add one extra for a null-terminated list. */
- msize = length;
- msize += 1;
- if (msize == 0 || msize - 1 != (uint32_t)length || length < 0)
- return KRB5_CC_NOMEM;
- *a = ALLOC(msize, krb5_authdata *);
- if (*a == NULL)
- return KRB5_CC_NOMEM;
+ /* times (4*4 bytes), is_skey (1 byte), ticket flags (4 bytes) */
+ ret = load_bytes(context, id, 4 * 4 + 1 + 4, buf);
+ if (ret)
+ return ret;
- for (i = 0; i < length; i++) {
- (*a)[i] = malloc(sizeof(krb5_authdata));
- if ((*a)[i] == NULL) {
- krb5_free_authdata(context, *a);
- *a = NULL;
- return KRB5_CC_NOMEM;
+ /* addresses and authdata, both lists of {type, length, data} */
+ for (i = 0; i < 2; i++) {
+ ret = read32(context, id, buf, &count);
+ if (ret)
+ return ret;
+ while (count-- > 0) {
+ ret = load_bytes(context, id, 2, buf);
+ if (ret)
+ return ret;
+ ret = load_data(context, id, maxsize, buf);
+ if (ret)
+ return ret;
}
- (*a)[i]->contents = NULL;
- kret = read_authdatum(context, id, (*a)[i]);
- CHECK(kret);
}
- return 0;
-errout:
- if (*a) {
- krb5_free_authdata(context, *a);
- *a = NULL;
- }
- return kret;
+ /* ticket and second_ticket */
+ ret = load_data(context, id, maxsize, buf);
+ if (ret)
+ return ret;
+ return load_data(context, id, maxsize, buf);
}
static krb5_error_code
-read_authdatum(krb5_context context, krb5_ccache id, krb5_authdata *a)
+read_principal(krb5_context context, krb5_ccache id, krb5_principal *princ)
{
- krb5_error_code kret;
- int32_t int32;
- int16_t ui2; /* negative authorization data types are allowed */
+ krb5_error_code ret;
+ struct k5buf buf;
+ size_t maxsize;
+ unsigned char *bytes;
+ *princ = NULL;
k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
+ k5_buf_init_dynamic(&buf);
- a->magic = KV5M_AUTHDATA;
- a->contents = NULL;
-
- kret = read16(context, id, (uint16_t *)&ui2);
- CHECK(kret);
- a->ad_type = (krb5_authdatatype)ui2;
- kret = read32(context, id, &int32);
- CHECK(kret);
- if ((int32 & VALID_INT_BITS) != int32) /* Overflow int??? */
- return KRB5_CC_NOMEM;
- a->length = int32;
- /* Value could have gotten truncated if int is smaller than 32 bits. */
- if (a->length != (uint32_t)int32)
- return KRB5_CC_NOMEM;
-
- if (a->length == 0)
- return 0;
-
- a->contents = malloc(a->length);
- if (a->contents == NULL)
- return KRB5_CC_NOMEM;
-
- kret = read_bytes(context, id, a->contents, a->length);
- CHECK(kret);
-
- return 0;
-errout:
- if (a->contents) {
- free(a->contents);
- a->contents = NULL;
+ /* Read the principal representation into memory. */
+ ret = get_size(context, id, &maxsize);
+ if (ret)
+ goto cleanup;
+ ret = load_principal(context, id, maxsize, &buf);
+ if (ret)
+ goto cleanup;
+ bytes = (unsigned char *)k5_buf_data(&buf);
+ if (bytes == NULL) {
+ ret = ENOMEM;
+ goto cleanup;
}
- return kret;
-}
-#undef CHECK
+ /* Unmarshal it from buf into princ. */
+ ret = k5_unmarshal_princ(bytes, k5_buf_len(&buf), version(id), princ);
-#define CHECK(ret) if (ret) return ret;
+cleanup:
+ k5_free_buf(&buf);
+ return ret;
+}
/* Write len bytes from buf into the cache file. Call with the mutex
* locked. */
@@ -729,131 +448,6 @@ write_bytes(krb5_context context, krb5_ccache id, const void *buf,
return 0;
}
-/*
- * FOR ALL OF THE FOLLOWING FUNCTIONS:
- *
- * Requires:
- * ((fcc_data *)id->data)->fd is open and at the right position.
- *
- * mutex is locked
- *
- * Effects:
- * Stores an encoded version of the second argument in the
- * cache file.
- *
- * Errors:
- * system errors
- */
-
-static krb5_error_code
-store_principal(krb5_context context, krb5_ccache id, krb5_principal princ)
-{
- fcc_data *data = id->data;
- krb5_error_code ret;
- int32_t i, length, tmp, type;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- type = princ->type;
- tmp = length = princ->length;
-
- if (data->version == FVNO_1) {
- /*
- * DCE-compatible format means that the length count
- * includes the realm. (It also doesn't include the
- * principal type information.)
- */
- tmp++;
- } else {
- ret = store32(context, id, type);
- CHECK(ret);
- }
-
- ret = store32(context, id, tmp);
- CHECK(ret);
-
- ret = store_data(context, id, &princ->realm);
- CHECK(ret);
-
- for (i = 0; i < length; i++) {
- ret = store_data(context, id, &princ->data[i]);
- CHECK(ret);
- }
-
- return 0;
-}
-
-static krb5_error_code
-store_addrs(krb5_context context, krb5_ccache id, krb5_address **addrs)
-{
- krb5_error_code ret;
- krb5_address **temp;
- int32_t i, length = 0;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- /* Count the number of components */
- if (addrs) {
- temp = addrs;
- while (*temp++)
- length += 1;
- }
-
- ret = store32(context, id, length);
- CHECK(ret);
- for (i = 0; i < length; i++) {
- ret = store_addr(context, id, addrs[i]);
- CHECK(ret);
- }
-
- return 0;
-}
-
-static krb5_error_code
-store_keyblock(krb5_context context, krb5_ccache id, krb5_keyblock *keyblock)
-{
- fcc_data *data = id->data;
- krb5_error_code ret;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- ret = store16(context, id, keyblock->enctype);
- CHECK(ret);
- if (data->version == FVNO_3) {
- ret = store16(context, id, keyblock->enctype);
- CHECK(ret);
- }
- ret = store32(context, id, keyblock->length);
- CHECK(ret);
- return write_bytes(context, id, keyblock->contents, keyblock->length);
-}
-
-static krb5_error_code
-store_addr(krb5_context context, krb5_ccache id, krb5_address *addr)
-{
- krb5_error_code ret;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- ret = store16(context, id, addr->addrtype);
- CHECK(ret);
- ret = store32(context, id, addr->length);
- CHECK(ret);
- return write_bytes(context, id, addr->contents, addr->length);
-}
-
-static krb5_error_code
-store_data(krb5_context context, krb5_ccache id, krb5_data *data)
-{
- krb5_error_code ret;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- ret = store32(context, id, data->length);
- CHECK(ret);
- return write_bytes(context, id, data->data, data->length);
-}
-
/* Store a 32-bit integer into the cache file according to the file format. */
static krb5_error_code
store32(krb5_context context, krb5_ccache id, uint32_t i)
@@ -885,73 +479,20 @@ store16(krb5_context context, krb5_ccache id, uint16_t i)
}
static krb5_error_code
-store_octet(krb5_context context, krb5_ccache id, unsigned char i)
-{
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- return write_bytes(context, id, &i, 1);
-}
-
-static krb5_error_code
-store_times(krb5_context context, krb5_ccache id, krb5_ticket_times *t)
-{
- fcc_data *data = id->data;
- krb5_error_code retval;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- if (data->version == FVNO_1 || data->version == FVNO_2) {
- return write_bytes(context, id, t, sizeof(krb5_ticket_times));
- } else {
- retval = store32(context, id, t->authtime);
- CHECK(retval);
- retval = store32(context, id, t->starttime);
- CHECK(retval);
- retval = store32(context, id, t->endtime);
- CHECK(retval);
- retval = store32(context, id, t->renew_till);
- CHECK(retval);
- return 0;
- }
-}
-
-static krb5_error_code
-store_authdata(krb5_context context, krb5_ccache id, krb5_authdata **a)
-{
- krb5_error_code ret;
- krb5_authdata **temp;
- int32_t i, length = 0;
-
- k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- if (a != NULL) {
- for (temp = a; *temp; temp++)
- length++;
- }
-
- ret = store32(context, id, length);
- CHECK(ret);
- for (i = 0; i < length; i++) {
- ret = store_authdatum(context, id, a[i]);
- CHECK(ret);
- }
- return 0;
-}
-
-static krb5_error_code
-store_authdatum(krb5_context context, krb5_ccache id, krb5_authdata *a)
+store_principal(krb5_context context, krb5_ccache id, krb5_principal princ)
{
krb5_error_code ret;
+ unsigned char *bytes;
+ size_t len;
k5_cc_mutex_assert_locked(context, &((fcc_data *)id->data)->lock);
-
- ret = store16(context, id, a->ad_type);
- CHECK(ret);
- ret = store32(context, id, a->length);
- CHECK(ret);
- return write_bytes(context, id, a->contents, a->length);
+ ret = k5_marshal_princ(princ, version(id), &bytes, &len);
+ if (ret)
+ return ret;
+ ret = write_bytes(context, id, bytes, len);
+ free(bytes);
+ return ret;
}
-#undef CHECK
/* Unlock and close the cache file. Call with the mutex locked. */
static krb5_error_code
@@ -996,7 +537,7 @@ open_cache_file(krb5_context context, krb5_ccache id, int mode)
fcc_data *data = id->data;
char fcc_fvno[2];
uint16_t fcc_flen, fcc_tag, fcc_taglen;
- int32_t time_offset, usec_offset;
+ uint32_t time_offset, usec_offset;
int f, open_flag, lock_flag, cnt;
char buf[1024];
@@ -1139,8 +680,8 @@ open_cache_file(krb5_context context, krb5_ccache id, int mode)
}
break;
}
- if (read32(context, id, &time_offset) ||
- read32(context, id, &usec_offset)) {
+ if (read32(context, id, NULL, &time_offset) ||
+ read32(context, id, NULL, &usec_offset)) {
ret = KRB5_CC_FORMAT;
goto done;
}
@@ -1547,52 +1088,44 @@ static krb5_error_code KRB5_CALLCONV
fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
krb5_creds *creds)
{
-#define TCHECK(ret) if (ret) goto lose;
krb5_error_code ret;
krb5_fcc_cursor *fcursor = *cursor;
- int32_t int32;
- unsigned char octet;
fcc_data *data = id->data;
+ struct k5buf buf;
+ size_t maxsize;
+ unsigned char *bytes;
memset(creds, 0, sizeof(*creds));
k5_cc_mutex_lock(context, &data->lock);
MAYBE_OPEN(context, id, FCC_OPEN_RDONLY);
+ k5_buf_init_dynamic(&buf);
if (fcc_lseek(data, fcursor->pos, SEEK_SET) == -1) {
ret = interpret_errno(context, errno);
- goto lose;
+ goto cleanup;
}
- ret = read_principal(context, id, &creds->client);
- TCHECK(ret);
- ret = read_principal(context, id, &creds->server);
- TCHECK(ret);
- ret = read_keyblock(context, id, &creds->keyblock);
- TCHECK(ret);
- ret = read_times(context, id, &creds->times);
- TCHECK(ret);
- ret = read_octet(context, id, &octet);
- TCHECK(ret);
- creds->is_skey = octet;
- ret = read32(context, id, &int32);
- TCHECK(ret);
- creds->ticket_flags = int32;
- ret = read_addrs(context, id, &creds->addresses);
- TCHECK(ret);
- ret = read_authdata(context, id, &creds->authdata);
- TCHECK(ret);
- ret = read_data(context, id, &creds->ticket);
- TCHECK(ret);
- ret = read_data(context, id, &creds->second_ticket);
- TCHECK(ret);
+ /* Load a marshalled cred into memory. */
+ ret = get_size(context, id, &maxsize);
+ if (ret)
+ return ret;
+ ret = load_cred(context, id, maxsize, &buf);
+ if (ret)
+ goto cleanup;
+ bytes = (unsigned char *)k5_buf_data(&buf);
+ if (bytes == NULL) {
+ ret = ENOMEM;
+ goto cleanup;
+ }
+ /* Unmarshal it from buf into creds. */
fcursor->pos = fcc_lseek(data, 0, SEEK_CUR);
+ ret = k5_unmarshal_cred(bytes, k5_buf_len(&buf), version(id), creds);
-lose:
+cleanup:
+ k5_free_buf(&buf);
MAYBE_CLOSE(context, id, ret);
k5_cc_mutex_unlock(context, &data->lock);
- if (ret)
- krb5_free_cred_contents(context, creds);
return ret;
}
@@ -1804,8 +1337,9 @@ fcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields,
static krb5_error_code KRB5_CALLCONV
fcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
{
-#define TCHECK(ret) if (ret) goto lose;
krb5_error_code ret;
+ unsigned char *bytes;
+ size_t len;
k5_cc_mutex_lock(context, &((fcc_data *)id->data)->lock);
@@ -1821,33 +1355,16 @@ fcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
return interpret_errno(context, errno);
}
- ret = store_principal(context, id, creds->client);
- TCHECK(ret);
- ret = store_principal(context, id, creds->server);
- TCHECK(ret);
- ret = store_keyblock(context, id, &creds->keyblock);
- TCHECK(ret);
- ret = store_times(context, id, &creds->times);
- TCHECK(ret);
- ret = store_octet(context, id, creds->is_skey);
- TCHECK(ret);
- ret = store32(context, id, creds->ticket_flags);
- TCHECK(ret);
- ret = store_addrs(context, id, creds->addresses);
- TCHECK(ret);
- ret = store_authdata(context, id, creds->authdata);
- TCHECK(ret);
- ret = store_data(context, id, &creds->ticket);
- TCHECK(ret);
- ret = store_data(context, id, &creds->second_ticket);
- TCHECK(ret);
-
-lose:
+ ret = k5_marshal_cred(creds, version(id), &bytes, &len);
+ if (ret == 0) {
+ ret = write_bytes(context, id, bytes, len);
+ free(bytes);
+ }
+
MAYBE_CLOSE(context, id, ret);
k5_cc_mutex_unlock(context, &((fcc_data *)id->data)->lock);
krb5_change_cache();
return ret;
-#undef TCHECK
}
/* Non-functional stub for removing a cred from the cache file. */