[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: gss_krb5_import_creds can't work with memory keytab



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