From f45a85530e0e807b33f9b01a7f835bf428df9447 Mon Sep 17 00:00:00 2001 From: Paul Park Date: Wed, 9 Aug 1995 21:24:45 +0000 Subject: [PATCH] First pass at kdb5 change-password code. Fix memory leaks git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6486 dc483132-0cff-0310-8789-dd5450dbe970 --- src/kadmin/v5server/admin.c | 124 +++++++++++++++++++++++++++++++---- src/kadmin/v5server/passwd.c | 80 ++++++++++++++++++++-- 2 files changed, 187 insertions(+), 17 deletions(-) diff --git a/src/kadmin/v5server/admin.c b/src/kadmin/v5server/admin.c index 5d8dee3f4..7db29bba3 100644 --- a/src/kadmin/v5server/admin.c +++ b/src/kadmin/v5server/admin.c @@ -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); diff --git a/src/kadmin/v5server/passwd.c b/src/kadmin/v5server/passwd.c index 63453547d..335aca0a3 100644 --- a/src/kadmin/v5server/passwd.c +++ b/src/kadmin/v5server/passwd.c @@ -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; ikey_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); -- 2.26.2