int ceo_read_password(char *password, unsigned int size, int use_stdin) { int tries = 0; unsigned int len; do { if (use_stdin) { if (fgets(password, size, stdin) == NULL) fatal("eof while reading password"); size = strlen(password); if (password[size - 1] == '\n') password[size - 1] = '\0'; } else { len = size; int retval = krb5_read_password(context, "New password", "Confirm password", password, &len); if (retval == KRB5_LIBOS_PWDINTR) { error("interrupted"); return -1; } else if (retval == KRB5_LIBOS_BADPWDMATCH) { fputs("Passwords do not match.\n", stderr); } else if (!password || !*password) { fputs("Please enter a password.\n", stderr); } } } while (++tries < 3 && !*password); if (!*password) { error("maximum tries exceeded reading password"); return -1; } return 0; }
krb5_error_code krb5_db_fetch_mkey(krb5_context context, krb5_principal mname, krb5_enctype etype, krb5_boolean fromkeyboard, krb5_boolean twice, char *db_args, krb5_data * salt, krb5_keyblock * key) { krb5_error_code retval; char password[BUFSIZ]; krb5_data pwd; unsigned int size = sizeof(password); int kvno; krb5_keyblock tmp_key; memset(&tmp_key, 0, sizeof(tmp_key)); if (fromkeyboard) { krb5_data scratch; if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1, twice ? krb5_mkey_pwd_prompt2 : 0, password, &size))) { goto clean_n_exit; } pwd.data = password; pwd.length = size; if (!salt) { retval = krb5_principal2salt(context, mname, &scratch); if (retval) goto clean_n_exit; } retval = krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch, key); if (!salt) krb5_xfree(scratch.data); memset(password, 0, sizeof(password)); /* erase it */ } else { kdb5_dal_handle *dal_handle; if (context->db_context == NULL) { retval = kdb_setup_lib_handle(context); if (retval) { goto clean_n_exit; } } dal_handle = (kdb5_dal_handle *) context->db_context; retval = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); if (retval) { goto clean_n_exit; } tmp_key.enctype = key->enctype; retval = dal_handle->lib_handle->vftabl.fetch_master_key(context, mname, &tmp_key, &kvno, db_args); get_errmsg(context, retval); kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); if (retval) { goto clean_n_exit; } key->contents = malloc(tmp_key.length); if (key->contents == NULL) { retval = ENOMEM; goto clean_n_exit; } key->magic = tmp_key.magic; key->enctype = tmp_key.enctype; key->length = tmp_key.length; memcpy(key->contents, tmp_key.contents, tmp_key.length); } clean_n_exit: if (tmp_key.contents) { memset(tmp_key.contents, 0, tmp_key.length); krb5_db_free(context, tmp_key.contents); } return retval; }
void kdb5_add_mkey(int argc, char *argv[]) { int optchar; krb5_error_code retval; char *mkey_fullname; char *pw_str = 0; unsigned int pw_size = 0; int do_stash = 0; krb5_data pwd; krb5_kvno new_mkey_kvno; krb5_keyblock new_mkeyblock; krb5_enctype new_master_enctype = ENCTYPE_UNKNOWN; char *new_mkey_password; krb5_db_entry *master_entry; krb5_timestamp now; /* * The command table entry for this command causes open_db_and_mkey() to be * called first to open the KDB and get the current mkey. */ memset(&new_mkeyblock, 0, sizeof(new_mkeyblock)); memset(&master_princ, 0, sizeof(master_princ)); master_salt.data = NULL; while ((optchar = getopt(argc, argv, "e:s")) != -1) { switch(optchar) { case 'e': if (krb5_string_to_enctype(optarg, &new_master_enctype)) { com_err(progname, EINVAL, _("%s is an invalid enctype"), optarg); exit_status++; return; } break; case 's': do_stash++; break; case '?': default: usage(); return; } } if (new_master_enctype == ENCTYPE_UNKNOWN) new_master_enctype = global_params.enctype; /* assemble & parse the master key name */ if ((retval = krb5_db_setup_mkey_name(util_context, global_params.mkey_name, global_params.realm, &mkey_fullname, &master_princ))) { com_err(progname, retval, _("while setting up master key name")); exit_status++; return; } retval = krb5_db_get_principal(util_context, master_princ, 0, &master_entry); if (retval != 0) { com_err(progname, retval, _("while getting master key principal %s"), mkey_fullname); exit_status++; goto cleanup_return; } printf(_("Creating new master key for master key principal '%s'\n"), mkey_fullname); printf(_("You will be prompted for a new database Master Password.\n")); printf(_("It is important that you NOT FORGET this password.\n")); fflush(stdout); pw_size = 1024; pw_str = malloc(pw_size); if (pw_str == NULL) { com_err(progname, ENOMEM, _("while creating new master key")); exit_status++; goto cleanup_return; } retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2, pw_str, &pw_size); if (retval) { com_err(progname, retval, _("while reading new master key from keyboard")); exit_status++; goto cleanup_return; } new_mkey_password = pw_str; pwd.data = new_mkey_password; pwd.length = strlen(new_mkey_password); retval = krb5_principal2salt(util_context, master_princ, &master_salt); if (retval) { com_err(progname, retval, _("while calculating master key salt")); exit_status++; goto cleanup_return; } retval = krb5_c_string_to_key(util_context, new_master_enctype, &pwd, &master_salt, &new_mkeyblock); if (retval) { com_err(progname, retval, _("while transforming master key from password")); exit_status++; goto cleanup_return; } new_mkey_kvno = get_next_kvno(util_context, master_entry); retval = add_new_mkey(util_context, master_entry, &new_mkeyblock, new_mkey_kvno); if (retval) { com_err(progname, retval, _("adding new master key to master principal")); exit_status++; goto cleanup_return; } if ((retval = krb5_timeofday(util_context, &now))) { com_err(progname, retval, _("while getting current time")); exit_status++; goto cleanup_return; } if ((retval = krb5_dbe_update_mod_princ_data(util_context, master_entry, now, master_princ))) { com_err(progname, retval, _("while updating the master key principal " "modification time")); exit_status++; goto cleanup_return; } if ((retval = krb5_db_put_principal(util_context, master_entry))) { (void) krb5_db_fini(util_context); com_err(progname, retval, _("while adding master key entry to the " "database")); exit_status++; goto cleanup_return; } if (do_stash) { retval = krb5_db_store_master_key(util_context, global_params.stash_file, master_princ, new_mkey_kvno, &new_mkeyblock, mkey_password); if (retval) { com_err(progname, errno, _("while storing key")); printf(_("Warning: couldn't stash master key.\n")); } } cleanup_return: /* clean up */ (void) krb5_db_fini(util_context); zap((char *)master_keyblock.contents, master_keyblock.length); free(master_keyblock.contents); zap((char *)new_mkeyblock.contents, new_mkeyblock.length); free(new_mkeyblock.contents); if (pw_str) { zap(pw_str, pw_size); free(pw_str); } free(master_salt.data); krb5_free_unparsed_name(util_context, mkey_fullname); return; }
/* * This routine is the "obtain" function for the SAM_CHALLENGE * preauthentication type. It presents the challenge... */ static krb5_error_code obtain_sam_padata(krb5_context context, krb5_pa_data *in_padata, krb5_etype_info etype_info, krb5_keyblock *def_enc_key, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_creds *creds, krb5_kdc_req *request, krb5_pa_data **out_padata) { krb5_error_code retval; krb5_data * scratch; krb5_data tmpsam; krb5_pa_data * pa; krb5_sam_challenge *sam_challenge = 0; krb5_sam_response sam_response; /* these two get encrypted and stuffed in to sam_response */ krb5_enc_sam_response_enc enc_sam_response_enc; krb5_keyblock * sam_use_key = 0; char * prompt; tmpsam.length = in_padata->length; tmpsam.data = (char *) in_padata->contents; retval = decode_krb5_sam_challenge(&tmpsam, &sam_challenge); if (retval) return retval; if (sam_challenge->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) { return KRB5_SAM_UNSUPPORTED; } enc_sam_response_enc.sam_nonce = sam_challenge->sam_nonce; if (!sam_challenge->sam_nonce) { retval = krb5_us_timeofday(context, &enc_sam_response_enc.sam_timestamp, &enc_sam_response_enc.sam_usec); sam_response.sam_patimestamp = enc_sam_response_enc.sam_timestamp; } if (retval) return retval; if (sam_challenge->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) { /* encrypt passcode in key by stuffing it here */ unsigned int pcsize = 256; char *passcode = malloc(pcsize+1); if (passcode == NULL) return ENOMEM; prompt = handle_sam_labels(sam_challenge); if (prompt == NULL) { free(passcode); return ENOMEM; } retval = krb5_read_password(context, prompt, 0, passcode, &pcsize); free(prompt); if (retval) { free(passcode); return retval; } enc_sam_response_enc.sam_sad.data = passcode; enc_sam_response_enc.sam_sad.length = pcsize; } else if (sam_challenge->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) { prompt = handle_sam_labels(sam_challenge); if (prompt == NULL) return ENOMEM; retval = sam_get_pass_from_user(context, etype_info, key_proc, key_seed, request, &sam_use_key, prompt); free(prompt); if (retval) return retval; enc_sam_response_enc.sam_sad.length = 0; } else { /* what *was* it? */ return KRB5_SAM_UNSUPPORTED; } /* so at this point, either sam_use_key is generated from the passcode * or enc_sam_response_enc.sam_sad is set to it, and we use * def_enc_key instead. */ /* encode the encoded part of the response */ if ((retval = encode_krb5_enc_sam_response_enc(&enc_sam_response_enc, &scratch)) != 0) return retval; if ((retval = krb5_encrypt_data(context, sam_use_key?sam_use_key:def_enc_key, 0, scratch, &sam_response.sam_enc_nonce_or_ts))) goto cleanup; krb5_free_data(context, scratch); scratch = 0; /* sam_enc_key is reserved for future use */ sam_response.sam_enc_key.ciphertext.length = 0; /* copy things from the challenge */ sam_response.sam_nonce = sam_challenge->sam_nonce; sam_response.sam_flags = sam_challenge->sam_flags; sam_response.sam_track_id = sam_challenge->sam_track_id; sam_response.sam_type = sam_challenge->sam_type; sam_response.magic = KV5M_SAM_RESPONSE; if ((retval = encode_krb5_sam_response(&sam_response, &scratch)) != 0) return retval; if ((pa = malloc(sizeof(krb5_pa_data))) == NULL) { retval = ENOMEM; goto cleanup; } pa->magic = KV5M_PA_DATA; pa->pa_type = KRB5_PADATA_SAM_RESPONSE; pa->length = scratch->length; pa->contents = (krb5_octet *) scratch->data; scratch = 0; /* so we don't free it! */ *out_padata = pa; retval = 0; cleanup: if (scratch) krb5_free_data(context, scratch); if (sam_challenge) free(sam_challenge); return retval; }