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;
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;
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
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,
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__ */
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);
(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
/* 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 */
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;
#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; \
} \
} \
#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)
#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;
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;
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;
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;
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;
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;
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))
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))
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);
}
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))
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;
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;
{
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);
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);
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) {
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);
{
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);
{
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);
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))
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)) {
{
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);
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))
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++)
{
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);
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;
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) {
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) {
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)
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;
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;
}
}
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;
}
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)
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;
}
unsigned int wlen;
char zeros[BUFSIZ];
- kret = k5_mutex_lock(&data->lock);
+ kret = k5_cc_mutex_lock(context, &data->lock);
if (kret)
return kret;
#endif /* MSDOS_FILESYSTEM */
cleanup:
- k5_mutex_unlock(&data->lock);
+ k5_cc_mutex_unlock(context, &data->lock);
dereference(context, data);
krb5_xfree(id);
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) {
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;
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;
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);
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;
}
}
done:
MAYBE_CLOSE(context, id, kret);
- k5_mutex_unlock(&data->lock);
+ k5_cc_mutex_unlock(context, &data->lock);
return kret;
}
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;
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;
}
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;
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;
(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);
/* 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);
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);
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);
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;
{
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;
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;
}
#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;
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);
}
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
{
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;
}
((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;
}
{
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)
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)
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,
};
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 */
} 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)
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
*/
(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);
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;
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;
}
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);
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;
}
d->numkeys = 0;
d->princ_id = 0;
+ krb5_krcc_update_change_time(d);
return KRB5_OK;
}
d = (krb5_krcc_data *) id->data;
- kret = k5_mutex_lock(&d->lock);
+ kret = k5_cc_mutex_lock(context, &d->lock);
if (kret)
return kret;
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);
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;
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;
}
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;
}
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;
}
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;
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;
}
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;
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;
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;
}
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;
}
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;
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;
} else {
d->numkeys++;
kret = KRB5_OK;
+ krb5_krcc_update_change_time(d);
}
errout:
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)
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;
} else {
d->princ_id = newkey;
kret = KRB5_OK;
+ krb5_krcc_update_change_time(d);
}
errout:
int psize;
krb5_krcc_bc bc;
- kret = k5_mutex_lock(&d->lock);
+ kret = k5_cc_mutex_lock(context, &d->lock);
if (kret)
return kret;
errout:
if (payload)
free(payload);
- k5_mutex_unlock(&d->lock);
+ k5_cc_mutex_unlock(context, &d->lock);
return kret;
}
return kret;
}
+/*
+ * 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.
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 */
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 */
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);
/* 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. */
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
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;
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;
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);
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)
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)
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;
}
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;
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);
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;
}
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;
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;
}
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;
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;
}
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;
(*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:
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",
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,
};
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,
cc_string_t ccstring = NULL;
char *name = NULL;
- // TODO set proper errors, check context param
if (!cursor || !cursor->data) {
err = ccErrInvalidContext;
}
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,
+#ifndef __KRB5_STDCC_H__
+#define __KRB5_STDCC_H__
+
#if defined(_WIN32) || defined(USE_CCAPI)
#include "k5-int.h" /* loads krb5.h */
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
#endif
#endif /* defined(_WIN32) || defined(USE_CCAPI) */
+
+#endif
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 **);
{
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
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;
*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;
+}
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.
{
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);
+}
+