/* * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ #include #include #include #include "apps_ui.h" static UI_METHOD *ui_method = NULL; static const UI_METHOD *ui_base_method = NULL; static int ui_open(UI *ui) { int (*opener)(UI *ui) = UI_method_get_opener(ui_base_method); if (opener != NULL) return opener(ui); return 1; } static int ui_read(UI *ui, UI_STRING *uis) { int (*reader)(UI *ui, UI_STRING *uis) = NULL; if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD && UI_get0_user_data(ui)) { switch (UI_get_string_type(uis)) { case UIT_PROMPT: case UIT_VERIFY: { const char *password = ((PW_CB_DATA *)UI_get0_user_data(ui))->password; if (password != NULL) { UI_set_result(ui, uis, password); return 1; } } break; case UIT_NONE: case UIT_BOOLEAN: case UIT_INFO: case UIT_ERROR: break; } } reader = UI_method_get_reader(ui_base_method); if (reader != NULL) return reader(ui, uis); /* Default to the empty password if we've got nothing better */ UI_set_result(ui, uis, ""); return 1; } static int ui_write(UI *ui, UI_STRING *uis) { int (*writer)(UI *ui, UI_STRING *uis) = NULL; if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD && UI_get0_user_data(ui)) { switch (UI_get_string_type(uis)) { case UIT_PROMPT: case UIT_VERIFY: { const char *password = ((PW_CB_DATA *)UI_get0_user_data(ui))->password; if (password != NULL) return 1; } break; case UIT_NONE: case UIT_BOOLEAN: case UIT_INFO: case UIT_ERROR: break; } } writer = UI_method_get_writer(ui_base_method); if (writer != NULL) return writer(ui, uis); return 1; } static int ui_close(UI *ui) { int (*closer)(UI *ui) = UI_method_get_closer(ui_base_method); if (closer != NULL) return closer(ui); return 1; } /* object_name defaults to prompt_info from ui user data if present */ static char *ui_prompt_construct(UI *ui, const char *phrase_desc, const char *object_name) { PW_CB_DATA *cb_data = (PW_CB_DATA *)UI_get0_user_data(ui); if (phrase_desc == NULL) phrase_desc = "pass phrase"; if (object_name == NULL && cb_data != NULL) object_name = cb_data->prompt_info; return UI_construct_prompt(NULL, phrase_desc, object_name); } int set_base_ui_method(const UI_METHOD *ui_meth) { if (ui_meth == NULL) ui_meth = UI_null(); ui_base_method = ui_meth; return 1; } int setup_ui_method(void) { ui_base_method = UI_null(); #ifndef OPENSSL_NO_UI_CONSOLE ui_base_method = UI_OpenSSL(); #endif ui_method = UI_create_method("OpenSSL application user interface"); return ui_method != NULL && 0 == UI_method_set_opener(ui_method, ui_open) && 0 == UI_method_set_reader(ui_method, ui_read) && 0 == UI_method_set_writer(ui_method, ui_write) && 0 == UI_method_set_closer(ui_method, ui_close) && 0 == UI_method_set_prompt_constructor(ui_method, ui_prompt_construct); } void destroy_ui_method(void) { if (ui_method != NULL) { UI_destroy_method(ui_method); ui_method = NULL; } } const UI_METHOD *get_ui_method(void) { return ui_method; } static void *ui_malloc(int sz, const char *what) { void *vp = OPENSSL_malloc(sz); if (vp == NULL) { BIO_printf(bio_err, "Could not allocate %d bytes for %s\n", sz, what); ERR_print_errors(bio_err); exit(1); } return vp; } int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data) { int res = 0; UI *ui; int ok = 0; char *buff = NULL; int ui_flags = 0; const char *prompt_info = NULL; char *prompt; if ((ui = UI_new_method(ui_method)) == NULL) return 0; if (cb_data != NULL && cb_data->prompt_info != NULL) prompt_info = cb_data->prompt_info; prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); if (prompt == NULL) { BIO_printf(bio_err, "Out of memory\n"); UI_free(ui); return 0; } ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); /* We know that there is no previous user data to return to us */ (void)UI_add_user_data(ui, cb_data); ok = UI_add_input_string(ui, prompt, ui_flags, buf, PW_MIN_LENGTH, bufsiz - 1); if (ok >= 0 && verify) { buff = ui_malloc(bufsiz, "password buffer"); ok = UI_add_verify_string(ui, prompt, ui_flags, buff, PW_MIN_LENGTH, bufsiz - 1, buf); } if (ok >= 0) do { ok = UI_process(ui); } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); OPENSSL_clear_free(buff, (unsigned int)bufsiz); if (ok >= 0) res = strlen(buf); if (ok == -1) { BIO_printf(bio_err, "User interface error\n"); ERR_print_errors(bio_err); OPENSSL_cleanse(buf, (unsigned int)bufsiz); res = 0; } if (ok == -2) { BIO_printf(bio_err, "aborted!\n"); OPENSSL_cleanse(buf, (unsigned int)bufsiz); res = 0; } UI_free(ui); OPENSSL_free(prompt); return res; }