Hello, The behavior is what most sites expect since its very common to split the administrative role (lha/[EMAIL PROTECTED]) from the user role ([EMAIL PROTECTED]).
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; - } } }