Drop changing the password, really need kadmin/ldap support to do it
authorLove Hörnquist Åstrand <lha@kth.se>
Tue, 2 Jun 2009 21:53:17 +0000 (21:53 +0000)
committerLove Hörnquist Åstrand <lha@kth.se>
Tue, 2 Jun 2009 21:53:17 +0000 (21:53 +0000)
right (like add aes support, propper kvno handling etc).

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@25257 ec53bebd-3082-4978-b11e-865c3cabbd6b

kcm/acquire.c

index 37f61a0160b4f951926ea4f48518886f68384745..f6ed5d0deca3140f80592def6696fc805baf2c6d 100644 (file)
@@ -34,9 +34,6 @@
 
 RCSID("$Id$");
 
-static krb5_error_code
-change_pw_and_update_keytab(krb5_context context, kcm_ccache ccache);
-
 /*
  * Get a new ticket using a keytab/cached key and swap it into
  * an existing redentials cache
@@ -53,7 +50,6 @@ kcm_ccache_acquire(krb5_context context,
     krb5_get_init_creds_opt *opt = NULL;
     krb5_ccache_data ccdata;
     char *in_tkt_service = NULL;
-    int done = 0;
 
     memset(&cred, 0, sizeof(cred));
 
@@ -108,31 +104,13 @@ kcm_ccache_acquire(krb5_context context,
                                           opt);
     } else {
        /* loosely based on lib/krb5/init_creds_pw.c */
-       while (!done) {
-           ret = krb5_get_init_creds_keytab(context,
-                                            &cred,
-                                            ccache->client,
-                                            ccache->key.keytab,
-                                            0,
-                                            in_tkt_service,
-                                            opt);
-           switch (ret) {
-           case KRB5KDC_ERR_KEY_EXPIRED:
-               if (in_tkt_service != NULL &&
-                   strcmp(in_tkt_service, "kadmin/changepw") == 0) {
-                   goto out;
-               }
-
-               ret = change_pw_and_update_keytab(context, ccache);
-               if (ret)
-                   goto out;
-               break;
-           case 0:
-           default:
-               done = 1;
-               break;
-           }
-       }
+       ret = krb5_get_init_creds_keytab(context,
+                                        &cred,
+                                        ccache->client,
+                                        ccache->key.keytab,
+                                        0,
+                                        in_tkt_service,
+                                        opt);
     }
 
     if (ret) {
@@ -165,373 +143,3 @@ out:
 
     return ret;
 }
