First pass at kdb5 change-password code. Fix memory leaks
authorPaul Park <pjpark@mit.edu>
Wed, 9 Aug 1995 21:24:45 +0000 (21:24 +0000)
committerPaul Park <pjpark@mit.edu>
Wed, 9 Aug 1995 21:24:45 +0000 (21:24 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6486 dc483132-0cff-0310-8789-dd5450dbe970

src/kadmin/v5server/admin.c
src/kadmin/v5server/passwd.c

index 5d8dee3f427389fd79e0b75c7681e3b05029535b..7db29bba3151517794dad4f5573bacba15db7e3d 100644 (file)
@@ -308,6 +308,7 @@ admin_merge_dbentries(kcontext, debug_level, who, defaultp,
     krb5_boolean       is_pwchange;
 {
     krb5_error_code    kret = 0;
+#ifndef        USE_KDB5_CPW
     krb5_timestamp     now;
     krb5_tl_data       *pwchg, *def_pwchg;
     krb5_tl_data       *new, *def;
@@ -315,6 +316,7 @@ admin_merge_dbentries(kcontext, debug_level, who, defaultp,
     krb5_int32         num_keys, num_ekeys, num_rkeys;
     krb5_key_data      *key_list;
     krb5_key_data      *ekey_list;
+#endif /* USE_KDB5_CPW */
     DPRINT(DEBUG_CALLS, debug_level, ("* admin_merge_dbentries()\n"));
 
     /*
@@ -323,11 +325,15 @@ admin_merge_dbentries(kcontext, debug_level, who, defaultp,
      *         and that we don't have a password and the random-password option.
      */
     kret = EINVAL;
+#ifndef        USE_KDB5_CPW
     num_keys = num_ekeys = num_rkeys = 0;
     key_list = (krb5_key_data *) NULL;
     ekey_list = (krb5_key_data *) NULL;
+#endif /* USE_KDB5_CPW */
     if (dbentp->princ &&
+#ifndef        USE_KDB5_CPW
        !(kret = krb5_timeofday(kcontext, &now)) &&
+#endif /* USE_KDB5_CPW */
        (!password || ((valid & KRB5_ADM_M_RANDOMKEY) == 0))) {
 
        /*
@@ -351,7 +357,9 @@ admin_merge_dbentries(kcontext, debug_level, who, defaultp,
        dbentp->last_failed = defaultp->last_failed;
        dbentp->fail_auth_count = defaultp->fail_auth_count;
        dbentp->len = defaultp->len;
+       kret = 0;
 
+#ifndef        USE_KDB5_CPW
        /*
         * Now merge tagged data.  This is a little bit painful, hold on.
         * First see if we already have a last change block.  If so, then just
@@ -416,7 +424,6 @@ admin_merge_dbentries(kcontext, debug_level, who, defaultp,
                krb5_free_principal(kcontext, modent.mod_princ);
            }
        }
-
        if (!kret) {
            /* See if this is a random key or not */
            if (password) {
@@ -496,12 +503,15 @@ admin_merge_dbentries(kcontext, debug_level, who, defaultp,
                }
            }
        }
+#endif /* USE_KDB5_CPW */
     }
 
+#ifndef        USE_KDB5_CPW
     if (key_list)
        key_free_key_data(key_list, num_keys);
     if (ekey_list)
        key_free_key_data(ekey_list, num_ekeys);
+#endif /* USE_KDB5_CPW */
     DPRINT(DEBUG_CALLS, debug_level, ("X admin_merge_dbentries()=%d\n", kret));
     return(kret);
 }
@@ -538,6 +548,10 @@ admin_add_modify(kcontext, debug_level, ticket, nargs, arglist,
     char               *new_password;
     krb5_int32         operation;
     const char         *op_msg;
+#ifdef USE_KDB5_CPW
+    krb5_int32         n_keysalts;
+    krb5_key_salt_tuple        *keysalts;
+#endif /* USE_KDB5_CPW */
 #ifdef DEBUG
     char               *dbg_op_msg;
 #endif /* DEBUG */
@@ -679,8 +693,73 @@ admin_add_modify(kcontext, debug_level, ticket, nargs, arglist,
                                                               valid_mask,
                                                               &new_dbentry,
                                                               pword_data.data,
-                                                              pwd_supplied)
-                                 )) {
+                                                              pwd_supplied))
+#ifdef USE_KDB5_CPW
+                               &&
+                               !(kret = key_dbent_to_keysalts(&new_dbentry,
+                                                              &n_keysalts,
+                                                              &keysalts))
+#endif /* USE_KDB5_CPW */
+                               ) {
+#ifdef USE_KDB5_CPW
+                               /*
+                                * Determine if this is a random key or not.
+                                */
+                               if ((valid_mask & KRB5_ADM_M_RANDOMKEY) ||
+                                   (!pword_data.data && should_exist)) {
+                                   /* Random key */
+                                   /*
+                                    * Determine if this is a change or a
+                                    * create operation.
+                                    */
+                                   if (should_exist) {
+                                       new_dbentry.key_data =
+                                           cur_dbentry.key_data;
+                                       new_dbentry.n_key_data =
+                                           cur_dbentry.n_key_data;
+                                       cur_dbentry.key_data =
+                                           (krb5_key_data *) NULL;
+                                       cur_dbentry.n_key_data = 0;
+                                       kret = krb5_dbe_crk(kcontext,
+                                                           key_master_encblock(),
+                                                           keysalts,
+                                                           n_keysalts,
+                                                           &new_dbentry);
+                                   }
+                                   else
+                                       kret = krb5_dbe_ark(kcontext,
+                                                           key_master_encblock(),
+                                                           keysalts,
+                                                           n_keysalts,
+                                                           &new_dbentry);
+                               }
+                               else {
+                                   if (should_exist) {
+                                       new_dbentry.key_data =
+                                           cur_dbentry.key_data;
+                                       new_dbentry.n_key_data =
+                                           cur_dbentry.n_key_data;
+                                       cur_dbentry.key_data =
+                                           (krb5_key_data *) NULL;
+                                       cur_dbentry.n_key_data = 0;
+                                       kret = krb5_dbe_cpw(kcontext,
+                                                           key_master_encblock(),
+                                                           keysalts,
+                                                           n_keysalts,
+                                                           pword_data.data,
+                                                           &new_dbentry);
+                                   }
+                                   else
+                                       kret = krb5_dbe_apw(kcontext,
+                                                           key_master_encblock(),
+                                                           keysalts,
+                                                           n_keysalts,
+                                                           pword_data.data,
+                                                           &new_dbentry);
+                               }
+                               krb5_xfree(keysalts);
+                               if (!kret) {
+#endif /* USE_KDB5_CPW */
                                int nument = 1;
 
                                /* Write the entry. */
@@ -706,6 +785,18 @@ admin_add_modify(kcontext, debug_level, ticket, nargs, arglist,
                                            arglist[0].data,
                                            client_name);
                                }
+#ifdef USE_KDB5_CPW
+                               }
+                               else {
+                                   /*
+                                    * Couldn't use the apw/cpw/ark/crk
+                                    */
+                                   DPRINT(DEBUG_PROTO, debug_level,
+                                          ("= password set failed for %s\n",
+                                           dbg_op_msg));
+                                   retval = KRB5_ADM_SYSTEM_ERROR;
+                               }
+#endif /* USE_KDB5_CPW */
 
                                /*
                                 * Clean up droppings from
@@ -746,12 +837,10 @@ admin_add_modify(kcontext, debug_level, ticket, nargs, arglist,
                               ("= argument list bad for %s\n", dbg_op_msg));
                        retval = KRB5_ADM_BAD_OPTION;
                    }
-                   krb5_db_free_principal(kcontext,
-                                          ((should_exist) ? 
-                                           &new_dbentry : &cur_dbentry),
-                                          1);
                    if (should_exist)
-                       principal = (krb5_principal) NULL;
+                       krb5_db_free_principal(kcontext, &cur_dbentry, 1);
+                   krb5_db_free_principal(kcontext, &new_dbentry, 1);
+                   principal = (krb5_principal) NULL;
                }
                else {
                    /* Database entry failed or yielded unexpected results */
