summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2004-06-30 23:24:42 +0000
committerKen Raeburn <raeburn@mit.edu>2004-06-30 23:24:42 +0000
commit4391b68b20f2e4f16368bd570fe3837f2ff6aecb (patch)
tree8944cc64e30c3ac35bf8c528802af8008678b8c9 /src
parentf8d9ab540ba7e5195443ae4987f4e3bfbcfb71ca (diff)
downloadkrb5-4391b68b20f2e4f16368bd570fe3837f2ff6aecb.tar.gz
krb5-4391b68b20f2e4f16368bd570fe3837f2ff6aecb.tar.xz
krb5-4391b68b20f2e4f16368bd570fe3837f2ff6aecb.zip
Thread-safety for file-based credentials caches
* cc_file.c (krb5_fcc_data): Added a mutex. (krb5_fcc_read*, krb5_fcc_write, krb5_fcc_store_*, krb5_fcc_open_file, krb5_fcc_skip_header, krb5_fcc_skip_principal): Verify that the mutex is locked. (MAYBE_OPEN): Verify that the mutex is locked; unlock it if returning an error. (krb5_fcc_initialize, krb5_fcc_start_seq_get, krb5_fcc_get_principal, krb5_fcc_store, krb5_fcc_set_flags): Lock and unlock the mutex. (krb5_fcc_close): Likewise. Destroy the mutex when done. (krb5_fcc_destroy): Merge stdio and non-stdio versions a little more. Destroy the mutex when done. (krb5_fcc_resolve): Initialize and lock the mutex. (krb5_fcc_next_cred): Lock and unlock the mutex. Merge the stdio and non-stdio branches a little more. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16534 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/lib/krb5/ccache/ChangeLog18
-rw-r--r--src/lib/krb5/ccache/cc_file.c251
2 files changed, 195 insertions, 74 deletions
diff --git a/src/lib/krb5/ccache/ChangeLog b/src/lib/krb5/ccache/ChangeLog
index ac653ace3..19e9add2a 100644
--- a/src/lib/krb5/ccache/ChangeLog
+++ b/src/lib/krb5/ccache/ChangeLog
@@ -1,3 +1,21 @@
+2004-06-30 Ken Raeburn <raeburn@mit.edu>
+
+ * cc_file.c (krb5_fcc_data): Added a mutex.
+ (krb5_fcc_read*, krb5_fcc_write, krb5_fcc_store_*,
+ krb5_fcc_open_file, krb5_fcc_skip_header,
+ krb5_fcc_skip_principal): Verify that the mutex is locked.
+ (MAYBE_OPEN): Verify that the mutex is locked; unlock it if
+ returning an error.
+ (krb5_fcc_initialize, krb5_fcc_start_seq_get,
+ krb5_fcc_get_principal, krb5_fcc_store, krb5_fcc_set_flags): Lock
+ and unlock the mutex.
+ (krb5_fcc_close): Likewise. Destroy the mutex when done.
+ (krb5_fcc_destroy): Merge stdio and non-stdio versions a little
+ more. Destroy the mutex when done.
+ (krb5_fcc_resolve): Initialize and lock the mutex.
+ (krb5_fcc_next_cred): Lock and unlock the mutex. Merge the stdio
+ and non-stdio branches a little more.
+
2004-06-29 Jeffrey Altman <jaltman@mit.edu>
* cc_mslsa.c:
diff --git a/src/lib/krb5/ccache/cc_file.c b/src/lib/krb5/ccache/cc_file.c
index 1b495edca..8ed18f673 100644
--- a/src/lib/krb5/ccache/cc_file.c
+++ b/src/lib/krb5/ccache/cc_file.c
@@ -82,22 +82,23 @@ format-vno ::= <int16>
etc.
*/
/* todo:
-Make sure that each time a function returns KRB5_NOMEM, everything
-allocated earlier in the function and stack tree is freed.
+ Make sure that each time a function returns KRB5_NOMEM, everything
+ allocated earlier in the function and stack tree is freed.
#ifndef USE_STDIO
-File locking
+ File locking
-fcc_nseq.c and fcc_read don't check return values a lot.
+ Use pread/pwrite if available, so multiple threads can read
+ simultaneously. (That may require reader/writer locks.)
+
+ fcc_nseq.c and fcc_read don't check return values a lot.
#else
-Overwrite cache file with nulls before removing it.
-#endif
+ Overwrite cache file with nulls before removing it.
-#ifdef USE_STDIO
-Check return values and sanity-check parameters more thoroughly. This
-code was derived from UNIX file I/O code, and the conversion of
-error-trapping may be incomplete. Probably lots of bugs dealing with
-end-of-file versus other errors.
+ Check return values and sanity-check parameters more thoroughly. This
+ code was derived from UNIX file I/O code, and the conversion of
+ error-trapping may be incomplete. Probably lots of bugs dealing with
+ end-of-file versus other errors.
#endif
*/
#include "k5-int.h"
@@ -299,6 +300,7 @@ static krb5_error_code krb5_fcc_open_file
typedef struct _krb5_fcc_data {
char *filename;
+ k5_mutex_t lock;
#ifndef USE_STDIO
int file;
#else
@@ -319,11 +321,18 @@ typedef struct _krb5_fcc_cursor {
#endif
} krb5_fcc_cursor;
-#define MAYBE_OPEN(CONTEXT, ID, MODE) \
+#define MAYBE_OPEN(CONTEXT, ID, MODE) \
{ \
+ k5_assert_locked(&((krb5_fcc_data *)(ID)->data)->lock); \
if (OPENCLOSE (ID)) { \
- krb5_error_code maybe_open_ret = krb5_fcc_open_file (CONTEXT,ID,MODE); \
- if (maybe_open_ret) return maybe_open_ret; } }
+ 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); \
+ return maybe_open_ret; \
+ } \
+ } \
+}
#define MAYBE_CLOSE(CONTEXT, ID, RET) \
{ \
@@ -339,7 +348,7 @@ typedef struct _krb5_fcc_cursor {
#endif
#define CHECK(ret) if (ret != KRB5_OK) goto errout;
-
+
#ifndef USE_STDIO
#define NO_FILE -1
#else
@@ -350,6 +359,9 @@ typedef struct _krb5_fcc_cursor {
* Effects:
* Reads len bytes from the cache id, storing them in buf.
*
+ * Requires:
+ * Must be called with mutex locked.
+ *
* Errors:
* KRB5_CC_END - there were not len bytes available
* system errors (read)
@@ -359,6 +371,8 @@ krb5_fcc_read(krb5_context context, krb5_ccache id, krb5_pointer buf, unsigned i
{
int ret;
+ k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
#ifndef USE_STDIO
ret = read(((krb5_fcc_data *) id->data)->file, (char *) buf, len);
if (ret == -1)
@@ -381,6 +395,8 @@ krb5_fcc_read(krb5_context context, krb5_ccache id, krb5_pointer buf, unsigned i
* Requires:
* id is open and set to read at the appropriate place in the file
*
+ * mutex is locked
+ *
* Effects:
* Fills in the second argument with data of the appropriate type from
* the file. In some cases, the functions have to allocate space for
@@ -406,6 +422,8 @@ 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);
+
if (data->version == KRB5_FCC_FVNO_1) {
type = KRB5_NT_UNKNOWN;
} else {
@@ -477,6 +495,8 @@ 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);
+
*addrs = 0;
/* Read the number of components */
@@ -519,6 +539,8 @@ 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);
+
keyblock->magic = KV5M_KEYBLOCK;
keyblock->contents = 0;
@@ -563,6 +585,8 @@ 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);
+
data->magic = KV5M_DATA;
data->data = 0;
@@ -601,6 +625,8 @@ 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);
+
addr->magic = KV5M_ADDRESS;
addr->contents = 0;
@@ -643,6 +669,8 @@ 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);
+
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
return krb5_fcc_read(context, id, (krb5_pointer) i, sizeof(krb5_int32));
@@ -666,6 +694,8 @@ 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);
+
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
return krb5_fcc_read(context, id, (krb5_pointer) i, sizeof(krb5_ui_2));
@@ -681,6 +711,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);
return krb5_fcc_read(context, id, (krb5_pointer) i, 1);
}
@@ -692,6 +723,8 @@ 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);
+
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
return krb5_fcc_read(context, id, (krb5_pointer) t, sizeof(krb5_ticket_times));
@@ -725,6 +758,8 @@ 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);
+
*a = 0;
/* Read the number of components */
@@ -769,6 +804,8 @@ 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);
+
a->magic = KV5M_AUTHDATA;
a->contents = NULL;
@@ -820,6 +857,9 @@ static krb5_error_code
krb5_fcc_write(krb5_context context, krb5_ccache id, krb5_pointer buf, unsigned int len)
{
int ret;
+
+ k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
#ifndef USE_STDIO
ret = write(((krb5_fcc_data *)id->data)->file, (char *) buf, len);
if (ret < 0)
@@ -842,6 +882,8 @@ krb5_fcc_write(krb5_context context, krb5_ccache id, krb5_pointer buf, unsigned
*
* Requires:
* ((krb5_fcc_data *) id->data)->file is open and at the right position.
+ *
+ * mutex is locked
*
* Effects:
* Stores an encoded version of the second argument in the
@@ -858,6 +900,8 @@ 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);
+
type = krb5_princ_type(context, princ);
tmp = length = krb5_princ_size(context, princ);
@@ -894,6 +938,8 @@ 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);
+
/* Count the number of components */
if (addrs) {
temp = addrs;
@@ -917,6 +963,8 @@ 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);
+
ret = krb5_fcc_store_ui_2(context, id, keyblock->enctype);
CHECK(ret);
if (data->version == KRB5_FCC_FVNO_3) {
@@ -933,6 +981,8 @@ 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);
+
ret = krb5_fcc_store_ui_2(context, id, addr->addrtype);
CHECK(ret);
ret = krb5_fcc_store_ui_4(context, id, addr->length);
@@ -946,6 +996,8 @@ 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);
+
ret = krb5_fcc_store_ui_4(context, id, data->length);
CHECK(ret);
return krb5_fcc_write(context, id, data->data, data->length);
@@ -957,6 +1009,8 @@ krb5_fcc_store_int32(krb5_context context, krb5_ccache id, krb5_int32 i)
krb5_fcc_data *data = (krb5_fcc_data *)id->data;
unsigned char buf[4];
+ k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
return krb5_fcc_write(context, id, (char *) &i, sizeof(krb5_int32));
@@ -978,6 +1032,8 @@ 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);
+
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
return krb5_fcc_write(context, id, (char *) &i, sizeof(krb5_int32));
@@ -1000,6 +1056,8 @@ 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);
+
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2)) {
ibuf = (krb5_ui_2) i;
@@ -1017,6 +1075,8 @@ 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);
+
ibuf = (krb5_octet) i;
return krb5_fcc_write(context, id, (char *) &ibuf, 1);
}
@@ -1027,6 +1087,8 @@ 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);
+
if ((data->version == KRB5_FCC_FVNO_1) ||
(data->version == KRB5_FCC_FVNO_2))
return krb5_fcc_write(context, id, (char *) t, sizeof(krb5_ticket_times));
@@ -1050,6 +1112,8 @@ 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);
+
if (a != NULL) {
for (temp=a; *temp; temp++)
length++;
@@ -1068,6 +1132,9 @@ static krb5_error_code
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);
+
ret = krb5_fcc_store_ui_2(context, id, a->ad_type);
CHECK(ret);
ret = krb5_fcc_store_ui_4(context, id, a->length);
@@ -1083,6 +1150,8 @@ krb5_fcc_close_file (krb5_context context, krb5_ccache id)
krb5_fcc_data *data = (krb5_fcc_data *)id->data;
krb5_error_code retval;
+ k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
if (data->file == NO_FILE)
return KRB5_FCC_INTERNAL;
@@ -1147,6 +1216,8 @@ krb5_fcc_open_file (krb5_context context, krb5_ccache id, int mode)
int lock_flag;
krb5_error_code retval = 0;
+ k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
+
if (data->file != NO_FILE) {
/* Don't know what state it's in; shut down and start anew. */
#ifndef USE_STDIO
@@ -1369,6 +1440,8 @@ 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);
+
#ifndef USE_STDIO
lseek(data->file, (off_t) sizeof(krb5_ui_2), SEEK_SET);
#else
@@ -1395,6 +1468,8 @@ 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);
+
kret = krb5_fcc_read_principal(context, id, &princ);
if (kret != KRB5_OK)
return kret;
@@ -1424,12 +1499,19 @@ krb5_fcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ)
int reti = 0;
#endif
+ kret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+ if (kret)
+ return kret;
+
#ifndef USE_STDIO
MAYBE_OPEN(context, id, FCC_OPEN_AND_ERASE);
#else
kret = krb5_fcc_open_file (context, id, FCC_OPEN_AND_ERASE);
- if (kret < 0)
- return krb5_fcc_interpret(context, errno);
+ if (kret < 0) {
+ int e = errno;
+ k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+ return krb5_fcc_interpret(context, e);
+ }
#endif
#ifndef USE_STDIO
@@ -1443,6 +1525,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);
return kret;
}
}
@@ -1451,6 +1534,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);
krb5_change_cache ();
return kret;
}
@@ -1470,6 +1554,9 @@ krb5_fcc_close(krb5_context context, krb5_ccache id)
register int closeval = KRB5_OK;
register krb5_fcc_data *data = (krb5_fcc_data *) id->data;
+ /* If locking fails, ignore it, since we're destroying the thing
+ anyways. */
+ k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
#ifndef USE_STDIO
if (data->file >= 0)
krb5_fcc_close_file(context, id);
@@ -1485,6 +1572,8 @@ krb5_fcc_close(krb5_context context, krb5_ccache id)
}
#endif
krb5_xfree(data->filename);
+ k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+ k5_mutex_destroy(&((krb5_fcc_data *) id->data)->lock);
krb5_xfree(data);
krb5_xfree(id);
@@ -1507,15 +1596,16 @@ krb5_fcc_close(krb5_context context, krb5_ccache id)
static krb5_error_code KRB5_CALLCONV
krb5_fcc_destroy(krb5_context context, krb5_ccache id)
{
+ krb5_error_code kret = 0;
+ krb5_fcc_data *data = (krb5_fcc_data *) id->data;
+ register int ret;
+
#ifndef USE_STDIO
struct stat buf;
unsigned long i, size;
unsigned int wlen;
char zeros[BUFSIZ];
- register int ret;
- krb5_error_code kret = 0;
-
-
+
if (OPENCLOSE(id)) {
ret = THREEPARAMOPEN(((krb5_fcc_data *) id->data)->filename, O_RDWR | O_BINARY, 0);
if (ret < 0) {
@@ -1618,16 +1708,7 @@ krb5_fcc_destroy(krb5_context context, krb5_ccache id)
#endif /* MSDOS_FILESYSTEM */
- cleanup:
- krb5_xfree(((krb5_fcc_data *) id->data)->filename);
- krb5_xfree(id->data);
- krb5_xfree(id);
-
- krb5_change_cache ();
- return kret;
#else
- krb5_fcc_data *data = (krb5_fcc_data *) id->data;
- register int ret;
if (!OPENCLOSE(id)) {
(void) fclose(data->file);
@@ -1636,7 +1717,7 @@ krb5_fcc_destroy(krb5_context context, krb5_ccache id)
ret = remove (data->filename);
if (ret < 0) {
- ret = krb5_fcc_interpret(context, errno);
+ kret = krb5_fcc_interpret(context, errno);
if (OPENCLOSE(id)) {
(void) fclose(data->file);
data->file = 0;
@@ -1651,16 +1732,17 @@ krb5_fcc_destroy(krb5_context context, krb5_ccache id)
*/
if (ret)
- ret = krb5_fcc_interpret(context, errno);
+ kret = krb5_fcc_interpret(context, errno);
+#endif
cleanup:
krb5_xfree(data->filename);
+ k5_mutex_destroy(&data->lock);
krb5_xfree(data);
krb5_xfree(id);
krb5_change_cache ();
- return ret;
-#endif
+ return kret;
}
extern const krb5_cc_ops krb5_fcc_ops;
@@ -1688,7 +1770,9 @@ static krb5_error_code KRB5_CALLCONV
krb5_fcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
{
krb5_ccache lid;
-
+ krb5_error_code kret;
+ krb5_fcc_data *data;
+
lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
if (lid == NULL)
return KRB5_CC_NOMEM;
@@ -1700,26 +1784,33 @@ krb5_fcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
krb5_xfree(lid);
return KRB5_CC_NOMEM;
}
+ data = (krb5_fcc_data *) lid->data;
+ data->filename = (char *) malloc(strlen(residual) + 1);
- ((krb5_fcc_data *) lid->data)->filename = (char *)
- malloc(strlen(residual) + 1);
-
- if (((krb5_fcc_data *) lid->data)->filename == NULL) {
- krb5_xfree(((krb5_fcc_data *) lid->data));
+ if (data->filename == NULL) {
+ krb5_xfree(data);
krb5_xfree(lid);
return KRB5_CC_NOMEM;
}
+ kret = k5_mutex_init(&data->lock);
+ if (kret) {
+ krb5_xfree(data->filename);
+ krb5_xfree(data);
+ krb5_xfree(lid);
+ return kret;
+ }
+
/* default to open/close on every trn */
- ((krb5_fcc_data *) lid->data)->flags = KRB5_TC_OPENCLOSE;
+ data->flags = KRB5_TC_OPENCLOSE;
#ifndef USE_STDIO
- ((krb5_fcc_data *) lid->data)->file = -1;
+ data->file = -1;
#else
- ((krb5_fcc_data *) lid->data)->file = 0;
+ data->file = 0;
#endif
/* Set up the filename */
- strcpy(((krb5_fcc_data *) lid->data)->filename, residual);
+ strcpy(data->filename, residual);
lid->magic = KV5M_CCACHE;
@@ -1749,14 +1840,21 @@ krb5_fcc_start_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cur
krb5_error_code kret = KRB5_OK;
krb5_fcc_data *data = (krb5_fcc_data *)id->data;
+ kret = k5_mutex_lock(&data->lock);
+ if (kret)
+ return kret;
+
fcursor = (krb5_fcc_cursor *) malloc(sizeof(krb5_fcc_cursor));
- if (fcursor == NULL)
- return KRB5_CC_NOMEM;
+ if (fcursor == NULL) {
+ k5_mutex_unlock(&data->lock);
+ return KRB5_CC_NOMEM;
+ }
#ifndef USE_STDIO
if (OPENCLOSE(id)) {
kret = krb5_fcc_open_file(context, id, FCC_OPEN_RDONLY);
if (kret) {
krb5_xfree(fcursor);
+ k5_mutex_unlock(&data->lock);
return kret;
}
}
@@ -1765,8 +1863,8 @@ krb5_fcc_start_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cur
/* Make sure we start reading right after the primary principal */
#ifdef USE_STDIO
MAYBE_OPEN (context, id, FCC_OPEN_RDONLY);
-
#endif
+
kret = krb5_fcc_skip_header(context, id);
if (kret) goto done;
kret = krb5_fcc_skip_principal(context, id);
@@ -1781,6 +1879,7 @@ krb5_fcc_start_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cur
done:
MAYBE_CLOSE(context, id, kret);
+ k5_mutex_unlock(&data->lock);
return kret;
}
@@ -1813,33 +1912,25 @@ krb5_fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
krb5_fcc_cursor *fcursor;
krb5_int32 int32;
krb5_octet octet;
+ krb5_fcc_data *d = (krb5_fcc_data *) id->data;
-#ifndef USE_STDIO
- memset((char *)creds, 0, sizeof(*creds));
-#else
-#define Z(field) creds->field = 0
- Z (client);
- Z (server);
- Z (keyblock.contents);
- Z (authdata);
- Z (ticket.data);
- Z (second_ticket.data);
- Z (addresses);
-#undef Z
-#endif
+ kret = k5_mutex_lock(&d->lock);
+ if (kret)
+ return kret;
+ memset((char *)creds, 0, sizeof(*creds));
MAYBE_OPEN(context, id, FCC_OPEN_RDONLY);
-
fcursor = (krb5_fcc_cursor *) *cursor;
#ifndef USE_STDIO
- kret = (lseek(((krb5_fcc_data *) id->data)->file, fcursor->pos, SEEK_SET) == (off_t) -1);
+ kret = (lseek(d->file, fcursor->pos, SEEK_SET) == (off_t) -1);
#else
- kret = (fseek(((krb5_fcc_data *) id->data)->file, fcursor->pos, 0) < 0);
+ kret = (fseek(d->file, fcursor->pos, 0) < 0);
#endif
if (kret) {
kret = krb5_fcc_interpret(context, errno);
MAYBE_CLOSE(context, id, kret);
+ k5_mutex_unlock(&d->lock);
return kret;
}
@@ -1867,23 +1958,17 @@ krb5_fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor,
TCHECK(kret);
#ifndef USE_STDIO
- fcursor->pos = lseek(((krb5_fcc_data *) id->data)->file, (off_t) 0,
- SEEK_CUR);
+ fcursor->pos = lseek(d->file, (off_t) 0, SEEK_CUR);
#else
- fcursor->pos = ftell(((krb5_fcc_data *) id->data)->file);
+ fcursor->pos = ftell(d->file);
#endif
cursor = (krb5_cc_cursor *) fcursor;
lose:
-#ifndef USE_STDIO
- MAYBE_CLOSE(context, id, kret); /* won't overwrite kret
- if already set */
-#endif
+ MAYBE_CLOSE (context, id, kret);
+ k5_mutex_unlock(&d->lock);
if (kret != KRB5_OK)
krb5_free_cred_contents(context, creds);
-#ifdef USE_STDIO
- MAYBE_CLOSE (context, id, kret);
-#endif
return kret;
}
@@ -1903,12 +1988,14 @@ lose:
static krb5_error_code KRB5_CALLCONV
krb5_fcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor)
{
+ /* We don't do anything with the file cache itself, so
+ no need to lock anything. */
+
/* don't close; it may be left open by the caller,
and if not, fcc_start_seq_get and/or fcc_next_cred will do the
MAYBE_CLOSE.
MAYBE_CLOSE(context, id, kret); */
krb5_xfree((krb5_fcc_cursor *) *cursor);
-
return 0;
}
@@ -2118,6 +2205,10 @@ 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);
+ if (kret)
+ return kret;
+
MAYBE_OPEN(context, id, FCC_OPEN_RDONLY);
/* make sure we're beyond the header */
@@ -2127,6 +2218,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);
return kret;
}
@@ -2156,6 +2248,10 @@ 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);
+ if (ret)
+ return ret;
+
/* Make sure we are writing to the end of the file */
MAYBE_OPEN(context, id, FCC_OPEN_RDWR);
@@ -2169,6 +2265,7 @@ krb5_fcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
#ifndef USE_STDIO
MAYBE_CLOSE_IGNORE(context, id);
#endif
+ k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
return krb5_fcc_interpret(context, errno);
}
@@ -2195,6 +2292,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);
krb5_change_cache ();
return ret;
#undef TCHECK
@@ -2229,6 +2327,10 @@ 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);
+ if (ret)
+ return ret;
+
/* XXX This should check for illegal combinations, if any.. */
if (flags & KRB5_TC_OPENCLOSE) {
/* asking to turn on OPENCLOSE mode */
@@ -2251,6 +2353,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);
return ret;
}