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

Re: Should kadmin ask for password



Hello,

The behavior is what most sites expect since its very
common to split the administrative role (lha/admin@SU.SE)
from the user role (lha@SU.SE).

But I agree that not being able to use a inital kadmin/admin
ticket that have a client that is not on the form foo/admin is broken,
so how about this patch ?

Love


--- heimdal/lib/kadm5/init_c.c	30 Nov 2006 18:15:37 +0100	1.56
+++ heimdal/lib/kadm5/init_c.c	06 Dec 2006 19:04:17 +0100	
@@ -224,6 +224,75 @@
     return 0;
 }
 
+/*
+ * Check the credential cache `id´ to figure out what principal to use
+ * when talking to the kadmind. If there is a initial kadmin/admin@
+ * credential in the cache, use that client principal. Otherwise, use
+ * the client principals first component and add /admin to the
+ * principal.
+ */
+
+static krb5_error_code
+get_cache_principal(krb5_context context,
+		    krb5_ccache id,
+		    krb5_principal *client)
+{
+    krb5_error_code ret;
+    const char *name, *inst;
+    krb5_principal p1, p2;
+    
+    ret = krb5_cc_get_principal(context, id, &p1);
+    if(ret)
+	return ret;
+
+    ret = krb5_make_principal(context, &p2, NULL, 
+			      "kadmin", "admin", NULL);
+    if (ret) {
+	krb5_free_principal(context, p1);
+	return ret;
+    }
+
+    {
+	krb5_creds in, *out;
+	krb5_kdc_flags flags;
+
+	flags.i = 0;
+	memset(&in, 0, sizeof(in));
+
+	in.client = p1;
+	in.server = p2;
+
+	/* check for initial ticket kadmin/admin */
+	ret = krb5_get_credentials_with_flags(context, KRB5_GC_CACHED, flags,
+					      id, &in, &out);
+	krb5_free_principal(context, p2);
+	if (ret == 0) {
+	    if (out->flags.b.initial) {
+		*client = p1;
+		krb5_free_creds(context, out);
+		return 0;
+	    }
+	    krb5_free_creds(context, out);
+	}
+    }
+
+    name = krb5_principal_get_comp_string(context, p1, 0);
+    inst = krb5_principal_get_comp_string(context, p1, 1);
+    if(inst == NULL || strcmp(inst, "admin") != 0) {
+	ret = krb5_make_principal(context, &p2, NULL, name, "admin", NULL);
+	krb5_free_principal(context, p1);
+	if(ret != 0)
+	    return ret;
+
+	*client = p2;
+	return 0;
+    }
+
+    *client = p1;
+
+    return 0;
+}
+
 krb5_error_code
 _kadm5_c_get_cred_cache(krb5_context context,
 			const char *client_name,
@@ -254,32 +323,10 @@
 	/* get principal from default cache, ok if this doesn't work */
 	ret = krb5_cc_default(context, &id);
 	if(ret == 0) {
-	    ret = krb5_cc_get_principal(context, id, &default_client);
+	    ret = get_cache_principal(context, id, &default_client);
 	    if(ret) {
 		krb5_cc_close(context, id);
 		id = NULL;
-	    } else {
-		const char *name, *inst;
-		krb5_principal tmp;
-		name = krb5_principal_get_comp_string(context, 
-						      default_client, 0);
-		inst = krb5_principal_get_comp_string(context, 
-						      default_client, 1);
-		if(inst == NULL || strcmp(inst, "admin") != 0) {
-		    ret = krb5_make_principal(context, &tmp, NULL, 
-					      name, "admin", NULL);
-		    if(ret != 0) {
-			krb5_free_principal(context, default_client);
-			if (client)
-			    krb5_free_principal(context, client);
-			krb5_cc_close(context, id);
-			return ret;
-		    }
-		    krb5_free_principal(context, default_client);
-		    default_client = tmp;
-		    krb5_cc_close(context, id);
-		    id = NULL;
-		}
 	    }
 	}