-
-static krb5_error_code
-change_pw(krb5_context context,
-         kcm_ccache ccache,
-         char *cpn,
-         char *newpw)
-{
-    krb5_error_code ret;
-    krb5_creds cpw_cred;
-    int result_code;
-    krb5_data result_code_string;
-    krb5_data result_string;
-    krb5_get_init_creds_opt *options;
-
-    memset(&cpw_cred, 0, sizeof(cpw_cred));
-
-    ret = krb5_get_init_creds_opt_alloc(context, &options);
-    if (ret)
-        return ret;
-    krb5_get_init_creds_opt_set_tkt_life(options, 60);
-    krb5_get_init_creds_opt_set_forwardable(options, FALSE);
-    krb5_get_init_creds_opt_set_proxiable(options, FALSE);
-
-    krb5_data_zero(&result_code_string);
-    krb5_data_zero(&result_string);
-
-    ret = krb5_get_init_creds_keytab(context,
-                                    &cpw_cred,
-                                    ccache->client,
-                                    ccache->key.keytab,
-                                    0,
-                                    "kadmin/changepw",
-                                    options);
-    krb5_get_init_creds_opt_free(context, options);
-    if (ret) {
-       kcm_log(0, "Failed to acquire password change credentials "
-               "for principal %s: %s",
-               cpn, krb5_get_err_text(context, ret));
-       goto out;
-    }
-
-    ret = krb5_set_password(context,
-                           &cpw_cred,
-                           newpw,
-                           ccache->client,
-                           &result_code,
-                           &result_code_string,
-                           &result_string);
-    if (ret) {
-       kcm_log(0, "Failed to change password for principal %s: %s",
-               cpn, krb5_get_err_text(context, ret));
-       goto out;
-    }
-
-    if (result_code) {
-       kcm_log(0, "Failed to change password for principal %s: %.*s",
-               cpn,
-               (int)result_string.length,
-               result_string.length > 0 ? (char *)result_string.data : "");
-       goto out;
-    }
-
-out:
-    krb5_data_free(&result_string);
-    krb5_data_free(&result_code_string);
-    krb5_free_cred_contents(context, &cpw_cred);
-
-    return ret;
-}
-
-struct kcm_keyseed_data {
-    krb5_salt salt;
-    const char *password;
-};
-
-static krb5_error_code
-kcm_password_key_proc(krb5_context context,
-                     krb5_enctype etype,
-                     krb5_salt salt,
-                     krb5_const_pointer keyseed,
-                     krb5_keyblock **key)
-{
-    krb5_error_code ret;
-    struct kcm_keyseed_data *s = (struct kcm_keyseed_data *)keyseed;
-
-    /* we may be called multiple times */
-    krb5_free_salt(context, s->salt);
-    krb5_data_zero(&s->salt.saltvalue);
-
-    /* stash the salt */
-    s->salt.salttype = salt.salttype;
-
-    ret = krb5_data_copy(&s->salt.saltvalue,
-                        salt.saltvalue.data,
-                        salt.saltvalue.length);
-    if (ret)
-       return ret;
-
-    *key = (krb5_keyblock *)malloc(sizeof(**key));
-    if (*key == NULL) {
-       return ENOMEM;
-    }
-
-    ret = krb5_string_to_key_salt(context, etype, s->password,
-                                 s->salt, *key);
-    if (ret) {
-       free(*key);
-       *key = NULL;
-    }
-
-    return ret;
-}
-
-static krb5_error_code
-get_salt_and_kvno(krb5_context context,
-                 kcm_ccache ccache,
-                 krb5_enctype *etypes,
-                 char *cpn,
-                 char *newpw,
-                 krb5_salt *salt,
-                 unsigned *kvno)
-{
-    krb5_error_code ret;
-    krb5_creds creds;
-    krb5_ccache_data ccdata;
-    krb5_flags options = 0;
-    krb5_kdc_rep reply;
-    struct kcm_keyseed_data s;
-
-    memset(&creds, 0, sizeof(creds));
-    memset(&reply, 0, sizeof(reply));
-
-    s.password = NULL;
-    s.salt.salttype = (int)ETYPE_NULL;
-    krb5_data_zero(&s.salt.saltvalue);
-
-    *kvno = 0;
-    kcm_internal_ccache(context, ccache, &ccdata);
-    s.password = newpw;
-
-    /* Do an AS-REQ to determine salt and key version number */
-    ret = krb5_copy_principal(context, ccache->client, &creds.client);
-    if (ret)
-       return ret;
-
-    /* Yes, get a ticket to ourselves */
-    ret = krb5_copy_principal(context, ccache->client, &creds.server);
-    if (ret) {
-       krb5_free_principal(context, creds.client);
-       return ret;
-    }
-       
-    ret = krb5_get_in_tkt(context,
-                         options,
-                         NULL,
-                         etypes,
-                         NULL,
-                         kcm_password_key_proc,
-                         &s,
-                         NULL,
-                         NULL,
-                         &creds,
-                         &ccdata,
-                         &reply);
-    if (ret) {
-       kcm_log(0, "Failed to get self ticket for principal %s: %s",
-               cpn, krb5_get_err_text(context, ret));
-       krb5_free_salt(context, s.salt);
-    } else {
-       *salt = s.salt; /* retrieve stashed salt */
-       if (reply.kdc_rep.enc_part.kvno != NULL)
-           *kvno = *(reply.kdc_rep.enc_part.kvno);
-    }
-    /* ccache may have been modified but it will get trashed anyway */
-
-    krb5_free_cred_contents(context, &creds);
-    krb5_free_kdc_rep(context, &reply);
-
-    return ret;
-}
-
-static krb5_error_code
-update_keytab_entry(krb5_context context,
-                   kcm_ccache ccache,
-                   krb5_enctype etype,
-                   char *cpn,
-                   char *spn,
-                   char *newpw,
-                   krb5_salt salt,
-                   unsigned kvno)
-{
-    krb5_error_code ret;
-    krb5_keytab_entry entry;
-    krb5_data pw;
-
-    memset(&entry, 0, sizeof(entry));
-
-    pw.data = (char *)newpw;
-    pw.length = strlen(newpw);
-
-    ret = krb5_string_to_key_data_salt(context, etype, pw,
-                                      salt, &entry.keyblock);
-    if (ret) {
-       kcm_log(0, "String to key conversion failed for principal %s "
-               "and etype %d: %s",
-               cpn, etype, krb5_get_err_text(context, ret));
-       return ret;
-    }
-
-    if (spn == NULL) {
-       ret = krb5_copy_principal(context, ccache->client,
-                                 &entry.principal);
-       if (ret) {
-           kcm_log(0, "Failed to copy principal name %s: %s",
-                   cpn, krb5_get_err_text(context, ret));
-           return ret;
-       }
-    } else {
-       ret = krb5_parse_name(context, spn, &entry.principal);
-       if (ret) {
-           kcm_log(0, "Failed to parse SPN alias %s: %s",
-                   spn, krb5_get_err_text(context, ret));
-           return ret;
-       }
-    }
-
-    entry.vno = kvno;
-    entry.timestamp = time(NULL);
-
-    ret = krb5_kt_add_entry(context, ccache->key.keytab, &entry);
-    if (ret) {
-       kcm_log(0, "Failed to update keytab for principal %s "
-               "and etype %d: %s",
-               cpn, etype, krb5_get_err_text(context, ret));
-    }
-
-    krb5_kt_free_entry(context, &entry);
-
-    return ret;
-}
-
-static krb5_error_code
-update_keytab_entries(krb5_context context,
-                     kcm_ccache ccache,
-                     krb5_enctype *etypes,
-                     char *cpn,
-                     char *spn,
-                     char *newpw,
-                     krb5_salt salt,
-                     unsigned kvno)
-{
-    krb5_error_code ret = 0;
-    int i;
-
-    for (i = 0; etypes[i] != ETYPE_NULL; i++) {
-       ret = update_keytab_entry(context, ccache, etypes[i],
-                                 cpn, spn, newpw, salt, kvno);
-       if (ret)
-           break;
-    }
-
-    return ret;
-}
-
-static void
-generate_random_pw(krb5_context context,
-                  char *buf,
-                  size_t bufsiz)
-{
-    unsigned char x[512], *p;
-    size_t i;
-
-    memset(x, 0, sizeof(x));
-    krb5_generate_random_block(x, sizeof(x));
-    p = x;
-
-    for (i = 0; i < bufsiz; i++) {
-       while (isprint(*p) == 0)
-           p++;
-
-       if (p - x >= sizeof(x)) {
-           krb5_generate_random_block(x, sizeof(x));
-           p = x;
-       }
-       buf[i] = (char)*p++;
-    }
-    buf[bufsiz - 1] = '\0';
-    memset(x, 0, sizeof(x));
-}
-
-static krb5_error_code
-change_pw_and_update_keytab(krb5_context context,
-                           kcm_ccache ccache)
-{
-    char newpw[121];
-    krb5_error_code ret;
-    unsigned kvno;
-    krb5_salt salt;
-    krb5_enctype *etypes = NULL;
-    int i;
-    char *cpn = NULL;
-    char **spns = NULL;
-
-    krb5_data_zero(&salt.saltvalue);
-
-    ret = krb5_unparse_name(context, ccache->client, &cpn);
-    if (ret) {
-       kcm_log(0, "Failed to unparse name: %s",
-               krb5_get_err_text(context, ret));
-       goto out;
-    }
-
-    ret = krb5_get_default_in_tkt_etypes(context, &etypes);
-    if (ret) {
-       kcm_log(0, "Failed to determine default encryption types: %s",
-               krb5_get_err_text(context, ret));
-       goto out;
-    }
-
-    /* Generate a random password (there is no set keys protocol) */
-    generate_random_pw(context, newpw, sizeof(newpw));
-
-    /* Change it */
-    ret = change_pw(context, ccache, cpn, newpw);
-    if (ret)
-       goto out;
-
-    /* Do an AS-REQ to determine salt and key version number */
-    ret = get_salt_and_kvno(context, ccache, etypes, cpn, newpw,
-                           &salt, &kvno);
-    if (ret) {
-       kcm_log(0, "Failed to determine salting principal for principal %s: %s",
-               cpn, krb5_get_err_text(context, ret));
-       goto out;
-    }
-
-    /* Add canonical name */
-    ret = update_keytab_entries(context, ccache, etypes, cpn,
-                               NULL, newpw, salt, kvno);
-    if (ret)
-       goto out;
-
-    /* Add SPN aliases, if any */
-    spns = krb5_config_get_strings(context, NULL, "kcm",
-                                  "system_ccache", "spn_aliases", NULL);
-    if (spns != NULL) {
-       for (i = 0; spns[i] != NULL; i++) {
-           ret = update_keytab_entries(context, ccache, etypes, cpn,
-                                       spns[i], newpw, salt, kvno);
-           if (ret)
-               goto out;
-       }
-    }
-
-    kcm_log(0, "Changed expired password for principal %s in cache %s",
-           cpn, ccache->name);
-
-out:
-    if (cpn != NULL)
-       free(cpn);
-    if (spns != NULL)
-       krb5_config_free_strings(spns);
-    if (etypes != NULL)
-       free(etypes);
-    krb5_free_salt(context, salt);
-    memset(newpw, 0, sizeof(newpw));
-
-    return ret;
-}
-