summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin Anderson <jander@mit.edu>2008-09-22 17:03:51 +0000
committerJustin Anderson <jander@mit.edu>2008-09-22 17:03:51 +0000
commit6e83d0bd31721ac86003530dd2450221dd05d0c2 (patch)
tree25c9defac58c7c982c3e7cad5b7847b530430191
parent85f452a27b855c2fb456e2c6d8c73a5c1f037841 (diff)
downloadkrb5-6e83d0bd31721ac86003530dd2450221dd05d0c2.tar.gz
krb5-6e83d0bd31721ac86003530dd2450221dd05d0c2.tar.xz
krb5-6e83d0bd31721ac86003530dd2450221dd05d0c2.zip
Merge 1.7 work on auxiliary ccache functions necessary for KIM. Adds krb5_cc_lock/unlock, krb5_cccol_lock/unlock, krb5_cc_last_change_time, krb5_cccol_last_change_time, krb5_cc_move, and adds pertype cursor support to some cache types
Locking functions work the same as the CCAPI cc_ccache_lock / cc_context_lock functions, though not as read/write locks. ticket: 6124 status: open git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20743 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/include/k5-int.h36
-rw-r--r--src/include/krb5/krb5.hin25
-rw-r--r--src/lib/krb5/ccache/cc-int.h20
-rw-r--r--src/lib/krb5/ccache/cc_file.c397
-rw-r--r--src/lib/krb5/ccache/cc_keyring.c138
-rw-r--r--src/lib/krb5/ccache/cc_memory.c150
-rw-r--r--src/lib/krb5/ccache/ccapi/stdcc.c90
-rw-r--r--src/lib/krb5/ccache/ccapi/stdcc.h20
-rw-r--r--src/lib/krb5/ccache/ccbase.c276
-rw-r--r--src/lib/krb5/ccache/cccursor.c36
-rw-r--r--src/lib/krb5/ccache/ccfns.c20
11 files changed, 1026 insertions, 182 deletions
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 545bd983a..111b12159 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -2027,11 +2027,14 @@ struct _krb5_cc_ops {
krb5_ccache *);
krb5_error_code (KRB5_CALLCONV *ptcursor_free)(krb5_context,
krb5_cc_ptcursor *);
- krb5_error_code (KRB5_CALLCONV *move)(krb5_context, krb5_ccache);
+ krb5_error_code (KRB5_CALLCONV *move)(krb5_context, krb5_ccache,
+ krb5_ccache);
krb5_error_code (KRB5_CALLCONV *lastchange)(krb5_context,
krb5_ccache, krb5_timestamp *);
krb5_error_code (KRB5_CALLCONV *wasdefault)(krb5_context, krb5_ccache,
krb5_timestamp *);
+ krb5_error_code (KRB5_CALLCONV *lock)(krb5_context, krb5_ccache);
+ krb5_error_code (KRB5_CALLCONV *unlock)(krb5_context, krb5_ccache);
};
extern const krb5_cc_ops *krb5_cc_dfl_ops;
@@ -2039,6 +2042,37 @@ extern const krb5_cc_ops *krb5_cc_dfl_ops;
krb5_error_code
krb5int_cc_os_default_name(krb5_context context, char **name);
+/* reentrant mutex used by krb5_cc_* functions */
+typedef struct _k5_cc_mutex {
+ k5_mutex_t lock;
+ krb5_context owner;
+ krb5_int32 refcount;
+} k5_cc_mutex;
+
+#define K5_CC_MUTEX_PARTIAL_INITIALIZER \
+ { K5_MUTEX_PARTIAL_INITIALIZER, NULL, 0 }
+
+krb5_error_code
+k5_cc_mutex_init(k5_cc_mutex *m);
+
+krb5_error_code
+k5_cc_mutex_finish_init(k5_cc_mutex *m);
+
+#define k5_cc_mutex_destroy(M) \
+k5_mutex_destroy(&(M)->lock);
+
+void
+k5_cc_mutex_assert_locked(krb5_context context, k5_cc_mutex *m);
+
+void
+k5_cc_mutex_assert_unlocked(krb5_context context, k5_cc_mutex *m);
+
+krb5_error_code
+k5_cc_mutex_lock(krb5_context context, k5_cc_mutex *m);
+
+krb5_error_code
+k5_cc_mutex_unlock(krb5_context context, k5_cc_mutex *m);
+
typedef struct _krb5_donot_replay {
krb5_magic magic;
krb5_ui_4 hash;
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index 403bb9f66..82e52ab52 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -1297,6 +1297,22 @@ const char * KRB5_CALLCONV
krb5_cc_get_type (krb5_context context, krb5_ccache cache);
krb5_error_code KRB5_CALLCONV
+krb5_cc_move (krb5_context context, krb5_ccache src, krb5_ccache dst);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_last_change_time (
+ krb5_context context,
+ krb5_ccache ccache,
+ krb5_timestamp *change_time);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_lock (krb5_context context, krb5_ccache ccache);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_unlock (krb5_context context, krb5_ccache ccache);
+
+
+krb5_error_code KRB5_CALLCONV
krb5_cccol_cursor_new(krb5_context context, krb5_cccol_cursor *cursor);
krb5_error_code KRB5_CALLCONV
@@ -1309,6 +1325,15 @@ krb5_error_code KRB5_CALLCONV
krb5_cccol_cursor_free(krb5_context context, krb5_cccol_cursor *cursor);
krb5_error_code KRB5_CALLCONV
+krb5_cccol_last_change_time(krb5_context context, krb5_timestamp *change_time);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_lock(krb5_context context);
+
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_unlock(krb5_context context);
+
+krb5_error_code KRB5_CALLCONV
krb5_cc_new_unique(
krb5_context context,
const char *type,
diff --git a/src/lib/krb5/ccache/cc-int.h b/src/lib/krb5/ccache/cc-int.h
index e533f4667..4c0db959d 100644
--- a/src/lib/krb5/ccache/cc-int.h
+++ b/src/lib/krb5/ccache/cc-int.h
@@ -65,8 +65,22 @@ krb5int_cc_typecursor_free(
krb5_cc_typecursor *cursor);
-extern k5_mutex_t krb5int_mcc_mutex;
-extern k5_mutex_t krb5int_krcc_mutex;
-extern k5_mutex_t krb5int_cc_file_mutex;
+extern k5_cc_mutex krb5int_mcc_mutex;
+extern k5_cc_mutex krb5int_krcc_mutex;
+extern k5_cc_mutex krb5int_cc_file_mutex;
+
+#ifdef USE_CCAPI_V3
+extern krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_lock
+(krb5_context context);
+
+extern krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_unlock
+(krb5_context context);
+#endif
+
+krb5_error_code
+k5_cc_mutex_force_unlock(k5_cc_mutex *m);
+
+krb5_error_code
+k5_cccol_force_unlock(void);
#endif /* __KRB5_CCACHE_H__ */
diff --git a/src/lib/krb5/ccache/cc_file.c b/src/lib/krb5/ccache/cc_file.c
index a24ff4502..22c01b8b7 100644
--- a/src/lib/krb5/ccache/cc_file.c
+++ b/src/lib/krb5/ccache/cc_file.c
@@ -166,6 +166,25 @@ static krb5_error_code krb5_fcc_skip_principal
static krb5_error_code KRB5_CALLCONV krb5_fcc_set_flags
(krb5_context, krb5_ccache id, krb5_flags flags);
+static krb5_error_code KRB5_CALLCONV krb5_fcc_ptcursor_new
+ (krb5_context context, krb5_cc_ptcursor *cursor);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_ptcursor_next
+ (krb5_context context, krb5_cc_ptcursor cursor, krb5_ccache *ccache);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_ptcursor_free
+ (krb5_context context, krb5_cc_ptcursor *cursor);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_last_change_time
+ (krb5_context context, krb5_ccache id, krb5_timestamp *change_time);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_lock
+ (krb5_context context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_unlock
+ (krb5_context context, krb5_ccache id);
+
+
extern const krb5_cc_ops krb5_cc_file_ops;
krb5_error_code krb5_change_cache (void);
@@ -205,6 +224,9 @@ static krb5_error_code krb5_fcc_close_file
(krb5_context, struct _krb5_fcc_data *data);
static krb5_error_code krb5_fcc_open_file
(krb5_context, krb5_ccache, int);
+static krb5_error_code krb5_fcc_data_last_change_time
+ (krb5_context context, struct _krb5_fcc_data *data,
+ krb5_timestamp *change_time);
#define KRB5_OK 0
@@ -261,7 +283,7 @@ typedef struct _krb5_fcc_data {
/* Lock this one before reading or modifying the data stored here
that can be changed. (Filename is fixed after
initialization.) */
- k5_mutex_t lock;
+ k5_cc_mutex lock;
int file;
krb5_flags flags;
int mode; /* needed for locking code */
@@ -301,9 +323,14 @@ struct fcc_set {
unsigned int refcount;
};
-k5_mutex_t krb5int_cc_file_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+k5_cc_mutex krb5int_cc_file_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER;
static struct fcc_set *fccs = NULL;
+/* Iterator over file caches. */
+struct krb5_fcc_ptcursor_data {
+ struct fcc_set *cur;
+};
+
/* An off_t can be arbitrarily complex */
typedef struct _krb5_fcc_cursor {
off_t pos;
@@ -311,12 +338,12 @@ typedef struct _krb5_fcc_cursor {
#define MAYBE_OPEN(CONTEXT, ID, MODE) \
{ \
- k5_assert_locked(&((krb5_fcc_data *)(ID)->data)->lock); \
+ k5_cc_mutex_assert_locked(CONTEXT, &((krb5_fcc_data *)(ID)->data)->lock); \
if (OPENCLOSE (ID)) { \
krb5_error_code maybe_open_ret; \
maybe_open_ret = krb5_fcc_open_file (CONTEXT,ID,MODE); \
if (maybe_open_ret) { \
- k5_mutex_unlock(&((krb5_fcc_data *)(ID)->data)->lock); \
+ k5_cc_mutex_unlock(CONTEXT, &((krb5_fcc_data *)(ID)->data)->lock); \
return maybe_open_ret; \
} \
} \
@@ -356,7 +383,7 @@ krb5_fcc_read(krb5_context context, krb5_ccache id, krb5_pointer buf, unsigned i
#if 0
int ret;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
ret = read(((krb5_fcc_data *) id->data)->file, (char *) buf, len);
if (ret == -1)
@@ -368,7 +395,7 @@ krb5_fcc_read(krb5_context context, krb5_ccache id, krb5_pointer buf, unsigned i
#else
krb5_fcc_data *data = (krb5_fcc_data *) id->data;
- k5_assert_locked(&data->lock);
+ k5_cc_mutex_assert_locked(context, &data->lock);
while (len > 0) {
int nread, e;
@@ -441,7 +468,7 @@ krb5_fcc_read_principal(krb5_context context, krb5_ccache id, krb5_principal *pr
krb5_int32 length, type;
int i;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
*princ = NULL;
@@ -517,7 +544,7 @@ krb5_fcc_read_addrs(krb5_context context, krb5_ccache id, krb5_address ***addrs)
size_t msize;
int i;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
*addrs = 0;
@@ -565,7 +592,7 @@ krb5_fcc_read_keyblock(krb5_context context, krb5_ccache id, krb5_keyblock *keyb
krb5_ui_2 ui2;
krb5_int32 int32;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
keyblock->magic = KV5M_KEYBLOCK;
keyblock->contents = 0;
@@ -613,7 +640,7 @@ krb5_fcc_read_data(krb5_context context, krb5_ccache id, krb5_data *data)
krb5_error_code kret;
krb5_int32 len;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
data->magic = KV5M_DATA;
data->data = 0;
@@ -655,7 +682,7 @@ krb5_fcc_read_addr(krb5_context context, krb5_ccache id, krb5_address *addr)
krb5_ui_2 ui2;
krb5_int32 int32;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
addr->magic = KV5M_ADDRESS;
addr->contents = 0;
@@ -701,7 +728,7 @@ krb5_fcc_read_int32(krb5_context context, krb5_ccache id, krb5_int32 *i)
unsigned char buf[4];
krb5_int32 val;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
@@ -726,7 +753,7 @@ krb5_fcc_read_ui_2(krb5_context context, krb5_ccache id, krb5_ui_2 *i)
krb5_error_code retval;
unsigned char buf[2];
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
@@ -743,7 +770,7 @@ krb5_fcc_read_ui_2(krb5_context context, krb5_ccache id, krb5_ui_2 *i)
static krb5_error_code
krb5_fcc_read_octet(krb5_context context, krb5_ccache id, krb5_octet *i)
{
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
return krb5_fcc_read(context, id, (krb5_pointer) i, 1);
}
@@ -755,7 +782,7 @@ krb5_fcc_read_times(krb5_context context, krb5_ccache id, krb5_ticket_times *t)
krb5_error_code retval;
krb5_int32 i;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
@@ -790,7 +817,7 @@ krb5_fcc_read_authdata(krb5_context context, krb5_ccache id, krb5_authdata ***a)
size_t msize;
int i;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
*a = 0;
@@ -840,7 +867,7 @@ krb5_fcc_read_authdatum(krb5_context context, krb5_ccache id, krb5_authdata *a)
krb5_int32 int32;
krb5_ui_2 ui2;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
a->magic = KV5M_AUTHDATA;
a->contents = NULL;
@@ -896,7 +923,7 @@ krb5_fcc_write(krb5_context context, krb5_ccache id, krb5_pointer buf, unsigned
{
int ret;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
invalidate_cache((krb5_fcc_data *) id->data);
ret = write(((krb5_fcc_data *)id->data)->file, (char *) buf, len);
@@ -930,7 +957,7 @@ krb5_fcc_store_principal(krb5_context context, krb5_ccache id, krb5_principal pr
krb5_error_code ret;
krb5_int32 i, length, tmp, type;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
type = krb5_princ_type(context, princ);
tmp = length = krb5_princ_size(context, princ);
@@ -968,7 +995,7 @@ krb5_fcc_store_addrs(krb5_context context, krb5_ccache id, krb5_address **addrs)
krb5_address **temp;
krb5_int32 i, length = 0;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
/* Count the number of components */
if (addrs) {
@@ -993,7 +1020,7 @@ krb5_fcc_store_keyblock(krb5_context context, krb5_ccache id, krb5_keyblock *key
krb5_fcc_data *data = (krb5_fcc_data *)id->data;
krb5_error_code ret;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
ret = krb5_fcc_store_ui_2(context, id, keyblock->enctype);
CHECK(ret);
@@ -1011,7 +1038,7 @@ krb5_fcc_store_addr(krb5_context context, krb5_ccache id, krb5_address *addr)
{
krb5_error_code ret;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
ret = krb5_fcc_store_ui_2(context, id, addr->addrtype);
CHECK(ret);
@@ -1026,7 +1053,7 @@ krb5_fcc_store_data(krb5_context context, krb5_ccache id, krb5_data *data)
{
krb5_error_code ret;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
ret = krb5_fcc_store_ui_4(context, id, data->length);
CHECK(ret);
@@ -1045,7 +1072,7 @@ krb5_fcc_store_ui_4(krb5_context context, krb5_ccache id, krb5_ui_4 i)
krb5_fcc_data *data = (krb5_fcc_data *)id->data;
unsigned char buf[4];
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
@@ -1069,7 +1096,7 @@ krb5_fcc_store_ui_2(krb5_context context, krb5_ccache id, krb5_int32 i)
krb5_ui_2 ibuf;
unsigned char buf[2];
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2)) {
@@ -1088,7 +1115,7 @@ krb5_fcc_store_octet(krb5_context context, krb5_ccache id, krb5_int32 i)
{
krb5_octet ibuf;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
ibuf = (krb5_octet) i;
return krb5_fcc_write(context, id, (char *) &ibuf, 1);
@@ -1100,7 +1127,7 @@ krb5_fcc_store_times(krb5_context context, krb5_ccache id, krb5_ticket_times *t)
krb5_fcc_data *data = (krb5_fcc_data *)id->data;
krb5_error_code retval;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
@@ -1125,7 +1152,7 @@ krb5_fcc_store_authdata(krb5_context context, krb5_ccache id, krb5_authdata **a)
krb5_authdata **temp;
krb5_int32 i, length=0;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
if (a != NULL) {
for (temp=a; *temp; temp++)
@@ -1146,7 +1173,7 @@ krb5_fcc_store_authdatum (krb5_context context, krb5_ccache id, krb5_authdata *a
{
krb5_error_code ret;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
ret = krb5_fcc_store_ui_2(context, id, a->ad_type);
CHECK(ret);
@@ -1162,7 +1189,7 @@ krb5_fcc_close_file (krb5_context context, krb5_fcc_data *data)
int ret;
krb5_error_code retval;
- k5_assert_locked(&data->lock);
+ k5_cc_mutex_assert_locked(context, &data->lock);
if (data->file == NO_FILE)
return KRB5_FCC_INTERNAL;
@@ -1201,7 +1228,7 @@ krb5_fcc_open_file (krb5_context context, krb5_ccache id, int mode)
int lock_flag;
krb5_error_code retval = 0;
- k5_assert_locked(&data->lock);
+ k5_cc_mutex_assert_locked(context, &data->lock);
invalidate_cache(data);
if (data->file != NO_FILE) {
@@ -1384,7 +1411,7 @@ krb5_fcc_skip_header(krb5_context context, krb5_ccache id)
krb5_error_code kret;
krb5_ui_2 fcc_flen;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
fcc_lseek(data, (off_t) sizeof(krb5_ui_2), SEEK_SET);
if (data->version == KRB5_FCC_FVNO_4) {
@@ -1402,7 +1429,7 @@ krb5_fcc_skip_principal(krb5_context context, krb5_ccache id)
krb5_error_code kret;
krb5_principal princ;
- k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_fcc_data *) id->data)->lock);
kret = krb5_fcc_read_principal(context, id, &princ);
if (kret != KRB5_OK)
@@ -1431,7 +1458,7 @@ krb5_fcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ)
krb5_error_code kret = 0;
int reti = 0;
- kret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+ kret = k5_cc_mutex_lock(context, &((krb5_fcc_data *) id->data)->lock);
if (kret)
return kret;
@@ -1447,7 +1474,7 @@ krb5_fcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ)
if (reti == -1) {
kret = krb5_fcc_interpret(context, errno);
MAYBE_CLOSE(context, id, kret);
- k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_unlock(context, &((krb5_fcc_data *) id->data)->lock);
return kret;
}
}
@@ -1455,7 +1482,7 @@ krb5_fcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ)
kret = krb5_fcc_store_principal(context, id, princ);
MAYBE_CLOSE(context, id, kret);
- k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_unlock(context, &((krb5_fcc_data *) id->data)->lock);
krb5_change_cache ();
return kret;
}
@@ -1469,7 +1496,7 @@ static krb5_error_code dereference(krb5_context context, krb5_fcc_data *data)
krb5_error_code kerr;
struct fcc_set **fccsp;
- kerr = k5_mutex_lock(&krb5int_cc_file_mutex);
+ kerr = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex);
if (kerr)
return kerr;
for (fccsp = &fccs; *fccsp != NULL; fccsp = &(*fccsp)->next)
@@ -1484,21 +1511,21 @@ static krb5_error_code dereference(krb5_context context, krb5_fcc_data *data)
temp = *fccsp;
*fccsp = (*fccsp)->next;
free(temp);
- k5_mutex_unlock(&krb5int_cc_file_mutex);
- k5_mutex_assert_unlocked(&data->lock);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ k5_cc_mutex_assert_unlocked(context, &data->lock);
free(data->filename);
zap(data->buf, sizeof(data->buf));
if (data->file >= 0) {
- kerr = k5_mutex_lock(&data->lock);
+ kerr = k5_cc_mutex_lock(context, &data->lock);
if (kerr)
return kerr;
krb5_fcc_close_file(context, data);
- k5_mutex_unlock(&data->lock);
+ k5_cc_mutex_unlock(context, &data->lock);
}
- k5_mutex_destroy(&data->lock);
+ k5_cc_mutex_destroy(&data->lock);
free(data);
} else
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
return 0;
}
@@ -1537,7 +1564,7 @@ krb5_fcc_destroy(krb5_context context, krb5_ccache id)
unsigned int wlen;
char zeros[BUFSIZ];
- kret = k5_mutex_lock(&data->lock);
+ kret = k5_cc_mutex_lock(context, &data->lock);
if (kret)
return kret;
@@ -1647,7 +1674,7 @@ krb5_fcc_destroy(krb5_context context, krb5_ccache id)
#endif /* MSDOS_FILESYSTEM */
cleanup:
- k5_mutex_unlock(&data->lock);
+ k5_cc_mutex_unlock(context, &data->lock);
dereference(context, data);
krb5_xfree(id);
@@ -1684,7 +1711,7 @@ krb5_fcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
krb5_fcc_data *data;
struct fcc_set *setptr;
- kret = k5_mutex_lock(&krb5int_cc_file_mutex);
+ kret = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex);
if (kret)
return kret;
for (setptr = fccs; setptr; setptr = setptr->next) {
@@ -1696,35 +1723,35 @@ krb5_fcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
assert(setptr->refcount != 0);
setptr->refcount++;
assert(setptr->refcount != 0);
- kret = k5_mutex_lock(&data->lock);
+ kret = k5_cc_mutex_lock(context, &data->lock);
if (kret) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
return kret;
}
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
} else {
data = malloc(sizeof(krb5_fcc_data));
if (data == NULL) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
return KRB5_CC_NOMEM;
}
data->filename = strdup(residual);
if (data->filename == NULL) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
free(data);
return KRB5_CC_NOMEM;
}
- kret = k5_mutex_init(&data->lock);
+ kret = k5_cc_mutex_init(&data->lock);
if (kret) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
free(data->filename);
free(data);
return kret;
}
- kret = k5_mutex_lock(&data->lock);
+ kret = k5_cc_mutex_lock(context, &data->lock);
if (kret) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
- k5_mutex_destroy(&data->lock);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ k5_cc_mutex_destroy(&data->lock);
free(data->filename);
free(data);
return kret;
@@ -1736,9 +1763,9 @@ krb5_fcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
data->valid_bytes = 0;
setptr = malloc(sizeof(struct fcc_set));
if (setptr == NULL) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
- k5_mutex_unlock(&data->lock);
- k5_mutex_destroy(&data->lock);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &data->lock);
+ k5_cc_mutex_destroy(&data->lock);
free(data->filename);
free(data);
return KRB5_CC_NOMEM;
@@ -1747,11 +1774,11 @@ krb5_fcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
setptr->data = data;
setptr->next = fccs;
fccs = setptr;
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
}
- k5_mutex_assert_locked(&data->lock);
- k5_mutex_unlock(&data->lock);
+ k5_cc_mutex_assert_locked(context, &data->lock);
+ k5_cc_mutex_unlock(context, &data->lock);
lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
if (lid == NULL) {
dereference(context, data);
@@ -1789,20 +1816,20 @@ krb5_fcc_start_seq_get(krb5_context context, krb5_ccache id,
krb5_error_code kret = KRB5_OK;
krb5_fcc_data *data = (krb5_fcc_data *)id->data;
- kret = k5_mutex_lock(&data->lock);
+ kret = k5_cc_mutex_lock(context, &data->lock);
if (kret)
return kret;
fcursor = (krb5_fcc_cursor *) malloc(sizeof(krb5_fcc_cursor));
if (fcursor == NULL) {
- k5_mutex_unlock(&data->lock);
+ k5_cc_mutex_unlock(context, &data->lock);
return KRB5_CC_NOMEM;
}
if (OPENCLOSE(id)) {
kret = krb5_fcc_open_file(context, id, FCC_OPEN_RDONLY);
if (kret) {
krb5_xfree(fcursor);
- k5_mutex_unlock(&data->lock);
+ k5_cc_mutex_unlock(context, &data->lock);
return kret;
}
}
@@ -1824,7 +1851,7 @@ krb5_fcc_start_seq_get(krb5_context context, krb5_ccache id,
done:
MAYBE_CLOSE(context, id, kret);
- k5_mutex_unlock(&data->lock);
+ k5_cc_mutex_unlock(context, &data->lock);
return kret;
}
@@ -1860,7 +1887,7 @@ krb5_fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
krb5_octet octet;
krb5_fcc_data *d = (krb5_fcc_data *) id->data;
- kret = k5_mutex_lock(&d->lock);
+ kret = k5_cc_mutex_lock(context, &d->lock);
if (kret)
return kret;
@@ -1872,7 +1899,7 @@ krb5_fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
if (kret) {
kret = krb5_fcc_interpret(context, errno);
MAYBE_CLOSE(context, id, kret);
- k5_mutex_unlock(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
return kret;
}
@@ -1903,7 +1930,7 @@ krb5_fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
lose:
MAYBE_CLOSE (context, id, kret);
- k5_mutex_unlock(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
if (kret != KRB5_OK)
krb5_free_cred_contents(context, creds);
return kret;
@@ -1966,7 +1993,7 @@ krb5_fcc_generate_new (krb5_context context, krb5_ccache *id)
struct fcc_set *setptr;
/* Set master lock */
- kret = k5_mutex_lock(&krb5int_cc_file_mutex);
+ kret = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex);
if (kret)
return kret;
@@ -1974,7 +2001,7 @@ krb5_fcc_generate_new (krb5_context context, krb5_ccache *id)
(void) strcat(scratch, "XXXXXX");
ret = mkstemp(scratch);
if (ret == -1) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
return krb5_fcc_interpret(context, errno);
}
set_cloexec_fd(ret);
@@ -1982,34 +2009,34 @@ krb5_fcc_generate_new (krb5_context context, krb5_ccache *id)
/* Allocate memory */
data = (krb5_pointer) malloc(sizeof(krb5_fcc_data));
if (data == NULL) {
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
close(ret);
unlink(scratch);
- k5_mutex_unlock(&krb5int_cc_file_mutex);
return KRB5_CC_NOMEM;
}
data->filename = strdup(scratch);
if (data->filename == NULL) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
free(data);
close(ret);
unlink(scratch);
return KRB5_CC_NOMEM;
}
- kret = k5_mutex_init(&data->lock);
+ kret = k5_cc_mutex_init(&data->lock);
if (kret) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
free(data->filename);
free(data);
close(ret);
unlink(scratch);
return kret;
}
- kret = k5_mutex_lock(&data->lock);
+ kret = k5_cc_mutex_lock(context, &data->lock);
if (kret) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
- k5_mutex_destroy(&data->lock);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ k5_cc_mutex_destroy(&data->lock);
free(data->filename);
free(data);
close(ret);
@@ -2064,9 +2091,9 @@ krb5_fcc_generate_new (krb5_context context, krb5_ccache *id)
setptr = malloc(sizeof(struct fcc_set));
if (setptr == NULL) {
- k5_mutex_unlock(&krb5int_cc_file_mutex);
- k5_mutex_unlock(&data->lock);
- k5_mutex_destroy(&data->lock);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &data->lock);
+ k5_cc_mutex_destroy(&data->lock);
free(data->filename);
free(data);
(void) close(ret);
@@ -2077,10 +2104,10 @@ krb5_fcc_generate_new (krb5_context context, krb5_ccache *id)
setptr->data = data;
setptr->next = fccs;
fccs = setptr;
- k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
- k5_mutex_assert_locked(&data->lock);
- k5_mutex_unlock(&data->lock);
+ k5_cc_mutex_assert_locked(context, &data->lock);
+ k5_cc_mutex_unlock(context, &data->lock);
lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
if (lid == NULL) {
dereference(context, data);
@@ -2102,8 +2129,8 @@ krb5_fcc_generate_new (krb5_context context, krb5_ccache *id)
return KRB5_OK;
err_out:
- k5_mutex_unlock(&krb5int_cc_file_mutex);
- k5_mutex_destroy(&data->lock);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ k5_cc_mutex_destroy(&data->lock);
free(data->filename);
free(data);
return kret;
@@ -2140,7 +2167,7 @@ krb5_fcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *pri
{
krb5_error_code kret = KRB5_OK;
- kret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+ kret = k5_cc_mutex_lock(context, &((krb5_fcc_data *) id->data)->lock);
if (kret)
return kret;
@@ -2153,7 +2180,7 @@ krb5_fcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *pri
done:
MAYBE_CLOSE(context, id, kret);
- k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_unlock(context, &((krb5_fcc_data *) id->data)->lock);
return kret;
}
@@ -2183,7 +2210,7 @@ krb5_fcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
#define TCHECK(ret) if (ret != KRB5_OK) goto lose;
krb5_error_code ret;
- ret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+ ret = k5_cc_mutex_lock(context, &((krb5_fcc_data *) id->data)->lock);
if (ret)
return ret;
@@ -2194,7 +2221,7 @@ krb5_fcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
ret = fcc_lseek((krb5_fcc_data *) id->data, (off_t) 0, SEEK_END);
if (ret < 0) {
MAYBE_CLOSE_IGNORE(context, id);
- k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_unlock(context, &((krb5_fcc_data *) id->data)->lock);
return krb5_fcc_interpret(context, errno);
}
@@ -2221,7 +2248,7 @@ krb5_fcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
lose:
MAYBE_CLOSE(context, id, ret);
- k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_unlock(context, &((krb5_fcc_data *) id->data)->lock);
krb5_change_cache ();
return ret;
#undef TCHECK
@@ -2256,7 +2283,7 @@ krb5_fcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags)
{
krb5_error_code ret = KRB5_OK;
- ret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+ ret = k5_cc_mutex_lock(context, &((krb5_fcc_data *) id->data)->lock);
if (ret)
return ret;
@@ -2274,7 +2301,7 @@ krb5_fcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags)
}
((krb5_fcc_data *) id->data)->flags = flags;
- k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_unlock(context, &((krb5_fcc_data *) id->data)->lock);
return ret;
}
@@ -2294,14 +2321,172 @@ krb5_fcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags *flags)
{
krb5_error_code ret = KRB5_OK;
- ret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+ ret = k5_cc_mutex_lock(context, &((krb5_fcc_data *) id->data)->lock);
if (ret)
return ret;
*flags = ((krb5_fcc_data *) id->data)->flags;
- k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+ k5_cc_mutex_unlock(context, &((krb5_fcc_data *) id->data)->lock);
return ret;
}
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_ptcursor_new(krb5_context context, krb5_cc_ptcursor *cursor)
+{
+ krb5_error_code ret = 0;
+ krb5_cc_ptcursor n = NULL;
+ struct krb5_fcc_ptcursor_data *cdata = NULL;
+
+ *cursor = NULL;
+
+ n = malloc(sizeof(*n));
+ if (n == NULL)
+ return ENOMEM;
+ n->ops = &krb5_fcc_ops;
+ cdata = malloc(sizeof(struct krb5_fcc_ptcursor_data));
+ if (cdata == NULL) {
+ ret = ENOMEM;
+ goto errout;
+ }
+ n->data = cdata;
+ ret = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex);
+ if (ret)
+ goto errout;
+ cdata->cur = fccs;
+ ret = k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ if (ret)
+ goto errout;
+
+errout:
+ if (ret) {
+ krb5_fcc_ptcursor_free(context, &n);
+ }
+ *cursor = n;
+ return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_ptcursor_next(krb5_context context,
+ krb5_cc_ptcursor cursor,
+ krb5_ccache *ccache)
+{
+ krb5_error_code ret = 0;
+ struct krb5_fcc_ptcursor_data *cdata = NULL;
+ krb5_ccache n;
+
+ *ccache = NULL;
+ n = malloc(sizeof(*n));
+ if (n == NULL)
+ return ENOMEM;
+
+ cdata = cursor->data;
+
+ ret = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex);
+ if (ret)
+ goto errout;
+
+ if (cdata->cur == NULL) {
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ free(n);
+ n = NULL;
+ goto errout;
+ }
+
+ n->ops = &krb5_fcc_ops;
+ n->data = cdata->cur->data;
+ cdata->cur->refcount++;
+
+ cdata->cur = cdata->cur->next;
+
+ ret = k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ if (ret)
+ goto errout;
+errout:
+ if (ret && n != NULL) {
+ free(n);
+ n = NULL;
+ }
+ *ccache = n;
+ return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_ptcursor_free(krb5_context context,
+ krb5_cc_ptcursor *cursor)
+{
+ if (*cursor == NULL)
+ return 0;
+ if ((*cursor)->data != NULL)
+ free((*cursor)->data);
+ free(*cursor);
+ *cursor = NULL;
+ return 0;
+}
+
+/*
+ * Modifies:
+ * change_time
+ *
+ * Effects:
+ * Returns the timestamp of id's file modification date.
+ * If an error occurs, change_time is set to 0.
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_last_change_time(krb5_context context, krb5_ccache id,
+ krb5_timestamp *change_time)
+{
+ krb5_error_code kret = KRB5_OK;
+ krb5_fcc_data *data = (krb5_fcc_data *) id->data;
+
+ kret = krb5_fcc_data_last_change_time(context, data, change_time);
+
+ return kret;
+}
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_lock(krb5_context context,
+ krb5_ccache id)
+{
+ krb5_error_code ret = 0;
+ krb5_fcc_data *data = (krb5_fcc_data *) id->data;
+ ret = k5_cc_mutex_lock(context, &data->lock);
+ return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV krb5_fcc_unlock(krb5_context context,
+ krb5_ccache id)
+{
+ krb5_error_code ret = 0;
+ krb5_fcc_data *data = (krb5_fcc_data *) id->data;
+ ret = k5_cc_mutex_unlock(context, &data->lock);
+ return ret;
+}
+
+static krb5_error_code
+krb5_fcc_data_last_change_time(krb5_context context, krb5_fcc_data *data,
+ krb5_timestamp *change_time)
+{
+ krb5_error_code kret = KRB5_OK;
+ register int ret;
+
+ struct stat buf;
+
+ *change_time = 0;
+
+ kret = k5_cc_mutex_lock(context, &data->lock);
+ if (kret) {
+ return kret;
+ }
+
+ ret = stat(data->filename, &buf);
+ if (ret == -1) {
+ kret = krb5_fcc_interpret(context, errno);
+ } else {
+ *change_time = (krb5_timestamp) buf.st_mtime;
+ }
+
+ k5_cc_mutex_unlock(context, &data->lock);
+
+ return kret;
+}
static krb5_error_code
krb5_fcc_interpret(krb5_context context, int errnum)
@@ -2374,6 +2559,14 @@ const krb5_cc_ops krb5_fcc_ops = {
krb5_fcc_remove_cred,
krb5_fcc_set_flags,
krb5_fcc_get_flags,
+ krb5_fcc_ptcursor_new,
+ krb5_fcc_ptcursor_next,
+ krb5_fcc_ptcursor_free,
+ NULL, /* move */
+ krb5_fcc_last_change_time,
+ NULL, /* wasdefault */
+ krb5_fcc_lock,
+ krb5_fcc_unlock,
};
#if defined(_WIN32)
@@ -2435,10 +2628,12 @@ const krb5_cc_ops krb5_cc_file_ops = {
krb5_fcc_remove_cred,
krb5_fcc_set_flags,
krb5_fcc_get_flags,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
+ krb5_fcc_ptcursor_new,
+ krb5_fcc_ptcursor_next,
+ krb5_fcc_ptcursor_free,
+ NULL, /* move */
+ krb5_fcc_last_change_time,
+ NULL, /* wasdefault */
+ krb5_fcc_lock,
+ krb5_fcc_unlock,
};
diff --git a/src/lib/krb5/ccache/cc_keyring.c b/src/lib/krb5/ccache/cc_keyring.c
index 2d8864af3..f2624ecca 100644
--- a/src/lib/krb5/ccache/cc_keyring.c
+++ b/src/lib/krb5/ccache/cc_keyring.c
@@ -177,12 +177,13 @@ typedef struct _krb5_krcc_cursor
typedef struct _krb5_krcc_data
{
char *name; /* Name for this credentials cache */
- k5_mutex_t lock; /* synchronization */
+ k5_cc_mutex lock; /* synchronization */
key_serial_t parent_id; /* parent keyring of this ccache keyring */
key_serial_t ring_id; /* keyring representing ccache */
key_serial_t princ_id; /* key holding principal info */
int numkeys; /* # of keys in this ring
* (does NOT include principal info) */
+ krb5_timestamp changetime;
} krb5_krcc_data;
/* Passed internally to assure we don't go past the bounds of our buffer */
@@ -193,7 +194,7 @@ typedef struct _krb5_krcc_buffer_cursor
} krb5_krcc_bc;
/* Global mutex */
-k5_mutex_t krb5int_krcc_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+k5_cc_mutex krb5int_krcc_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER;
/*
* Internal functions (exported via the krb5_krcc_ops)
@@ -249,6 +250,15 @@ static krb5_error_code KRB5_CALLCONV krb5_krcc_set_flags
static krb5_error_code KRB5_CALLCONV krb5_krcc_get_flags
(krb5_context context, krb5_ccache id, krb5_flags * flags);
+static krb5_error_code KRB5_CALLCONV krb5_krcc_last_change_time
+ (krb5_context, krb5_ccache, krb5_timestamp *);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_lock
+ (krb5_context context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_krcc_unlock
+ (krb5_context context, krb5_ccache id);
+
/*
* Internal utility functions
*/
@@ -339,6 +349,8 @@ static krb5_error_code krb5_krcc_unparse_ui_4
(krb5_context, krb5_ccache id, krb5_ui_4 i, krb5_krcc_bc * bc);
static krb5_error_code krb5_krcc_unparse_ui_2
(krb5_context, krb5_ccache id, krb5_int32 i, krb5_krcc_bc * bc);
+static void krb5_krcc_update_change_time
+ (krb5_krcc_data *);
/* Note the following is a stub function for Linux */
extern krb5_error_code krb5_change_cache(void);
@@ -381,7 +393,7 @@ krb5_krcc_initialize(krb5_context context, krb5_ccache id,
DEBUG_PRINT(("krb5_krcc_initialize: entered\n"));
- kret = k5_mutex_lock(&((krb5_krcc_data *) id->data)->lock);
+ kret = k5_cc_mutex_lock(context, &((krb5_krcc_data *) id->data)->lock);
if (kret)
return kret;
@@ -394,7 +406,7 @@ krb5_krcc_initialize(krb5_context context, krb5_ccache id,
krb5_change_cache();
out:
- k5_mutex_unlock(&((krb5_krcc_data *) id->data)->lock);
+ k5_cc_mutex_unlock(context, &((krb5_krcc_data *) id->data)->lock);
return kret;
}
@@ -416,7 +428,7 @@ krb5_krcc_close(krb5_context context, krb5_ccache id)
d = (krb5_krcc_data *) id->data;
krb5_xfree(d->name);
- k5_mutex_destroy(&d->lock);
+ k5_cc_mutex_destroy(&d->lock);
krb5_xfree(d);
krb5_xfree(id);
@@ -445,7 +457,7 @@ krb5_krcc_clearcache(krb5_context context, krb5_ccache id)
krb5_krcc_data *d;
int res;
- k5_assert_locked(&((krb5_krcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_krcc_data *) id->data)->lock);
d = (krb5_krcc_data *) id->data;
@@ -458,6 +470,7 @@ krb5_krcc_clearcache(krb5_context context, krb5_ccache id)
}
d->numkeys = 0;
d->princ_id = 0;
+ krb5_krcc_update_change_time(d);
return KRB5_OK;
}
@@ -480,7 +493,7 @@ krb5_krcc_destroy(krb5_context context, krb5_ccache id)
d = (krb5_krcc_data *) id->data;
- kret = k5_mutex_lock(&d->lock);
+ kret = k5_cc_mutex_lock(context, &d->lock);
if (kret)
return kret;
@@ -494,8 +507,8 @@ krb5_krcc_destroy(krb5_context context, krb5_ccache id)
goto cleanup;
}
cleanup:
- k5_mutex_unlock(&d->lock);
- k5_mutex_destroy(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
+ k5_cc_mutex_destroy(&d->lock);
krb5_xfree(d);
krb5_xfree(id);
@@ -649,7 +662,7 @@ krb5_krcc_start_seq_get(krb5_context context, krb5_ccache id,
DEBUG_PRINT(("krb5_krcc_start_seq_get: entered\n"));
d = id->data;
- kret = k5_mutex_lock(&d->lock);
+ kret = k5_cc_mutex_lock(context, &d->lock);
if (kret)
return kret;
@@ -664,7 +677,7 @@ krb5_krcc_start_seq_get(krb5_context context, krb5_ccache id,
krcursor = (krb5_krcc_cursor) malloc(size);
if (krcursor == NULL) {
- k5_mutex_unlock(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
return KRB5_CC_NOMEM;
}
@@ -675,7 +688,7 @@ krb5_krcc_start_seq_get(krb5_context context, krb5_ccache id,
DEBUG_PRINT(("Read %d bytes from keyring, numkeys %d: %s\n",
res, d->numkeys, strerror(errno)));
free(krcursor);
- k5_mutex_unlock(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
return KRB5_CC_IO;
}
@@ -683,7 +696,7 @@ krb5_krcc_start_seq_get(krb5_context context, krb5_ccache id,
krcursor->currkey = 0;
krcursor->princ_id = d->princ_id;
- k5_mutex_unlock(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
*cursor = (krb5_cc_cursor) krcursor;
return KRB5_OK;
}
@@ -796,7 +809,7 @@ krb5_krcc_new_data(const char *name, key_serial_t ring,
if (d == NULL)
return KRB5_CC_NOMEM;
- kret = k5_mutex_init(&d->lock);
+ kret = k5_cc_mutex_init(&d->lock);
if (kret) {
krb5_xfree(d);
return kret;
@@ -804,7 +817,7 @@ krb5_krcc_new_data(const char *name, key_serial_t ring,
d->name = strdup(name);
if (d->name == NULL) {
- k5_mutex_destroy(&d->lock);
+ k5_cc_mutex_destroy(&d->lock);
krb5_xfree(d);
return KRB5_CC_NOMEM;
}
@@ -812,6 +825,8 @@ krb5_krcc_new_data(const char *name, key_serial_t ring,
d->ring_id = ring;
d->parent_id = parent_ring;
d->numkeys = 0;
+ d->changetime = 0;
+ krb5_krcc_update_change_time(d);
*datapp = d;
return 0;
@@ -848,7 +863,7 @@ krb5_krcc_generate_new(krb5_context context, krb5_ccache * id)
lid->ops = &krb5_krcc_ops;
- kret = k5_mutex_lock(&krb5int_krcc_mutex);
+ kret = k5_cc_mutex_lock(context, &krb5int_krcc_mutex);
if (kret) {
free(lid);
return kret;
@@ -876,7 +891,7 @@ krb5_krcc_generate_new(krb5_context context, krb5_ccache * id)
while (1) {
kret = krb5int_random_string(context, uniquename, sizeof(uniquename));
if (kret) {
- k5_mutex_unlock(&krb5int_krcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_krcc_mutex);
free(lid);
return kret;
}
@@ -892,7 +907,7 @@ krb5_krcc_generate_new(krb5_context context, krb5_ccache * id)
kret = errno;
DEBUG_PRINT(("krb5_krcc_generate_new: '%s' trying to "
"create '%s'\n", strerror(errno), uniquename));
- k5_mutex_unlock(&krb5int_krcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_krcc_mutex);
return kret;
}
break;
@@ -900,7 +915,7 @@ krb5_krcc_generate_new(krb5_context context, krb5_ccache * id)
}
kret = krb5_krcc_new_data(uniquename, key, ring_id, &d);
- k5_mutex_unlock(&krb5int_krcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_krcc_mutex);
if (kret) {
krb5_xfree(lid);
return kret;
@@ -1014,7 +1029,7 @@ krb5_krcc_store(krb5_context context, krb5_ccache id, krb5_creds * creds)
DEBUG_PRINT(("krb5_krcc_store: entered\n"));
- kret = k5_mutex_lock(&d->lock);
+ kret = k5_cc_mutex_lock(context, &d->lock);
if (kret)
return kret;
@@ -1042,6 +1057,7 @@ krb5_krcc_store(krb5_context context, krb5_ccache id, krb5_creds * creds)
} else {
d->numkeys++;
kret = KRB5_OK;
+ krb5_krcc_update_change_time(d);
}
errout:
@@ -1050,10 +1066,47 @@ krb5_krcc_store(krb5_context context, krb5_ccache id, krb5_creds * creds)
if (payload)
free(payload);
- k5_mutex_unlock(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
return kret;
}
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_last_change_time(krb5_context context, krb5_ccache id,
+ krb5_timestamp *change_time)
+{
+ krb5_error_code ret = 0;
+ krb5_krcc_data *data = (krb5_krcc_data *) id->data;
+
+ *change_time = 0;
+
+ ret = k5_cc_mutex_lock(context, &data->lock);
+ if (!ret) {
+ *change_time = data->changetime;
+ k5_cc_mutex_unlock(context, &data->lock);
+ }
+
+ return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_lock(krb5_context context, krb5_ccache id)
+{
+ krb5_error_code ret = 0;
+ krb5_krcc_data *data = (krb5_krcc_data *) id->data;
+ ret = k5_cc_mutex_lock(context, &data->lock);
+ return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_krcc_unlock(krb5_context context, krb5_ccache id)
+{
+ krb5_error_code ret = 0;
+ krb5_krcc_data *data = (krb5_krcc_data *) id->data;
+ ret = k5_cc_mutex_unlock(context, &data->lock);
+ return ret;
+}
+
+
static krb5_error_code
krb5_krcc_save_principal(krb5_context context, krb5_ccache id,
krb5_principal princ)
@@ -1065,7 +1118,7 @@ krb5_krcc_save_principal(krb5_context context, krb5_ccache id,
unsigned int payloadsize;
krb5_krcc_bc bc;
- k5_assert_locked(&((krb5_krcc_data *) id->data)->lock);
+ k5_cc_mutex_assert_locked(context, &((krb5_krcc_data *) id->data)->lock);
d = (krb5_krcc_data *) id->data;
@@ -1102,6 +1155,7 @@ krb5_krcc_save_principal(krb5_context context, krb5_ccache id,
} else {
d->princ_id = newkey;
kret = KRB5_OK;
+ krb5_krcc_update_change_time(d);
}
errout:
@@ -1119,7 +1173,7 @@ krb5_krcc_retrieve_principal(krb5_context context, krb5_ccache id,
int psize;
krb5_krcc_bc bc;
- kret = k5_mutex_lock(&d->lock);
+ kret = k5_cc_mutex_lock(context, &d->lock);
if (kret)
return kret;
@@ -1143,7 +1197,7 @@ krb5_krcc_retrieve_principal(krb5_context context, krb5_ccache id,
errout:
if (payload)
free(payload);
- k5_mutex_unlock(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
return kret;
}
@@ -1973,6 +2027,22 @@ krb5_krcc_unparse_cred(krb5_context context, krb5_ccache id,
}
/*
+ * Utility routine: called by krb5_krcc_* functions to keep
+ * result of krb5_krcc_last_change_time up to date.
+ * Value monotonically increases -- based on but not guaranteed to be actual
+ * system time.
+ */
+
+static void
+krb5_krcc_update_change_time(krb5_krcc_data *d)
+{
+ krb5_timestamp now_time = time(NULL);
+ d->changetime = (d->changetime >= now_time) ?
+ d->changetime + 1 : now_time;
+}
+
+
+/*
* ccache implementation storing credentials in the Linux keyring facility
* The default is to put them at the session keyring level.
* If "KEYRING:process:" or "KEYRING:thread:" is specified, then they will
@@ -1995,7 +2065,15 @@ const krb5_cc_ops krb5_krcc_ops = {
krb5_krcc_end_seq_get,
krb5_krcc_remove_cred,
krb5_krcc_set_flags,
- krb5_krcc_get_flags /* added after 1.4 release */
+ krb5_krcc_get_flags, /* added after 1.4 release */
+ NULL,
+ NULL,
+ NULL,
+ NULL, /* move */
+ krb5_krcc_last_change_time, /* lastchange */
+ NULL, /* wasdefault */
+ krb5_krcc_lock,
+ krb5_krcc_unlock,
};
#else /* !USE_KEYRING_CCACHE */
@@ -2020,6 +2098,14 @@ const krb5_cc_ops krb5_krcc_ops = {
NULL,
NULL,
NULL,
- NULL /* added after 1.4 release */
+ NULL, /* added after 1.4 release */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
};
#endif /* USE_KEYRING_CCACHE */
diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c
index dc0fd3422..4a3b67c80 100644
--- a/src/lib/krb5/ccache/cc_memory.c
+++ b/src/lib/krb5/ccache/cc_memory.c
@@ -75,18 +75,24 @@ static krb5_error_code KRB5_CALLCONV krb5_mcc_store
static krb5_error_code KRB5_CALLCONV krb5_mcc_set_flags
(krb5_context, krb5_ccache id , krb5_flags flags );
-static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_new(
- krb5_context,
- krb5_cc_ptcursor *);
+static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_new
+ (krb5_context, krb5_cc_ptcursor *);
-static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_next(
- krb5_context,
- krb5_cc_ptcursor,
- krb5_ccache *);
+static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_next
+ (krb5_context, krb5_cc_ptcursor, krb5_ccache *);
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_free
+ (krb5_context, krb5_cc_ptcursor *);
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_last_change_time
+ (krb5_context, krb5_ccache, krb5_timestamp *);
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_lock
+ (krb5_context context, krb5_ccache id);
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_unlock
+ (krb5_context context, krb5_ccache id);
-static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_free(
- krb5_context,
- krb5_cc_ptcursor *);
extern const krb5_cc_ops krb5_mcc_ops;
extern krb5_error_code krb5_change_cache (void);
@@ -102,9 +108,10 @@ typedef struct _krb5_mcc_link {
/* Per-cache data header. */
typedef struct _krb5_mcc_data {
char *name;
- k5_mutex_t lock;
+ k5_cc_mutex lock;
krb5_principal prin;
krb5_mcc_cursor link;
+ krb5_timestamp changetime;
} krb5_mcc_data;
/* List of memory caches. */
@@ -118,9 +125,11 @@ struct krb5_mcc_ptcursor_data {
struct krb5_mcc_list_node *cur;
};
-k5_mutex_t krb5int_mcc_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
+k5_cc_mutex krb5int_mcc_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER;
static krb5_mcc_list_node *mcc_head = 0;
+static void update_mcc_change_time(krb5_mcc_data *);
+
/*
* Modifies:
* id
@@ -142,15 +151,18 @@ krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ)
krb5_mcc_data *d;
d = (krb5_mcc_data *)id->data;
- ret = k5_mutex_lock(&d->lock);
+ ret = k5_cc_mutex_lock(context, &d->lock);
if (ret)
return ret;
krb5_mcc_free(context, id);
+
+ d = (krb5_mcc_data *)id->data;
ret = krb5_copy_principal(context, princ,
- &((krb5_mcc_data *)id->data)->prin);
+ &d->prin);
+ update_mcc_change_time(d);
- k5_mutex_unlock(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
if (ret == KRB5_OK)
krb5_change_cache();
return ret;
@@ -202,7 +214,7 @@ krb5_mcc_destroy(krb5_context context, krb5_ccache id)
krb5_mcc_data *d;
krb5_error_code err;
- err = k5_mutex_lock(&krb5int_mcc_mutex);
+ err = k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
if (err)
return err;
@@ -215,16 +227,16 @@ krb5_mcc_destroy(krb5_context context, krb5_ccache id)
break;
}
}
- k5_mutex_unlock(&krb5int_mcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
- err = k5_mutex_lock(&d->lock);
+ err = k5_cc_mutex_lock(context, &d->lock);
if (err)
return err;
krb5_mcc_free(context, id);
krb5_xfree(d->name);
- k5_mutex_unlock(&d->lock);
- k5_mutex_destroy(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
+ k5_cc_mutex_destroy(&d->lock);
krb5_xfree(d);
krb5_xfree(id);
@@ -261,7 +273,7 @@ krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
krb5_error_code err;
krb5_mcc_data *d;
- err = k5_mutex_lock(&krb5int_mcc_mutex);
+ err = k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
if (err)
return err;
for (ptr = mcc_head; ptr; ptr=ptr->next)
@@ -272,11 +284,11 @@ krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
else {
err = new_mcc_data(residual, &d);
if (err) {
- k5_mutex_unlock(&krb5int_mcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
return err;
}
}
- k5_mutex_unlock(&krb5int_mcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
if (lid == NULL)
@@ -310,11 +322,11 @@ krb5_mcc_start_seq_get(krb5_context context, krb5_ccache id,
krb5_mcc_data *d;
d = id->data;
- err = k5_mutex_lock(&d->lock);
+ err = k5_cc_mutex_lock(context, &d->lock);
if (err)
return err;
mcursor = d->link;
- k5_mutex_unlock(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
*cursor = (krb5_cc_cursor) mcursor;
return KRB5_OK;
}
@@ -396,8 +408,8 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
d = malloc(sizeof(krb5_mcc_data));
if (d == NULL)
return KRB5_CC_NOMEM;
-
- err = k5_mutex_init(&d->lock);
+
+ err = k5_cc_mutex_init(&d->lock);
if (err) {
krb5_xfree(d);
return err;
@@ -405,12 +417,14 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
d->name = malloc(strlen(name) + 1);
if (d->name == NULL) {
- k5_mutex_destroy(&d->lock);
+ k5_cc_mutex_destroy(&d->lock);
krb5_xfree(d);
return KRB5_CC_NOMEM;
}
d->link = NULL;
d->prin = NULL;
+ d->changetime = 0;
+ update_mcc_change_time(d);
/* Set up the filename */
strcpy(d->name, name);
@@ -418,7 +432,7 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
n = malloc(sizeof(krb5_mcc_list_node));
if (n == NULL) {
free(d->name);
- k5_mutex_destroy(&d->lock);
+ k5_cc_mutex_destroy(&d->lock);
free(d);
return KRB5_CC_NOMEM;
}
@@ -461,7 +475,7 @@ krb5_mcc_generate_new (krb5_context context, krb5_ccache *id)
lid->ops = &krb5_mcc_ops;
- err = k5_mutex_lock(&krb5int_mcc_mutex);
+ err = k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
if (err) {
free(lid);
return err;
@@ -473,7 +487,7 @@ krb5_mcc_generate_new (krb5_context context, krb5_ccache *id)
err = krb5int_random_string (context, uniquename, sizeof (uniquename));
if (err) {
- k5_mutex_unlock(&krb5int_mcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
free(lid);
return err;
}
@@ -488,7 +502,7 @@ krb5_mcc_generate_new (krb5_context context, krb5_ccache *id)
err = new_mcc_data(uniquename, &d);
- k5_mutex_unlock(&krb5int_mcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
if (err) {
krb5_xfree(lid);
return err;
@@ -636,12 +650,13 @@ krb5_mcc_store(krb5_context ctx, krb5_ccache id, krb5_creds *creds)
free(new_node);
return err;
}
- err = k5_mutex_lock(&mptr->lock);
+ err = k5_cc_mutex_lock(ctx, &mptr->lock);
if (err)
return err;
new_node->next = mptr->link;
mptr->link = new_node;
- k5_mutex_unlock(&mptr->lock);
+ update_mcc_change_time(mptr);
+ k5_cc_mutex_unlock(ctx, &mptr->lock);
return 0;
}
@@ -666,11 +681,11 @@ krb5_mcc_ptcursor_new(
goto errout;
}
n->data = cdata;
- ret = k5_mutex_lock(&krb5int_mcc_mutex);
+ ret = k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
if (ret)
goto errout;
cdata->cur = mcc_head;
- ret = k5_mutex_unlock(&krb5int_mcc_mutex);
+ ret = k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
if (ret)
goto errout;
@@ -702,11 +717,11 @@ krb5_mcc_ptcursor_next(
(*ccache)->ops = &krb5_mcc_ops;
(*ccache)->data = cdata->cur->cache;
- ret = k5_mutex_lock(&krb5int_mcc_mutex);
+ ret = k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
if (ret)
goto errout;
cdata->cur = cdata->cur->next;
- ret = k5_mutex_unlock(&krb5int_mcc_mutex);
+ ret = k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
if (ret)
goto errout;
errout:
@@ -731,6 +746,57 @@ krb5_mcc_ptcursor_free(
return 0;
}
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_last_change_time(
+ krb5_context context,
+ krb5_ccache id,
+ krb5_timestamp *change_time)
+{
+ krb5_error_code ret = 0;
+ krb5_mcc_data *data = (krb5_mcc_data *) id->data;
+
+ *change_time = 0;
+
+ ret = k5_cc_mutex_lock(context, &data->lock);
+ if (!ret) {
+ *change_time = data->changetime;
+ k5_cc_mutex_unlock(context, &data->lock);
+ }
+
+ return ret;
+}
+
+/*
+ Utility routine: called by krb5_mcc_* functions to keep
+ result of krb5_mcc_last_change_time up to date
+ */
+
+static void
+update_mcc_change_time(krb5_mcc_data *d)
+{
+ krb5_timestamp now_time = time(NULL);
+ d->changetime = (d->changetime >= now_time) ?
+ d->changetime + 1 : now_time;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_lock(krb5_context context, krb5_ccache id)
+{
+ krb5_error_code ret = 0;
+ krb5_mcc_data *data = (krb5_mcc_data *) id->data;
+ ret = k5_cc_mutex_lock(context, &data->lock);
+ return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_unlock(krb5_context context, krb5_ccache id)
+{
+ krb5_error_code ret = 0;
+ krb5_mcc_data *data = (krb5_mcc_data *) id->data;
+ ret = k5_cc_mutex_unlock(context, &data->lock);
+ return ret;
+}
+
const krb5_cc_ops krb5_mcc_ops = {
0,
"MEMORY",
@@ -752,7 +818,9 @@ const krb5_cc_ops krb5_mcc_ops = {
krb5_mcc_ptcursor_new,
krb5_mcc_ptcursor_next,
krb5_mcc_ptcursor_free,
- NULL,
- NULL,
- NULL,
+ NULL, /* move */
+ krb5_mcc_last_change_time,
+ NULL, /* wasdefault */
+ krb5_mcc_lock,
+ krb5_mcc_unlock,
};
diff --git a/src/lib/krb5/ccache/ccapi/stdcc.c b/src/lib/krb5/ccache/ccapi/stdcc.c
index 83d6176cc..a5e171e24 100644
--- a/src/lib/krb5/ccache/ccapi/stdcc.c
+++ b/src/lib/krb5/ccache/ccapi/stdcc.c
@@ -90,9 +90,11 @@ krb5_cc_ops krb5_cc_stdcc_ops = {
krb5_stdccv3_ptcursor_new,
krb5_stdccv3_ptcursor_next,
krb5_stdccv3_ptcursor_free,
- NULL,
- NULL,
- NULL,
+ NULL, /* move */
+ krb5_stdccv3_last_change_time, /* lastchange */
+ NULL, /* wasdefault */
+ krb5_stdccv3_lock,
+ krb5_stdccv3_unlock,
#else
krb5_stdcc_get_name,
krb5_stdcc_resolve,
@@ -908,7 +910,6 @@ krb5_stdccv3_ptcursor_next(
cc_string_t ccstring = NULL;
char *name = NULL;
- // TODO set proper errors, check context param
if (!cursor || !cursor->data) {
err = ccErrInvalidContext;
}
@@ -984,6 +985,87 @@ krb5_stdccv3_ptcursor_free(
return 0;
}
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_last_change_time
+ (krb5_context context, krb5_ccache id,
+ krb5_timestamp *change_time)
+{
+ krb5_error_code err = 0;
+ stdccCacheDataPtr ccapi_data = id->data;
+ cc_time_t ccapi_change_time = 0;
+
+ *change_time = 0;
+
+ if (!err) {
+ err = stdccv3_setup(context, ccapi_data);
+ }
+ if (!err) {
+ err = cc_ccache_get_change_time (ccapi_data->NamedCache, &ccapi_change_time);
+ }
+ if (!err) {
+ *change_time = ccapi_change_time;
+ }
+
+ return cc_err_xlate (err);
+}
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_lock
+(krb5_context context, krb5_ccache id)
+{
+ krb5_error_code err = 0;
+ stdccCacheDataPtr ccapi_data = id->data;
+
+ if (!err) {
+ err = stdccv3_setup(context, ccapi_data);
+ }
+ if (!err) {
+ err = cc_ccache_lock(ccapi_data->NamedCache, cc_lock_write, cc_lock_block);
+ }
+ return cc_err_xlate(err);
+}
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_unlock
+(krb5_context context, krb5_ccache id)
+{
+ krb5_error_code err = 0;
+ stdccCacheDataPtr ccapi_data = id->data;
+
+ if (!err) {
+ err = stdccv3_setup(context, ccapi_data);
+ }
+ if (!err) {
+ err = cc_ccache_unlock(ccapi_data->NamedCache);
+ }
+ return cc_err_xlate(err);
+}
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_lock
+(krb5_context context)
+{
+ krb5_error_code err = 0;
+
+ if (!err && !gCntrlBlock) {
+ err = cc_initialize (&gCntrlBlock, ccapi_version_max, &gCCVersion, NULL);
+ }
+ if (!err) {
+ err = cc_context_lock(gCntrlBlock, cc_lock_write, cc_lock_block);
+ }
+ return cc_err_xlate(err);
+}
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_unlock
+(krb5_context context)
+{
+ krb5_error_code err = 0;
+
+ if (!err && !gCntrlBlock) {
+ err = cc_initialize (&gCntrlBlock, ccapi_version_max, &gCCVersion, NULL);
+ }
+ if (!err) {
+ err = cc_context_unlock(gCntrlBlock);
+ }
+ return cc_err_xlate(err);
+}
+
#else /* !USE_CCAPI_V3 */
static krb5_error_code stdcc_setup(krb5_context context,
diff --git a/src/lib/krb5/ccache/ccapi/stdcc.h b/src/lib/krb5/ccache/ccapi/stdcc.h
index dcd8b6b6c..e9ec085eb 100644
--- a/src/lib/krb5/ccache/ccapi/stdcc.h
+++ b/src/lib/krb5/ccache/ccapi/stdcc.h
@@ -1,3 +1,6 @@
+#ifndef __KRB5_STDCC_H__
+#define __KRB5_STDCC_H__
+
#if defined(_WIN32) || defined(USE_CCAPI)
#include "k5-int.h" /* loads krb5.h */
@@ -97,6 +100,21 @@ krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_next
krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_free
(krb5_context context, krb5_cc_ptcursor *cursor);
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_last_change_time
+ (krb5_context context, krb5_ccache id,
+ krb5_timestamp *change_time);
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_lock
+ (krb5_context, krb5_ccache id);
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_unlock
+ (krb5_context, krb5_ccache id);
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_lock
+ (krb5_context context);
+
+krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_unlock
+ (krb5_context context);
#else
@@ -154,3 +172,5 @@ krb5_error_code KRB5_CALLCONV krb5_stdcc_remove
#endif
#endif /* defined(_WIN32) || defined(USE_CCAPI) */
+
+#endif
diff --git a/src/lib/krb5/ccache/ccbase.c b/src/lib/krb5/ccache/ccbase.c
index e8bd9cec6..f54486f7d 100644
--- a/src/lib/krb5/ccache/ccbase.c
+++ b/src/lib/krb5/ccache/ccbase.c
@@ -83,6 +83,9 @@ static struct krb5_cc_typelist cc_krcc_entry = { &krb5_krcc_ops, NEXT };
static struct krb5_cc_typelist *cc_typehead = INITIAL_TYPEHEAD;
static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+/* mutex for krb5_cccol_[un]lock */
+static k5_cc_mutex cccol_lock = K5_CC_MUTEX_PARTIAL_INITIALIZER;
+
static krb5_error_code
krb5int_cc_getops(krb5_context, const char *, const krb5_cc_ops **);
@@ -91,19 +94,22 @@ krb5int_cc_initialize(void)
{
int err;
- err = k5_mutex_finish_init(&krb5int_mcc_mutex);
+ err = k5_cc_mutex_finish_init(&cccol_lock);
+ if (err)
+ return err;
+ err = k5_cc_mutex_finish_init(&krb5int_mcc_mutex);
if (err)
return err;
err = k5_mutex_finish_init(&cc_typelist_lock);
if (err)
return err;
#ifndef NO_FILE_CCACHE
- err = k5_mutex_finish_init(&krb5int_cc_file_mutex);
+ err = k5_cc_mutex_finish_init(&krb5int_cc_file_mutex);
if (err)
return err;
#endif
#ifdef USE_KEYRING_CCACHE
- err = k5_mutex_finish_init(&krb5int_krcc_mutex);
+ err = k5_cc_mutex_finish_init(&krb5int_krcc_mutex);
if (err)
return err;
#endif
@@ -114,13 +120,15 @@ void
krb5int_cc_finalize(void)
{
struct krb5_cc_typelist *t, *t_next;
+ k5_cccol_force_unlock();
+ k5_cc_mutex_destroy(&cccol_lock);
k5_mutex_destroy(&cc_typelist_lock);
#ifndef NO_FILE_CCACHE
- k5_mutex_destroy(&krb5int_cc_file_mutex);
+ k5_cc_mutex_destroy(&krb5int_cc_file_mutex);
#endif
- k5_mutex_destroy(&krb5int_mcc_mutex);
+ k5_cc_mutex_destroy(&krb5int_mcc_mutex);
#ifdef USE_KEYRING_CCACHE
- k5_mutex_destroy(&krb5int_krcc_mutex);
+ k5_cc_mutex_destroy(&krb5int_krcc_mutex);
#endif
for (t = cc_typehead; t != INITIAL_TYPEHEAD; t = t_next) {
t_next = t->next;
@@ -353,3 +361,259 @@ krb5int_cc_typecursor_free(krb5_context context, krb5_cc_typecursor *t)
*t = NULL;
return 0;
}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_move (krb5_context context, krb5_ccache src, krb5_ccache dst)
+{
+ krb5_error_code ret = 0;
+ krb5_principal princ = NULL;
+
+ ret = krb5_cccol_lock(context);
+ if (ret) {
+ return ret;
+ }
+
+ ret = krb5_cc_lock(context, src);
+ if (ret) {
+ krb5_cccol_unlock(context);
+ return ret;
+ }
+
+ ret = krb5_cc_get_principal(context, src, &princ);
+ if (!ret) {
+ ret = krb5_cc_initialize(context, dst, princ);
+ }
+ if (!ret) {
+ ret = krb5_cc_lock(context, dst);
+ }
+ if (!ret) {
+ ret = krb5_cc_copy_creds(context, src, dst);
+ krb5_cc_unlock(context, dst);
+ }
+
+ krb5_cc_unlock(context, src);
+ if (!ret) {
+ ret = krb5_cc_destroy(context, src);
+ }
+ krb5_cccol_unlock(context);
+ if (princ) {
+ krb5_free_principal(context, princ);
+ princ = NULL;
+ }
+
+ return ret;
+}
+
+krb5_error_code
+k5_cc_mutex_init(k5_cc_mutex *m)
+{
+ krb5_error_code ret = 0;
+
+ ret = k5_mutex_init(&m->lock);
+ if (ret) return ret;
+ m->owner = NULL;
+ m->refcount = 0;
+
+ return ret;
+}
+
+krb5_error_code
+k5_cc_mutex_finish_init(k5_cc_mutex *m)
+{
+ krb5_error_code ret = 0;
+
+ ret = k5_mutex_finish_init(&m->lock);
+ if (ret) return ret;
+ m->owner = NULL;
+ m->refcount = 0;
+
+ return ret;
+}
+
+void
+k5_cc_mutex_assert_locked(krb5_context context, k5_cc_mutex *m)
+{
+#ifdef DEBUG_THREADS
+ assert(m->refcount > 0);
+ assert(m->owner == context);
+#endif
+ k5_assert_locked(&m->lock);
+}
+
+void
+k5_cc_mutex_assert_unlocked(krb5_context context, k5_cc_mutex *m)
+{
+#ifdef DEBUG_THREADS
+ assert(m->refcount == 0);
+ assert(m->owner == NULL);
+#endif
+ k5_assert_unlocked(&m->lock);
+}
+
+krb5_error_code
+k5_cc_mutex_lock(krb5_context context, k5_cc_mutex *m)
+{
+ krb5_error_code ret = 0;
+
+ // not locked or already locked by another context
+ if (m->owner != context) {
+ // acquire lock, blocking until available
+ ret = k5_mutex_lock(&m->lock);
+ m->owner = context;
+ m->refcount = 1;
+ }
+ // already locked by this context, just increase refcount
+ else {
+ m->refcount++;
+ }
+ return ret;
+}
+
+krb5_error_code
+k5_cc_mutex_unlock(krb5_context context, k5_cc_mutex *m)
+{
+ krb5_error_code ret = 0;
+
+ /* verify owner and sanity check refcount */
+ if ((m->owner != context) || (m->refcount < 1)) {
+ return ret;
+ }
+ /* decrement & unlock when count reaches zero */
+ m->refcount--;
+ if (m->refcount == 0) {
+ m->owner = NULL;
+ k5_mutex_unlock(&m->lock);
+ }
+ return ret;
+}
+
+/* necessary to make reentrant locks play nice with krb5int_cc_finalize */
+krb5_error_code
+k5_cc_mutex_force_unlock(k5_cc_mutex *m)
+{
+ krb5_error_code ret = 0;
+
+ m->refcount = 0;
+ m->owner = NULL;
+ if (m->refcount > 0) {
+ k5_mutex_unlock(&m->lock);
+ }
+ return ret;
+}
+
+/*
+ * holds on to all pertype global locks as well as typelist lock
+ */
+
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_lock(krb5_context context)
+{
+ krb5_error_code ret = 0;
+
+ ret = k5_cc_mutex_lock(context, &cccol_lock);
+ if (ret) {
+ return ret;
+ }
+ ret = k5_mutex_lock(&cc_typelist_lock);
+ if (ret) {
+ k5_cc_mutex_unlock(context, &cccol_lock);
+ return ret;
+ }
+ ret = k5_cc_mutex_lock(context, &krb5int_cc_file_mutex);
+ if (ret) {
+ k5_mutex_unlock(&cc_typelist_lock);
+ k5_cc_mutex_unlock(context, &cccol_lock);
+ return ret;
+ }
+ ret = k5_cc_mutex_lock(context, &krb5int_mcc_mutex);
+ if (ret) {
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ k5_mutex_unlock(&cc_typelist_lock);
+ k5_cc_mutex_unlock(context, &cccol_lock);
+ return ret;
+ }
+#ifdef USE_CCAPI_V3
+ ret = krb5_stdccv3_context_lock(context);
+#endif
+#ifdef USE_KEYRING_CCACHE
+ ret = k5_cc_mutex_lock(context, &krb5int_krcc_mutex);
+#endif
+ if (ret) {
+ k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ k5_mutex_unlock(&cc_typelist_lock);
+ k5_cc_mutex_unlock(context, &cccol_lock);
+ return ret;
+ }
+ k5_mutex_unlock(&cc_typelist_lock);
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_unlock(krb5_context context)
+{
+ krb5_error_code ret = 0;
+
+ /* sanity check */
+ k5_cc_mutex_assert_locked(context, &cccol_lock);
+
+ ret = k5_mutex_lock(&cc_typelist_lock);
+ if (ret) {
+ k5_cc_mutex_unlock(context, &cccol_lock);
+ return ret;
+ }
+
+ // unlock each type in the opposite order
+#ifdef USE_KEYRING_CCACHE
+ k5_cc_mutex_assert_locked(context, &krb5int_krcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_krcc_mutex);
+#endif
+#ifdef USE_CCAPI_V3
+ krb5_stdccv3_context_unlock(context);
+#endif
+ k5_cc_mutex_assert_locked(context, &krb5int_mcc_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_mcc_mutex);
+ k5_cc_mutex_assert_locked(context, &krb5int_cc_file_mutex);
+ k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex);
+ k5_mutex_assert_locked(&cc_typelist_lock);
+
+ k5_mutex_unlock(&cc_typelist_lock);
+ k5_cc_mutex_unlock(context, &cccol_lock);
+
+ return ret;
+}
+
+/* necessary to make reentrant locks play nice with krb5int_cc_finalize */
+krb5_error_code
+k5_cccol_force_unlock()
+{
+ krb5_error_code ret = 0;
+
+ /* sanity check */
+ if ((&cccol_lock)->refcount == 0) {
+ return 0;
+ }
+
+ ret = k5_mutex_lock(&cc_typelist_lock);
+ if (ret) {
+ (&cccol_lock)->refcount = 0;
+ (&cccol_lock)->owner = NULL;
+ k5_mutex_unlock(&(&cccol_lock)->lock);
+ return ret;
+ }
+
+ // unlock each type in the opposite order
+#ifdef USE_KEYRING_CCACHE
+ k5_cc_mutex_force_unlock(&krb5int_krcc_mutex);
+#endif
+#ifdef USE_CCAPI_V3
+ krb5_stdccv3_context_unlock(NULL);
+#endif
+ k5_cc_mutex_force_unlock(&krb5int_mcc_mutex);
+ k5_cc_mutex_force_unlock(&krb5int_cc_file_mutex);
+
+ k5_mutex_unlock(&cc_typelist_lock);
+ k5_cc_mutex_force_unlock(&cccol_lock);
+
+ return ret;
+}
diff --git a/src/lib/krb5/ccache/cccursor.c b/src/lib/krb5/ccache/cccursor.c
index 31b4737cf..5a062d443 100644
--- a/src/lib/krb5/ccache/cccursor.c
+++ b/src/lib/krb5/ccache/cccursor.c
@@ -198,6 +198,42 @@ krb5_cccol_cursor_free(
return 0;
}
+krb5_error_code KRB5_CALLCONV
+krb5_cccol_last_change_time(
+ krb5_context context,
+ krb5_timestamp *change_time)
+{
+ krb5_error_code ret = 0;
+ krb5_cccol_cursor c = NULL;
+ krb5_ccache ccache = NULL;
+ krb5_timestamp last_time = 0;
+ krb5_timestamp max_change_time = 0;
+
+ *change_time = 0;
+
+ ret = krb5_cccol_cursor_new(context, &c);
+
+ while (!ret) {
+ ret = krb5_cccol_cursor_next(context, c, &ccache);
+ if (ccache) {
+ ret = krb5_cc_last_change_time(context, ccache, &last_time);
+ if (!ret && last_time > max_change_time) {
+ max_change_time = last_time;
+ }
+ ret = 0;
+ }
+ else {
+ break;
+ }
+ }
+ *change_time = max_change_time;
+ return ret;
+}
+
+/*
+ * krb5_cccol_lock and krb5_cccol_unlock are defined in ccbase.c
+ */
+
/*
* Determine if a ccache from a per-type cursor was already one of the
* higher-priority defaults.
diff --git a/src/lib/krb5/ccache/ccfns.c b/src/lib/krb5/ccache/ccfns.c
index 15bc87df6..853d6c90b 100644
--- a/src/lib/krb5/ccache/ccfns.c
+++ b/src/lib/krb5/ccache/ccfns.c
@@ -166,3 +166,23 @@ krb5_cc_get_type (krb5_context context, krb5_ccache cache)
{
return cache->ops->prefix;
}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_last_change_time (krb5_context context, krb5_ccache ccache,
+ krb5_timestamp *change_time)
+{
+ return ccache->ops->lastchange(context, ccache, change_time);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_lock (krb5_context context, krb5_ccache ccache)
+{
+ return ccache->ops->lock(context, ccache);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_cc_unlock (krb5_context context, krb5_ccache ccache)
+{
+ return ccache->ops->unlock(context, ccache);
+}
+