On Thu, 2005-12-01 at 21:12 +1100, Andrew Bartlett wrote: > On Thu, 2005-12-01 at 20:49 +1100, Andrew Bartlett wrote: > > On Thu, 2005-12-01 at 09:20 +0100, Love Hörnquist Åstrand wrote: > > > Andrew Bartlett <abartlet@samba.org> writes: > > > > > > > I've been trying to move Samba4 across to using the new > > > > gss_krb5_import_creds function. This should reduce our custom hacks > > > > significantly, and I thought it provided the correct semantics. > > > [...] > > > > the code in keytab_memory.c > > > > could be changed to record the list of keytabs (with reference counting > > > > etc), much as the in-memory ccache code does. > > > > > > I think I like reference counting better, how about this ? > > > > It's my preferred option. I'll test this out and let you know. > > This works, except that the reference count 'works' on a keytab of name > 'MEMORY:'. Perhaps this should be a special case that always makes a > new keytab? I'm thinking an application may have relied on the previous > behaviour. (early Samba3 I know used 'MEMORY:', but only ever had one > keytab). One bug. d->refcount is uninitialised (must be initialised to 1). Andrew Bartlett -- Andrew Bartlett http://samba.org/~abartlet/ Authentication Developer, Samba Team http://samba.org Student Network Administrator, Hawker College http://hawkerc.net
Index: heimdal/lib/krb5/keytab_memory.c
===================================================================
--- heimdal/lib/krb5/keytab_memory.c (revision 11986)
+++ heimdal/lib/krb5/keytab_memory.c (working copy)
@@ -40,19 +40,67 @@
struct mkt_data {
krb5_keytab_entry *entries;
int num_entries;
+ char *name;
+ int refcount;
+ struct mkt_data *next;
};
+/* this mutex protects mkt_head, ->refcount, and ->next
+ * content is not protected (name is static and need no protection)
+ */
+static HEIMDAL_MUTEX mkt_mutex = HEIMDAL_MUTEX_INITIALIZER;
+static struct mkt_data *mkt_head;
+
+
+static struct mkt_data *
+find_name(const char *name)
+{
+ struct mkt_data *d;
+
+ for (d = mkt_head; d != NULL; d = d->next)
+ if (strcmp(d->name, name) == 0)
+ return d;
+ return NULL;
+}
+
+
static krb5_error_code
mkt_resolve(krb5_context context, const char *name, krb5_keytab id)
{
struct mkt_data *d;
+
+ HEIMDAL_MUTEX_lock(&mkt_mutex);
+
+ d = find_name(name);
+ if (d) {
+ if (d->refcount < 1)
+ krb5_abortx(context, "krb5 internal error, "
+ "memory keytab refcount < 1");
+ d->refcount++;
+ id->data = d;
+ HEIMDAL_MUTEX_unlock(&mkt_mutex);
+ return 0;
+ }
+
d = malloc(sizeof(*d));
if(d == NULL) {
+ HEIMDAL_MUTEX_unlock(&mkt_mutex);
krb5_set_error_string (context, "malloc: out of memory");
return ENOMEM;
}
+ d->name = strdup(name);
+ if (d->name == NULL) {
+ HEIMDAL_MUTEX_unlock(&mkt_mutex);
+ free(d);
+ krb5_set_error_string (context, "malloc: out of memory");
+ return ENOMEM;
+ }
d->entries = NULL;
d->num_entries = 0;
+ d->next = mkt_head;
+ d->refcount = 1;
+ mkt_head = d;
+ HEIMDAL_MUTEX_unlock(&mkt_mutex);
id->data = d;
return 0;
}
@@ -60,8 +108,23 @@
static krb5_error_code
mkt_close(krb5_context context, krb5_keytab id)
{
- struct mkt_data *d = id->data;
+ struct mkt_data *d = id->data, **dp;
int i;
+
+ HEIMDAL_MUTEX_lock(&mkt_mutex);
+ if (d->refcount-- > 0) {
+ HEIMDAL_MUTEX_unlock(&mkt_mutex);
+ return 0;
+ }
+ for (dp = &mkt_head; *dp != NULL; dp = &(*dp)->next) {
+ if (*dp == d) {
+ *dp = d->next;
+ break;
+ }
+ }
+ HEIMDAL_MUTEX_unlock(&mkt_mutex);
+
+ free(d->name);
for(i = 0; i < d->num_entries; i++)
krb5_kt_free_entry(context, &d->entries[i]);
free(d->entries);
@@ -75,7 +138,8 @@
char *name,
size_t namesize)
{
- strlcpy(name, "", namesize);
+ struct mkt_data *d = id->data;
+ strlcpy(name, d->name, namesize);
return 0;
}
This is a digitally signed message part