From 253efdb61b1e50eeeb5651c9254ea5cf8d119568 Mon Sep 17 00:00:00 2001 From: Chris Provenzano Date: Thu, 3 Aug 1995 16:17:45 +0000 Subject: [PATCH] cpw.c : New change password code for kdb5_edit. dumpv4.c : Get it to compile with new kdb format. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6398 dc483132-0cff-0310-8789-dd5450dbe970 --- src/admin/edit/ChangeLog | 5 + src/admin/edit/cpw.c | 452 +++++++++++++++++++++++++++++++++++++++ src/admin/edit/dumpv4.c | 158 +++++++------- 3 files changed, 542 insertions(+), 73 deletions(-) create mode 100644 src/admin/edit/cpw.c diff --git a/src/admin/edit/ChangeLog b/src/admin/edit/ChangeLog index 5ee9bc81a..32085fb43 100644 --- a/src/admin/edit/ChangeLog +++ b/src/admin/edit/ChangeLog @@ -1,4 +1,9 @@ +Thu Aug 03 12:13:50 1995 Chris Provenzano (proven@mit.edu) + + * cpw.c : New change password code for kdb5_edit. + * dumpv4.c : Get it to compile with new kdb format. + Mon Jul 31 15:47:30 EDT 1995 Paul Park (pjpark@mit.edu) * kdb5_edit.c - Use libkadm string conversion routines. These are shared by all utilities. diff --git a/src/admin/edit/cpw.c b/src/admin/edit/cpw.c new file mode 100644 index 000000000..fd8988253 --- /dev/null +++ b/src/admin/edit/cpw.c @@ -0,0 +1,452 @@ +/* + * admin/edit/cpw.c + * + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * Change passwords for a KDC db entry. + */ + +#include "k5-int.h" +#include "com_err.h" +#include "adm.h" +#include "adm_proto.h" +#include +#include + +#include "kdb5_edit.h" + +extern char *Err_no_master_msg; +extern char *Err_no_database; +extern char *current_dbname; + + +/* + * XXX Ick, ick, ick. These global variables shouldn't be global.... + */ +/* +static char search_name[40]; +static int num_name_tokens; +static char search_instance[40]; +static int num_instance_tokens; +static int must_be_first[2]; +static char *mkey_password = 0; +static char *stash_file = (char *) NULL; +*/ + +/* + * I can't figure out any way for this not to be global, given how ss + * works. + */ + +extern int exit_status; + +extern krb5_context edit_context; + +extern krb5_keyblock master_keyblock; +extern krb5_principal master_princ; +extern krb5_db_entry master_entry; +extern krb5_encrypt_block master_encblock; +extern krb5_pointer master_random; +extern int valid_master_key; + +extern char *krb5_default_pwd_prompt1, *krb5_default_pwd_prompt2; + +extern char *progname; +extern char *cur_realm; +extern char *mkey_name; +extern krb5_boolean manual_mkey; +extern krb5_boolean dbactive; + +/* + * This is the guts of add_rnd_key() and change_rnd_key() + */ +void +enter_rnd_key(argc, argv, change) + int argc; + char ** argv; + int change; +{ + krb5_error_code retval; + krb5_keyblock * tempkey; + krb5_principal newprinc; + krb5_key_data * key_data; + krb5_db_entry entry; + krb5_boolean more; + int nprincs = 1; + int vno; + + if (argc < 2) { + com_err(argv[0], 0, "Too few arguments"); + com_err(argv[0], 0, "Usage: %s principal", argv[0]); + exit_status++; + return; + } + if (!dbactive) { + com_err(argv[0], 0, Err_no_database); + exit_status++; + return; + } + if (!valid_master_key) { + com_err(argv[0], 0, Err_no_master_msg); + exit_status++; + return; + } + if (retval = krb5_parse_name(edit_context, argv[1], &newprinc)) { + com_err(argv[0], retval, "while parsing '%s'", argv[1]); + exit_status++; + return; + } + if (retval = krb5_db_get_principal(edit_context, newprinc, &entry, + &nprincs, &more)) { + com_err(argv[0], retval, "while trying to get principal's database entry"); + exit_status++; + return; + } + if (change && !nprincs) { + com_err(argv[0], 0, "No principal '%s' exists", argv[1]); + exit_status++; + goto errout; + } + if (!change && nprincs) { + com_err(argv[0], 0, "Principal '%s' already exists.", argv[1]); + exit_status++; + goto errout; + } + + if (!change) { + if (retval = create_db_entry(newprinc, &entry)) { + com_err(argv[0], retval, "While creating new db entry."); + exit_status++; + goto errout; + } + if (retval = krb5_dbe_create_key_data(edit_context, &entry)) { + com_err(argv[0], retval, "While creating key_data for db_entry."); + exit_status++; + goto errout; + } + nprincs = 1; + vno = 1; + } else { + vno = entry.key_data[0].key_data_kvno++; + } + /* For now we only set the first key_data */ + key_data = entry.key_data; + + if (retval = krb5_random_key(edit_context, &master_encblock, + master_random, &tempkey)) { + com_err(argv[0], retval, "while generating random key"); + exit_status++; + return; + } + + /* Encoding over an old key_data will free old key contents */ + retval = krb5_dbekd_encrypt_key_data(edit_context, &master_encblock, + tempkey, NULL, vno, key_data); + krb5_free_keyblock(edit_context, tempkey); + if (retval) { + com_err(argv[0], retval, "while encrypting key for '%s'", argv[1]); + exit_status++; + goto errout; + } + + if (retval = krb5_db_put_principal(edit_context, &entry, &nprincs)) { + com_err(argv[0], retval, "while storing entry for '%s'\n", argv[1]); + exit_status++; + goto errout; + } + + if (nprincs != 1) { + com_err(argv[0], 0, "entry not stored in database (unknown failure)"); + exit_status++; + } + +errout: + krb5_free_principal(edit_context, newprinc); + if (nprincs) + krb5_db_free_principal(edit_context, &entry, nprincs); + return; +} + +void add_rnd_key(argc, argv) + int argc; + char *argv[]; +{ + enter_rnd_key(argc, argv, 0); +} + +void change_rnd_key(argc, argv) + int argc; + char *argv[]; +{ + enter_rnd_key(argc, argv, 1); +} + +krb5_key_salt_tuple ks_tuple_default = { KEYTYPE_DES, 0 }; +void change_pwd_key(argc, argv) + int argc; + char *argv[]; +{ + krb5_key_salt_tuple * ks_tuple = NULL; + krb5_db_entry db_entry; + krb5_error_code retval; + krb5_principal princ; + krb5_boolean more; + krb5_kvno vno; + int one; + int i; + + char password[KRB5_ADM_MAX_PASSWORD_LEN]; + int pwsize = KRB5_ADM_MAX_PASSWORD_LEN; + + if (!dbactive) { + com_err(argv[0], 0, Err_no_database); + exit_status++; + return; + } + if (!valid_master_key) { + com_err(argv[0], 0, Err_no_master_msg); + exit_status++; + return; + } + + if (argc < 2) { + com_err(argv[0], 0, "Usage: % [-]> principal", + argv[0]); + exit_status++; + return; + } + + for (i = 1; i < (argc - 1); i++) { + char * salt_type_name; + + if (!ks_tuple) { + ks_tuple = (krb5_key_salt_tuple *)malloc( + sizeof(krb5_key_salt_tuple)); + } else { + ks_tuple = (krb5_key_salt_tuple *)realloc(ks_tuple, + sizeof(krb5_key_salt_tuple) * i); + } + if (!ks_tuple) { + com_err(argv[0], 0, "Insufficient memory to proceed"); + exit_status++; + return; + } + + while (salt_type_name = strchr(argv[i], ':')) { + *salt_type_name++ = '\0'; + if (!strcmp(salt_type_name, "v4")) { + ks_tuple[i - 1].ks_salttype = KRB5_KDB_SALTTYPE_V4; + break; + } + if (!strcmp(salt_type_name, "normal")) { + ks_tuple[i - 1].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL; + break; + } + if (!strcmp(salt_type_name, "norealm")) { + ks_tuple[i - 1].ks_salttype = KRB5_KDB_SALTTYPE_NOREALM; + break; + } + if (!strcmp(salt_type_name, "onlyrealm")) { + ks_tuple[i - 1].ks_salttype = KRB5_KDB_SALTTYPE_ONLYREALM; + break; + } + com_err(argv[0], 0, "Unknown salt type %s", salt_type_name); + exit_status++; + return; + } + + if (!strcmp(argv[i], "des")) { + ks_tuple[i - 1].ks_keytype = KRB5_KDB_SALTTYPE_ONLYREALM; + continue; + } + com_err(argv[0], 0, "Unknown key type %s", argv[i]); + goto change_pwd_key_error; + } + + if (retval = krb5_parse_name(edit_context, argv[i], &princ)) { + com_err(argv[0], retval, "while parsing '%s'", argv[i]); + goto change_pwd_key_error; + } + if ((retval = krb5_db_get_principal(edit_context, princ, &db_entry, + &one, &more)) || (!one) || (more)) { + com_err(argv[0], 0, "No principal '%s' exists!", argv[i]); + krb5_free_principal(edit_context, princ); + goto change_pwd_key_error; + } + + /* Done with principal */ + krb5_free_principal(edit_context, princ); + + if (retval = krb5_read_password(edit_context, krb5_default_pwd_prompt1, + krb5_default_pwd_prompt2, + password, &pwsize)) { + com_err(argv[0], retval, "while reading password for '%s'", argv[i]); + goto change_pwd_key_error; + } + + if (retval = krb5_dbe_cpw(edit_context, &master_encblock, &db_entry, + ks_tuple ? ks_tuple : &ks_tuple_default, + i, password)) { + com_err(argv[0], retval, "while storing entry for '%s'\n", argv[i]); + krb5_dbe_free_contents(edit_context, &db_entry); + goto change_pwd_key_error; + } + + /* Write the entry back out and we're done */ + if (retval = krb5_db_put_principal(edit_context, &db_entry, &one)) { + com_err(argv[0], retval, "while storing entry for '%s'\n", argv[i]); + } + +change_pwd_key_error:; + krb5_xfree(ks_tuple); + if (retval) + exit_status++; + return; +} + +void change_v4_key(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code retval; + krb5_principal newprinc; + krb5_kvno vno; + + if (argc < 2) { + com_err(argv[0], 0, "Too few arguments"); + com_err(argv[0], 0, "Usage: %s principal", argv[0]); + exit_status++; + return; + } + if (!dbactive) { + com_err(argv[0], 0, Err_no_database); + exit_status++; + return; + } + if (!valid_master_key) { + com_err(argv[0], 0, Err_no_master_msg); + exit_status++; + return; + } + if (retval = krb5_parse_name(edit_context, argv[1], &newprinc)) { + com_err(argv[0], retval, "while parsing '%s'", argv[1]); + exit_status++; + return; + } + if ((vno = princ_exists(argv[0], newprinc)) == 0) { + com_err(argv[0], 0, "No principal '%s' exists!", argv[1]); + exit_status++; + krb5_free_principal(edit_context, newprinc); + return; + } + enter_pwd_key(argv[0], argv[1], newprinc, newprinc, vno, + KRB5_KDB_SALTTYPE_V4); + krb5_free_principal(edit_context, newprinc); + return; +} + +void +enter_pwd_key(cmdname, newprinc, princ, string_princ, vno, salttype) + char * cmdname; + char * newprinc; + krb5_const_principal princ; + krb5_const_principal string_princ; + krb5_kvno vno; + int salttype; +{ + krb5_error_code retval; + char password[BUFSIZ]; + int pwsize = sizeof(password); + krb5_keyblock tempkey; + krb5_keysalt salt; + krb5_data pwd; + + if (retval = krb5_read_password(edit_context, krb5_default_pwd_prompt1, + krb5_default_pwd_prompt2, + password, &pwsize)) { + com_err(cmdname, retval, "while reading password for '%s'", newprinc); + exit_status++; + return; + } + pwd.data = password; + pwd.length = pwsize; + + switch (salt.type = salttype) { + case KRB5_KDB_SALTTYPE_NORMAL: + if (retval = krb5_principal2salt(edit_context,string_princ,&salt.data)){ + com_err(cmdname, retval, + "while converting principal to salt for '%s'", newprinc); + exit_status++; + return; + } + break; + case KRB5_KDB_SALTTYPE_V4: + salt.data.length = 0; + salt.data.data = 0; + break; + case KRB5_KDB_SALTTYPE_NOREALM: + if (retval = krb5_principal2salt_norealm(edit_context, string_princ, + &salt.data)) { + com_err(cmdname, retval, + "while converting principal to salt for '%s'", newprinc); + exit_status++; + return; + } + break; + case KRB5_KDB_SALTTYPE_ONLYREALM: { + krb5_data * saltdata; + if (retval = krb5_copy_data(edit_context, + krb5_princ_realm(edit_context,string_princ), + &saltdata)) { + com_err(cmdname, retval, + "while converting principal to salt for '%s'", newprinc); + exit_status++; + return; + } + salt.data = *saltdata; + krb5_xfree(saltdata); + break; + } + default: + com_err(cmdname, 0, "Don't know how to enter salt type %d", salttype); + exit_status++; + return; + } + retval = krb5_string_to_key(edit_context, &master_encblock, + master_keyblock.keytype, &tempkey, + &pwd, &salt.data); + memset(password, 0, sizeof(password)); /* erase it */ + if (retval) { + com_err(cmdname, retval, "while converting password to key for '%s'", + newprinc); + if (salt.data.data) + krb5_xfree(salt.data.data); + exit_status++; + return; + } + add_key(cmdname, newprinc, princ, &tempkey, ++vno, + (salttype == KRB5_KDB_SALTTYPE_NORMAL) ? NULL : &salt); + memset((char *)tempkey.contents, 0, tempkey.length); + if (salt.data.data) + krb5_xfree(salt.data.data); + krb5_xfree(tempkey.contents); + return; +} + diff --git a/src/admin/edit/dumpv4.c b/src/admin/edit/dumpv4.c index 50b081f62..9e8c59651 100644 --- a/src/admin/edit/dumpv4.c +++ b/src/admin/edit/dumpv4.c @@ -78,13 +78,16 @@ v4_print_time(file, timeval) krb5_error_code dump_v4_iterator(ptr, entry) -krb5_pointer ptr; -krb5_db_entry *entry; + krb5_pointer ptr; + krb5_db_entry *entry; { - krb5_error_code retval; struct dump_record *arg = (struct dump_record *) ptr; - char *name=NULL, *mod_name=NULL; - int i; + krb5_tl_mod_princ *mod_princ = NULL; + krb5_error_code retval; + char *mod_name=NULL; + char *name=NULL; + int i, max_kvno, ok_key; + struct v4princ { char name[ANAME_SZ+1]; char instance[INST_SZ+1]; @@ -102,83 +105,99 @@ krb5_db_entry *entry; principal = &v4princ; - if (retval = krb5_unparse_name(edit_context, entry->principal, &name)) { + if (retval = krb5_unparse_name(edit_context, entry->princ, &name)) { com_err(arg->comerr_name, retval, "while unparsing principal"); exit_status++; return retval; } - if (retval = krb5_unparse_name(edit_context, entry->mod_name, &mod_name)) { - free(name); - com_err(arg->comerr_name, retval, "while unparsing principal"); - exit_status++; - return retval; - } - - if (entry->salt_type != KRB5_KDB_SALTTYPE_V4) { - free(name); - free(mod_name); - /* skip this because it's a new style key and we can't help it */ - return 0; - } - if (strcmp(krb5_princ_realm(edit_context, entry->principal)->data, - arg->realm)) { + if (strcmp(krb5_princ_realm(edit_context, entry->princ)->data, arg->realm)){ + /* + * skip this because it's a key for a different realm, probably + * a paired krbtgt key + */ free(name); - free(mod_name); - /* skip this because it's a key for a different realm, probably - a paired krbtgt key */ return 0; } - strncpy(principal->name, - krb5_princ_component(edit_context, entry->principal, 0)->data, - ANAME_SZ); - if (!principal->name[0]) { - strcpy(principal->name, "*"); - } + krb5_princ_component(edit_context, entry->princ, 0)->data,ANAME_SZ); if (!strcmp(principal->name, "host")) { - strcpy(principal->name, "rcmd"); + strcpy(principal->name, "rcmd"); } - - if (entry->principal->length > 1) { - char *inst; - strncpy(principal->instance, - krb5_princ_component(edit_context, entry->principal, 1)->data, - INST_SZ); - inst = strchr(principal->instance, '.'); - if (inst && strcmp(principal->name, "krbtgt")) { - /* nuke domain off the end of anything that isn't a tgt */ - *inst = '\0'; - } + if (!principal->name[0]) { + strcpy(principal->name, "*"); } - else { - principal->instance[0] = '*'; - principal->instance[1] = '\0'; + + if (entry->princ->length > 1) { + char *inst; + strncpy(principal->instance, + krb5_princ_component(edit_context, entry->princ, 1)->data, + INST_SZ); + inst = strchr(principal->instance, '.'); + if (inst && strcmp(principal->name, "krbtgt")) { + /* nuke domain off the end of anything that isn't a tgt */ + *inst = '\0'; + } + } else { + principal->instance[0] = '*'; + principal->instance[1] = '\0'; } + free(name); + /* Now move to mod princ */ + if (retval = krb5_dbe_decode_mod_princ_data(edit_context,entry,&mod_princ)){ + com_err(arg->comerr_name, retval, "while unparsing db entry"); + exit_status++; + return retval; + } + if (retval=krb5_unparse_name(edit_context,mod_princ->mod_princ,&mod_name)) { + com_err(arg->comerr_name, retval, "while unparsing principal"); + exit_status++; + return retval; + } strncpy(principal->mod_name, - krb5_princ_component(edit_context, entry->mod_name, 0)->data, + krb5_princ_component(edit_context, mod_princ->mod_princ, 0)->data, ANAME_SZ); if (!principal->mod_name[0]) { strcpy(principal->mod_name, "*"); } - if (entry->mod_name->length > 1) { - strncpy(principal->mod_instance, - krb5_princ_component(edit_context, entry->mod_name, 1)->data, - INST_SZ); + if (mod_princ->mod_princ->length > 1) { + strncpy(principal->mod_instance, + krb5_princ_component(edit_context,mod_princ->mod_princ,1)->data, + INST_SZ); + } else { + principal->mod_instance[0] = '*'; + principal->mod_instance[1] = '\0'; } - else { - principal->mod_instance[0] = '*'; - principal->mod_instance[1] = '\0'; + free(mod_name); + + /* OK deal with the key now. */ + for (max_kvno = i = 0; i < entry->n_key_data; i++) { + if (max_kvno < entry->key_data[i].key_data_kvno) { + max_kvno = entry->key_data[i].key_data_kvno; + ok_key = i; + } } + while (ok_key < entry->n_key_data) { + if (max_kvno == entry->key_data[ok_key].key_data_kvno) { + if (entry->key_data[ok_key].key_data_type[1] + == KRB5_KDB_SALTTYPE_V4) { + goto found_one; + } + } + ok_key++; + } + /* skip this because it's a new style key and we can't help it */ + return 0; +found_one:; + principal->key_version = max_kvno; principal->max_life = entry->max_life / (60 * 5); principal->kdc_key_ver = entry->mkvno; /* ??? not preserved incoming */ - principal->key_version = entry->kvno; principal->attributes = 0; /* ??? not preserved either */ - + fprintf(arg->f, "%s %s %d %d %d %d ", principal->name, principal->instance, @@ -187,26 +206,21 @@ krb5_db_entry *entry; principal->key_version, principal->attributes); - handle_one_key(arg, arg->v5master, &entry->key, v4key); + handle_one_key(arg, arg->v5master, &entry->key_data[ok_key], v4key); - for (i=0; i<8; i++) { + for (i = 0; i < 8; i++) { fprintf(arg->f, "%02x", ((unsigned char*)v4key)[i]); if (i == 3) fputc(' ', arg->f); } v4_print_time(arg->f, entry->expiration); - v4_print_time(arg->f, entry->mod_date); - - fprintf(arg->f, " %s %s\n", - principal->mod_name, - principal->mod_instance); + v4_print_time(arg->f, mod_princ->mod_date); - free(name); - free(mod_name); + fprintf(arg->f, " %s %s\n", principal->mod_name, principal->mod_instance); return 0; } -/*ARGSUSED*/ +/*ARGSUSED*/ void dump_v4db(argc, argv) int argc; char **argv; @@ -349,10 +363,10 @@ int handle_keys(arg) } handle_one_key(arg, v5master, v5key, v4key) - struct dump_record *arg; - krb5_encrypt_block *v5master; - krb5_encrypted_keyblock *v5key; - des_cblock v4key; + struct dump_record *arg; + krb5_encrypt_block *v5master; + krb5_key_data *v5key; + des_cblock v4key; { krb5_error_code retval; @@ -360,10 +374,9 @@ handle_one_key(arg, v5master, v5key, v4key) krb5_keyblock v5plainkey; /* v4key is the actual v4 key from the file. */ - retval = krb5_kdb_decrypt_key(edit_context, v5master, v5key, &v5plainkey); - if (retval) { + if (retval = krb5_dbekd_decrypt_key_data(edit_context, v5master, v5key, + &v5plainkey, NULL)) return retval; - } /* v4v5key.contents = (krb5_octet *)v4key; */ /* v4v5key.keytype = KEYTYPE_DES; */ @@ -382,7 +395,6 @@ handle_one_key(arg, v5master, v5key, v4key) (C_Block *) arg->v4_master_key, ENCRYPT); #endif /* KDB4_DISABLE */ - return 0; } -- 2.26.2