From b96ea2f14721e4b20cb08188c383f6b63a03b5b2 Mon Sep 17 00:00:00 2001 From: Tom Yu Date: Thu, 29 Nov 2007 00:53:20 +0000 Subject: [PATCH] pull up r20109 from trunk r20109@cathode-dark-space: raeburn | 2007-10-09 00:03:59 -0400 ticket: 5777 kt_file.c: Support multiple iterators active simultaneously, using a counter. In get_entry, if the file was already open, rewind it to just after the version number, and don't close it when done. Don't allow add or remove calls if any iterator is active. t_keytab.c: Test mixing two iterators with get_entry calls. ticket: 5777 git-svn-id: svn://anonsvn.mit.edu/krb5/branches/krb5-1-6@20170 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/keytab/kt_file.c | 88 +++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 13 deletions(-) diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c index 776727a01..93c9c8ba2 100644 --- a/src/lib/krb5/keytab/kt_file.c +++ b/src/lib/krb5/keytab/kt_file.c @@ -53,9 +53,29 @@ typedef struct _krb5_ktfile_data { FILE *openf; /* open file, if any. */ char iobuf[BUFSIZ]; /* so we can zap it later */ int version; /* Version number of keytab */ + unsigned int iter_count; /* Number of active iterators */ + long start_offset; /* Starting offset after version */ k5_mutex_t lock; /* Protect openf, version */ } krb5_ktfile_data; +/* + * Some limitations: + * + * If the file OPENF is left open between calls, we have an iterator + * active, and OPENF is opened in read-only mode. So, no changes + * can be made via that handle. + * + * An advisory file lock is used while the file is open. Thus, + * multiple handles on the same underlying file cannot be used without + * disrupting the locking in effect. + * + * The start_offset field is only valid if the file is open. It will + * almost certainly always be the same constant. It's used so that + * if an iterator is active, and we start another one, we don't have + * to seek back to the start and re-read the version number to set + * the position for the iterator. + */ + /* * Macros */ @@ -64,6 +84,8 @@ typedef struct _krb5_ktfile_data { #define KTFILEP(id) (((krb5_ktfile_data *)(id)->data)->openf) #define KTFILEBUFP(id) (((krb5_ktfile_data *)(id)->data)->iobuf) #define KTVERSION(id) (((krb5_ktfile_data *)(id)->data)->version) +#define KTITERS(id) (((krb5_ktfile_data *)(id)->data)->iter_count) +#define KTSTARTOFF(id) (((krb5_ktfile_data *)(id)->data)->start_offset) #define KTLOCK(id) k5_mutex_lock(&((krb5_ktfile_data *)(id)->data)->lock) #define KTUNLOCK(id) k5_mutex_unlock(&((krb5_ktfile_data *)(id)->data)->lock) #define KTCHECKLOCK(id) k5_mutex_assert_locked(&((krb5_ktfile_data *)(id)->data)->lock) @@ -208,6 +230,7 @@ krb5_ktfile_resolve(krb5_context context, const char *name, krb5_keytab *id) (void) strcpy(data->name, name); data->openf = 0; data->version = 0; + data->iter_count = 0; (*id)->data = (krb5_pointer)data; (*id)->magic = KV5M_KEYTAB; @@ -255,15 +278,27 @@ krb5_ktfile_get_entry(krb5_context context, krb5_keytab id, int found_wrong_kvno = 0; krb5_boolean similar; int kvno_offset = 0; + int was_open; kerror = KTLOCK(id); if (kerror) return kerror; - /* Open the keyfile for reading */ - if ((kerror = krb5_ktfileint_openr(context, id))) { - KTUNLOCK(id); - return(kerror); + if (KTFILEP(id) != NULL) { + was_open = 1; + + if (fseek(KTFILEP(id), KTSTARTOFF(id), SEEK_SET) == -1) { + KTUNLOCK(id); + return errno; + } + } else { + was_open = 0; + + /* Open the keyfile for reading */ + if ((kerror = krb5_ktfileint_openr(context, id))) { + KTUNLOCK(id); + return(kerror); + } } /* @@ -370,12 +405,13 @@ krb5_ktfile_get_entry(krb5_context context, krb5_keytab id, kerror = KRB5_KT_NOTFOUND; } if (kerror) { - (void) krb5_ktfileint_close(context, id); + if (was_open == 0) + (void) krb5_ktfileint_close(context, id); KTUNLOCK(id); krb5_kt_free_entry(context, &cur_entry); return kerror; } - if ((kerror = krb5_ktfileint_close(context, id)) != 0) { + if (was_open == 0 && (kerror = krb5_ktfileint_close(context, id)) != 0) { KTUNLOCK(id); krb5_kt_free_entry(context, &cur_entry); return kerror; @@ -430,18 +466,28 @@ krb5_ktfile_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor * if (retval) return retval; - if ((retval = krb5_ktfileint_openr(context, id))) { - KTUNLOCK(id); - return retval; + if (KTITERS(id) == 0) { + if ((retval = krb5_ktfileint_openr(context, id))) { + KTUNLOCK(id); + return retval; + } } if (!(fileoff = (long *)malloc(sizeof(*fileoff)))) { - krb5_ktfileint_close(context, id); + if (KTITERS(id) == 0) + krb5_ktfileint_close(context, id); KTUNLOCK(id); return ENOMEM; } - *fileoff = ftell(KTFILEP(id)); + *fileoff = KTSTARTOFF(id); *cursorp = (krb5_kt_cursor)fileoff; + KTITERS(id)++; + if (KTITERS(id) == 0) { + /* Wrapped?! */ + KTITERS(id)--; + KTUNLOCK(id); + return KRB5_KT_IOERR; /* XXX */ + } KTUNLOCK(id); return 0; @@ -490,7 +536,11 @@ krb5_ktfile_end_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursor krb5_xfree(*cursor); KTLOCK(id); - kerror = krb5_ktfileint_close(context, id); + KTITERS(id)--; + if (KTFILEP(id) != NULL && KTITERS(id) == 0) + kerror = krb5_ktfileint_close(context, id); + else + kerror = 0; KTUNLOCK(id); return kerror; } @@ -811,6 +861,7 @@ krb5_ktfile_wresolve(krb5_context context, const char *name, krb5_keytab *id) (void) strcpy(data->name, name); data->openf = 0; data->version = 0; + data->iter_count = 0; (*id)->data = (krb5_pointer)data; (*id)->magic = KV5M_KEYTAB; @@ -830,6 +881,11 @@ krb5_ktfile_add(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) retval = KTLOCK(id); if (retval) return retval; + if (KTFILEP(id)) { + /* Iterator(s) active -- no changes. */ + KTUNLOCK(id); + return KRB5_KT_IOERR; /* XXX */ + } if ((retval = krb5_ktfileint_openw(context, id))) { KTUNLOCK(id); return retval; @@ -858,6 +914,11 @@ krb5_ktfile_remove(krb5_context context, krb5_keytab id, krb5_keytab_entry *entr kerror = KTLOCK(id); if (kerror) return kerror; + if (KTFILEP(id)) { + /* Iterator(s) active -- no changes. */ + KTUNLOCK(id); + return KRB5_KT_IOERR; /* XXX */ + } if ((kerror = krb5_ktfileint_openw(context, id))) { KTUNLOCK(id); @@ -1114,6 +1175,7 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode) return KRB5_KEYTAB_BADVNO; } } + KTSTARTOFF(id) = ftell(KTFILEP(id)); return 0; } @@ -1424,7 +1486,7 @@ krb5_ktfileint_write_entry(krb5_context context, krb5_keytab id, krb5_keytab_ent krb5_timestamp timestamp; krb5_int32 princ_type; krb5_int32 size_needed; - krb5_int32 commit_point; + krb5_int32 commit_point = -1; int i; KTCHECKLOCK(id); -- 2.26.2