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

Bad interraction between krb5_context and krb5_ccache



In lib/krb5/cache.c, the function allocate_ccache only copies the ops
pointer into the new ccache. Unfortunately, when the context is
destroyed, ops->prefix is freed and the ccache becomes invalid, which can
cause a subsequent use of it to segfault.

This has hurt me in a pam kerberos module where the ccache needed to be
stored between multiple context creations and destruction.

I've attached a patch that copies ops content instead of only copying
the pointer. I hope this is a correct behaviour.


Joel K.

-- 
I want to  argue that an  effective way of  promoting true computer literacy
would be to make Unix basics part of the curriculum... for everybody.
   -- Martin Vermeer --          http://linuxtoday.org/stories/1846.html
--- cache.c.orig-heimdal	Tue Nov 14 18:41:58 2000
+++ cache.c	Tue Nov 14 19:02:07 2000
@@ -89,11 +89,24 @@
 {
     krb5_error_code ret;
     krb5_ccache p;
+    krb5_cc_ops *q;
 
     p = malloc(sizeof(*p));
     if(p == NULL)
 	return KRB5_CC_NOMEM;
-    p->ops = ops;
+
+    q = malloc(sizeof(*q));
+    if(q == NULL)
+        return KRB5_CC_NOMEM;
+    memcpy(q, ops, sizeof(*q));
+    q->prefix = strdup(ops->prefix);
+    if(q->prefix == NULL)
+    {
+        free(q);
+        return KRB5_CC_NOMEM;
+    }
+    
+    p->ops = q;
     *id = p;
     ret = p->ops->resolve(context, id, residual);
     if(ret)
@@ -141,11 +154,24 @@
 		krb5_ccache *id)
 {
     krb5_ccache p;
+    krb5_cc_ops *q;
 
     p = malloc (sizeof(*p));
     if (p == NULL)
 	return KRB5_CC_NOMEM;
-    p->ops = ops;
+
+    q = malloc(sizeof(*q));
+    if(q == NULL)
+        return KRB5_CC_NOMEM;
+    memcpy(q, ops, sizeof(*q));
+    q->prefix = strdup(ops->prefix);
+    if(q->prefix == NULL)
+    {
+        free(q);
+        return KRB5_CC_NOMEM;
+    }
+    
+    p->ops = q;
     *id = p;
     return p->ops->gen_new(context, id);
 }
@@ -248,6 +274,8 @@
 {
     krb5_error_code ret;
     ret = id->ops->close(context, id);
+    free(id->ops->prefix);
+    free((krb5_cc_ops *)id->ops);
     free(id);
     return ret;
 }