@@ -906,11 +995,20 @@ admin_delete_rename(kcontext, debug_level, ticket, original, new)
                                orig_entry.princ = new_principal;
 
                                /* Update our stats */
-                               if (!krb5_dbe_decode_mod_princ_data(kcontext,
-                                                                   &orig_entry,
-                                                                   &mprinc)) {
-                                   krb5_free_principal(kcontext,
-                                                       mprinc->mod_princ);
+                               mprinc = (krb5_tl_mod_princ *) NULL;
+                               (void) krb5_dbe_decode_mod_princ_data(kcontext,
+                                                                     &orig_entry,
+                                                                     &mprinc);
+                               if (!mprinc) {
+                                   mprinc = (krb5_tl_mod_princ *)
+                                       malloc(sizeof(krb5_tl_mod_princ));
+                                   if (mprinc)
+                                       memset(mprinc, 0, sizeof(*mprinc));
+                               }
+                               if (mprinc) {
+                                   if (mprinc->mod_princ)
+                                       krb5_free_principal(kcontext,
+                                                           mprinc->mod_princ);
                                    krb5_copy_principal(kcontext,
                                                        client,
                                                        &mprinc->mod_princ);
index 63453547d58ad846d5c5dc73419b4461facd6635..335aca0a32b995314aac83a1622ac117b086c35e 100644 (file)
@@ -114,10 +114,12 @@ passwd_check_opass_ok(kcontext, debug_level, princ, dbentp, pwdata)
     krb5_data          *pwdata;
 {
     krb5_boolean       pwret;
-    krb5_int32         num_keys, num_dkeys;
+    krb5_int32         num_keys, num_dkeys, tmpn;
     krb5_key_data      *key_list, *dkey_list, *kent, *tmp;
     krb5_key_salt_tuple        keysalt;
     krb5_error_code    kret;
+    krb5_key_data      *skey_list;
+    krb5_int16         nskeys;
     int                        i;
 
     DPRINT(DEBUG_CALLS, debug_level, ("* passwd_check_opass_ok()\n"));
@@ -126,6 +128,10 @@ passwd_check_opass_ok(kcontext, debug_level, princ, dbentp, pwdata)
     /* Initialize */
     num_keys = num_dkeys = 0;
     key_list = dkey_list = (krb5_key_data *) NULL;
+    nskeys = dbentp->n_key_data;
+    skey_list = dbentp->key_data;
+    dbentp->n_key_data = 0;
+    dbentp->key_data = (krb5_key_data *) NULL;
 
     /* Make key(s) using alleged old password */
     kret = key_string_to_keys(kcontext,
@@ -137,12 +143,12 @@ passwd_check_opass_ok(kcontext, debug_level, princ, dbentp, pwdata)
                              &key_list);
 
     /* Now decrypt database entries */
-    num_dkeys = dbentp->n_key_data;
+    num_dkeys = nskeys;
     if (!kret)
        kret = key_decrypt_keys(kcontext,
                                dbentp,
                                &num_dkeys,
-                               dbentp->key_data,
+                               skey_list,
                                &dkey_list);
     if (kret)
        goto cleanup;
@@ -151,7 +157,9 @@ passwd_check_opass_ok(kcontext, debug_level, princ, dbentp, pwdata)
      * Compare decrypted keys.  If they differ, then we're wrong!
      */
     tmp = dbentp->key_data;
+    tmpn = dbentp->n_key_data;
     dbentp->key_data = dkey_list;
+    dbentp->n_key_data = num_dkeys;
     for (i=0; i<num_keys; i++) {
        keysalt.ks_keytype = (krb5_keytype) key_list[i].key_data_type[0];
        keysalt.ks_salttype = (krb5_int32) key_list[i].key_data_type[1];
@@ -166,6 +174,7 @@ passwd_check_opass_ok(kcontext, debug_level, princ, dbentp, pwdata)
        }
     }
     dbentp->key_data = tmp;
+    dbentp->n_key_data = tmpn;
 
  cleanup:
     if (kret)
@@ -174,6 +183,10 @@ passwd_check_opass_ok(kcontext, debug_level, princ, dbentp, pwdata)
        key_free_key_data(key_list, num_keys);
     if (num_dkeys && dkey_list)
        key_free_key_data(dkey_list, num_dkeys);
+    if (dbentp->key_data && dbentp->n_key_data)
+       key_free_key_data(dbentp->key_data, dbentp->n_key_data);
+    dbentp->key_data = skey_list;
+    dbentp->n_key_data = nskeys;
     DPRINT(DEBUG_CALLS, debug_level,
           ("X passwd_check_opass_ok() = %d\n", pwret));
     return(pwret);
@@ -192,15 +205,70 @@ passwd_set_npass(kcontext, debug_level, princ, dbentp, pwdata)
 {
     krb5_error_code    kret;
     krb5_db_entry      entry2write;
+    int                        nwrite;
+#ifdef USE_KDB5_CPW
+    krb5_int32         n_keysalts;
+    krb5_key_salt_tuple        *keysalts;
+    char               *tmppw;
+#else  /* USE_KDB5_CPW */
     krb5_int32         num_keys;
     krb5_key_data      *key_list;
     krb5_tl_data       *pwchg;
     krb5_tl_mod_princ  modent;
-    int                        nwrite;
     krb5_timestamp     now;
+#endif /* USE_KDB5_CPW */
 
     DPRINT(DEBUG_CALLS, debug_level, ("* passwd_set_npass()\n"));
 
+#ifdef USE_KDB5_CPW
+    keysalts = (krb5_key_salt_tuple *) NULL;
+    n_keysalts = 0;
+
+    /* Copy our database entry */
+    memcpy((char *) &entry2write, (char *) dbentp, sizeof(krb5_db_entry));
+
+    /*
+     * Zap stuff which we're not going to use.
+     *
+     * We're going to recreate the whole tl_data and key_data structures,
+     * so blast what we copied from above.
+     */
+    entry2write.tl_data = (krb5_tl_data *) NULL;
+    entry2write.n_tl_data = 0;
+    entry2write.key_data = (krb5_key_data *) NULL;
+    entry2write.n_key_data = 0;
+    entry2write.princ = (krb5_principal) NULL;
+
+    /*
+     * Generate the key/salt tuple list from our key list.
+     */
+    if (!(kret = krb5_copy_principal(kcontext,
+                                    dbentp->princ,
+                                    &entry2write.princ)) &&
+       !(kret = key_dbent_to_keysalts(dbentp, &n_keysalts, &keysalts))) {
+       /* Get scratch space for our password */
+       if (tmppw = (char *) malloc((size_t) (pwdata->length+1))) {
+           memcpy(tmppw, pwdata->data, pwdata->length);
+           tmppw[pwdata->length] = '\0';
+           /*
+            * Change the password.
+            */
+           kret = krb5_dbe_cpw(kcontext,
+                               key_master_encblock(),
+                               keysalts,
+                               n_keysalts,
+                               tmppw,
+                               &entry2write);
+           memset(tmppw, 0, pwdata->length);
+           free(tmppw);
+       }
+       else
+           kret = ENOMEM;
+       krb5_xfree(keysalts);
+    }
+    if (kret)
+       goto cleanup;
+#else  /* USE_KDB5_CPW */
     /* Initialize */
     num_keys = 0;
     key_list = (krb5_key_data *) NULL;
@@ -266,6 +334,7 @@ passwd_set_npass(kcontext, debug_level, princ, dbentp, pwdata)
        kret = krb5_dbe_encode_mod_princ_data(kcontext, &modent, &entry2write);
        krb5_free_principal(kcontext, modent.mod_princ);
     }
+#endif /* USE_KDB5_CPW */
 
     /* Now write the entry */
     nwrite = 1;
@@ -278,8 +347,11 @@ passwd_set_npass(kcontext, debug_level, princ, dbentp, pwdata)
     (void) krb5_db_free_principal(kcontext, &entry2write, 1);
 
  cleanup:
+#ifndef        USE_KDB5_CPW
     if (num_keys && key_list)
        key_free_key_data(key_list, num_keys);
+#endif /* USE_KDB5_CPW */
+
     DPRINT(DEBUG_CALLS, debug_level,
           ("X passwd_set_npass() = %d\n", kret));
     return(kret);